标签:des style blog http io color ar os 使用
这几天的课程给了我们足够多的时间编写代码,让我们更熟练使用套接字编程。课程的代码也更多了。几个要实现的代码:编写抓包程序,封装网络数据包,网络层数据发送,编写简易的web服务器,arp应用层数据分析,实现ftp客户端。使用http实现简单的文件下载器。
为了对网络五层有更加深入的了解,通过下面的程序对网卡的数据进行抓包分析。实现类似与wireshark的功能。
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <linux/if_ether.h> 4 #include <linux/ip.h> 5 #include <linux/udp.h> 6 #include <linux/tcp.h> 7 #include <netinet/in.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #pragma pack(1) 12 struct my_arphdr{ 13 unsigned short h_type; 14 unsigned short p_type; 15 unsigned char h_len; 16 unsigned char p_len; 17 unsigned short op; 18 unsigned char source_mac[6]; 19 unsigned long source_ip; 20 unsigned char dest_mac[6]; 21 unsigned long dest_ip; 22 }; 23 void show_mac(const unsigned char *data); 24 void show_ip(const unsigned char *data); 25 void show_arp(const unsigned char *data); 26 void show_tcp(const unsigned char *data); 27 void show_udp(const unsigned char *data); 28 void show_app(const unsigned char *data); 29 30 int main() 31 { 32 int fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));//接收所有通过网卡的数据包 33 if(fd < 0){ 34 perror("socket"); 35 return 1; 36 } 37 38 int ret = 0; 39 int i = 0; 40 unsigned char buff[1024] = {0}; 41 while(1){ 42 memset(buff, 0, 1024); 43 ret = read(fd, buff, 1024);//将数据包的内容保存到数组中 44 if(ret < 0){ 45 perror("read"); 46 continue; 47 } 48 if(ret < 42)//不处理错误包 49 continue; 50 show_mac(buff); 51 printf("\n\n\n"); 52 } 53 54 } 55 56 void show_mac(const unsigned char *data){ 57 struct ethhdr *eth = (struct ethhdr *)data; 58 printf("--------------数据链路-----------\n"); 59 printf("dest mac is %02x:%02x:%02x:%02x:%02x:%02x\n", 60 eth->h_dest[0], eth->h_dest[1], 61 eth->h_dest[2], eth->h_dest[3], 62 eth->h_dest[4], eth->h_dest[5] 63 ); 64 printf("src mac is %02x:%02x:%02x:%02x:%02x:%02x\n", 65 eth->h_source[0], eth->h_source[1], 66 eth->h_source[2], eth->h_source[3], 67 eth->h_source[4], eth->h_source[5] 68 ); 69 printf("nework proto is %04x\n", ntohs(eth->h_proto)); 70 if(ntohs(eth->h_proto)==0x0800) 71 show_ip(data+sizeof(struct ethhdr)); 72 if(ntohs(eth->h_proto)==0x0806) 73 show_arp(data+sizeof(struct ethhdr)); 74 } 75 void show_ip(const unsigned char *data){ 76 struct iphdr *ipth = (struct iphdr *)data; 77 printf("--------------网络层-----------\n"); 78 printf("version is %d\n",ipth->version); 79 printf("ip leng is %d\n",ipth->ihl * ipth->version); 80 printf("tos is %d\n",ipth->tos); 81 printf("tot_len is %04d\n",ntohs(ipth->tot_len)); 82 printf("id is %04d\n",ntohs(ipth->id)); 83 printf("frag_off is %04d\n",ntohs(ipth->frag_off)); 84 printf("ttl is %d\n",ipth->ttl); 85 printf("protocol is %d\n",ipth->protocol); 86 printf("check is %04d\n",ntohs(ipth->check)); 87 printf("sourre ip is %s\n",inet_ntoa(ipth->saddr)); 88 printf("dest ip is %s\n",inet_ntoa(ipth->daddr)); 89 if(ipth->protocol==6) 90 show_tcp(data+sizeof(struct iphdr)); 91 if(ipth->protocol==17) 92 show_udp(data+sizeof(struct iphdr)); 93 } 94 void show_arp(const unsigned char *data){ 95 printf("--------------arp-----------\n"); 96 struct my_arphdr *my_arp = (struct my_arphdr *)data; 97 printf("h_type is %d\n",ntohs(my_arp->h_type)); 98 printf("p_type is %d\n",ntohs(my_arp->p_type)); 99 printf("h_len is %d\n",my_arp->h_len); 100 printf("p_len is %d\n",my_arp->h_len); 101 printf("op is %d\n",ntohs(my_arp->op)); 102 printf("src_mac is %02x:%02x:%02x:%02x:%02x:%02x\n", 103 my_arp->source_mac[0],my_arp->source_mac[1], 104 my_arp->source_mac[2],my_arp->source_mac[3], 105 my_arp->source_mac[4],my_arp->source_mac[5] 106 ); 107 printf("sourre ip is %s\n",inet_ntoa(my_arp->source_ip)); 108 printf("dest_mac is %02x:%02x:%02x:%02x:%02x:%02x\n", 109 my_arp->dest_mac[0],my_arp->dest_mac[1], 110 my_arp->dest_mac[2],my_arp->dest_mac[3], 111 my_arp->dest_mac[4],my_arp->dest_mac[5] 112 ); 113 printf("sourre ip is %s\n",inet_ntoa(my_arp->dest_ip)); 114 115 116 117 } 118 void show_udp(const unsigned char *data){ 119 struct udphdr *udpth = (struct udphdr *)data; 120 printf("--------------传输层-----------\n"); 121 printf("source port is %d\n",ntohs(udpth->source)); 122 printf("dest port is %d\n",ntohs(udpth->dest)); 123 printf("len is %04d\n",ntohs(udpth->len)); 124 printf("check is %04d\n",ntohs(udpth->check)); 125 show_app(data+sizeof(struct udphdr)); 126 } 127 void show_tcp(const unsigned char *data){ 128 struct tcphdr *tcpth = (struct tcphdr *)data; 129 printf("--------------传输层-----------\n"); 130 printf("source port is %d\n",ntohs(tcpth->source)); 131 printf("dest port is %d\n",ntohs(tcpth->dest)); 132 printf("seq is %d\n",ntohl(tcpth->seq)); 133 printf("ack_seq is %d\n",ntohl(tcpth->ack_seq)); 134 show_app(data+sizeof(struct tcphdr)); 135 136 } 137 void show_app(const unsigned char *data){ 138 printf("--------------应用层-----------\n"); 139 int i = 0; 140 for(i=0;i<20;i++) 141 printf("%c",*(data+i)); 142 printf("\n"); 143 }
对于网络抓包程序的编写,主要是要熟练掌握几个协议的首部。了解其中的运作机制。在学习过程中,还对校验和使用的回滚算法进行编写。下面是回滚算法的实现:
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 unsigned short check_sum(unsigned char *data,int len); 5 int main() 6 { 7 unsigned char data[1024] ={ 8 0x45, 0x00, 9 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11, 10 0x00, 0x00, 0xc0, 0xa8, 0x1f, 0x72, 0xc0, 0xa8, 11 0x1f, 0x7a 12 }; 13 unsigned short ret = 0; 14 ret = check_sum(data,20); 15 printf("check sum is %x\n",htons(ret)); 16 17 } 18 unsigned short check_sum(unsigned char *data,int len){ 19 unsigned short ret = 0; 20 unsigned long retsum = 0; 21 unsigned short *buff = (unsigned short*)data; 22 // 以两字节为单位反复累加 23 while(len > 1){ 24 retsum = retsum + *buff++; 25 len = len -2; 26 } 27 //如果是单数的话,加最后一个 28 if(len){ 29 retsum = retsum + *buff; 30 } 31 // 将位累加和的高位与低位第一次相加 32 retsum = ((retsum >>16) & 0xffff) +(retsum & 0xffff); 33 return ~ret; 34 }
下面的代码是对于数据包的封装,以及发送网络层数据。
1 #include<stdlib.h> 2 #include<stdio.h> 3 #include<sys/socket.h> 4 #include<netinet/in.h> 5 #include<string.h> 6 #pragma pack(1) 7 struct udphdr{ 8 unsigned short source; 9 unsigned short dest; 10 unsigned short len; 11 unsigned short check; 12 }; 13 struct iphdr{ 14 unsigned char ihl : 4; 15 unsigned char version : 4; 16 unsigned char tos ; 17 unsigned short tot_len ; 18 unsigned short id ; 19 unsigned short frag_off; 20 unsigned char ttl ; 21 unsigned char protocol; 22 unsigned short check; 23 unsigned long saddr ; 24 unsigned long daddr ; 25 }; 26 void encapsulation_ip(char *buff,unsigned short tolen); 27 void encapsulation_udp(char *buff,unsigned short udp_len); 28 void encapsulation_app(char *buff,char *data,unsigned short data_len); 29 30 int main(void) 31 { 32 unsigned char *data = "hello"; 33 unsigned char buff[1024] = {0}; 34 unsigned short tolen = sizeof(struct iphdr)+sizeof(struct udphdr) + strlen(data); 35 unsigned short udp_len=sizeof(struct udphdr)+strlen(data); 36 unsigned short data_len=sizeof(struct udphdr)+sizeof(struct iphdr); 37 38 encapsulation_ip(buff,tolen); 39 encapsulation_udp(buff+sizeof(struct iphdr),udp_len); 40 encapsulation_app(buff+data_len,data,data_len); 41 int fd = socket(AF_INET,SOCK_RAW,IPPROTO_UDP);//创建套接字,使用的是原始数据。 42 if(fd < 0){ 43 perror("socket"); 44 return 1; 45 } 46 struct sockaddr_in recv; 47 recv.sin_family = AF_INET; 48 recv.sin_port = htons(9527); 49 recv.sin_addr.s_addr = inet_addr("192.168.1.10"); 50 51 int ret = 0; 52 int value = 1; 53 int len = 4; 54 ret = setsockopt(fd,IPPROTO_IP,IP_HDRINCL,&value,len);//设置套机字,从网络层发送数据,如果value为0,则从传输层发送数据。 55 if (ret < 0){ 56 perror("setsockopt"); 57 return 1; 58 } 59 ret = sendto(fd,buff,tolen,0,(struct sockaddr*)&recv,sizeof(struct sockaddr));//发送数据给接收端 60 if (ret < 0){ 61 perror("sendto"); 62 return 1; 63 } 64 } 65 66 67 void encapsulation_ip( char *buff,unsigned short tolen){ 68 struct iphdr *ipth = (struct iphdr *)buff; 69 ipth->version = 4; 70 ipth->ihl = 5; 71 ipth->tos = 0; 72 ipth->tot_len = htons(tolen); 73 ipth->id = htons(0); 74 ipth->frag_off = htons(0); 75 ipth->ttl = 64; 76 ipth->protocol = 17; 77 ipth->check = htons(0); 78 ipth->saddr = inet_addr("192.168.1.10"); 79 ipth->daddr = inet_addr("192.168.1.10"); 80 81 } 82 void encapsulation_udp(char *buff,unsigned short udp_len){ 83 struct udphdr *udp = (struct udphdr *)buff; 84 udp->source = htons(9999); 85 udp->dest = htons(9527); 86 udp->len = htons(udp_len); 87 udp->check = htons(0);//填零系统会自动计算校验和 88 } 89 90 void encapsulation_app(char *buff,char *data,unsigned short data_len){ 91 92 char * newbuff = NULL; 93 newbuff =memmove(buff,data,strlen(data));//使用memcopy可能会产生数据重叠,所以一般使用memmove函数。 94 if(newbuff == NULL){ 95 perror("memmove"); 96 exit(EXIT_FAILURE); 97 } 98 99 }
标签:des style blog http io color ar os 使用
原文地址:http://www.cnblogs.com/linrong/p/4093666.html