千家信息网

C语言分析数据包程序

发表于:2024-11-21 作者:千家信息网编辑
千家信息网最后更新 2024年11月21日,#include #include #include #include #include #include #include #include #include #include #include #
千家信息网最后更新 2024年11月21日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;}


0