经过了好几天的网络编程学习,熟悉了套接字的使用,今天需要我们做的是:实现简单的抓包软件并且对数据进行简单分析,实现校验和使用的回滚算法的编写:
下面是简单的抓包软件及分析数据的代码,通过这个程序,我们可以更深层次的了解网络的运行机制,以及数据是怎样在网络中进行传送:
1 #include <stdio.h> 2 #include <string.h> 3 #include <sys/socket.h> 4 #include <netinet/in.h> 5 #include <linux/ip.h> 6 #include <linux/udp.h> 7 #include <linux/if_ether.h> 8 9 void show_mac(unsigned char *data); 10 void show_ip(unsigned char *data); 11 void show_udp(unsigned char *data); 12 void show_app(unsigned char *data); 13 14 int main() 15 { 16 /*接收所有经过该网卡的包*/ 17 int fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 18 if(fd < 0) { 19 perror("socket"); 20 return 1; 21 } 22 23 int ret = 0; 24 int i = 0; 25 unsigned char buff[1024] = {0}; 26 while(1) { 27 memset(buff, 0, 1024); 28 ret = read(fd, buff, 1024);//将接收的包存在数组里面 29 printf("%d\n", strlen(buff)); 30 if(ret < 0) { 31 perror("read"); 32 continue; 33 } 34 if(ret < 42) {//不处理错误的包 35 continue; 36 } 37 printf("socrce ip is:\t %x\t%x\t%x\t%x\n", 38 buff[14 + 12], buff[14 + 13], 39 buff[14 + 14], buff[14 + 15]); 40 printf("dest ip is:\t %x\t%x\t%x\t%x\n", 41 buff[14 + 16], buff[14 + 17], 42 buff[14 + 18], buff[14 + 19]); 43 44 if(buff[14 + 19] != 102) {//只处理发给本机的包 45 continue; 46 } 47 48 for(i = 0; i < ret; i++) { 49 printf("%x\t", buff[i]); 50 if(i % 8 == 0) { 51 printf("\n"); 52 } 53 } 54 printf("\n\n\n"); 55 show_mac(buff); 56 break; 57 58 } 59 60 return 0; 61 } 62 63 void show_mac(unsigned char *data) 64 { 65 printf("----------------eth--------------------\n"); 66 struct ethhdr *eth = (struct ethhdr *)data; 67 printf("destination eth addr: %x:%x:%x:%x:%x:%x\n", 68 eth->h_dest[0], eth->h_dest[1], 69 eth->h_dest[2], eth->h_dest[3], 70 eth->h_dest[4], eth->h_dest[5]); 71 printf("source eth addr: %x:%x:%x:%x:%x:%x\n", 72 eth->h_source[0], eth->h_source[1], 73 eth->h_source[2], eth->h_source[3], 74 eth->h_source[4], eth->h_source[5]); 75 printf("protocol is: %04x\n", ntohs(eth->h_proto)); 76 if(ntohs(eth->h_proto) == 0x0800) { 77 show_ip(data + sizeof(struct ethhdr)); 78 } 79 else { 80 printf("unkonw mac protocol\n"); 81 } 82 83 } 84 85 void show_ip(unsigned char *data) 86 { 87 printf("----------------ip--------------------\n"); 88 struct iphdr *ip = (struct iphdr *)data; 89 printf("version is %d\n", ip->version); 90 printf("head len is %d\n", ip->ihl * 4); 91 printf("total len is %d\n", ntohs(ip->tot_len)); 92 printf("ttl is %d\n", ip->ttl); 93 printf("protocol is %d\n", ip->protocol); 94 printf("check is %x\n", ip->check); 95 printf("saddr is %s\n", inet_ntoa(ip->saddr)); 96 printf("daddr is %s\n", inet_ntoa(ip->daddr)); 97 if(ip->protocol == 17) { 98 show_udp(data + sizeof(struct iphdr)); 99 } 100 else { 101 printf("unkown ip procotol\n"); 102 } 103 104 } 105 106 void show_udp(unsigned char *data) 107 { 108 printf("----------------udp--------------------\n"); 109 struct udphdr *udp = (struct udphdr *)data; 110 printf("source port %d\n", htons(udp->source)); 111 printf("dest port %d\n", htons(udp->dest)); 112 printf("udp len %d\n", htons(udp->len)); 113 printf("check %x\n", htons(udp->check)); 114 115 show_app(data + sizeof(struct udphdr)); 116 } 117 118 void show_app(unsigned char *data) 119 { 120 printf("data is %s\n", data); 121 }
下面是校验和回滚算法的代码:
1 #include <stdio.h> 2 #include <linux/if_ether.h> 3 4 unsigned short check_sum(unsigned char *data, int len); 5 6 int main() 7 { 8 //7af7 9 unsigned char data[1024] = { 10 0x45, 0x00, 11 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11, 12 0x00, 0x00, 0xc0, 0xa8, 0x1f, 0x44, 0xc0, 0xa8, 13 0x1f, 0x41 14 }; 15 16 printf("check sum is %x\n", check_sum(data, 20)); 17 } 18 19 unsigned short check_sum(unsigned char *data, int len) 20 { 21 unsigned long sum = 0; 22 unsigned long ret = 0; 23 unsigned short *tmp = (unsigned short *)data; 24 unsigned short buff[1024] = {0}; 25 26 //以两字节为单位反复累加 27 while(len > 1) { 28 sum = sum + *tmp++; 29 len = len - 2; 30 } 31 32 //如果是单数,加最后一个 33 if(len) { 34 sum = sum + *tmp; 35 } 36 37 //将累加和的高位与低位相加,直至高位为0(回滚) 38 ret = (sum & 0x00ff0000) >> 16; 39 if(ret != 0) { 40 sum = sum + ret; 41 ret = (sum & 0x00ff0000) >> 16; 42 } 43 44 return ntohs(~sum); 45 }