changeset 1280:4947ec3aa896 draft

Add arp from Sandeep Sharma and Kyungwan Han.
author Rob Landley <rob@landley.net>
date Mon, 12 May 2014 06:12:20 -0500
parents 29603c5a3317
children 6b78ac1d7d58
files toys/pending/arp.c
diffstat 1 files changed, 306 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/pending/arp.c	Mon May 12 06:12:20 2014 -0500
@@ -0,0 +1,306 @@
+/* arp.c - manipulate the system ARP cache
+ *
+ * Copyright 2014 Sandeep Sharma <sandeep.jack2756@gmail.com>
+ * Copyright 2014 Kyungwan Han <asura321@gamil.com>
+ * No Standard 
+
+USE_ARP(NEWTOY(arp, "vi:nDsdap:A:H:[+Ap][!sd]", TOYFLAG_USR|TOYFLAG_BIN))
+
+config ARP
+  bool "arp"
+  default n
+  help
+    Usage: arp 
+    [-vn] [-H HWTYPE] [-i IF] -a [HOSTNAME]
+    [-v]              [-i IF] -d HOSTNAME [pub]
+    [-v]  [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [temp]
+    [-v]  [-H HWTYPE] [-i IF] -s HOSTNAME HWADDR [netmask MASK] pub
+    [-v]  [-H HWTYPE] [-i IF] -Ds HOSTNAME IFACE [netmask MASK] pub
+
+    Manipulate ARP cache
+
+    -a    Display (all) hosts
+    -s    Set new ARP entry
+    -d    Delete a specified entry
+    -v    Verbose
+    -n    Don't resolve names
+    -i IF Network interface
+    -D    Read <hwaddr> from given device
+    -A,-p AF  Protocol family
+    -H    HWTYPE Hardware address type
+
+*/
+
+#define FOR_arp
+#include "toys.h"
+#include <net/if_arp.h>
+
+GLOBALS(
+    char *hw_type;
+    char *af_type_A;
+    char *af_type_p;
+    char *interface;
+    
+    int sockfd;
+    char *device;
+)
+
+struct arpreq req; //Global request structure 
+
+struct type {
+  char *name;
+  int val;
+};
+
+struct type hwtype[] = {
+  {"ether", ARPHRD_ETHER }, 
+  {"loop" ,ARPHRD_LOOPBACK},
+  {"ppp" ,ARPHRD_PPP},
+  {"infiniband" ,ARPHRD_INFINIBAND},
+  {NULL, -1},
+};
+
+struct type aftype[] = {
+  {"inet", AF_INET }, 
+  {"inet6" ,AF_INET6},
+  {"unspec" ,AF_UNSPEC},
+  {NULL, -1},
+};
+
+struct type flag_type[] = {
+  {"PERM", ATF_PERM }, 
+  {"PUB" ,ATF_PUBL},
+  {"DONTPUB" ,ATF_DONTPUB},
+  {"TRAIL" ,ATF_USETRAILERS},
+  {NULL, -1},
+};
+
+static int get_index(struct type arr[], char *name)
+{
+  int i;
+  
+  for (i = 0; arr[i].name; i++) 
+    if (!strcmp(arr[i].name, name)) break;
+  return arr[i].val;
+}
+
+
+void get_hw_add(char *hw_addr, char *ptr) 
+{
+  char *p = ptr, *hw = hw_addr;
+
+  while (*hw_addr && (p-ptr) < 6) {
+    int val, len = 0;
+
+    if (*hw_addr == ':') hw_addr++;
+    sscanf(hw_addr, "%2x%n", &val, &len);
+    if (!len || len > 2) break;
+    hw_addr += len;
+    *p++ = val;
+  }
+
+  if ((p-ptr) != 6 || *hw_addr)
+    error_exit("bad hw addr '%s'", hw);
+}
+
+static void resolve_host(char *host, struct sockaddr *sa)
+{
+  struct addrinfo hints, *res = NULL;
+  int ret;
+
+  memset(&hints, 0, sizeof hints);
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  if ((ret = getaddrinfo(host, NULL, &hints, &res))) 
+    perror_exit("%s", gai_strerror(ret));
+
+  memcpy(sa, res->ai_addr, res->ai_addrlen);
+  freeaddrinfo(res);
+}
+
+static void check_flags(int *i, char** argv)
+{
+  struct sockaddr sa;
+  int flag = *i, j;
+  struct flags {
+    char *name;
+    int or, flag;
+  } f[] = {
+    {"pub",  1 ,ATF_PUBL},
+    {"priv", 0 ,~ATF_PUBL},
+    {"trail", 1, ATF_USETRAILERS},
+    {"temp", 0, ~ATF_PERM},
+    {"dontpub",1, ATF_DONTPUB},
+  };
+  
+  for (;*argv; argv++) {
+    for (j = 0;  j < ARRAY_LEN(f); j++) { 
+      if (!strcmp(*argv, f[j].name)) {
+        (f[j].or) ?(flag |= f[j].flag):(flag &= f[j].flag);
+        break;
+      }
+    }
+    if (j > 4 && !strcmp(*argv, "netmask")) {
+      if (!*++argv) error_exit("NULL netmask");
+      if (strcmp(*argv, "255.255.255.255")) {
+        resolve_host(toys.optargs[0], &sa);
+        memcpy(&req.arp_netmask, &sa, sizeof(sa));
+        flag |= ATF_NETMASK;
+      } else argv++; 
+    } else if (j > 4 && !strcmp(*argv, "dev")) {
+      if (!*++argv) error_exit("NULL dev");
+      TT.device = *argv;
+    } else if (j > 4) error_exit("invalid arg");
+  }
+  *i = flag;
+}
+
+static int set_entry(void) 
+{
+  int flags = 0;
+  
+  if (!toys.optargs[1]) error_exit("bad syntax");
+
+  if (!(toys.optflags & FLAG_D)) get_hw_add(toys.optargs[1], (char*)&req.arp_ha.sa_data);
+  else {
+    struct ifreq ifre;
+
+    xstrncpy(ifre.ifr_name, toys.optargs[1], IFNAMSIZ);
+    xioctl(TT.sockfd, SIOCGIFHWADDR, &ifre);
+    if ((toys.optflags & FLAG_H) && (ifre.ifr_hwaddr.sa_family != ARPHRD_ETHER)) 
+      error_exit("protocol type mismatch");
+    memcpy(&req.arp_ha, &(ifre.ifr_hwaddr), sizeof(req.arp_ha));
+  }
+
+  flags = ATF_PERM | ATF_COM;
+  if (toys.optargs[2]) check_flags(&flags, (toys.optargs+2));
+  req.arp_flags = flags;
+  strncpy(req.arp_dev, TT.device, sizeof(TT.device));
+  xioctl(TT.sockfd, SIOCSARP, &req);
+  
+  if (toys.optflags & FLAG_v) xprintf("Entry set for %s\n", toys.optargs[0]);
+  return 0;
+}
+
+static int ip_to_host(struct sockaddr *sa, int flag) 
+{
+  int status = 0;
+  char hbuf[NI_MAXHOST] = {0,}, sbuf[NI_MAXSERV] = {0,}; 
+  socklen_t len = sizeof(struct sockaddr_in6);
+  
+  *toybuf = 0;
+  if (!(status = getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf, 
+          sizeof(sbuf), flag))) {
+    strcpy(toybuf, hbuf);
+    return 0;
+  }
+  return 1;
+}
+
+static int delete_entry(void)
+{
+  int flags;
+  
+  flags = ATF_PERM;
+  if (toys.optargs[1]) check_flags(&flags, (toys.optargs+1));
+  req.arp_flags = flags;
+  strncpy(req.arp_dev, TT.device, sizeof(TT.device));
+  xioctl(TT.sockfd, SIOCDARP, &req);
+  
+  if (toys.optflags & FLAG_v) xprintf("Delete entry for  %s\n", toys.optargs[0]);
+  return 0;
+}
+
+void arp_main(void)
+{
+  struct sockaddr sa;
+  char ip[128], hw_addr[128], mask[12], dev[128], *host_ip = NULL, *buf;
+  int h_type, type, flag, i, fd, entries = 0, disp = 0;
+
+  TT.device = "";
+  memset(&sa, 0, sizeof(sa));
+  memset(&req, 0, sizeof(req));
+  TT.sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
+
+  if ((toys.optflags & FLAG_A) || (toys.optflags & FLAG_p)) {
+    if ((type = get_index(aftype, 
+            (TT.af_type_A)?TT.af_type_A:TT.af_type_p)) != AF_INET) 
+      error_exit((type != -1)?"only inet supported by kernel":"unknown family");
+  } 
+
+  req.arp_ha.sa_family = ARPHRD_ETHER;
+  if (toys.optflags & FLAG_H) {
+    if ((type = get_index(hwtype, TT.hw_type)) != ARPHRD_ETHER) 
+      error_exit((type != -1)?"h/w type not supported":"unknown h/w type");
+    req.arp_ha.sa_family = type;
+  }
+
+  if (((toys.optflags & FLAG_s) || toys.optflags & FLAG_d)) { 
+    if (!toys.optargs[0]) error_exit("host name req");
+    resolve_host(toys.optargs[0], &sa);
+    memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr));
+  }
+
+  if ((toys.optflags & FLAG_s) && !set_entry()) return;
+  if ((toys.optflags & FLAG_d) && !delete_entry()) return; 
+
+  //show arp chache
+  fd = xopen("/proc/net/arp", O_RDONLY);
+  buf = get_line(fd);
+  free(buf); //skip first line
+
+  if (toys.optargs[0]) {
+    resolve_host(toys.optargs[0], &sa);
+    ip_to_host(&sa, NI_NUMERICHOST);
+    host_ip = xstrdup(toybuf);
+  }
+
+  while ((buf = get_line(fd))) {
+    char *host_name = "?";
+    
+    if ((sscanf(buf, "%s 0x%x 0x%x %s %s %s\n", ip,
+        &h_type, &flag, hw_addr, mask, dev )) != 6) break;
+    entries++;
+    if (((toys.optflags & FLAG_H) && (get_index(hwtype, TT.hw_type) != h_type))
+     || ((toys.optflags & FLAG_i) && strcmp(TT.interface, dev))
+     || (toys.optargs[0] && strcmp(host_ip, ip))) {
+      free(buf);
+      continue;
+    }
+
+    resolve_host(buf, &sa);
+    if (!(toys.optflags & FLAG_n)) { 
+      if (!ip_to_host(&sa, NI_NAMEREQD)) host_name = toybuf;
+    } else ip_to_host(&sa, NI_NUMERICHOST);
+    
+    disp++;
+    printf("%s (%s) at" , host_name, ip);
+
+    for (i = 0; hwtype[i].name; i++) 
+      if (hwtype[i].val & h_type) break;
+    if (!hwtype[i].name) error_exit("unknown h/w type");
+
+    if (!(flag & ATF_COM)) {
+      if ((flag & ATF_PUBL)) printf(" *");
+      else printf(" <incomplete>");
+    } else printf(" %s [%s]", hw_addr, hwtype[i].name);
+
+    if (flag & ATF_NETMASK) printf("netmask %s ", mask);
+
+    for (i = 0; flag_type[i].name; i++) 
+      if (flag_type[i].val & flag) printf(" %s", flag_type[i].name);
+
+    printf(" on %s\n", dev);
+    free(buf);
+  }
+  
+  if (toys.optflags & FLAG_v) 
+    xprintf("Entries: %d\tSkipped: %d\tFound: %d\n",
+        entries, entries - disp, disp);
+  if (!disp) xprintf("No Match found in %d entries\n", entries);
+  
+  if (CFG_TOYBOX_FREE) {
+    free(host_ip);
+    xclose(fd);
+  }
+}