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;}
数据
流量
地址
结构
进程
包头
进网
网络
服务
以太网
大小
字节
以太
代表
信息
内存
十进制
目标
十进
子网
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
西安星空软件开发有限公司
ftp服务器允许用户上传文件吗
怎么知道网站服务器到期了
端游绝地求生显示服务器繁忙
平板可以做软件开发吗
郑州高新区网络安全宣传周
数据库连接池技术好处
网络安全大赛kk战队 新闻
微信服务器连接不上qq
网络安全保障的对象是哪些
数据库数据筛选
内网的dns服务器
立达服务器
20万左右的华为服务器
网络时间协议服务器指什么
网络技术学院录取分数线
小狗互联网科技有限公司
数据库收获
qt5登录服务器
远程入侵服务器
用友u8应用服务器改ip
大理 软件开发
网络安全法泄漏多少条入罪
sql语句 创建数据库
云服务器开端口教程
华为网络技术工程师很累
传统网络安全 虚拟化安全
服务器主板点不亮核显灯亮
华为服务器面板指示灯
fidaol4数据库