iproute: support onelink route option and print route flags
[oweals/busybox.git] / networking / libiproute / iproute.c
index 14fc16c4d930d54fc539c65506381923d7d9aa38..170c67b30d470857e739d8ad1834c39b1f113c31 100644 (file)
@@ -73,7 +73,7 @@ static unsigned get_hz(void)
                fclose(fp);
        }
        if (!hz_internal)
-               hz_internal = sysconf(_SC_CLK_TCK);
+               hz_internal = bb_clk_tck();
        return hz_internal;
 }
 
@@ -82,7 +82,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
 {
        struct rtmsg *r = NLMSG_DATA(n);
        int len = n->nlmsg_len;
-       struct rtattr * tb[RTA_MAX+1];
+       struct rtattr *tb[RTA_MAX+1];
        char abuf[256];
        inet_prefix dst;
        inet_prefix src;
@@ -159,8 +159,21 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
        }
 
        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;
+               src.bytelen = (r->rtm_family == AF_INET6 ? 16 : 4);
+               memcpy(src.data, RTA_DATA(tb[RTA_SRC]), src.bytelen);
+       }
+       if (tb[RTA_DST]) {
+               dst.bitlen = r->rtm_dst_len;
+               dst.bytelen = (r->rtm_family == AF_INET6 ? 16 : 4);
+               memcpy(dst.data, RTA_DATA(tb[RTA_DST]), dst.bytelen);
+       }
+
        if (G_filter.rdst.family
         && inet_addr_match(&dst, &G_filter.rdst, G_filter.rdst.bitlen)
        ) {
@@ -190,6 +203,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
        }
 
        if (G_filter.flushb) {
+               struct nlmsghdr *fn;
+
                /* We are creating route flush commands */
 
                if (r->rtm_family == AF_INET6
@@ -201,12 +216,11 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
                        return 0;
                }
 
-               struct nlmsghdr *fn;
                if (NLMSG_ALIGN(G_filter.flushp) + n->nlmsg_len > G_filter.flushe) {
                        if (flush_update())
                                bb_error_msg_and_die("flush");
                }
-               fn = (struct nlmsghdr*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
+               fn = (void*)(G_filter.flushb + NLMSG_ALIGN(G_filter.flushp));
                memcpy(fn, n, n->nlmsg_len);
                fn->nlmsg_type = RTM_DELROUTE;
                fn->nlmsg_flags = NLM_F_REQUEST;
@@ -284,6 +298,19 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
        if (tb[RTA_PRIORITY]) {
                printf(" metric %d ", *(uint32_t*)RTA_DATA(tb[RTA_PRIORITY]));
        }
+       if (r->rtm_flags & RTNH_F_DEAD) {
+               printf("dead ");
+       }
+       if (r->rtm_flags & RTNH_F_ONLINK) {
+               printf("onlink ");
+       }
+       if (r->rtm_flags & RTNH_F_PERVASIVE) {
+               printf("pervasive ");
+       }
+       if (r->rtm_flags & RTM_F_NOTIFY) {
+               printf("notify ");
+       }
+
        if (r->rtm_family == AF_INET6) {
                struct rta_cacheinfo *ci = NULL;
                if (tb[RTA_CACHEINFO]) {
@@ -316,7 +343,7 @@ static int iproute_modify(int cmd, unsigned flags, char **argv)
 {
        static const char keywords[] ALIGN1 =
                "src\0""via\0""mtu\0""lock\0""protocol\0"IF_FEATURE_IP_RULE("table\0")
-               "dev\0""oif\0""to\0""metric\0";
+               "dev\0""oif\0""to\0""metric\0""onlink\0";
        enum {
                ARG_src,
                ARG_via,
@@ -327,6 +354,7 @@ IF_FEATURE_IP_RULE(ARG_table,)
                ARG_oif,
                ARG_to,
                ARG_metric,
+               ARG_onlink,
        };
        enum {
                gw_ok = 1 << 0,
@@ -417,6 +445,8 @@ IF_FEATURE_IP_RULE(ARG_table,)
                        NEXT_ARG();
                        metric = get_u32(*argv, "metric");
                        addattr32(&req.n, sizeof(req), RTA_PRIORITY, metric);
+               } else if (arg == ARG_onlink) {
+                       req.r.rtm_flags |= RTNH_F_ONLINK;
                } else {
                        int type;
                        inet_prefix dst;
@@ -425,7 +455,8 @@ IF_FEATURE_IP_RULE(ARG_table,)
                                NEXT_ARG();
                        }
                        if ((**argv < '0' || **argv > '9')
-                        && rtnl_rtntype_a2n(&type, *argv) == 0) {
+                        && rtnl_rtntype_a2n(&type, *argv) == 0
+                       ) {
                                NEXT_ARG();
                                req.r.rtm_type = type;
                                ok |= type_ok;