基于PLC1850平台的ICMP包请求与响应

1、以太网IP包报文格式shell

  IP包是链接在以太网首部(以太网目的MAC地址(6个字节)+以太网源MAC地址(6个字节)+帧类型(2个字节))以后。ide

  IP报文中各个字段分析以下:函数

  ①、版本:在IP报文中,版本占了4个bit位,用来表示该协议采用的是哪个版本的IP,相同版本的IP才能进行通讯。通常此处的值为4,表示IPv4。ui

  ②、头长度:指IP报文中头部的长度,占了4个bit位,一个数值单位表示4个字节(32个bit)。若是忽略可选项,此处的值为5,表示IP包头部为20个字节。spa

  ③、服务类型:指所须要服务的质量,占1个字节。debug

    优先(0~2比特位):该值越大,数据报相对于其余数据报的优先级越高。3d

    时延(3比特位):若是须要较低的时延,需将该位置1,不然置0。code

    吞吐量(4比特位):若是须要较高的吞吐量,须要将该位置1,不然置0。blog

    可靠性(5比特位):若是须要较高的可靠性,需将该位置1,不然置0。接口

    保留(6,7比特位):未使用。

  ④、总长度:指IP数据报的总长度,占2个字节。最大为65535字节,单位:字节。

  ⑤、标识:在分片中使用,同一报文的全部分片具备相同的标识号,占2个字节,方便IP分片的重组。

  ⑥、标志:占3个bit。该字段是与IP分片有关的。只有两位是有效的,分别为MF和DF。MF标识后面是否还有分片,为1时,表示后面还有分片。DF标识是否能分片,为0表示能够分片。保留(0比特位)表示未使用;不分                                片(1比特位)指该数据报信息字段不能分片;还有分片(2比特位)指若是该位置1表示后面还有分片,若是为0,表示该数据包为最后一个分片或者数据报未分片。

  ⑦、段偏移:该字段是与IP分片后,相应的IP片在总的IP片的位置。该字段的单位是8字节。好比,一个长度为4000字节的IP报文,到达路由器。这是超过了链路层的MTU,须要进行分片,4000字节中,20字节为包头,                                      3980字节为数据,须要分红3个IP片(链路层MTU为1500),那么第一个分片的片偏移就是0,表示该分片在3980的第0位开始,第1479位结束。第二个IP片的片偏移为185(1480/8),表示该分片开始的位                                    置在原来IP的第1480位,结束在2959。第三个IP片的片偏移为370(2960/8),表示开始的时候是2960位,结束的时候在3979位。

  ⑧、生存时间(TTL):占1个字节。IP数据包每通过一个路由器,该值减1,若是该值减为0,那么该数据包将被丢弃。Windows系统该值默认为128。

  ⑨、协议:占1个字节。协议值以下表所示。

    

  ⑩、校验和:占2个字节。该值是对整个数据包的包头进行的校验。将整个IP报头部一个字节一个字节相加,最后结果将超过16位的数据取出,加到数据尾部。而后对结果进行取反。

  十一、源IP地址:占4个字节。目的IP地址:占4个字节。

  十二、可选项:占4个字节。

  1三、数据:长度可变,要发送的数据部份内容(原始数据报被分片后的一个分片数据部分)。

2、ICMP报的请求与响应

  ICMP报文是放在IP报的数据部分,ICMP报格式以下:

  ①、类型:占1个字节。类型值有以下:

  ②、代码:占1个字节,指示不一样的“子类型”。

  ③、校验和:占2个字节。为ICMP报文提供错误检测,它是ICMP报文从ICMP类型开始计算的16位反码和的密码。为了计算该校验和,校验和字段应为0。

  ④、数据:取决于报文的类型。通常状况下,在差错报告报文中,该字段包含不能被交付的原始IP数据报的一部分。

  ICMP请求:

  第一步:将LPC1850网口与电脑网口相链接,将电脑IP改为与板子IP在同一个网段,如:板子IP为192.168.1.190,则电脑IP能够改成192.168.1.2。

  主程序代码以下:

 1 #include "LPC18xx.h"
 2 #include "led.h"
 3 
 4 
 5 extern void taskEth (void);  6 
 7 int main(void)  8 {  9  SystemInit(); 10 
11  ledInit(); 12     SysTick_Config(GetCoreClock() / 1000); 13 
14  taskEth(); 15 
16     while (1); 17 } 18 
19 void SysTick_Handler(void) 20 { 21     static int counter = 0; 22 
23     counter++; 24     if (counter >= 100) 25  { 26         counter = 0; 27  ledRolling(); 28  } 29 }
 1 #include <stdlib.h>
 2 #include <lpc18xx.h>
 3 #include "lpc18xx_emac.h"
 4 #include "lpc18xx_debug.h"
 5 
 6 extern uint32_t ipatol(char * p_input);  7 extern void ipInit(uint8_t * mac, uint32_t ip);  8 extern uint32_t ipRcvMacFrame(uint8_t * block, uint32_t frameLen);  9 
