# HG changeset patch # User Rob Landley # Date 1411357460 18000 # Node ID 4542db35efd8d25bf0328a22dae7db49518e6542 # Parent ca340df928bc67c5543df5c667a502fd43dce77a Start on ping.c. diff -r ca340df928bc -r 4542db35efd8 toys/pending/ping.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toys/pending/ping.c Sun Sep 21 22:44:20 2014 -0500 @@ -0,0 +1,110 @@ +/* ping.c - check network connectivity + * + * Copyright 2014 Rob Landley + * + * 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 + +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); +}