changeset 1495:4542db35efd8

Start on ping.c.
author Rob Landley <rob@landley.net>
date Sun, 21 Sep 2014 22:44:20 -0500
parents ca340df928bc
children a2796b4cef49
files toys/pending/ping.c
diffstat 1 files changed, 110 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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 <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);
+}