/* 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;
  xstrncpy(req.arp_dev, TT.device, sizeof(req.arp_dev));
  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;
  xstrncpy(req.arp_dev, TT.device, sizeof(req.arp_dev));
  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 = xopenro("/proc/net/arp");
  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);
    free(buf);
    xclose(fd);
  }
}
