view toys/pending/ping.c @ 1539:3e85af1f7e22 draft

First batch of sed tests. Only good for TEST_HOST=1 at the moment because the test infrastructure itself depends on sed, so if an unfinished sed is in the $PATH it goes boing. But hey, corner cases! I have... more.
author Rob Landley <>
date Wed, 29 Oct 2014 18:44:33 -0500
parents 4542db35efd8
line wrap: on
line source

/* 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
    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.

    -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>

  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)
                &((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));
      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);