#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); }