--- a/toys/pending/route.c	2015-07-13 10:51:26.000000000 +0530
+++ b/toys/pending/route.c	2015-07-13 15:03:38.000000000 +0530
@@ -8,7 +8,7 @@
 USE_ROUTE(NEWTOY(route, "?neA:", TOYFLAG_BIN))
 config ROUTE
   bool "route"
-  default n
+  default y
   help
     usage: route -neA inet{6} / [{add|del}]
 
@@ -28,140 +28,67 @@
   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) routehelp()
 
-#define TEST_ARGV(argv) if (!*argv) show_route_help()
+unsigned flagarray[] = {
+  RTF_GATEWAY, RTF_HOST, RTF_REINSTATE, RTF_DYNAMIC,
+  RTF_MODIFIED, RTF_DEFAULT, RTF_ADDRCONF, RTF_CACHE };
 
-struct _arglist {
+typedef struct _arglist {
   char *arg;
   int action;
-};
+} ARGLIST;
 
-static struct _arglist arglist1[] = {
-  { "add", 1 }, { "del", 2 },
-  { "delete", 2 }, { NULL, 0 }
-};
-
-static struct _arglist arglist2[] = {
-  { "-net", 1 }, { "-host", 2 },
-  { NULL, 0 }
-};
+static ARGLIST arglist1[] = {{"add",1},{"del",2},{"delete",2},{NULL,0}};
+static ARGLIST arglist2[] = {{"-net",1},{"-host",2},{NULL,0}};
 
-// display help info and exit.
-static void show_route_help(void)
+static void routehelp(void)
 {
   toys.exithelp = 1;
   error_exit("Invalid Argument");
 }
 
 // to get the host name from the given ip.
-static int get_hostname(char *ipstr, struct sockaddr_in *sockin)
+static int get_hostname(char *ip, struct sockaddr_in *sin)
 {
   struct hostent *host;
 
-  sockin->sin_family = AF_INET;
-  sockin->sin_port = 0;
+  sin->sin_family = AF_INET;
+  sin->sin_port = 0;
 
-  if (!strcmp(ipstr, "default")) {
-    sockin->sin_addr.s_addr = INADDR_ANY;
+  if (!strcmp(ip, "default")) {
+    sin->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));
+  if (inet_aton(ip, &sin->sin_addr)) return 0;
+  if (!(host = gethostbyname(ip))) perror_exit("resolving '%s'", ip);
+  memcpy(&sin->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)
+static void get_addrinfo(char *ip, struct sockaddr_in6 *sin6)
 {
   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");
+  if ((status = getaddrinfo(ip, NULL, &hints, &result)))
+    error_exit("bad address '%s' : %s", ip, gai_strerror(status));
 
-    //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);
+  memcpy(sin6, result->ai_addr, result->ai_addrlen);
+  freeaddrinfo(result);
 }
 
-
-/*
- * 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)
+// actions: add/del/net/host. Return the index of action.
+static int get_action(char ***argv, ARGLIST *list)
 {
-  struct _arglist *alist;
+  ARGLIST *alist;
 
   if (!**argv) return 0;
-  for (alist = list; alist->arg; alist++) { //find the given parameter in list
+  for (alist = list; alist->arg; alist++) {
     if (!strcmp(**argv, alist->arg)) {
       *argv += 1;
       return alist->action;
@@ -170,84 +97,70 @@
   return 0;
 }
 
-/*
- * get prefix len (if any) and remove the prefix from target ip.
- * if no prefix then set netmask as default.
- */
+// No prefix -> "netmask = default".
+// if prefix -> verify route conflict and set af.
 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.
+    unsigned long plen = atolx_range(prefix+1, 0, 32);
+
     (((struct sockaddr_in *)&((rt)->rt_genmask))->sin_addr.s_addr)
-      = htonl( ~(INVALID_ADDR >> plen));
+      = htonl(~(INVALID_ADDR >> plen));
     *prefix = '\0';
     rt->rt_genmask.sa_family = AF_INET;
-  } else *netmask = "default"; //default netmask.
+  } else *netmask = "default";
 }
 
