Home | History | Annotate | Download | only in pending
      1 /* ping.c - check network connectivity
      2  *
      3  * Copyright 2014 Rob Landley <rob (at) landley.net>
      4  *
      5  * Not in SUSv4.
      6 
      7 USE_PING(NEWTOY(ping, "<1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN))
      8 
      9 config PING
     10   bool "ping"
     11   default n
     12   help
     13     usage: ping [OPTIONS] HOST
     14 
     15     Check network connectivity by sending packets to a host and reporting
     16     its response.
     17 
     18     Send ICMP ECHO_REQUEST packets to ipv4 or ipv6 addresses and prints each
     19     echo it receives back, with round trip time.
     20 
     21     Options:
     22     -4, -6      Force IPv4 or IPv6
     23     -c CNT      Send CNT many packets
     24     -I IFACE/IP Source interface or address
     25     -q          Quiet, only displays output at start and when finished
     26     -s SIZE     Packet SIZE in bytes (default 56)
     27     -t TTL      Set Time (number of hops) To Live
     28     -W SEC      Seconds to wait for response after all packets sent (default 10)
     29     -w SEC      Exit after this many seconds
     30 */
     31 
     32 #define FOR_ping
     33 #include "toys.h"
     34 
     35 #include <ifaddrs.h>
     36 
     37 GLOBALS(
     38   long wait_exit;
     39   long wait_resp;
     40   char *iface;
     41   long size;
     42   long count;
     43   long ttl;
     44 
     45   int sock;
     46 )
     47 
     48 void ping_main(void)
     49 {
     50   int family, protocol;
     51   union {
     52     struct in_addr in;
     53     struct in6_addr in6;
     54   } src_addr;
     55   char *host = 0;
     56 
     57   // Determine IPv4 vs IPv6 type
     58 
     59   if(!(toys.optflags & (FLAG_4|FLAG_6))) {
     60 // todo getaddrinfo instead?
     61     if (inet_pton(AF_INET6, toys.optargs[0], (void*)&src_addr))
     62       toys.optflags |= FLAG_6;
     63   }
     64 
     65   if (toys.optflags & FLAG_6) {
     66     family = AF_INET6;
     67     protocol = IPPROTO_ICMPV6;
     68   } else {
     69     family = AF_INET;
     70     protocol = IPPROTO_ICMP;
     71   }
     72 
     73   if (!(toys.optflags & FLAG_s)) TT.size = 56; // 64-PHDR_LEN
     74 
     75   if (TT.iface) {
     76     memset(&src_addr, 0, sizeof(src_addr));
     77 
     78     // IP address?
     79     if (!inet_pton(family, TT.iface, &src_addr)) {
     80       struct ifaddrs *ifsave, *ifa = 0;
     81 
     82       // Interface name?
     83       if (!getifaddrs(&ifsave)) {
     84         for (ifa = ifsave; ifa; ifa = ifa->ifa_next) {
     85           if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != family) continue;
     86           if (!strcmp(ifa->ifa_name, TT.iface)) {
     87             if (family == AF_INET)
     88               memcpy(&src_addr,
     89                 &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
     90                 sizeof(struct in_addr));
     91             else memcpy(&src_addr,
     92                 &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
     93                 sizeof(struct in6_addr));
     94             break;
     95           }
     96         }
     97         freeifaddrs(ifsave);
     98       }
     99       if (!ifa)
    100         error_exit("no v%d addr for -I %s", 4+2*(family==AF_INET6), TT.iface);
    101     }
    102     inet_ntop(family, &src_addr, toybuf, sizeof(toybuf));
    103     host = xstrdup(toybuf);
    104   }
    105 
    106 printf("host=%s\n", host);
    107 
    108   // Open raw socket
    109   TT.sock = xsocket(family, SOCK_RAW, protocol);
    110 }
    111