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
c:ping [2019-02-22 12:17]
ziggi
c:ping [2019-02-22 16:15] (current)
ziggi
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>​