C语言分析数据包程序

网友投稿 322 2022-10-28


C语言分析数据包程序

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  /**/typedef struct value{   u_int32_t sip;                                 /*源IP*/   unsigned long long packets;                    /* 报数 */   unsigned long long tcp;               unsigned long long udp;   unsigned long long icmp;   unsigned long long other;   unsigned long long bytes;                      /* 流量 */ }value; /*  */ typedef struct{   value v;                        /* 结构体 value*/   unsigned long long fpacket;     /* 进包数 */   unsigned long long fbytes;      /* 进流量 */ }xvalue; #define HASHSIZE 10000        /* hash表大小 */ #define HASHSIZEIN 1000       /* hash表大小 */ /*自定义结构体 */ typedef struct node{   u_int32_t ip;                                          // ip地址,次结构体记录Ip对应的以下属性    unsigned long long bytes;                  /* 字节数 */   unsigned long long packets;                /* 数据包数 */   unsigned long long fbytes;                 /* 进流量 */   unsigned long long fpacket;                /* 进包数 */   unsigned long long tcp;                    /*  是否为tcp协议 */   unsigned long long udp;                    /* 是否为udp协议 */   unsigned long long icmp;                   /* 是否为icmp协议 */   unsigned long long other;                  /* 其他 */   struct node *next;                         /* 下一个节点指针 */ }htnode; typedef htnode **hashtable; unsigned  long long     in_bytes;           //进网流量 unsigned  long long     in_packets;         //进网包数 unsigned  long long    out_bytes;           //出网流量 unsigned  long long    out_packets=0;       //出网包数 bpf_u_int32 netp,maskp;       /* 网络地址 , 子网掩码*/ hashtable ht,ht_out;   pthread_mutex_t hash_lock;    /*线程锁*/ pthread_attr_t attr; sigset_t mask_sig; int hash(u_int32_t ip, int size) {     return ip % size; } htnode * hashtable_search(hashtable T, int size, u_int32_t ip){       htnode *p=T[hash(ip, size)];       while(p!=NULL && p->ip!=ip)         p=p->next;       return p; } int hashtable_insert(hashtable T, int size, htnode *s) {     int d;       htnode *p=hashtable_search(T, size, s->ip);       if(p!=NULL){           p->fbytes  += s->fbytes;           p->fpacket += s->fpacket;           p->bytes   += s->bytes;           p->packets += s->packets;           p->tcp     += s->tcp;           p->udp     += s->udp;           p->icmp    += s->icmp;           p->other   += s->other;           free(s);           s=NULL;       }else{           d=hash(s->ip, size);           s->next = T[d];           T[d]=s;       } } //哈希表销毁void hashtable_descrty(hashtable h, int size, int in_out){     value *v;     xvalue vs[400];     int sock,j=1;   struct sockaddr_in svraddr;    if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ exit(1); }   svraddr.sin_family = AF_INET;   svraddr.sin_port = htons(4200);   if(inet_pton(AF_INET, "IP地址", &svraddr.sin_addr) < 0){ exit(1); }      //将IP地址由点分十进制 转为 网络字节序格式    if(connect(sock, (const struct sockaddr *)&svraddr, sizeof(svraddr)) < 0){ close(sock);return; }  //启动socket,连接服务端,准备推送数据   memset(&vs[0], 0, sizeof(xvalue));   //外网ip记录的数据       if(in_out==0){         vs[0].v.other = 0;         vs[0].fbytes  = out_bytes;         vs[0].fpacket = out_packets;   //内网ip记录的数据   }else{         vs[0].v.other = 1;         vs[0].fbytes  = in_bytes;         vs[0].fpacket = in_packets;     }   int i;     for (i = 0; i < size; i++)  {         htnode *p,*t;         p = h[i];         if (p ==NULL ) continue;         while(p->next != NULL){             vs[j].v.sip     = p->ip;             vs[j].v.tcp     = p->tcp;             vs[j].v.udp     = p->udp;             vs[j].v.icmp    = p->icmp;             vs[j].v.other   = p->other;             vs[j].v.bytes   = p->bytes;             vs[j].v.packets = p->packets;             vs[j].fbytes    = p->fbytes;             vs[j].fpacket   = p->fpacket;             j++;      t = p->next;             free(p);      p=t;         }     vs[j].v.sip     = p->ip;         vs[j].v.tcp     = p->tcp;         vs[j].v.udp     = p->udp;         vs[j].v.icmp    = p->icmp;         vs[j].v.other   = p->other;         vs[j].v.bytes   = p->bytes;         vs[j].v.packets = p->packets;         vs[j].fbytes    = p->fbytes;         vs[j].fpacket   = p->fpacket;         j++;         free(p);         p=NULL;     }     free(h);     h=NULL;     write(sock, vs, sizeof(xvalue) * j);    //将数据传给服务端     close(sock); } int insert_top(hashtable T, htnode *p, int newsize){     struct in_addr addr;     htnode *t,*f;     int i;     for (i = 0; i < newsize; ++i)  {         if (T[i] != NULL){             if(p->bytes > T[i]->bytes){                 t = T[i];                 int j=i;                 while(j<(newsize-1) && t!=NULL){                     j++;                     f=T[j];                     T[j]=t;                     t=f;                 }                 if(t!=NULL) free(t);                 p->next = NULL;                 T[i] = p;                 return 0;             }         }else{             p->next = NULL;             T[i] = p;             return 0;         }     }    return 1; } hashtable hashtable_top(hashtable h, int size, int newsize){     hashtable topht;     if((topht = (struct node **)calloc(newsize, sizeof(struct node*))) == NULL) exit(-1);     int i;     for (i = 0; i < size; i++)  {         htnode *p,*t;         p = h[i];         if (p ==NULL ) continue;         while(p->next != NULL){             t = p->next;             if (insert_top(topht,p,newsize)){                 free(p);                 p=NULL;             }             p=t;         }         if (insert_top(topht,p,newsize)){             free(p);             p=NULL;         }     }     free(h);     h=NULL;     return topht; } /*数据包处理程序*/ void callPacket(u_char *arg, const struct pcap_pkthdr* pack, const u_char *content)  {     struct ether_header *ethernet;        /* 结构体    以太网包头 */     struct iphdr *ip;                     /* 结构体    ip包头    */     ethernet=(struct ether_header *)content;  /*从content中提取以太网包头信息*/   //ip  检测数据包是否为IP包     if(ntohs(ethernet->ether_type)==ETHERTYPE_IP)  {     ip=(struct iphdr*)(content+14);  /*content前14byte 为以太网包头,将指针移动14byte之后为IP包头开始位置 ,此处 从content中提取IP包头数据 */         int tot_len=ntohs(ip->tot_len) + 18;   /*计算数据包总长度 ip->tot_len代表 ip首部记录的ip包数据包大小, 18= 14+4 14:代表以太网的(源地址+目标地址+类型) 4代表(CRC)*/     //外网包         htnode *hv_out;         if( (hv_out = (struct node*)calloc(1, sizeof(struct node))) ==NULL) exit(-1);   /* 分配内存*/         hv_out->bytes = tot_len;          hv_out->packets = 1;     //内网包          htnode *hv;  // 包含所有内网Ip的进流量、进包数、出流量、出包数     if( (hv    = (struct node*)calloc(1, sizeof(struct node))) ==NULL) exit(-1);         hv->bytes = tot_len;         hv->packets = 1;     switch(ip->protocol)    {             case 6:                 hv_out->tcp = 1;                  hv->tcp    = 1;                 break;             case 17:                 hv_out->udp = 1;                  hv->udp    = 1;                 break;             case 1:                 hv_out->icmp = 1;                  hv->icmp    = 1;                 break;             default:                 hv_out->other = 1;                  hv->other    = 1;                 break;        }     //出网包   如果数据包是从服务端流向客户端     if      ( ((ip->saddr & maskp)==netp) && ((ip->daddr & maskp)!=netp) ){         //内网ip  记录此内网Ip的出流量、出包数             hv->ip = ip->saddr;        //数据包中的源IP地址 此处为内网IP地址             pthread_mutex_lock(&hash_lock);             hashtable_insert(ht, HASHSIZE, hv);        //将hv添加到hash表             pthread_mutex_unlock(&hash_lock);       //外网ip  记录服务端返回给此外网ip的返回流量、返回包数       hv_out->ip = ip->daddr;    //数据包中的目标IP地址 此处为外网ip地址              pthread_mutex_lock(&hash_lock);             hashtable_insert(ht_out, HASHSIZEIN, hv_out); //将hv_out添加到hash表       out_bytes += tot_len;    //出网流量增加             out_packets++;            //出网报数增加             pthread_mutex_unlock(&hash_lock);     //进网包  如果数据包是从客户端流向服务端     }else if( ((ip->daddr & maskp)==netp) && ((ip->saddr & maskp)!=netp) ){         //内网ip    记录此内网ip的进流量、进包数             hv->fbytes  = tot_len;              hv->fpacket = 1;             hv->ip = ip->daddr;           //数据包中的目标id 此处为内网IP地址             pthread_mutex_lock(&hash_lock);             hashtable_insert(ht, HASHSIZE, hv);           //将数据插入ht shah表             pthread_mutex_unlock(&hash_lock);       //外网ip 记录此外网ip的请求流量,请求包数             hv_out->fbytes  = tot_len;             hv_out->fpacket = 1;             hv_out->ip = ip->saddr;           //数据包中的源IP, 此处为外网IP             pthread_mutex_lock(&hash_lock);             hashtable_insert(ht_out, HASHSIZEIN, hv_out);        //将数据插入ht_out             in_bytes += tot_len;         //进网流量增加             in_packets++;                   //进网包数增加             pthread_mutex_unlock(&hash_lock);     //内网广播包     }else if( ((ip->daddr & maskp)==netp) && ((ip->saddr & maskp)==netp) ){              free(hv);             hv=NULL;             free(hv_out);             hv_out=NULL;             in_bytes += tot_len;               //将内网广播包当做进入流量             in_packets++;                        //将内网数据包当做进入流量     //外网包     }else{              free(hv);             hv=NULL;             free(hv_out);             hv_out=NULL;             out_bytes += tot_len;             out_packets++;              }   // ARP包 作为 进网包,大小为60byte   else if(ntohs (ethernet->ether_type) == ETHERTYPE_ARP) {         in_bytes += 60;         in_packets++;     } } /*抓包程序*/ void *th_works(void *devname){   char errBuf[PCAP_ERRBUF_SIZE];    /* 定义错误信息 */     pcap_t *device = pcap_open_live(devname, 65535, 1, 0, errBuf); /* 准备抓包 */     pcap_loop(device, -1, callPacket, NULL);  /* 循环抓包,并将抓取到的数据包作为参数传给callPacket()函数 */     pcap_close(device); /*结束抓包*/ } void th_sigs(){     for(;;){         int sig;         if (sigwait(&mask_sig, &sig) != 0){ printf("wait signal error\n"); exit(1); }         hashtable oldht, oldht_out, topht, topht_out;         switch (sig){             case SIGTERM:                 printf("Recv signal term, proc will exit...\n");          exit(0);             case SIGINT:                 printf("Ctrl + C, proc will exit...\n");          exit(0);             case SIGALRM:                 oldht = ht;          oldht_out = ht_out;         if((ht     = (struct node **)calloc(HASHSIZE,   sizeof(struct node*))) == NULL) exit(-1);         if((ht_out = (struct node **)calloc(HASHSIZEIN, sizeof(struct node*))) == NULL) exit(-1);         alarm(300);         //printf("in_bytes:%lld in_packets:%lld out_bytes:%lld out_packets:%lld\n", in_bytes, in_packets, out_bytes, out_packets);         syslog(LOG_NOTICE, "in_bytes:%llu in_packets:%llu out_bytes:%llu out_packets:%llu", in_bytes, in_packets, out_bytes, out_packets);         //内网ip                 hashtable_descrty(oldht, HASHSIZE, 1);         //外网ip排序,取前20                 topht_out = hashtable_top(oldht_out, HASHSIZEIN, 20);         hashtable_descrty(topht_out, 20, 0);         in_bytes=0; in_packets=0; out_bytes=0; out_packets=0;         break;             default:                 printf("Recv signum = %i\n", sig); break;    }     } } /*退出进程*/ void myexit(void){     pthread_mutex_destroy(&hash_lock);     pthread_attr_destroy(&attr); } /*将 本进程作为守护进程 */ void Daemon(void){       pid_t mypid1, mypid2;       u_short n = 0;       openlog("sniffer3",LOG_PID, LOG_LOCAL7);       umask(0);       if ((mypid1 = fork()) == -1) {     syslog(LOG_ERR, "fork: %s", strerror(errno));exit(1);   }       if (mypid1 > 0)      exit(0);       setsid();       signal(SIGHUP, SIG_IGN);       if ((mypid2 = fork()) == -1) {     syslog(LOG_ERR, "fork: %s", strerror(errno));     exit(1);   }       if (mypid2 > 0)      exit(0);       chdir("/");       for(; n < 1025; n++)             close(n);       open("/dev/null", O_RDWR);       dup(0);     dup(0); } int main(){   /* 将此进程作为守护进程 */   Daemon();      char errBuf[PCAP_ERRBUF_SIZE], *devname;   /*定义错误信息 ,设备名称*/     devname = pcap_lookupdev(errBuf);  /*自动获取设备*/     char net[20],mask[20];   /* 定义网路地址 子网掩码 */     struct in_addr addr;     /*结构体 in_addr 用来表示一个32位的IPv4地址*/   int ret,perr;   ret = pcap_lookupnet(devname, &netp, &maskp, errBuf); /* 更具网卡 自动查询网络地址和子网掩码*/   addr.s_addr = netp;  /*赋值*/   strcpy(net,inet_ntoa(addr));  /*将网络字节序IP 转为 点分十进制IP*/    addr.s_addr = maskp;   strcpy(mask,inet_ntoa(addr)); /*原理同上,将网络字节序IP 转为 点分十进制IP */   pthread_mutex_init(&hash_lock, NULL);      pthread_t sigtid,workid,workid2;     pthread_attr_init(&attr);  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);     atexit(myexit);  ht     = (struct node **)calloc(HASHSIZE  , sizeof(struct node*));           /*动态分配内存,hash表*/     ht_out = (struct node **)calloc(HASHSIZEIN, sizeof(struct node*));      /*动态分配内存,hash表*/   sigfillset(&mask_sig);   if ((perr = pthread_sigmask(SIG_BLOCK, &mask_sig, NULL)) != 0 ){         printf("pthread_sigmask error\n"); exit(1);     }   if ((perr = pthread_create(&sigtid, &attr, (void *)th_sigs, NULL)) != 0){         printf("pthread_th_sigs error\n"); exit(1);     }   //创建进程 执行th_works(devname)函数   if ((perr = pthread_create(&workid, NULL, th_works, devname)) != 0 ){         printf("pthread_th_works error\n"); exit(1);     }      alarm(300);   int forint=0;   for (;;){         forint++; sleep(60);     }   return 0; }


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java安全框架——Shiro的使用详解(附springboot整合Shiro的demo)
下一篇:二. 第六单元.shell脚本命令
相关文章

 发表评论

暂时没有评论,来抢沙发吧~