1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
// ******* IP ******* //IP首部长度 #define IP_HEADER_LEN 20 //IP版本号位置 以太网首部2+6+6,与下面那个在用的时候上区别下 #define IP_HEADER_LEN_VER_P 0xe //IP版本号位置 以太网首部2+6+6 #define IP_P 0xe //IP 16位标志位置 #define IP_FLAGS_P 0x14 //IP 生存时间位置 #define IP_TTL_P 0x16 //IP协议类型位置,如ICMP,TCP,UDP 1个字节 #define IP_PROTO_P 0x17 //首部校验和 #define IP_CHECKSUM_P 0x18 // IP源地址位置 14+12 #define IP_SRC_P 0x1a // IP目标地址位置 14+12+4 #define IP_DST_P 0x1e //IP总长度 #define IP_TOTLEN_H_P 0x10 #define IP_TOTLEN_L_P 0x11 //协议类型 #define IP_PROTO_ICMP_V 0x01 #define IP_PROTO_TCP_V 0x06 #define IP_PROTO_UDP_V 0x11 |
1
2 3 4 5 6 7 8 9 10 11 12 13 |
|
// make a return eth header from a received eth packet void make_eth( unsigned char *buf) { unsigned char i = 0; //copy the destination mac from the source and fill my mac into src while(i < sizeof(mac_addr)) { buf[ETH_DST_MAC + i] = buf[ETH_SRC_MAC + i]; buf[ETH_SRC_MAC + i] = macaddr[i]; i++; } } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
//判定过程与eth_type_is_arp_and_my_ip类似 unsigned char eth_type_is_ip_and_my_ip( unsigned char *buf, unsigned int len) { unsigned char i = 0; //eth+ip+udp header is 42 if(len < MIN_FRAMELEN) { return( 0); } if(buf[ETH_TYPE_H_P] != ETHTYPE_IP_H_V || buf[ETH_TYPE_L_P] != ETHTYPE_IP_L_V) { return( 0); } if(buf[IP_HEADER_LEN_VER_P] != 0x45) { // must be IP V4 and 20 byte header return( 0); } while(i < sizeof(ipv4_addr)) { if(buf[IP_DST_P + i] != ipaddr[i]) { return( 0); } i++; } return( 1); } //下面那个ip填充函数调用它,主要是补充填充和校验和 void fill_ip_hdr_checksum( unsigned char *buf) { unsigned int ck; // clear the 2 byte checksum buf[IP_CHECKSUM_P] = 0; buf[IP_CHECKSUM_P + 1] = 0; buf[IP_FLAGS_P] = 0x40; // don't fragment buf[IP_FLAGS_P + 1] = 0; // fragement offset buf[IP_TTL_P] = 64; // ttl // calculate the checksum: //校验和计算,在下下面那个函数里面,输入参数的含义下面看就晓得了 ck = checksum(&buf[IP_P], IP_HEADER_LEN, 0); buf[IP_CHECKSUM_P] = ck >> 8; buf[IP_CHECKSUM_P + 1] = ck & 0xff; } // make a return ip header from a received ip packet //与以太网填充函数类似,填充ip地址 void make_ip( unsigned char *buf) { unsigned char i = 0; while(i < sizeof(ipv4_addr)) { buf[IP_DST_P + i] = buf[IP_SRC_P + i]; buf[IP_SRC_P + i] = ipaddr[i]; i++; } fill_ip_hdr_checksum(buf); } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
unsigned
int checksum(
unsigned
char * buf,
unsigned
int len,
unsigned
char type)
{ // type 0=ip // 1=udp // 2=tcp unsigned long sum = 0; //if(type==0){ // // do not add anything //} if(type== 1) { sum+=IP_PROTO_UDP_V; // protocol udp // the length here is the length of udp (data+header len) // =length given to this function - (IP.scr+IP.dst length) sum+=len- 8; // = real tcp len } if(type== 2) { sum+=IP_PROTO_TCP_V; // the length here is the length of tcp (data+header len) // =length given to this function - (IP.scr+IP.dst length) sum+=len- 8; // = real tcp len } // build the sum of 16bit words while(len > 1) { sum += 0xFFFF & (*buf<<8|*(buf+ 1)); buf+= 2; len-= 2; } // if there is a byte left then add it (padded with zero) if (len) { sum += (0xFF & *buf)<< 8; } // now calculate the sum over the bytes in the sum // until the result is only 16bit long while (sum>> 16) { sum = (sum & 0xFFFF)+(sum >> 16); } // build 1's complement: return( ( unsigned int) sum ^ 0xFFFF); } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
// ******* ICMP *******
//回显应答 #define ICMP_TYPE_ECHOREPLY_V 0 //回显请求 #define ICMP_TYPE_ECHOREQUEST_V 8 //ICMP类型 #define ICMP_TYPE_P 0x22 //ICMP首部校验和 #define ICMP_CHECKSUM_P 0x24 void make_echo_reply_from_request( unsigned char * buf, unsigned int len) { make_eth(buf); make_ip(buf);
//ICMP_DEBUG插入此处
buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V; //回显应答 // we changed only the icmp.type field from request(=8) to reply(=0). // we can therefore easily correct the checksum: if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)) { buf[ICMP_CHECKSUM_P+ 1]++; } buf[ICMP_CHECKSUM_P]+=0x08; // enc28j60PacketSend(len,buf); } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
void make_echo_reply_from_request(
unsigned
char * buf,
unsigned
int len)
{ int i= 0; make_eth(buf); make_ip(buf); #ifdef ICMP_DEBUG printf( "ping命令发起者的IP地址 : \r\n"); while(i< sizeof(ipv4_addr)) { //注意这里是IP_SRC_P,不是ARP包了,因为包的类型变了 printf( "%d",buf[IP_SRC_P+i]); /*这里错了,应该是IP_DST_P,why?看函数名,好了,看了串口的输出才看出来的*/ if(i!= sizeof(ipv4_addr)- 1) printf( "."); else printf( "\r\n"); i++; } i= 0; #endif buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V; //回送应答 // we changed only the icmp.type field from request(=8) to reply(=0). // we can therefore easily correct the checksum: if (buf[ICMP_CHECKSUM_P] > (0xff-0x08)) { buf[ICMP_CHECKSUM_P+ 1]++; } buf[ICMP_CHECKSUM_P]+=0x08; // enc28j60PacketSend(len,buf); } |