C语言分析数据包程序
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,#include #include #include #include #include #include #include #include #include #include #include #
千家信息网最后更新 2025年12月02日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;}
数据
流量
地址
结构
进程
包头
进网
网络
服务
以太网
大小
字节
以太
代表
信息
内存
十进制
目标
十进
子网
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
i开头单词大数据库
中国数据库技术第一人
学什么网络技术比较有用
筑牢网络安全之基
并集数据库
网络安全和黑客技术
短视频服务器哪个配置好
初级网络安全工程师认证
软件开发培训学校在哪
软件开发是商标第几类
惠普服务器改装
哪个数据库查高考准确
服务器机房怎么做
山东星云伟业网络技术
服务器3650更换硬盘步骤
质量软件开发过程检测中心
零基础学软件开发学费一览表
php连接数据库的文件是什么
幼儿园网络安全自查情况报告
液质谱数据库
开局32k服务器
搜狗软件开发者
做兼职的软件开发
数据库及应用插件安全的升级
网络安全实战特训营
维普生物医学数据库
x3100m5服务器
捷豹智能驭领服务器
数据库技术国外差距
三级网络技术有计算题吗