User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
c:ping [2019-02-22 12:17]
ziggi
c:ping [2020-02-15 00:57] (current)
Line 2: Line 2:
  
 I wrote it for test purpose. I wrote it for test purpose.
 +
 +For Win target I uses MinGW and GCC.
  
 <code c file.c> <code c file.c>
 /* $Id: ping.c,v 1.1 2019/02/20 13:01:37 ziggi Exp ziggi $ */ /* $Id: ping.c,v 1.1 2019/02/20 13:01:37 ziggi Exp ziggi $ */
  
-#include <​sys/​types.h>​ +#ifdef __WINNT__ 
-#include <​sys/​stat.h>​+#define __WINNT 1 
 +#endif
  
 #include <​stdio.h>​ #include <​stdio.h>​
 #include <​stdlib.h>​ #include <​stdlib.h>​
 #include <​string.h>​ #include <​string.h>​
 +#include <​stdint.h>​
 +#include <​limits.h>​
 +#include <​unistd.h>​
 +
 +#ifdef __WINNT__
 +
 +#include <​sys/​types.h>​
 +#include <​sys/​stat.h>​
 +#define _WIN32_WINNT 0x0501
 +#include <​winsock2.h>​
 +#include <​ws2tcpip.h>​
 +#include <​pshpack1.h>​
 +
 +#else
  
 #include <​sys/​socket.h>​ #include <​sys/​socket.h>​
 #include <​arpa/​inet.h>​ #include <​arpa/​inet.h>​
- 
 #include <​netinet/​in.h>​ #include <​netinet/​in.h>​
 #include <​netinet/​ip.h>​ #include <​netinet/​ip.h>​
 #include <​netinet/​ip_icmp.h>​ #include <​netinet/​ip_icmp.h>​
- 
 #include <​netdb.h>​ #include <​netdb.h>​
  
-#include <​unistd.h>​ +#endif 
-#include <​limits.h>​+ 
 +#ifdef __WINNT__ 
 +struct ip { 
 +        u_char ​ ip_hl:​4; ​               /* header length */ 
 +        u_char ​ ip_v:​4; ​                /* version */ 
 +        u_char ​ ip_tos; ​                /* type of service */ 
 +        u_short ip_len; ​                /* total length */ 
 +        u_short ip_id; ​                 /* identification */ 
 +        u_short ip_off; ​                /* fragment offset field */ 
 +        u_char ​ ip_ttl; ​                /* time to live */ 
 +        u_char ​ ip_p;                   /* protocol */ 
 +        u_short ip_sum; ​                /* checksum */ 
 +        struct ​ in_addr ip_src; 
 +        struct ​ in_addr ip_dst; ​        /* source and dest address */ 
 +} __packed; 
 + 
 +struct icmp { 
 +    u_char ​  ​icmp_type;​ 
 +    u_char ​  ​icmp_code;​ 
 +    u_short ​ icmp_cksum;​ 
 + 
 +    u_short ​ icmp_id; 
 +    u_short ​ icmp_seq; 
 +}; 
 +#endif 
 + 
 +typedef struct ip ip_hdr_t; 
 +typedef struct icmp icmp_hdr_t;
  
 +#define HOST "​v5.unix7.org"​
  
-uint16_t ​icmp_checksum(const uint16_t * const data, const size_t byte_sz) {+uint16_t ​icmpv4_checksum(const uint16_t *const data, const size_t byte_sz) {
     if (0 != (byte_sz & 1)) {     if (0 != (byte_sz & 1)) {
-        fprintf(stderr,​ "# wrong number of bytes %zu must be even", ​byte_sz); +        fprintf(stderr,​ "# wrong number of bytes %must be even", (int)byte_sz);
-        exit(1);+
     }     }
     uint32_t accu = 0;     uint32_t accu = 0;
Line 42: Line 84:
 } }
  
