// // THIS CODE IS BASED ON THE CODE FROM // THE BOOK WINSOCK 2.0 BY LEWIS NAPPER... // // #include "RestfulFunc.h" #if defined(_MSC_VER) #include //路由选项类型,占用3字节 #define IP_RECORD_ROUTE 0x7 //IP时间戳选项 #define IP_TIMESTAMP 0x44 #define DEFAULT_PACKET_SIZE 32 #define MAX_PACKET 1024 + 12 + 20 + 1 #define MAX_IP_HDR_SIZE 60 //回送请求或回答 #define ICMP_ECHO 8 #define ICMP_ECHO_REPLY 0 #define MAX_UNSIGNED_SHORT 65535 #define DEFAULT_TIMEOUT 3000 #define DEFAULT_INTERVAL 1000 typedef struct _iphdr { //注意顺序,网络字节序,大端 unsigned int h_len : 4; unsigned int version : 4; unsigned char tos; // type of service unsigned short total_len; // Total length of the packet unsigned short ident; // Unique identifier unsigned short frag_and_flags; // 标志和片偏移 unsigned char ttl; // time to live unsigned char proto; unsigned short checksum; unsigned int sourceIP; unsigned int destIP; }IpHeader; #define DEFAULT_IP_HEAD_SIZE 20 typedef struct _icmphdr { BYTE btType; //type of icmp BYTE btCode; // code of icmp 进一步定义查询或消息的类型 默认0 USHORT usCksum; //16bits 对ICMP头内容的一个补余求和 USHORT usId; //identification USHORT usSeq; //选项值 ULONG ulTimestamp; }IcmpHeader; #define DEFAULT_ICMP_HEAD_SIZE sizeof(IcmpHeader) const double MAX_GSM_SIGNAL_STRENGTH = 31.0; ///*TODO: to implement!!!! (80374374@11/15/2023)*/ int PingTest(const std::string& dst_ip) { return -1; } #else #include #include #include #include #include #include #include typedef uint32_t DWORD; typedef int SOCKET; typedef struct sockaddr_in* LPSOCKADDR_IN; typedef struct hostent* LPHOSTENT; #define SOCKET_ERROR (-1) #define FAILURE (-1) #define SIZE_LINE_NORMAL (1024) #define SUCCESS (0) #pragma pack(1) #define ICMP_ECHOREPLY 0 #define ICMP_ECHOREQ 8 // IP Header -- RFC 791 typedef struct tagIPHDR { u_char VIHL; // Version and IHL u_char TOS; // Type Of Service short TotLen; // Total Length short ID; // Identification short FlagOff; // Flags and Fragment Offset u_char TTL; // Time To Live u_char Protocol; // Protocol u_short Checksum; // Checksum struct in_addr iaSrc; // Internet Address - Source struct in_addr iaDst; // Internet Address - Destination } IPHDR, * PIPHDR; // ICMP Header - RFC 792 typedef struct tagICMPHDR { u_char Type; // Type u_char Code; // Code u_short Checksum; // Checksum u_short ID; // Identification u_short Seq; // Sequence char Data; // Data } ICMPHDR, * PICMPHDR; #define REQ_DATASIZE 32 // Echo Request Data size // ICMP Echo Request typedef struct tagECHOREQUEST { ICMPHDR icmpHdr; DWORD dwTime; char cData[REQ_DATASIZE]; } ECHOREQUEST, * PECHOREQUEST; // ICMP Echo Reply typedef struct tagECHOREPLY { IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller[256]; } ECHOREPLY, * PECHOREPLY; #pragma pack() static u_short api_checksum16(u_short* buffer, int size); static int gen_icmp_packet(struct icmp* icmp_packet, int type, int seq); int gen_icmp_packet(struct icmp* icmp_packet, int type, int seq) { if (!icmp_packet) { return FAILURE; } icmp_packet->icmp_type = type; icmp_packet->icmp_code = 0; icmp_packet->icmp_cksum = 0; icmp_packet->icmp_id = htons(getpid()); icmp_packet->icmp_seq = htons(seq); gettimeofday((struct timeval*)icmp_packet->icmp_data, NULL); icmp_packet->icmp_cksum = api_checksum16((unsigned short*)icmp_packet, sizeof(struct icmp)); return SUCCESS; } u_short api_checksum16(u_short* buffer, int size) { u_int cksum = 0; if (!buffer) { printf("NULL\n"); return 0; } while (size > 1) { printf("1. Cksum: 0x%08x + 0x%04x\n", cksum, *buffer); cksum += *buffer++; size -= sizeof(u_short); } if (size) { cksum += *(u_char*)buffer; } printf("2. Cksum: 0x%08x\n", cksum); /* 32 bit change to 16 bit */ while (cksum >> 16) { cksum = (cksum >> 16) + (cksum & 0xFFFF); printf("3. Cksum: 0x%08x\n", cksum); } return (u_short)(~cksum); } int PingTest(const std::string& dst_ip) { int ret = FAILURE; int sd = 0; char buf[SIZE_LINE_NORMAL] = { 0 }; struct ip* ip = NULL; struct sockaddr_in dst_addr = { 0 }; struct icmp icmp_packet = { 0 }; struct timeval tm = { .tv_sec = 1, .tv_usec = 0 }; fd_set rdfds; if (dst_ip.empty()) { goto _E1; } sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sd < 0) { printf("socket fail: %d\n", errno); goto _E1; } dst_addr.sin_family = AF_INET; dst_addr.sin_addr.s_addr = inet_addr(dst_ip.c_str()); ret = gen_icmp_packet(&icmp_packet, 8, 1); if (SUCCESS != ret) { goto _E2; } ret = sendto(sd, &icmp_packet, sizeof(struct icmp), 0, (struct sockaddr*)&dst_addr, sizeof(struct sockaddr_in)); if (ret < 0) { goto _E2; } /* Timeout 1s to recv icmp */ FD_ZERO(&rdfds); FD_SET(sd, &rdfds); ret = select(sd + 1, &rdfds, NULL, NULL, &tm); if (-1 == ret && EINTR != errno) { /* if serial error */ printf("select fail\n"); goto _E2; } else if (0 == ret) { /* timeout */ printf("recv timeout\n"); ret = FAILURE; goto _E2; } if (FD_ISSET(sd, &rdfds)) { ret = recv(sd, buf, sizeof(buf), 0); if (ret <= 0) { perror("recv\n"); goto _E2; } ip = (struct ip*)buf; printf("from: %s\n", inet_ntoa(ip->ip_src)); printf(" to: %s\n", inet_ntoa(ip->ip_dst)); } ret = SUCCESS; _E2: close(sd); _E1: return ret; } #endif //_MSC_VER