libiproute: handle table ids larger than 255
[oweals/busybox.git] / networking / libiproute / iproute.c
index 82827488f547eb07d2c47ba2fafb5a760fcfdc0b..0f2b89682d2e92b50bec8bce1327aceeb2d78ae7 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include "ip_common.h"  /* #include "libbb.h" is inside */
+#include "common_bufsiz.h"
 #include "rt_names.h"
 #include "utils.h"
 
@@ -43,7 +44,8 @@ struct filter_t {
 } FIX_ALIASING;
 typedef struct filter_t filter_t;
 
-#define G_filter (*(filter_t*)&bb_common_bufsiz1)
+#define G_filter (*(filter_t*)bb_common_bufsiz1)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
 
 static int flush_update(void)
 {
@@ -64,6 +66,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
        inet_prefix dst;
        inet_prefix src;
        int host_len = -1;
+       uint32_t tid;
 
        if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) {
                fprintf(stderr, "Not a route: %08x %08x %08x\n",
@@ -76,6 +79,14 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
        if (len < 0)
                bb_error_msg_and_die("wrong nlmsg len %d", len);
 
+       memset(tb, 0, sizeof(tb));
+       parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
+
+       if (tb[RTA_TABLE])
+               tid = *(uint32_t *)RTA_DATA(tb[RTA_TABLE]);
+       else
+               tid = r->rtm_table;
+
        if (r->rtm_family == AF_INET6)
                host_len = 128;
        else if (r->rtm_family == AF_INET)
@@ -105,7 +116,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
                        }
                }
        } else {
-               if (G_filter.tb > 0 && G_filter.tb != r->rtm_table) {
+               if (G_filter.tb > 0 && G_filter.tb != tid) {
                        return 0;
                }
        }
@@ -134,10 +145,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
                return 0;
        }
 
-       memset(tb, 0, sizeof(tb));
        memset(&src, 0, sizeof(src));
        memset(&dst, 0, sizeof(dst));
-       parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
 
        if (tb[RTA_SRC]) {
                src.bitlen = r->rtm_src_len;
@@ -256,6 +265,10 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
        if (tb[RTA_OIF]) {
                printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
        }
+#if ENABLE_FEATURE_IP_RULE
+       if (tid && tid != RT_TABLE_MAIN && !G_filter.tb)
+               printf("table %s ", rtnl_rttable_n2a(tid));
+#endif
 
        /* Todo: parse & show "proto kernel", "scope link" here */
 
@@ -360,10 +373,9 @@ IF_FEATURE_IP_RULE(ARG_table,)
                req.r.rtm_scope = RT_SCOPE_NOWHERE;
 
        if (cmd != RTM_DELROUTE) {
+               req.r.rtm_scope = RT_SCOPE_UNIVERSE;
                if (RTPROT_BOOT != 0)
                        req.r.rtm_protocol = RTPROT_BOOT;
-               if (RT_SCOPE_UNIVERSE != 0)
-                       req.r.rtm_scope = RT_SCOPE_UNIVERSE;
                if (RTN_UNICAST != 0)
                        req.r.rtm_type = RTN_UNICAST;
        }
@@ -418,7 +430,12 @@ IF_FEATURE_IP_RULE(ARG_table,)
                        NEXT_ARG();
                        if (rtnl_rttable_a2n(&tid, *argv))
                                invarg_1_to_2(*argv, "table");
-                       req.r.rtm_table = tid;
+                       if (tid < 256)
+                               req.r.rtm_table = tid;
+                       else {
+                               req.r.rtm_table = RT_TABLE_UNSPEC;
+                               addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
+                       }
 #endif
                } else if (arg == ARG_dev || arg == ARG_oif) {
                        NEXT_ARG();
@@ -902,6 +919,8 @@ int FAST_FUNC do_iproute(char **argv)
        unsigned flags = 0;
        int cmd = RTM_NEWROUTE;
 
+       INIT_G();
+
        if (!*argv)
                return iproute_list_or_flush(argv, 0);