/* route.c - Display routing table.
 *
 * Copyright 2012 Ranjan Kumar <ranjankumar.bth@gmail.com>
 * Copyright 2013 Kyungwan Han <asura321@gmail.com>
 *
 * No Standard
 *
USE_ROUTE(NEWTOY(route, "?neA:", TOYFLAG_BIN))
config ROUTE
  bool "route"
  default n
  help
    usage: route -neA inet{6} / [{add|del}]

    Display/Edit kernel routing tables.

    -n  Don't resolve names
    -e  Display other/more information
    -A  inet{6} Select Address Family
*/

#define FOR_route
#include "toys.h"
#include <net/route.h>
#include <sys/param.h>

GLOBALS(
  char *family;
)

#define DEFAULT_PREFIXLEN 128
#define INVALID_ADDR 0xffffffffUL
#define IPV6_ADDR_LEN 40 //32 + 7 (':') + 1 ('\0')

#define TEST_ARGV(argv) if (!*argv) help_exit(0)

struct _arglist {
  char *arg;
  int action;
};

static struct _arglist arglist1[] = {
  { "add", 1 }, { "del", 2 },
  { "delete", 2 }, { NULL, 0 }
};

static struct _arglist arglist2[] = {
  { "-net", 1 }, { "-host", 2 },
  { NULL, 0 }
};

// to get the host name from the given ip.
static int get_hostname(char *ipstr, struct sockaddr_in *sockin)
{
  struct hostent *host;

  sockin->sin_family = AF_INET;
  sockin->sin_port = 0;

  if (!strcmp(ipstr, "default")) {
    sockin->sin_addr.s_addr = INADDR_ANY;
    return 1;
  }

  if (inet_aton(ipstr, &sockin->sin_addr)) return 0;
  if (!(host = gethostbyname(ipstr))) return -1;
  memcpy(&sockin->sin_addr, host->h_addr_list[0], sizeof(struct in_addr));
  return 0;
}

// used to extract the address info from the given ip.
static int get_addrinfo(char *ip, struct sockaddr_in6 *sock_in6)
{
  struct addrinfo hints, *result;
  int status = 0;

  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET6;
  if ((status = getaddrinfo(ip, NULL, &hints, &result))) {
    perror_msg("getaddrinfo: %s", gai_strerror(status));
    return -1;
  }
  if (result) {
    memcpy(sock_in6, result->ai_addr, sizeof(*sock_in6));
    freeaddrinfo(result);
  }
  return 0;
}

//get the flag values for route command.
static void get_flag_value(char *str, int flags)
{
  int i = 0;
  static unsigned flagarray[] = {
    RTF_GATEWAY, RTF_HOST, RTF_REINSTATE, RTF_DYNAMIC,
    RTF_MODIFIED, RTF_DEFAULT, RTF_ADDRCONF, RTF_CACHE
  };

  *str++ = 'U';
  while ((*str = "GHRDMDAC"[i]))
    if (flags & flagarray[i++]) ++str;
}

