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-20 15:07]
ziggi
c:ping [2019-02-22 16:15]
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 $ */
 +
 +#ifdef __WINNT__
 +#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/​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 <​unistd.h>​ +#endif
-#include <​limits.h>​+
  
-#include <​netdb.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;
  
-//#include <​winsock2.h>​ +struct icmp { 
-//#include <​ws2tcpip.h>​+    ​u_char ​  ​icmp_type;​ 
 +    u_char ​  ​icmp_code;​ 
 +    u_short ​ icmp_cksum;
  
 +    u_short ​ icmp_id;
 +    u_short ​ icmp_seq;
 +};
 +#endif
  
-uint16_t ​icmp_checksum(const uint16_t * const data, const size_t byte_sz) {+typedef struct ip ip_hdr_t; 
 +typedef struct icmp icmp_hdr_t;​ 
 + 
 +#define HOST "​v5.unix7.org"​ 
 + 
 +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;
     for (size_t i = 0; i < (byte_sz >> 1); ++i) {     for (size_t i = 0; i < (byte_sz >> 1); ++i) {
Line 43: Line 84:
 } }
  
-#define HOST "​www.he.net"​+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;
  
-    ​struct hostent *hostEnt ​gethostbyname(host); +    ​#define WSVERSION 0x0202 
-    if (hostEnt ​== NULL) { +    int iResult ​WSAStartup(WSVERSION, &​wsaData); 
-        ​fprintf(stderr, ​"# ​cannot resolve host name %s\n", host); +    if (iResult !0) { 
-        exit(1)+        ​printf("# ​wsastartup() failed: ​%d\n", ​iResult); 
-    } else { +        ​__exit();
-        printf("#​ host %s have addresses:\n", ​hostEnt->​h_name); +
-        ​int i = 0; +
-        while (hostEnt->​h_addr_list[i] != NULL) { +
-            char *addr = inet_ntoa(*(struct in_addr *)(hostEnt->​h_addr_list[i])); +
-            printf("# ​  ​address %d %s\n", i, addr); +
-            i++; +
-        }+
     }     }
 +#endif
  
-    struct ​in_addr dest_inaddr+    struct ​addrinfo hints
-    ​bcopy((struct in_addr *)(hostEnt->​h_addr_list[0]), &​dest_inaddr, sizeof(dest_inaddr) +    ​memset(&​hints, ​0, sizeof(hints));
-        ​);+
  
-    ​printf("#​ select destination %s\n", inet_ntoa(dest_inaddr));+    ​hints.ai_family = AF_UNSPEC;​ 
 +    hints.ai_socktype = SOCK_STREAM;​ 
 +    hints.ai_protocol = IPPROTO_TCP;
  
 +    struct addrinfo *result = NULL;
  
-    ​struct sockaddr_in dest_sockaddr;+    ​int retval; 
 +    if ((retval = getaddrinfo(HOST,​ NULL, &hints, &​result)) != 0) { 
 +        printf("#​ getaddrinfo() failed with error: %d\n", retval); 
 +        __exit(); 
 +    }
  
-    ​memset(&​dest_sockaddr,​ 0, sizeof(dest_sockaddr));​ +    ​struct sockaddr_in *sockaddr ​NULL;
-    dest_sockaddr.sin_family ​AF_INET; +
-    dest_sockaddr.sin_addr = dest_inaddr;+
  
-    ​int ident = htons(1234 /*getpid() & 0xFFFF ​*/);+    ​for(struct addrinfo ​*ptr = result; ptr != NULL ;ptr = ptr->​ai_next) { 
 +        switch ​(ptr->​ai_family
 +            case AF_INET: 
 +                sockaddr = (struct sockaddr_in ​*)ptr->​ai_addr;​ 
 +                printf("#​ host %s have ipv4 address %s\n", HOST, inet_ntoa(sockaddr->​sin_addr));​ 
 +                break; 
 +            default: 
 +                break; 
 +        } 
 +        if (sockaddr != NULL) { 
 +            break; 
 +        } 
 +    }
  
-    struct ​icmp icmp_header+    struct ​sockaddr_in dest_sockaddr
-    ​memset(&icmp_header0, sizeof(icmp_header));+    ​memcpy(&dest_sockaddrsockaddr, sizeof(dest_sockaddr)); 
 +    freeaddrinfo(result);
  
-    ​icmp_header.icmp_type = ICMP_ECHO+    ​int sock
-    ​icmp_header.icmp_code ​= 0; +    ​if ((sock ​socket(AF_INET,​ SOCK_RAW, IPPROTO_ICMP)) < 0) { 
-    ​icmp_header.icmp_cksum = 0+        ​printf("#​ socket creation failed\n"​)
-    ​icmp_header.icmp_seq = htons(12345); +        ​__exit(); 
-    ​icmp_header.icmp_id = htons(45678);​+    ​}
  
-    icmp_header.icmp_cksum = icmp_checksum((uint16_t *)&​icmp_header,​ sizeof(icmp_header));​ 
  
-    int osock+    ​#define SOCKET_ERROR (-1) 
-    if ((osock = socket(AF_INETSOCK_RAWIPPROTO_ICMP)) < 0) { +    const int ttl = 16; 
-        fprintf(stderr,​ "# ​raw output socket create ​failed\n"​);​ +#ifdef __WINNT__ 
-        ​exit(1);+    if (setsockopt(sockIPPROTO_IPIP_TTL, (char *)&ttl, sizeof(ttl)) < 0) { 
 +        fprintf(stderr,​ "# ​setting ttl setsockopt ​failed\n"​);​ 
 +        ​__exit();
     }     }
- +#else 
-    int isock; +    if (setsockopt(sockIPPROTO_IPIP_TTL, &ttl, sizeof(ttl)) < 0) { 
-    if ((isock = socket(AF_INETSOCK_RAWIPPROTO_ICMP)) < 0) { +        fprintf(stderr,​ "# ​setting ttl setsockopt ​failed\n"​);​ 
-        fprintf(stderr,​ "# ​raw input socket create ​failed\n"​);​ +        ​__exit();
-        ​exit(1);+
     }     }
 +#endif
  
-    const ssize_t sent_bytes = sendto( +#define PAYLOAD_LEN 4 
-        ​osock,​ +#define OBUFFER_SIZE ​sizeof(icmp_hdr_t+ PAYLOAD_LEN
-        &​icmp_header,​ +
-        ​sizeof(icmp_header),​ +
-        0, +
-        (struct sockaddr *)&​dest_sockaddr,​ +
-        sizeof(dest_sockaddr) +
-    ​);+
  
-    char buffer[IP_MAXPACKET];​+#ifndef ICMP_ECHO 
 +#define ICMP_ECHO 8 
 +#endif
  
-    struct sockaddr_in src_sockaddr;​ +#ifndef ICMP_ECHOREPLY 
-    ​socklen_t fromlen = sizeof(src_sockaddr);​+#define ICMP_ECHOREPLY 0 
 +#endif
  
-#define SLEEP_TIME 1000         // 1ms +#ifndef ICMP_CODE 
-#​define ​DELAY_TIME 1000 * 1000  // 1 sec+#​define ​ICMP_CODE 0 
 +#endif
  
-    ​int i = 0, count = DELAY_TIME / SLEEP_TIME+    ​char obuffer[OBUFFER_SIZE]
-    ​while (1{+    ​icmp_hdr_t *icmp_hdr;​ 
 +    icmp_hdr = (icmp_hdr_t *)obuffer;
  
-        ssize_t res_count ​recvfrom( +    icmp_hdr->​icmp_type ​ICMP_ECHO; 
-            ​isock,​ +    ​icmp_hdr->​icmp_code = ICMP_CODE; 
-            &​buffer,​ +    ​icmp_hdr->​icmp_id = htons(1234); 
-            sizeof(buffer), +    ​icmp_hdr->​icmp_cksum = 0; 
-            0, +    ​icmp_hdr->​icmp_seq = htons(4567);
-            (struct sockaddr *)&​src_sockaddr,​ +
-            &​fromlen +
-        ​);+
  
 +    char *payload = obuffer + sizeof(icmp_hdr_t);​
 +    memset(payload,​ '<',​ PAYLOAD_LEN);​
  
-        if (res_count ​0) { +    icmp_hdr->icmp_cksum = icmpv4_checksum((uint16_t *)obufferOBUFFER_SIZE);
-            printf("# received %zd bytes\n"​res_count);+
  
-            printf("# icmp from %s\n"inet_ntoa(src_sockaddr.sin_addr));+    sendto(sock, (char *)obuffer, OBUFFER_SIZE,​ 0, 
 +        (struct sockaddr *)&​dest_sockaddr,​ sizeof(dest_sockaddr));
  
-            struct ip *ip = (struct ip *)&​buffer;​ +#define IBUFFER_SIZE 2048 
-            ​printf("​responce ttl %d\n", ip->​ip_ttl);​+#define SLEEP_TIME 1     // 1 ms 
 +#define DELAY_TIME 1000  // 1 sec
  
-            int ip_header_len = ip->​ip_hl >> 2;+    char ibuffer[IBUFFER_SIZE];
  
-            ​struct ​icmp *icmp_header ​= (struct ​icmp *)(ip + ip_header_len);+    ​struct ​sockaddr_in src_sockaddr;​ 
 +    memset(&​src_sockaddr,​ 0, sizeof(src_sockaddr));​ 
 +    socklen_t src_sockaddr_size ​sizeof(src_sockaddr);​ 
 + 
 +    int i = 0, count = DELAY_TIME / SLEEP_TIME;​ 
 +    while (1) { 
 + 
 +        ssize_t res_count = recvfrom(sock,​ (char *)ibuffer, IBUFFER_SIZE,​ 0, 
 +            ​(struct ​sockaddr ​*)&​src_sockaddr,​ &​src_sockaddr_size);​ 
 + 
 +        if (res_count > 0) { 
 +            printf("#​ received %d bytes\n",​ (int)res_count);​ 
 +            printf("#​ icmp from %s\n", inet_ntoa(src_sockaddr.sin_addr));
  
 +            ip_hdr_t *ip_hdr = (struct ip *)ibuffer;
 +            printf("# ​  ​responce ttl %d\n", ip_hdr->​ip_ttl);​
 +            size_t ip_header_len = ip_hdr->​ip_hl >> 2;
 +            struct icmp *icmp_header = (struct icmp *)(ip_hdr + 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"​);​
             }             }
-            printf("#​ icmp id %d\n", ntohs(icmp_header->​icmp_id));​ +            printf("# ​  ​icmp id %d\n", ntohs(icmp_header->​icmp_id));​ 
-            printf("#​ icmp seq %d\n", ntohs(icmp_header->​icmp_seq));​+            printf("# ​  ​icmp seq %d\n", ntohs(icmp_header->​icmp_seq));​
             break;             break;
         }         }
Line 156: Line 231:
             break;             break;
         }         }
-        ​usleep(SLEEP_TIME);​+#ifdef __WINNT__ 
 +        Sleep(SLEEP_TIME);​ 
 +#else  
 +        ​usleep(SLEEP_TIME ​* 1000); 
 +#endif
     }     }
-    ​close(isock); + 
-    ​close(osock);+    ​close(sock); 
 +#ifdef __WINNT__ 
 +    ​WSACleanup(); 
 +#endif
 } }
 /* EOF */ /* EOF */
Line 166: Line 248:
 ===Out=== ===Out===
 <​file>​ <​file>​
-# host he.net have addresses:​ +# host wiki.unix7.org ​have ipv4 address ​93.171.216.21 
-#   address ​0 216.218.186.2 +# received ​52 bytes 
-# select destination ​216.218.186.2 +# icmp from 93.171.216.21 
-# received ​48 bytes +  ​responce ttl 55 
-# icmp from 216.218.186.2 +  ​type ICMP_ECHOREPLY 
-# responce ttl 53 +  ​icmp id 45678 
-# type ICMP_ECHOREPLY +  ​icmp seq 12345
-# icmp id 45678 +
-# icmp seq 12345+
 </​file>​ </​file>​
  
 ---- ----
 [<>] [<>]