C语言分析数据包程序
发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,#include #include #include #include #include #include #include #include #include #include #include #
千家信息网最后更新 2025年02月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安全错误
数据库的锁怎样保障安全
北京it 软件开发品牌企业
天容信好的网络安全公司
考勤管理系统 数据库设计
王立飞 网络安全
同学们网络安全工作
5e连接不了服务器打什么代码
人体信息大数据库
软件开发责任的问题
c 数据库编程入门经典
中学生 网络安全 故事
服务器和vps
北京智多维网络技术地税罚款
大型游戏服务器的运营成本
数据库汇总两个表格数据表
数据库安全性常用方法
基于内容的推荐算法数据库
设某数据库有学生表和选课表
网络安全大赛举办
苏州憨妈妈网络技术
和平区 网络安全和信息化
宣传部网络安全工作要点
耐特安网络技术有限公司
网络安全二本有哪些
软件开发项目管理专业怎么样
pos机服务器未找到商户
服务器和vps
网络安全的考试题
公司网络安全管理的好处
标准地址数据库
南京云主机服务器维修电话