// extract inet4 route info from /proc/net/route file and display it.
static void display_routes(void)
{
  unsigned long dest, gate, mask;
  int flags, ref, use, metric, mss, win, irtt, items;
  char iface[64] = {0,}, flag_val[10]; //there are 9 flags "UGHRDMDAC" for route.

  FILE *fp = xfopen("/proc/net/route", "r");

  xprintf("Kernel IP routing table\n"
      "Destination     Gateway         Genmask         Flags %s Iface\n",
      (toys.optflags & FLAG_e)? "  MSS Window  irtt" : "Metric Ref    Use");

  if (fscanf(fp, "%*[^\n]\n") < 0) perror_exit("fscanf"); //skip 1st line
  while ((items = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", iface, &dest, 
          &gate, &flags, &ref, &use, &metric, &mask, &mss, &win, &irtt)) == 11) {

    char *destip = toybuf, *gateip = toybuf+32, *maskip = toybuf+64; //ip string 16
    memset(flag_val, 0, 10);

    if (!(flags & RTF_UP)) continue; //skip down interfaces.

    if (!dest && !(toys.optflags & FLAG_n)) strcpy( destip, "default");
    else if (!inet_ntop(AF_INET, &dest, destip, 32)) perror_exit("inet");

    if (!gate && !(toys.optflags & FLAG_n)) strcpy( gateip, "*");
    else if (!inet_ntop(AF_INET, &gate, gateip, 32)) perror_exit("inet");

    if (!inet_ntop(AF_INET, &mask, maskip, 32)) perror_exit("inet");

    //Get flag Values
    get_flag_value(flag_val, (flags & (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE
            |RTF_DYNAMIC|RTF_MODIFIED)));
    if (flags & RTF_REJECT) flag_val[0] = '!';
    xprintf("%-15.15s %-15.15s %-16s%-6s", destip, gateip, maskip, flag_val);
    if (toys.optflags & FLAG_e) xprintf("%5d %-5d %6d %s\n", mss, win, irtt, iface);
    else xprintf("%-6d %-2d %7d %s\n", metric, ref, use, iface);
  }

  if (items > 0 && feof(fp)) perror_exit("fscanf %d", items);
  fclose(fp);
}


/*
 * find the given parameter in list like add/del/net/host.
 * and if match found return the appropriate action.
 */
static int get_action(char ***argv, struct _arglist *list)
{
  struct _arglist *alist;

  if (!**argv) return 0;
  for (alist = list; alist->arg; alist++) { //find the given parameter in list
    if (!strcmp(**argv, alist->arg)) {
      *argv += 1;
      return alist->action;
    }
  }
  return 0;
}

/*
 * get prefix len (if any) and remove the prefix from target ip.
 * if no prefix then set netmask as default.
 */
static void is_prefix(char **tip, char **netmask, struct rtentry *rt)
{
  char *prefix = strchr(*tip, '/');
  if (prefix) {
    unsigned long plen;
    plen = atolx_range(prefix + 1, 0, 32);
    //used to verify the netmask and route conflict.
    (((struct sockaddr_in *)&((rt)->rt_genmask))->sin_addr.s_addr)
      = htonl( ~(INVALID_ADDR >> plen));
    *prefix = '\0';
    rt->rt_genmask.sa_family = AF_INET;
  } else *netmask = "default"; //default netmask.
}

/*
 * used to get the params like: metric, netmask, gw, mss, window, irtt, dev and their values.
 * additionally set the flag values for reject, mod, dyn and reinstate.
 */
