| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- #include "board.h"
- #include "api.h"
- #include "sockets.h"
- typedef struct icmp_hdr
- {
- unsigned char icmp_type; // 消息类型
- unsigned char icmp_code; // 代码
- unsigned short icmp_checksum; // 校验和
- // 下面是回显头
- unsigned short icmp_id; // 用来惟一标识此请求的ID号
- unsigned short icmp_sequence; // 序列号
- unsigned long icmp_timestamp; // 时间戳
- } ICMP_HDR, *PICMP_HDR;
- typedef struct _IPHeader// 20字节的IP头
- {
- uint8_t iphVerLen; // 版本号和头长度(各占4位)
- uint8_t ipTOS; // 服务类型
- uint16_t ipLength; // 封包总长度,即整个IP报的长度
- uint16_t ipID; // 封包标识,惟一标识发送的每一个数据报
- uint16_t ipFlags; // 标志
- uint8_t ipTTL; // 生存时间,就是TTL
- uint8_t ipProtocol; // 协议,可能是TCP、UDP、ICMP等
- uint16_t ipChecksum; // 校验和
- uint32_t ipSource; // 源IP地址
- uint32_t ipDestination; // 目标IP地址
- } IPHeader, *PIPHeader;
- typedef int SOCKET;
- void ping_test(void)
- {
- const char * szDestIp = "192.168.137.1";
- long nRet = 0;
- ICMP_HDR* pIcmp = NULL;
- char buff[sizeof(ICMP_HDR) + 32];
- socklen_t nLen = 0;
- ICMP_HDR* pRecvIcmp = NULL;
- /*****************第一步:申请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);
- goto exit;
- }
- // 设置接收超时
- struct timeval tv_out;
- tv_out.tv_sec = 10;
- 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封包
- 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);
- goto exit;
- }
- printf("sendto = %ld\r\n",nRet);
- /*****************第四步:接收ICMP包************************************/
- char recvBuf[1024];
- struct sockaddr_in from;
- nLen = sizeof(from);
- nRet = (long)recvfrom(sRaw, recvBuf, 1024, 0, (struct sockaddr *)&from, &nLen);
- if(nRet == -1) {
- printf(" recvfrom() failed: %d\r\n", errno);
- goto exit;
- }
- 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 0 // 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
- 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);
- goto exit;
- }
- if(pRecvIcmp->icmp_id != 0x1234) {
- printf(" someone else's packet! \r\n");
- goto exit;
- }
- printf(" %d bytes from %s:", (int)nRet, inet_ntoa(from.sin_addr));
- printf(" icmp_seq = %d. ", pRecvIcmp->icmp_sequence);
- printf(" \r\n");
- exit:
- if (sRaw != -1)
- lwip_close(sRaw);
- return ;
- }
|