/* ping.c - check network connectivity * * Copyright 2014 Rob Landley <rob@landley.net> * * Not in SUSv4. USE_PING(NEWTOY(ping, "<1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN)) config PING bool "ping" default n help usage: ping [OPTIONS] HOST Check network connectivity by sending packets to a host and reporting its response. Send ICMP ECHO_REQUEST packets to ipv4 or ipv6 addresses and prints each echo it receives back, with round trip time. Options: -4, -6 Force IPv4 or IPv6 -c CNT Send CNT many packets -I IFACE/IP Source interface or address -q Quiet, only displays output at start and when finished -s SIZE Packet SIZE in bytes (default 56) -t TTL Set Time (number of hops) To Live -W SEC Seconds to wait for response after all packets sent (default 10) -w SEC Exit after this many seconds */ #define FOR_ping #include "toys.h" #include <ifaddrs.h> GLOBALS( long wait_exit; long wait_resp; char *iface; long size; long count; long ttl; int sock; ) void ping_main(void) { int family, protocol; union { struct in_addr in; struct in6_addr in6; } src_addr; char *host = 0; // Determine IPv4 vs IPv6 type if(!(toys.optflags & (FLAG_4|FLAG_6))) { // todo getaddrinfo instead? if (inet_pton(AF_INET6, toys.optargs[0], (void*)&src_addr)) toys.optflags |= FLAG_6; } if (toys.optflags & FLAG_6) { family = AF_INET6; protocol = IPPROTO_ICMPV6; } else { family = AF_INET; protocol = IPPROTO_ICMP; } if (!(toys.optflags & FLAG_s)) TT.size = 56; // 64-PHDR_LEN if (TT.iface) { memset(&src_addr, 0, sizeof(src_addr)); // IP address? if (!inet_pton(family, TT.iface, &src_addr)) { struct ifaddrs *ifsave, *ifa = 0; // Interface name? if (!getifaddrs(&ifsave)) { for (ifa = ifsave; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != family) continue; if (!strcmp(ifa->ifa_name, TT.iface)) { if (family == AF_INET) memcpy(&src_addr, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, sizeof(struct in_addr)); else memcpy(&src_addr, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, sizeof(struct in6_addr)); break; } } freeifaddrs(ifsave); } if (!ifa) error_exit("no v%d addr for -I %s", 4+2*(family==AF_INET6), TT.iface); } inet_ntop(family, &src_addr, toybuf, sizeof(toybuf)); host = xstrdup(toybuf); } printf("host=%s\n", host); // Open raw socket TT.sock = xsocket(family, SOCK_RAW, protocol); }