static void get_next_params(char **argv, struct rtentry *rt, char **netmask)
{
  while (*argv) {
    //set the metric field in the routing table.
    if (!strcmp(*argv, "metric")) {
      argv++;
      TEST_ARGV(argv);
      rt->rt_metric = atolx_range(*argv, 0, ULONG_MAX) + 1;
      argv++;
    } else if (!strcmp(*argv, "netmask")) {
      //when adding a network route, the netmask to be used.
      struct sockaddr sock;
      unsigned int addr_mask = (((struct sockaddr_in *)&((rt)->rt_genmask))->sin_addr.s_addr);
      if (addr_mask) help_exit("dup netmask");
      argv++;
      TEST_ARGV(argv);
      *netmask = *argv;
      if (get_hostname(*netmask, (struct sockaddr_in *) &sock) < 0)
        perror_exit("resolving '%s'", *netmask);
      rt->rt_genmask = sock;
      argv++;
    } else if (!strcmp(*argv, "gw")) { 
      //route packets via a gateway.
      if (!(rt->rt_flags & RTF_GATEWAY)) {
        int ishost;
        argv++;
        TEST_ARGV(argv);
        if ((ishost = get_hostname(*argv, (struct sockaddr_in *) &rt->rt_gateway)) == 0) {
          rt->rt_flags |= RTF_GATEWAY;
          argv++;
        } else if (ishost < 0) perror_exit("resolving '%s'", *argv);
        else perror_exit("gateway '%s' is a NETWORK", *argv);
      } else help_exit("dup gw");
    } else if (!strcmp(*argv, "mss")) {
      //set the TCP Maximum Segment Size for connections over this route.
      argv++;
      TEST_ARGV(argv);
      rt->rt_mss = atolx_range(*argv, 64, 32768); //MSS low and max
      rt->rt_flags |= RTF_MSS;
      argv++;
    } else if (!strcmp(*argv, "window")) {
      //set the TCP window size for connections over this route to W bytes.
      argv++;
      TEST_ARGV(argv);
      rt->rt_window = atolx_range(*argv, 128, INT_MAX); //win low
      rt->rt_flags |= RTF_WINDOW;
      argv++;
    } else if (!strcmp(*argv, "irtt")) {
      long nclock_ticks = sysconf(_SC_CLK_TCK); //number of clock ticks per second.
      argv++;
      TEST_ARGV(argv);
      nclock_ticks /= 100;
      rt->rt_irtt = strtoul(*argv, NULL, 10);
      if (nclock_ticks > 0) rt->rt_irtt *= nclock_ticks;
      rt->rt_flags |= 0x0100; //RTF_IRTT
      argv++;
    } else if (!strcmp(*argv, "dev")) {
      argv++;
      TEST_ARGV(argv);
      if ((!rt->rt_dev)) rt->rt_dev = *argv;
      argv++;
    } else if (!strcmp(*argv, "reject")) {
      rt->rt_flags |= RTF_REJECT;
      argv++;
    } else if (!strcmp(*argv, "mod")) {
      rt->rt_flags |= RTF_MODIFIED;
      argv++;
    } else if (!strcmp(*argv, "dyn")) {
      rt->rt_flags |= RTF_DYNAMIC;
      argv++;
    } else if (!strcmp(*argv, "reinstate")) {
      rt->rt_flags |= RTF_REINSTATE;
      argv++;
    } else help_exit("no '%s'", *argv);  //No match found; exit form the application.
  }//end of while loop.

  if (!rt->rt_dev && (rt->rt_flags & RTF_REJECT)) rt->rt_dev = (char *)"lo";
}

// verify the netmask and conflict in netmask and route address.
static void verify_netmask(struct rtentry *rt, char *netmask)
{
  unsigned int addr_mask = (((struct sockaddr_in *)&((rt)->rt_genmask))->sin_addr.s_addr);
  unsigned int router_addr = ~(unsigned int)(((struct sockaddr_in *)&((rt)->rt_dst))->sin_addr.s_addr);

  if (addr_mask) {
    addr_mask = ~ntohl(addr_mask);
    if ((rt->rt_flags & RTF_HOST) && addr_mask != INVALID_ADDR)
      perror_exit("conflicting netmask and host route");
    if (addr_mask & (addr_mask + 1)) perror_exit("wrong netmask '%s'", netmask);
    addr_mask = ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr;
    if (addr_mask & router_addr) perror_exit("conflicting netmask and route address");
  }
}

// add/del a route.
static void setroute(char **argv)
{
  struct rtentry rt;
  char *netmask = NULL, *targetip;
  int is_net_or_host = 0, sokfd, arg2_action;
  int action = get_action(&argv, arglist1); //verify the arg for add/del.

  if (!action || !*argv) help_exit("setroute");

  arg2_action = get_action(&argv, arglist2); //verify the arg for -net or -host
  if (!*argv) help_exit("setroute");

  memset(&rt, 0, sizeof(struct rtentry));
  targetip = *argv++;

  is_prefix((char **)&targetip, (char **)&netmask, &rt);
  if ((is_net_or_host = get_hostname(targetip, 
          (struct sockaddr_in *) &rt.rt_dst)) < 0)
    perror_exit("resolving '%s'", targetip);

  if (arg2_action) is_net_or_host = arg2_action & 1;
  rt.rt_flags = ((is_net_or_host) ? RTF_UP : (RTF_UP | RTF_HOST));

  get_next_params(argv, &rt, (char **)&netmask);
  verify_netmask(&rt, (char *)netmask);

  if ((action == 1) && (rt.rt_flags & RTF_HOST))
    (((struct sockaddr_in *)&((rt).rt_genmask))->sin_addr.s_addr) = INVALID_ADDR;

  sokfd = xsocket(AF_INET, SOCK_DGRAM, 0);
  if (action == 1) xioctl(sokfd, SIOCADDRT, &rt);
  else xioctl(sokfd, SIOCDELRT, &rt);
  xclose(sokfd);
}

