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