-#define HOST "​wiki.unix7.org"​+int __exit(void) { 
 +#ifdef __WINNT__ 
 +    WSACleanup();​ 
 +#endif 
 +    exit(1); 
 +
  
 int main(int argc, char **argv) { int main(int argc, char **argv) {
  
-    const char *host HOST;+#ifdef __WINNT__ 
 +    WSADATA wsaData; 
 + 
 +    #define WSVERSION 0x0202 
 +    int iResult ​WSAStartup(WSVERSION,​ &​wsaData);​ 
 +    if (iResult != 0) { 
 +        printf("#​ wsastartup() failed: %d\n", iResult); 
 +        __exit(); 
 +    } 
 +#endif
  
     struct addrinfo hints;     struct addrinfo hints;
Line 57: Line 114:
     struct addrinfo *result = NULL;     struct addrinfo *result = NULL;
  
-    if (getaddrinfo(HOST,​ NULL, &hints, &​result)) { +    ​int retval; 
-        ​fprintf(stderr, ​"# ​cannot resolve host name %s\n", ​host); +    ​if ((retval = getaddrinfo(HOST,​ NULL, &hints, &​result)) != 0) { 
-        ​exit(1);+        ​printf("# ​getaddrinfo() failed with error: ​%d\n", ​retval); 
 +        ​__exit();
     }     }
  
     struct sockaddr_in *sockaddr = NULL;     struct sockaddr_in *sockaddr = NULL;
 +
     for(struct addrinfo *ptr = result; ptr != NULL ;ptr = ptr->​ai_next) {     for(struct addrinfo *ptr = result; ptr != NULL ;ptr = ptr->​ai_next) {
         switch (ptr->​ai_family) {         switch (ptr->​ai_family) {
Line 72: Line 131:
                 break;                 break;
         }         }
- if (sockaddr != NULL) { +        ​if (sockaddr != NULL) { 
-     ​break; +            break; 
- }+        }
     }     }
  
     struct sockaddr_in dest_sockaddr;​     struct sockaddr_in dest_sockaddr;​
-    memset(&​dest_sockaddr,​ 0, sizeof(dest_sockaddr));​ 
     memcpy(&​dest_sockaddr,​ sockaddr, sizeof(dest_sockaddr));​     memcpy(&​dest_sockaddr,​ sockaddr, sizeof(dest_sockaddr));​
     freeaddrinfo(result);​     freeaddrinfo(result);​
 +
 +    int sock;
 +    if ((sock = socket(AF_INET,​ SOCK_RAW, IPPROTO_ICMP)) < 0) {
 +        printf("#​ socket creation failed\n"​);​
 +        __exit();
 +    }
 +
 +
 +    #define SOCKET_ERROR (-1)
 +    const int ttl = 16;
 +#ifdef __WINNT__
 +    if (setsockopt(sock,​ IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl)) < 0) {
 +        fprintf(stderr,​ "# setting ttl setsockopt failed\n"​);​
 +        __exit();
 +    }
 +#else
 +    if (setsockopt(sock,​ IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
 +        fprintf(stderr,​ "# setting ttl setsockopt failed\n"​);​
 +        __exit();
 +    }
 +#endif
  
 #define PAYLOAD_LEN 4 #define PAYLOAD_LEN 4
-#​define ​OBUFFER_LEN ​sizeof(struct icmp) + PAYLOAD_LEN+#​define ​OBUFFER_SIZE ​sizeof(icmp_hdr_t) + PAYLOAD_LEN
  
-    char obuffer[ OBUFFER_LEN ]; +#ifndef ICMP_ECHO 
-    ​memset(obuffer,​ 0, OBUFFER_LEN);​+#define ICMP_ECHO 8 
 +#endif
  
-    struct icmp *icmp_header = (struct icmp *)obuffer;+#ifndef ICMP_ECHOREPLY 
 +#define ICMP_ECHOREPLY 0 
 +#endif
  
-    icmp_header->​icmp_type = ICMP_ECHO; +#ifndef ICMP_CODE 
-    ​icmp_header->​icmp_code = 0; +#define ICMP_CODE ​
-    ​icmp_header->​icmp_cksum = 0; +#endif
-    icmp_header->​icmp_seq = htons(12345);​ +
-    icmp_header->​icmp_id = htons(45678);​+
  
-    char *payload = obuffer + sizeof(icmp_header);+    ​char obuffer[OBUFFER_SIZE];​ 
 +    icmp_hdr_t *icmp_hdr;​ 
 +    icmp_hdr = (icmp_hdr_t *)obuffer;​ 
 + 
 +    icmp_hdr->​icmp_type = ICMP_ECHO;​ 
 +    icmp_hdr->​icmp_code = ICMP_CODE;​ 
 +    icmp_hdr->​icmp_id = htons(1234);​ 
 +    icmp_hdr->​icmp_cksum = 0; 
 +    icmp_hdr->​icmp_seq = htons(4567);​ 
 + 
 +    ​char *payload = obuffer + sizeof(icmp_hdr_t);
     memset(payload,​ '<',​ PAYLOAD_LEN);​     memset(payload,​ '<',​ PAYLOAD_LEN);​
  
-    ​icmp_header->​icmp_cksum = icmp_checksum((uint16_t *)obuffer, ​OBUFFER_LEN);+    ​icmp_hdr->​icmp_cksum = icmpv4_checksum((uint16_t *)obuffer, ​OBUFFER_SIZE);
  
-    ​int osock; +    ​sendto(sock, (char *)obufferOBUFFER_SIZE, 0, 
-    if ((osock = socket(AF_INETSOCK_RAWIPPROTO_ICMP)) < 0) { +        (struct sockaddr *)&​dest_sockaddrsizeof(dest_sockaddr));
-        ​fprintf(stderr"# raw output socket create failed\n"​);​ +
-        exit(1); +
-    }+
  
-    ​const ssize_t sent_bytes = sendto( +#define IBUFFER_SIZE 2048 
-        osock, +#define SLEEP_TIME 1     ​// 1 ms 
-        obuffer, +#define DELAY_TIME 1000  // 1 sec
-        OBUFFER_LEN,​ +
-        0, +
-        (struct sockaddr *)&​dest_sockaddr,​  +
-        sizeof(dest_sockaddr) +
-    );+
  
-#define IBUFFER_LEN IP_MAXPACKET +    ​char ibuffer[IBUFFER_SIZE];
-    ​char ibuffer[IBUFFER_LEN]+
-    memset(ibuffer,​ 0, IBUFFER_LEN);+
  
     struct sockaddr_in src_sockaddr;​     struct sockaddr_in src_sockaddr;​
-    socklen_t src_sockaddr_len = sizeof(src_sockaddr);​ 
     memset(&​src_sockaddr,​ 0, sizeof(src_sockaddr));​     memset(&​src_sockaddr,​ 0, sizeof(src_sockaddr));​
- +    socklen_t src_sockaddr_size ​sizeof(src_sockaddr);
-    int isock; +
-    if ((isock ​socket(AF_INET,​ SOCK_RAW, IPPROTO_ICMP)) < 0) { +
-        fprintf(stderr,​ "# raw input socket create failed\n"​);​ +
-        exit(1); +
-    } +
- +
-#define SLEEP_TIME 1000         // 1ms +
-#define DELAY_TIME 1000 * 1000  // 1 sec+
  
     int i = 0, count = DELAY_TIME / SLEEP_TIME;     int i = 0, count = DELAY_TIME / SLEEP_TIME;
     while (1) {     while (1) {
  
-        ssize_t res_count = recvfrom( +        ssize_t res_count = recvfrom(sock(char *)ibuffer, ​IBUFFER_SIZE, 0, 
-            isock, +            (struct sockaddr *)&​src_sockaddr,​ &src_sockaddr_size);
-            ​ibuffer, +
-            IBUFFER_LEN, +
-            ​0, +
-            (struct sockaddr *)&​src_sockaddr,​ +
-            ​&src_sockaddr_len +
-        ​);+
  
         if (res_count > 0) {         if (res_count > 0) {
-            printf("#​ received %zd bytes\n",​ res_count); +            printf("#​ received %bytes\n", ​(int)res_count);
             printf("#​ icmp from %s\n", inet_ntoa(src_sockaddr.sin_addr));​             printf("#​ icmp from %s\n", inet_ntoa(src_sockaddr.sin_addr));​
  
-            ​struct ip *ip = (struct ip *)ibuffer;​ +            ​ip_hdr_t ​*ip_hdr ​= (struct ip *)ibuffer;​ 
-            printf("# ​  ​responce ttl %d\n", ​ip->​ip_ttl);​ +            printf("# ​  ​responce ttl %d\n", ​ip_hdr->​ip_ttl);​ 
- +            size_t ip_header_len = ip_hdr->ip_hl >> 2; 
-            size_t ip_header_len = ip->ip_hl >> 2; +            struct icmp *icmp_header = (struct icmp *)(ip_hdr ​+ ip_header_len);​
- +
-            struct icmp *icmp_header = (struct icmp *)(ip + ip_header_len);​ +
             if (icmp_header->​icmp_type == ICMP_ECHOREPLY) {             if (icmp_header->​icmp_type == ICMP_ECHOREPLY) {
                 printf("# ​  type ICMP_ECHOREPLY\n"​);​                 printf("# ​  type ICMP_ECHOREPLY\n"​);​
Line 170: Line 231:
             break;             break;
         }         }
-        ​usleep(SLEEP_TIME);​+#ifdef __WINNT__ 
 +        Sleep(SLEEP_TIME);​ 
 +#else  
 +        ​usleep(SLEEP_TIME ​* 1000); 
 +#endif
     }     }
-    ​close(osock); + 
-    ​close(isock);+    ​close(sock); 
 +#ifdef __WINNT__ 
 +    ​WSACleanup(); 
 +#endif
 } }
 +/* EOF */
 </​code>​ </​code>​