/*
 * get prefix len (if any) and remove the prefix from target ip.
 * if no prefix then set default prefix len.
 */
static void is_prefix_inet6(char **tip, struct in6_rtmsg *rt)
{
  unsigned long plen;
  char *prefix = strchr(*tip, '/');

  if (prefix) {
    *prefix = '\0';
    plen = atolx_range(prefix + 1, 0, 128); //DEFAULT_PREFIXLEN);
  } else plen = DEFAULT_PREFIXLEN;

  rt->rtmsg_flags = (plen == DEFAULT_PREFIXLEN) ? (RTF_UP | RTF_HOST) : RTF_UP;
  rt->rtmsg_dst_len = plen;
}

/*
 * used to get the params like: metric, gw, dev and their values.
 * additionally set the flag values for mod and dyn.
 */
static void get_next_params_inet6(char **argv, struct sockaddr_in6 *sock_in6, struct in6_rtmsg *rt, char **dev_name)
{
  while (*argv) {
    if (!strcmp(*argv, "metric")) {
      //set the metric field in the routing table.
      argv++;
      TEST_ARGV(argv);
      rt->rtmsg_metric = atolx_range(*argv, 0, ULONG_MAX);
      argv++;
    } else if (!strcmp(*argv, "gw")) {
      //route packets via a gateway.
      if (!(rt->rtmsg_flags & RTF_GATEWAY)) {
        argv++;
        TEST_ARGV(argv);
        if (!get_addrinfo(*argv, (struct sockaddr_in6 *) &sock_in6)) {
          memcpy(&rt->rtmsg_gateway, sock_in6->sin6_addr.s6_addr, sizeof(struct in6_addr));
          rt->rtmsg_flags |= RTF_GATEWAY;
          argv++;
        } else perror_exit("resolving '%s'", *argv);
      } else help_exit(0);
    } else if (!strcmp(*argv, "dev")) {
      argv++;
      TEST_ARGV(argv);
      if (!*dev_name) *dev_name = *argv;
      argv++;
    } else if (!strcmp(*argv, "mod")) {
      rt->rtmsg_flags |= RTF_MODIFIED;
      argv++;
    } else if (!strcmp(*argv, "dyn")) {
      rt->rtmsg_flags |= RTF_DYNAMIC;
      argv++;
    } else help_exit(0);
  }//end of while loop.
}

// add/del a route.
static void setroute_inet6(char **argv)
{
  struct sockaddr_in6 sock_in6;
  struct in6_rtmsg rt;
  char *targetip;
  int sockfd, action = get_action(&argv, arglist1);

  if (!action || !*argv) help_exit(0);
  memset(&sock_in6, 0, sizeof(struct sockaddr_in6));
  memset(&rt, 0, sizeof(struct in6_rtmsg));
  targetip = *argv++;
  if (*argv) {
    unsigned long plen = 0;
    char *dev_name = NULL;
    if (!strcmp(targetip, "default")) {
      rt.rtmsg_flags = RTF_UP;
      rt.rtmsg_dst_len = plen;
    } else {
      is_prefix_inet6((char **)&targetip, &rt);
      if (get_addrinfo(targetip, (struct sockaddr_in6 *) &sock_in6))
        perror_exit("resolving '%s'", targetip);
    }
    rt.rtmsg_metric = 1; //default metric.
    memcpy(&rt.rtmsg_dst, sock_in6.sin6_addr.s6_addr, sizeof(struct in6_addr));
    get_next_params_inet6(argv, &sock_in6, &rt, (char **)&dev_name);

    sockfd = xsocket(AF_INET6, SOCK_DGRAM, 0);
    if (dev_name) {
      char ifre_buf[sizeof(struct ifreq)] = {0,};
      struct ifreq *ifre = (struct ifreq*)ifre_buf;
      xstrncpy(ifre->ifr_name, dev_name, IFNAMSIZ);
      xioctl(sockfd, SIOGIFINDEX, ifre);
      rt.rtmsg_ifindex = ifre->ifr_ifindex;
    }          
    if (action == 1) xioctl(sockfd, SIOCADDRT, &rt);
    else xioctl(sockfd, SIOCDELRT, &rt);
    xclose(sockfd);
  } else help_exit(0);
}

