sys_ping.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include "sys_ping.h"
  2. #include "lwip/inet.h"
  3. #include "lwip/sockets.h"
  4. #include "lwip/icmp.h"
  5. #include "string.h"
  6. #include "main.h"
  7. #include "usart.h"
  8. #include "timer.h"
  9. void ETH_PingWork(void const * szDestIp)
  10. {
  11. long nRet = 0;
  12. char recvBuf[1024];
  13. /*****************第一步:申请SOCKET************************************/
  14. uint32_t ip = inet_addr(szDestIp);
  15. SOCKET sRaw = lwip_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  16. if(sRaw == -1)
  17. {
  18. printf("Cannot create socket! Error %d\r\n", errno);
  19. }
  20. // 设置接收超时
  21. struct timeval tv_out;
  22. tv_out.tv_sec = 5;
  23. tv_out.tv_usec = 0;
  24. nRet = setsockopt(sRaw, SOL_SOCKET,SO_RCVTIMEO, &tv_out, sizeof(tv_out));
  25. if(-1 == nRet)
  26. {
  27. printf("Cannot set timeout! %d \r\n",errno);
  28. }
  29. /*****************第二步:组ICMP包************************************/
  30. // 创建ICMP封包
  31. char buff[sizeof(ICMP_HDR) + 32];
  32. ICMP_HDR* pIcmp = (ICMP_HDR*)buff;
  33. // 填写ICMP封包数据
  34. pIcmp->icmp_type = 8; // 请求一个ICMP回显
  35. pIcmp->icmp_code = 0;
  36. pIcmp->icmp_id = (uint16_t)0x1234;
  37. pIcmp->icmp_checksum = 0;
  38. pIcmp->icmp_sequence = 0;
  39. pIcmp->icmp_timestamp = 0xffff;
  40. // 填充数据部分,可以为任意
  41. memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
  42. /*****************第三步:发送ICMP包************************************/
  43. //设置目的地址
  44. struct sockaddr_in dest;
  45. dest.sin_family = AF_INET;
  46. dest.sin_port = htons(0);
  47. dest.sin_addr.s_addr = ip;
  48. //pIcmp->icmp_checksum = checksum((uint16_t*)buff, sizeof(ICMP_HDR) + 32); //如果ping过去没回应需要屏蔽这条
  49. //printf("icmp_checksum = %x\r\n",pIcmp->icmp_checksum);
  50. nRet = (long)sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (struct sockaddr *)&dest, sizeof(dest));
  51. if(nRet == -1)
  52. {
  53. printf(" sendto() failed: %d \r\n", errno);
  54. }
  55. printf("sendto = %ld\r\n",nRet);
  56. /*****************第四步:接收ICMP包************************************/
  57. struct sockaddr_in from;
  58. socklen_t nLen = sizeof(from);
  59. while(1)
  60. {
  61. nRet = (long)recvfrom(sRaw, recvBuf, 64, 0, (struct sockaddr *)&from, &nLen);
  62. if(nRet == -1)
  63. {
  64. printf(" recvfrom() failed: %d\r\n", errno);
  65. goto __eixt;
  66. }
  67. printf("recvfrom = %ld\r\n",nRet);
  68. /*****************第五步:解析ICMP包************************************/
  69. if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
  70. {
  71. printf(" Too few bytes from %s \r\n", inet_ntoa(from.sin_addr));
  72. }
  73. #if 1 // IP头解析
  74. IPHeader * header = (IPHeader*)recvBuf;
  75. struct in_addr a;
  76. a.s_addr = header->ipSource;
  77. printf("source ip %s\n", inet_ntoa(a));
  78. a.s_addr = header->ipDestination;
  79. printf("dest ip %s\n", inet_ntoa(a));
  80. #endif
  81. ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); // 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头
  82. if(pRecvIcmp->icmp_type != 0)// 回显
  83. {
  84. printf("nonecho type %d recvd \r\n", pRecvIcmp->icmp_type);
  85. }
  86. if(pRecvIcmp->icmp_id != 0x1234)
  87. {
  88. printf(" someone else's packet! \r\n");
  89. }
  90. printf(" %d bytes from %s:", (int)nRet, inet_ntoa(from.sin_addr));
  91. printf(" icmp_seq = %d. ", pRecvIcmp->icmp_sequence);
  92. printf(" \r\n");
  93. __eixt:
  94. memset( recvBuf, 0, sizeof(recvBuf));
  95. vTaskDelay(100);
  96. }
  97. }
  98. void ping_task_creat()
  99. {
  100. osThreadDef(PING, ETH_PingWork, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 4);
  101. osThreadCreate (osThread(PING), NULL);
  102. }