-/*
- * 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)
+// parse the arguments like: metric, netmask, gw, mss, window, irtt, dev.
+// set rtentry variables and flags accordingly.
+static void parse_args(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++;
+      rt->rt_metric = atolx_range(*argv++, 0, LONG_MAX) + 1;
     } 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) show_route_help();
-      argv++;
+      if ((((struct sockaddr_in *)&((rt)->rt_genmask))->sin_addr.s_addr))
+        routehelp();
+      *netmask = *++argv;
       TEST_ARGV(argv);
-      *netmask = *argv;
-      if (get_hostname(*netmask, (struct sockaddr_in *) &sock) < 0)
-        perror_exit("resolving '%s'", *netmask);
+      get_hostname(*netmask, (struct sockaddr_in *) &sock);
       rt->rt_genmask = sock;
       argv++;
-    } else if (!strcmp(*argv, "gw")) { 
+    } 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) {
+        if (!get_hostname(*argv++, (struct sockaddr_in *)&rt->rt_gateway)) {
           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 show_route_help();
+        } else perror_exit("gateway '%s' is a NETWORK", *argv);
+      } else routehelp();
     } 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_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_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);
+      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);
@@ -265,7 +178,10 @@
     } else if (!strcmp(*argv, "reinstate")) {
       rt->rt_flags |= RTF_REINSTATE;
       argv++;
-    } else show_route_help();  //No match found; exit form the application.
+    } else { // last arg can be without dev keyword.
+      if ((!rt->rt_dev) && !*++argv) rt->rt_dev = argv[-1];
+      else routehelp(); //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";
@@ -274,16 +190,16 @@
 // 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);
+  unsigned int mask = (((struct sockaddr_in *)
+        &((rt)->rt_genmask))->sin_addr.s_addr), addr = ~mask;
 
-  if (addr_mask) {
-    addr_mask = ~ntohl(addr_mask);
-    if ((rt->rt_flags & RTF_HOST) && addr_mask != INVALID_ADDR)
+  if (mask) {
+    mask = ~ntohl(mask);
+    if ((rt->rt_flags & RTF_HOST) && 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");
+    if (mask & (mask + 1)) perror_exit("wrong netmask '%s'", netmask);
+    mask = ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr;
+    if (mask & addr) perror_exit("conflicting netmask and route address");
   }
 }
 
@@ -291,80 +207,67 @@
 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) show_route_help();
-
-  arg2_action = get_action(&argv, arglist2); //verify the arg for -net or -host
-  if (!*argv) show_route_help(); 
+  char *netmask = NULL, *tip;
+  int ret=0, sokfd, action[2] = {0,};
 
+  // action0 add/del.
+  if (!(action[0]=get_action(&argv, arglist1)) || !*argv) routehelp();
+  action[1] = get_action(&argv, arglist2); // action1 -net/-host
+  if (!*argv) routehelp();
   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);
+  tip = *argv++;
+  is_prefix(&tip, &netmask, &rt);
+  ret = get_hostname(tip, (struct sockaddr_in *)&rt.rt_dst);
 
-  if (arg2_action) is_net_or_host = arg2_action & 1;
-  rt.rt_flags = ((is_net_or_host) ? RTF_UP : (RTF_UP | RTF_HOST));
+  if (action[1]) ret = action[1] & 1;
+  rt.rt_flags = RTF_UP | (ret ? 0 : RTF_HOST);
 
-  get_next_params(argv, &rt, (char **)&netmask);
+  parse_args(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;
+  if ((action[0] == 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);
+  if (action[0] == 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)
+// set prefix len and rtmsg_flags.
+static void is_prefix6(char **tip, struct in6_rtmsg *rt)
 {
-  unsigned long plen;
   char *prefix = strchr(*tip, '/');
 
+  rt->rtmsg_dst_len = 128;
   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;
+    rt->rtmsg_dst_len = atolx_range(prefix+1, 0, 128);
+  }
+  rt->rtmsg_flags = RTF_UP | ((rt->rtmsg_dst_len == 128) ? RTF_HOST : 0);
 }
 
-/*
- * 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)
+// parse the arguments like: metric, gw, dev.
+// set the rtentry variables and flags accordingly.
+static void parse_args6(char **argv, struct sockaddr_in6 *sin6,
+    struct in6_rtmsg *rt, char **dev_name)
 {
   while (*argv) {
     if (!strcmp(*argv, "metric")) {
-      //set the metric field in the routing table.
+      // set the metric field in the routing table.
       argv++;
       TEST_ARGV(argv);
-      rt->rtmsg_metric = atolx_range(*argv, 0, ULONG_MAX);
-      argv++;
+      rt->rtmsg_metric = atolx_range(*argv++, 0, LONG_MAX);
     } else if (!strcmp(*argv, "gw")) {
-      //route packets via a gateway.
+      // 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 show_route_help();
+        get_addrinfo(*argv++, (struct sockaddr_in6 *) &sin6);
+        memcpy(&rt->rtmsg_gateway, sin6->sin6_addr.s6_addr,
+            sizeof(struct in6_addr));
+        rt->rtmsg_flags |= RTF_GATEWAY;
+      } else routehelp();
     } else if (!strcmp(*argv, "dev")) {
       argv++;
       TEST_ARGV(argv);
@@ -376,110 +279,151 @@
     } else if (!strcmp(*argv, "dyn")) {
       rt->rtmsg_flags |= RTF_DYNAMIC;
       argv++;
-    } else show_route_help();
-  }//end of while loop.
+    } else {// last arg can be without dev keyword.
+      if ((!*dev_name) && !*++argv) *dev_name = argv[-1];
+      else routehelp();
+    }
+  }
 }
 
-// add/del a route.
-static void setroute_inet6(char **argv)
+// add/del a route6.
+static void setroute6(char **argv)
 {
-  struct sockaddr_in6 sock_in6;
+  struct sockaddr_in6 sin6;
   struct in6_rtmsg rt;
-  char *targetip;
+  char *tip, *dev = NULL;
   int sockfd, action = get_action(&argv, arglist1);
 
-  if (!action || !*argv) show_route_help();
-  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 show_route_help();
-}
-
-/*
- * 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)
+  if (!action || !*argv) routehelp();
+  memset(&sin6, 0, sizeof(sin6));
+  memset(&rt, 0, sizeof(rt));
+  tip = *argv++;
+  if (!*argv) routehelp();
+
+  if (!strcmp(tip, "default")) {
+    rt.rtmsg_flags = RTF_UP;
+    rt.rtmsg_dst_len = 0;
+  } else {
+    is_prefix6(&tip, &rt);
+    get_addrinfo(tip, (struct sockaddr_in6 *)&sin6);
+  }
+  rt.rtmsg_metric = 1; //default metric.
+  memcpy(&rt.rtmsg_dst, sin6.sin6_addr.s6_addr, sizeof(struct in6_addr));
+  parse_args6(argv, &sin6, &rt, (char **)&dev);
+
+  sockfd = xsocket(AF_INET6, SOCK_DGRAM, 0);
+  if (dev) {
+    char ifre_buf[sizeof(struct ifreq)] = {0,};
+    struct ifreq *ifre = (struct ifreq*)ifre_buf;
+    xstrncpy(ifre->ifr_name, dev, 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);
+}
+
+// Format IPv6 ips (like: 2002:6b6d:26c8:d:ea03:9aff:fe65:9d62)
+static void do_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");
-    }
+  while (*ptr && i < 40) {
     addr[i++] = *ptr++;
-    if (!((i+1) % 5)) addr[i++] = ':'; //put ':' after 4th bit
+    if (!((i+1) % 5)) addr[i++] = ':';
   }
+  if (i != 40)
+    error_exit("IPv6 ip format error");
+  addr[i - 1] = 0;
 }
 
-static void display_routes6(void)
+static void 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)];
-
+  char iface[16] = {0,}, dstaddr[41], srcaddr[41], flagstr[10],
+       flagchars[] = "GHRDMDAC", *str, buf2[INET6_ADDRSTRLEN],
+       buf[sizeof(struct in6_addr)];
+  int plen, metric, use, refcount, flags, nitems, i, RTF_flags;
   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);
+  while (fgets(toybuf, sizeof(toybuf), fp)) {
+    memset(flagstr, 0, sizeof(flagstr));
+    if ((nitems = sscanf(toybuf, "%32s%x%*s%*x%32s%x%x%x%x%10s\n", dstaddr+8,
+            &plen, srcaddr+8, &metric, &use, &refcount, &flags, iface)) != 8) {
+      if ((nitems < 0) && feof(fp)) break;
+      perror_exit("sscanf");
     }
-
-    if (inet_pton(AF_INET6, ipv6_src_addr, buf) <= 0) perror_exit("inet");
+    if (!(flags & RTF_UP)) continue; // skip down interfaces.
+    do_formating(dstaddr+8, dstaddr);
+    do_formating(srcaddr+8, srcaddr);
+
+    // Get flags
+    RTF_flags = flags & (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|
+        RTF_ADDRCONF|RTF_CACHE);
+    for (i=0, str=flagstr, *str++='U'; (*str=flagchars[i]); i++)
+      if (RTF_flags & flagarray[i]) ++str;
+    if (inet_pton(AF_INET6, dstaddr, buf) <= 0) perror_exit("inet");
+    if (inet_ntop(AF_INET6, buf, buf2, INET6_ADDRSTRLEN))
+      sprintf(toybuf, "%s/%d", buf2, plen);
+    if (inet_pton(AF_INET6, srcaddr, 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);
+          toybuf, buf2, flagstr, metric, refcount, use, iface);
     }
   }
-  if ((items > 0) && feof(fp)) perror_exit("fscanf");
+  fclose(fp);
+}
+
+void routes(int moreinfo, int nresolve)
+{
+  int i, flags, ref, use, metric, mss, win, irtt;
+  unsigned long dst, gw, mask, RTF_flags;
+  char *str, iface[64], flagchars[] = "GHRDMDAC", flagstr[10];
+  FILE *fp = xfopen("/proc/net/route", "r");
 
+  xprintf("Kernel IP routing table\n"
+      "Destination     Gateway         Genmask         Flags %s Iface\n",
+      moreinfo ? "  MSS Window  irtt" : "Metric Ref    Use");
+  // skip header.
+  if (!fgets(toybuf, sizeof(toybuf), fp)) error_exit("fgets");
+  while (fgets(toybuf, sizeof(toybuf), fp)) {
+    int nitems = 0;
+    char *dstip = NULL, *gwip = NULL, *maskip = NULL;
+
+    memset(flagstr, 0, sizeof(flagstr));
+    if ((nitems = sscanf(toybuf, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
+            iface, &dst, &gw, &flags, &ref, &use, &metric, &mask,
+            &mss, &win, &irtt)) != 11) {
+      if ((nitems < 0) && feof(fp)) break;
+      perror_exit("sscanf");
+    }
+    if (!(flags & RTF_UP)) continue; // Do not proceed with down interfaces.
+    if (dst) {// For Destination
+      if (inet_ntop(AF_INET, &dst, toybuf, sizeof(toybuf)))
+        dstip = xstrdup(toybuf);
+    } else dstip = nresolve ? xstrdup("0.0.0.0") : xstrdup("default");
+    if (gw) {// For Gateway
+      if (inet_ntop(AF_INET, &gw, toybuf, sizeof(toybuf)) )
+        gwip = xstrdup(toybuf);
+    } else gwip = nresolve ? xstrdup("0.0.0.0") : xstrdup("*");
+    // For Mask
+    if (inet_ntop(AF_INET, &mask, toybuf, sizeof(toybuf)))
+      maskip = xstrdup(toybuf);
+    // For Flags
+    RTF_flags = flags & (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|
+        RTF_DYNAMIC|RTF_MODIFIED);
+    for (i=0, str=flagstr, *str++='U'; (*str=flagchars[i]); i++)
+      if (RTF_flags & flagarray[i]) ++str;
+    if (flags & RTF_REJECT) flagstr[0] = '!';
+    xprintf("%-15.15s %-15.15s %-16s%-6s", dstip, gwip, maskip, flagstr);
+    if (dstip) free(dstip);
+    if (gwip) free(gwip);
+    if (maskip) free(maskip);
+    moreinfo ? xprintf("%5d %-5d %6d %s\n", mss, win, irtt, iface) :
+      xprintf("%-6d %-2d %7d %s\n", metric, ref, use, iface);
+  }
   fclose(fp);
 }
 
@@ -487,12 +431,12 @@
 {
   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 show_route_help();
-    return;
-  }//End of if statement.
-
-  if (!strcmp(TT.family, "inet6")) setroute_inet6(toys.optargs);
-  else setroute(toys.optargs);
+    if (!strcmp(TT.family, "inet"))
+      routes(!(toys.optflags & FLAG_e), (toys.optflags & FLAG_n));
+    else if (!strcmp(TT.family, "inet6")) routes6();
+    else routehelp();
+  } else {
+    if (!strcmp(TT.family, "inet6")) setroute6(toys.optargs);
+    else setroute(toys.optargs);
+  }
 }