/*
 * format the dest and src address in ipv6 format.
 * e.g. 2002:6b6d:26c8:d:ea03:9aff:fe65:9d62
 */
static void ipv6_addr_formating(char *ptr, char *addr)
{
  int i = 0;
  while (i <= IPV6_ADDR_LEN) {
    if (!*ptr) {
      if (i == IPV6_ADDR_LEN) {
        addr[IPV6_ADDR_LEN - 1] = 0; //NULL terminating the ':' seperated address.
        break;
      }
      error_exit("IPv6 ip format error");
    }
    addr[i++] = *ptr++;
    if (!((i+1) % 5)) addr[i++] = ':'; //put ':' after 4th bit
  }
}

static void display_routes6(void)
{
  char iface[16] = {0,}, ipv6_dest_addr[41]; 
  char ipv6_src_addr[41], flag_val[10], buf2[INET6_ADDRSTRLEN];
  int prefixlen, metric, use, refcount, flag, items = 0;
  unsigned char buf[sizeof(struct in6_addr)];

  FILE *fp = xfopen("/proc/net/ipv6_route", "r");

  xprintf("Kernel IPv6 routing table\n"
      "%-43s%-40s Flags Metric Ref    Use Iface\n", "Destination", "Next Hop");

  while ((items = fscanf(fp, "%32s%x%*s%*x%32s%x%x%x%x%10s\n", ipv6_dest_addr+8,
          &prefixlen, ipv6_src_addr+8, &metric, &use, &refcount, &flag, 
          iface)) == 8) {

    memset(flag_val, 0, 10);

    if (!(flag & RTF_UP)) continue; //skip down interfaces.

    //ipv6_dest_addr+8: as the values are filled from the 8th location of the array.
    ipv6_addr_formating(ipv6_dest_addr+8, ipv6_dest_addr);
    ipv6_addr_formating(ipv6_src_addr+8, ipv6_src_addr);

    get_flag_value(flag_val, (flag & (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|
            RTF_ADDRCONF|RTF_CACHE)));
    if (inet_pton(AF_INET6, ipv6_dest_addr, buf) <= 0) perror_exit("inet");
    if (inet_ntop(AF_INET6, buf, buf2, INET6_ADDRSTRLEN)) {
      sprintf(toybuf, "%s/%d", buf2, prefixlen);
    }

    if (inet_pton(AF_INET6, ipv6_src_addr, buf) <= 0) perror_exit("inet");
    if (inet_ntop(AF_INET6, buf, buf2, INET6_ADDRSTRLEN)) {
      xprintf("%-43s %-39s %-5s %-6d %-4d %5d %-8s\n",
          toybuf, buf2, flag_val, metric, refcount, use, iface);
    }
  }
  if ((items > 0) && feof(fp)) perror_exit("fscanf");

  fclose(fp);
}

void route_main(void)
{
  if (!(toys.optflags & FLAG_A)) TT.family = "inet";
  if (!*toys.optargs) {
    if (!strcmp(TT.family, "inet")) display_routes();
    else if (!strcmp(TT.family, "inet6")) display_routes6();
    else help_exit(0);
    return;
  }//End of if statement.

  if (!strcmp(TT.family, "inet6")) setroute_inet6(toys.optargs);
  else setroute(toys.optargs);
}
