libiproute: handle table ids larger than 255
authorLukasz Nowak <lnowak@tycoint.com>
Tue, 13 Dec 2016 12:58:31 +0000 (12:58 +0000)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 18 Dec 2016 17:56:49 +0000 (18:56 +0100)
Linux kernel, starting from 2.6.19 allows ip table ids to have 32-bit values.
In order to preserve compatibility, the old 8-bit field: rtm_table is still
in use when table id is lower than 256.

Add support for the 32-bit table id (RTA_TABLE attribute) in:
- ip route print
- ip route modify
- ip rule print
- ip rule modify

Add printing of table ids to ip route.

Changes are compatible with the mainline iproute2 utilities.

These changes are required for compatibility with ConnMan, which by default
uses table ids greater than 255.

function                                             old     new   delta
print_route                                         1588    1637     +49
do_iproute                                          2187    2222     +35
do_iprule                                            955     987     +32
print_rule                                           617     630     +13
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 129/0)             Total: 129 bytes

Signed-off-by: Lukasz Nowak <lnowak@tycoint.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/libiproute/iproute.c
networking/libiproute/iprule.c

index 48dc6e3d9c90ce6423af85058e0e6786afbcbffa..0f2b89682d2e92b50bec8bce1327aceeb2d78ae7 100644 (file)
@@ -66,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",
@@ -78,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)
@@ -107,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;
                }
        }
@@ -136,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;
@@ -258,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 */
 
@@ -419,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();
index c486834b073746ccd137f69967af24e0dc54a874..8f3f86286466f7165080997fdbf86fb5b6820abe 100644 (file)
@@ -114,7 +114,9 @@ static int FAST_FUNC print_rule(const struct sockaddr_nl *who UNUSED_PARAM,
                printf("iif %s ", (char*)RTA_DATA(tb[RTA_IIF]));
        }
 
-       if (r->rtm_table)
+       if (tb[RTA_TABLE])
+               printf("lookup %s ", rtnl_rttable_n2a(*(uint32_t*)RTA_DATA(tb[RTA_TABLE])));
+       else if (r->rtm_table)
                printf("lookup %s ", rtnl_rttable_n2a(r->rtm_table));
 
        if (tb[RTA_FLOW]) {
@@ -256,7 +258,12 @@ static int iprule_modify(int cmd, char **argv)
                        NEXT_ARG();
                        if (rtnl_rttable_a2n(&tid, *argv))
                                invarg_1_to_2(*argv, "table ID");
-                       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);
+                       }
                        table_ok = 1;
                } else if (key == ARG_dev ||
                           key == ARG_iif