123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #include "sys_ping.h"
- #include "lwip/inet.h"
- #include "lwip/sockets.h"
- #include "lwip/icmp.h"
- #include "string.h"
- #include "main.h"
- #include "usart.h"
- #include "timer.h"
- void ETH_PingWork(void const * szDestIp)
- {
- long nRet = 0;
- char recvBuf[1024];
- /*****************第一步:申请SOCKET************************************/
- uint32_t ip = inet_addr(szDestIp);
- SOCKET sRaw = lwip_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if(sRaw == -1)
- {
- printf("Cannot create socket! Error %d\r\n", errno);
- }
- // 设置接收超时
- struct timeval tv_out;
- tv_out.tv_sec = 5;
- tv_out.tv_usec = 0;
- nRet = setsockopt(sRaw, SOL_SOCKET,SO_RCVTIMEO, &tv_out, sizeof(tv_out));
- if(-1 == nRet)
- {
- printf("Cannot set timeout! %d \r\n",errno);
- }
-
- /*****************第二步:组ICMP包************************************/
-
- // 创建ICMP封包
- char buff[sizeof(ICMP_HDR) + 32];
- ICMP_HDR* pIcmp = (ICMP_HDR*)buff;
-
- // 填写ICMP封包数据
- pIcmp->icmp_type = 8; // 请求一个ICMP回显
- pIcmp->icmp_code = 0;
- pIcmp->icmp_id = (uint16_t)0x1234;
- pIcmp->icmp_checksum = 0;
- pIcmp->icmp_sequence = 0;
- pIcmp->icmp_timestamp = 0xffff;
- // 填充数据部分,可以为任意
- memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
-
-
-
- /*****************第三步:发送ICMP包************************************/
-
- //设置目的地址
- struct sockaddr_in dest;
- dest.sin_family = AF_INET;
- dest.sin_port = htons(0);
- dest.sin_addr.s_addr = ip;
- //pIcmp->icmp_checksum = checksum((uint16_t*)buff, sizeof(ICMP_HDR) + 32); //如果ping过去没回应需要屏蔽这条
- //printf("icmp_checksum = %x\r\n",pIcmp->icmp_checksum);
- nRet = (long)sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (struct sockaddr *)&dest, sizeof(dest));
- if(nRet == -1)
- {
- printf(" sendto() failed: %d \r\n", errno);
- }
- printf("sendto = %ld\r\n",nRet);
-
- /*****************第四步:接收ICMP包************************************/
-
-
- struct sockaddr_in from;
- socklen_t nLen = sizeof(from);
- while(1)
- {
- nRet = (long)recvfrom(sRaw, recvBuf, 64, 0, (struct sockaddr *)&from, &nLen);
- if(nRet == -1)
- {
- printf(" recvfrom() failed: %d\r\n", errno);
- goto __eixt;
- }
- printf("recvfrom = %ld\r\n",nRet);
-
- /*****************第五步:解析ICMP包************************************/
-
- if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
- {
- printf(" Too few bytes from %s \r\n", inet_ntoa(from.sin_addr));
- }
- #if 1 // IP头解析
- IPHeader * header = (IPHeader*)recvBuf;
- struct in_addr a;
- a.s_addr = header->ipSource;
- printf("source ip %s\n", inet_ntoa(a));
- a.s_addr = header->ipDestination;
- printf("dest ip %s\n", inet_ntoa(a));
- #endif
- ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); // 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头
- if(pRecvIcmp->icmp_type != 0)// 回显
- {
- printf("nonecho type %d recvd \r\n", pRecvIcmp->icmp_type);
- }
- if(pRecvIcmp->icmp_id != 0x1234)
- {
- printf(" someone else's packet! \r\n");
- }
- printf(" %d bytes from %s:", (int)nRet, inet_ntoa(from.sin_addr));
- printf(" icmp_seq = %d. ", pRecvIcmp->icmp_sequence);
- printf(" \r\n");
- __eixt:
- memset( recvBuf, 0, sizeof(recvBuf));
- vTaskDelay(100);
- }
- }
- void ping_task_creat()
- {
- osThreadDef(PING, ETH_PingWork, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 4);
- osThreadCreate (osThread(PING), NULL);
- }
-
|