10 uint8_t gFlag = 0; 11 
12 uint8_t g_emacBuffer[2048]; 13 
14 uint8_t g_ethMac[6]; 15 
16 // EMAC接口接收到数据,通知应用层回调函数
17 void ethReadReadyCb() 18 { 19     gFlag = 1; 20 } 21 
22 void taskEth (void) 23 { 24  uint32_t len; 25 
26     g_ethMac[0] = 0x11; 27     g_ethMac[1] = 0x1F; 28     g_ethMac[2] = 0xE0; 29     g_ethMac[3] = 0x12; 30     g_ethMac[4] = 0x1E; 31     g_ethMac[5] = 0x0F; 32 
33  debugComInit(); 34     uartPrint("uart init\r\n"); 35 
36     while (ethInit(ethReadReadyCb, g_ethMac) == 0); 37 
38     uartPrint("eth init complete\r\n"); 39     //为以太网接口指定MAC地址和IP地址
40     ipInit(g_ethMac, 0xBE01A8C0);   // 192.168.1.190
41 
42     while (1) 43  { 44         if (!gFlag) 45  { 46             continue; 47  } 48 
49         len = ethRead(g_emacBuffer, 2048); 50         if (len) 51  { 52             ipRcvMacFrame((uint8_t *)g_emacBuffer, len); 53  } 54 
55         gFlag = 0; 56  } 57 }

  IP代码以下:

 1 #include <stdint.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include "lpc18xx_emac.h"
 5 #include "lpc18xx_debug.h"
 6 //#include "shell.h"
 7 
 8 #define MAC_TYPE_IP   0x0800  //ipÀàÐÍ
 9 #define MAC_TYPE_ARP  0x0806  //macÀàÐÍ
 10 
 11 #define ARP_REQ 0x0001      //ARPÇëÇó
 12 #define ARP_RSP 0x0002        //ARPÏìÓ¦
 13 
 14 #define ICMP_ECHO_REQUEST    8                   // message is an echo request
 15 #define ICMP_ECHO_REPLY      0                   // message is an echo reply
 16 
 17 #define PROT_ICMP            1                   // Internet Control Message Protocol
 18 #define PROT_TCP             6                   // Transmission Control Protocol
 19 #define PROT_UDP             17                  // User Datagram Protocol
 20 
 21 #define DONT_FRAGMENT       0x4000 //fragment
 22 #define MORE_FRAGMENT       0x2000
 23 #define FRAGMENT_OFFSET     0x1FFF
 24 
 25 
 26 uint8_t g_ethMacAddr[6];  27 uint32_t g_ethIpAddr;  28 
 29 uint32_t g_ipSndBuffer[64];  30 
 31 uint16_t g_ipIdentifier = 0;  32 
 33 // ½«×Ö´ÓÖ÷»úÐò×ªÎªÍøÂçÐò
 34 uint16_t htons(uint16_t word)  35 {  36     return ((word >> 8) & 0x00FF) | ((word << 8) & 0xFF00);  37 }  38 
 39 // ½«×Ö´ÓÍøÂçÐòתΪÖ÷»úÐò
 40 uint16_t ntohs(uint16_t word)  41 {  42     return ((word >> 8) & 0x00FF) | ((word << 8) & 0xFF00);  43 }  44 
 45 
 46 uint16_t calcChecksum(uint16_t * buffer, uint32_t size)  47 {  48  uint32_t cksum;  49     
 50     cksum = 0;  51 
 52     while (size > 1)  53  {  54         cksum += *buffer++;  55         size -= sizeof(uint16_t);  56  }  57 
 58     if (size)  59  {  60         cksum += *(uint8_t*)buffer;  61  }  62 
 63     cksum = (cksum >> 16) + (cksum & 0xffff);  64     cksum += (cksum >>16);  65     
 66     return (uint16_t)(~cksum);  67 }  68 
 69 // ·¢ËÍARPÏìÓ¦
 70 void arpSndRsp(uint32_t dstIp, uint8_t * mac)  71 {  72     uint8_t * block;  73     //uint32_t blockLen;
 74 
 75     block = (uint8_t *)g_ipSndBuffer;  76 
 77     memcpy(block, mac, 6);  78 
 79     memcpy(block + 6, g_ethMacAddr, 6);  80 
 81     // arp type
 82     *(uint16_t *)&block[12] = htons(MAC_TYPE_ARP);  83 
 84     // --------- ARP ²ã  85     
 86     // Hardway type : Ethernet
 87     block[14] = 0x00;  88     block[15] = 0x01;  89 
 90     // ip type
 91     *(uint16_t *)&block[16] = htons(MAC_TYPE_IP);  92 
 93     // Hardway size
 94     block[18] = 0x06;  95 
 96     // Protocal size
 97     block[19] = 0x04;  98 
 99     // arp reply
100     *(uint16_t *)&block[20] = htons(ARP_RSP); 101 
102     // Sender MAC address
103     memcpy(block + 22, g_ethMacAddr, 6); 104 
105     // Sender IP address
106     *(uint32_t *)&block[28] = g_ethIpAddr; 107 
108     // Target MAC address
109     memcpy(block + 32, mac, 6); 110 
111     // Target IP address : 192.168.0.67
112     block[38] = (uint8_t)dstIp; 113     block[39] = (uint8_t)(dstIp >> 8); 114     block[40] = (uint8_t)(dstIp >> 16); 115     block[41] = (uint8_t)(dstIp >> 24); 116 
117     // 18¸öÌî³ä×Ö½Ú
118     memset(block + 42, 0, 18); 119 
120     ethWrite((uint8_t *)block, 60); 121 } 122 
123 void arpRcv(uint8_t * block, uint32_t frameLen) 124 { 125  uint32_t srcIp, dstIp; 126  uint16_t msgType; 127                
128     msgType = ntohs(*(uint16_t *)(block+6)); 129 
130     srcIp = (uint32_t)*(uint16_t *)(block + 14); 131     srcIp|= ((uint32_t)*(uint16_t *)(block + 16)) << 16; 132 
133     dstIp = (uint32_t)*(uint16_t *)(block + 24); 134     dstIp|= ((uint32_t)*(uint16_t *)(block + 26)) << 16; 135 
136     if (dstIp != g_ethIpAddr) 137  { 138         return; 139  } 140 
141     if (msgType == ARP_REQ) 142  { 143         arpSndRsp(srcIp, block + 8); 144  } 145 } 146 
147 // ²»¹Ü³É¹¦Óë·ñ,¶¼ÓÉIP²ãÀ´ÊÍ·ÅÊý¾Ý°ü¡£
148 void ipSnd(uint32_t dstIp, uint8_t * block, uint32_t len, uint8_t protoType, uint8_t * mac) 149 { 150     block-= 20; 151     len+= 20; 152     
153     // ------------ IP ²ã
154     
155     block[0] = 0x45;  // IP V4. length 20(5*4)
156     
157     block[1] = 0x00;  // service
158     
159     *(uint16_t *)&block[2] = htons(len); 160     
161     *(uint16_t *)&block[4] = htons((uint16_t)g_ipIdentifier++); // identification
162     
163     *(uint16_t *)&block[6] = 0x0040; // flag and fragment
164 
165     block[8] = 128;  // TTL
166 
167     block[9] = protoType; 168     
169     *(uint16_t *)&block[10] = 0; // УÑéºÍÏÈÌîÉÏ0
170     
171     *(uint16_t *)&block[12] = (uint16_t)g_ethIpAddr; 172     *(uint16_t *)&block[14] = (uint16_t)(g_ethIpAddr >> 16); 173 
174     *(uint16_t *)&block[16] = (uint16_t)dstIp; 175     *(uint16_t *)&block[18] = (uint16_t)(dstIp >> 16); 176     
177     *(uint16_t *)&block[10] = calcChecksum((uint16_t *)block, 20); 178 
179     // ------------ MAC ²ã
180 
181     block-= 14; 182     len+= 14; 183     
184     memcpy(block, mac , 6); 185     
186     memcpy(block + 6, g_ethMacAddr, 6); 187 
188     *(uint16_t *)&block[12] = htons(MAC_TYPE_IP); 189 
190     if (len < 60) 191  { 192         // MACÖ¡Ì«¶Ì£¬²¹µ½×î¶Ì³¤¶È¡£
193         memset(block + len, 0, 60 - len); 194         len = 60; 195  } 196 
197     ethWrite((uint8_t *)block, len); 198 } 199 
200 // ICMPÊÕµ½ÇëÇó£¬ÐèÒª»ØÏìÓ¦¡£
201 void icmpRcvRequest(uint32_t srcIp, uint8_t * icmp, uint32_t len, uint8_t * mac) 202 { 203     uint8_t * block; 204 
205     block = (uint8_t *)g_ipSndBuffer; 206 
207     // Áô³ö 14(MAC)+20(IP)¸ö×Ö½Ú 
208     block+=(14+20); 209     
210     // ----------- ICMP ²ã
211         icmp[8]='R'; 212         icmp[9]='e'; 213         icmp[10]='c'; 214         icmp[11]='e'; 215         icmp[12]='i'; 216         icmp[13]='v'; 217         icmp[14]='e'; 218         icmp[15]='d'; 219         
220         icmp[16]=' '; 221         icmp[17]='I'; 222         icmp[18]='C'; 223         icmp[19]='M'; 224         icmp[20]='P'; 225         icmp[22]=' '; 226         icmp[22]='R'; 227         icmp[23]='e'; 228         icmp[24]='q'; 229         icmp[25]='u'; 230         icmp[26]='e'; 231         icmp[27]='s'; 232         icmp[28]='t'; 233         icmp[29]='!'; 234         
235  memcpy(block, icmp, len); 236     
237     block[0] = ICMP_ECHO_REPLY; 238     block[1] = 0;   // code
239     
240     *(uint16_t *)&block[2] = 0;  // УÑéºÍÏÈÌîÉÏ0
241     
242     *(uint16_t *)&block[2] = calcChecksum((uint16_t *)block, len); 243         uartPrint("The ICMP response!\r\n"); 244     ipSnd(srcIp, (void *)block, len, PROT_ICMP, mac); 245 } 246 
247 // ½ÓÊÕµ½IP°üµÄ´¦Àí
248 void ipRcv(uint8_t * frame, uint32_t frameLen, uint8_t * mac) 249 { 250  uint16_t ipLength, flag,i; 251  uint32_t srcIp, dstIp; 252 
253     if (frameLen < 20) 254  { 255         return; 256  } 257 
258     if (calcChecksum((uint16_t *)frame, 20)) 259  { 260         // УÑéºÍ²»ÕýÈ·
261         return; 262  } 263 
264     if (frame[0] != 0x45) 265  { 266         // IP VERSION ӦΪ4£¬³¤¶ÈӦΪ20£¨5¸öbit32£©×Ö½Ú¡£
267         return; 268  } 269 
270     // ignore Type Of Service
271     
272     ipLength = ntohs(*(uint16_t *)&frame[2]); 273     // ignore identification
274 
275     flag = ntohs(*(uint16_t *)&frame[6]); 276 
277     if (!(flag & DONT_FRAGMENT)) 278  { 279         // IP¿ÉÒÔ±»·Ö°ü£¬µ«ÎÒÃÇÖ»´¦Àí²»·Ö°üµÄÇé¿ö¡£
280         
281         if (flag & MORE_FRAGMENT) 282  { 283             // ·Ç×îºóµÄÒ»°ü£¬¶ªÆú¡£
284             return; 285  } 286         
287         // ÊÇ×îºóÒ»°ü¡£
288         
289         if (flag & FRAGMENT_OFFSET) 290  { 291             // ÊÇ×îºóÒ»°ü£¬ÇÒÆ«ÒÆÁ¿²»Îª0£¬Ò²¶ªÆú¡£
292             return; 293  } 294         
295         // ×îºóÒ»°ü£¬ÇÒÆ«ÒÆÁ¿Îª0£¬ÊÇÕû°ü£¬´¦Àí£¡
296  } 297     
298     if (frameLen < ipLength) 299  { 300         return; 301  } 302     
303     // ignore fragment offset 304 
305     //ttl = (uint32_t)frame[8]; 306 
307     //srcIp = (frame[12] | (frame[13]<< 8) | (frame[14] << 16) | (frame[15] << 24)); 308     //dstIp = (frame[16] | (frame[17]<< 8) | (frame[18] << 16) | (frame[19] << 24));
309 
310     srcIp = *(uint16_t *)(frame + 12) | ((uint32_t)*(uint16_t *)(frame + 14) << 16); 311     dstIp = *(uint16_t *)(frame + 16) | ((uint32_t)*(uint16_t *)(frame + 18) << 16); 312 
313     if ((dstIp != g_ethIpAddr) && (dstIp != 0x0100007F) && (dstIp != 0xffffffff)) 314  { 315         return; 316  } 317 
318     if (frame[9] != PROT_ICMP) 319  { 320         // ·ÇICMP°ü£¬Ôݲ»´¦Àí
321         return; 322  } 323         //ÊÕµ½ICMPÇëÇ󣬴òÓ¡³öICMP°ü
324     if (frame[20] == ICMP_ECHO_REQUEST) 325  { 326             uartPrint("ICMP Header:\r\n"); 327             uartPrint("Type:%d\r\n",*(frame+20)); 328             uartPrint("Code:%d\r\n",*(frame+21)); 329             uartPrint("Checksum:0x%04x\r\n",ntohs(*(uint16_t *)(frame+22))); 330       uartPrint("Id:0x%04x\r\n",ntohs(*(uint16_t *)(frame+24))); 331       uartPrint("Sequence:%d\r\n",ntohs(*(uint16_t *)(frame+26))); 332       uartPrint("Data:\r\n"); 333        for(i=0;i<ipLength-28;i++) 334  { 335          uartPrint("%c",frame[28+i]); 336  } 337       uartPrint("\r\n---------------------------------\r\n"); 338       icmpRcvRequest(srcIp, frame + 20, ipLength - 20, mac); 339  } 340 } 341 
342 
343 // IP²ã½ÓÊÕMAC²ãÊý¾ÝÖ¡µÄº¯Êý
344 uint32_t ipRcvMacFrame(uint8_t * block, uint32_t frameLen) 345 { 346     //0xFFFF ¹ã²¥·½Ê½
347     if ( ((*(uint16_t *)block == 0xFFFF) && (*(uint16_t *)(block + 2) == 0xFFFF) && (*(uint16_t *)(block + 4) == 0xFFFF)) 348        ||(memcmp(block, g_ethMacAddr, 6) == 0)) 349  { 350         // ÊÇ·¢¸ø±¾»úµÄ¡£
351         switch (ntohs(*(uint16_t *)(block+12))) 352  { 353         case MAC_TYPE_ARP: 354             arpRcv(block + 14, frameLen -14); 355             break; 356         case MAC_TYPE_IP: 357             ipRcv(block + 14, frameLen - 14, block+6); 358             break; 359         default: 360             break; 361  } 362  } 363 
364     return 1; 365 } 366 
367 void ipInit(uint8_t * mac, uint32_t ip) 368 { 369     memcpy(g_ethMacAddr, mac, 6); 370     g_ethIpAddr = ip; 371 }

  将程序烧写到PLC1850板子上,将板子与电脑用网线,串口线链接。打开cmd,输入ping 192.168.1.190回车。串口将打印出电脑请求的ICMP报的信息。同时可以使用wireshark软件查看相关信息。

相关文章
相关标签/搜索