xz: omit explicit \0 from HEADER_MAGIC
[oweals/busybox.git] / networking / libiproute / iproute.c
index c4b3450dd35a9c32d4063f4f7fa36a4166fe17c9..f8a67d9eedc43f3ede19c506773ce20933b39f61 100644 (file)
@@ -1,19 +1,16 @@
 /* vi: set sw=4 ts=4: */
 /*
- * iproute.c           "ip route".
- *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
- *
- * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
  * Changes:
  *
- * Rani Assaf <rani@magic.metawire.com> 980929:        resolve addresses
+ * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
  * Kunihiro Ishiguro <kunihiro@zebra.org> 001102: rtnh_ifindex was not initialized
  */
 
-#include "ip_common.h" /* #include "libbb.h" is inside */
+#include "ip_common.h"  /* #include "libbb.h" is inside */
 #include "rt_names.h"
 #include "utils.h"
 
@@ -22,7 +19,7 @@
 #endif
 
 
-typedef struct filter_t {
+struct filter_t {
        int tb;
        smallint flushed;
        char *flushb;
@@ -34,8 +31,8 @@ typedef struct filter_t {
        //int type; - read-only
        //int typemask; - unused
        //int tos, tosmask; - unused
-       int iif, iifmask;
-       int oif, oifmask;
+       int iif;
+       int oif;
        //int realm, realmmask; - unused
        //inet_prefix rprefsrc; - read-only
        inet_prefix rvia;
@@ -43,14 +40,15 @@ typedef struct filter_t {
        inet_prefix mdst;
        inet_prefix rsrc;
        inet_prefix msrc;
-} filter_t;
+} FIX_ALIASING;
+typedef struct filter_t filter_t;
 
 #define G_filter (*(filter_t*)&bb_common_bufsiz1)
 
 static int flush_update(void)
 {
        if (rtnl_send(G_filter.rth, G_filter.flushb, G_filter.flushp) < 0) {
-               bb_perror_msg("failed to send flush request");
+               bb_perror_msg("can't send flush request");
                return -1;
        }
        G_filter.flushp = 0;
@@ -84,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;
@@ -161,39 +159,68 @@ 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 (G_filter.rdst.family && inet_addr_match(&dst, &G_filter.rdst, G_filter.rdst.bitlen))
+       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)
+       ) {
                return 0;
-       if (G_filter.mdst.family && G_filter.mdst.bitlen >= 0 &&
-           inet_addr_match(&dst, &G_filter.mdst, r->rtm_dst_len))
+       }
+       if (G_filter.mdst.family
+        && G_filter.mdst.bitlen >= 0
+        && inet_addr_match(&dst, &G_filter.mdst, r->rtm_dst_len)
+       ) {
                return 0;
-
-       if (G_filter.rsrc.family && inet_addr_match(&src, &G_filter.rsrc, G_filter.rsrc.bitlen))
+       }
+       if (G_filter.rsrc.family
+        && inet_addr_match(&src, &G_filter.rsrc, G_filter.rsrc.bitlen)
+       ) {
                return 0;
+       }
        if (G_filter.msrc.family && G_filter.msrc.bitlen >= 0
         && inet_addr_match(&src, &G_filter.msrc, r->rtm_src_len)
        ) {
                return 0;
        }
-
-       if (G_filter.flushb
-        && r->rtm_family == AF_INET6
-        && r->rtm_dst_len == 0
-        && r->rtm_type == RTN_UNREACHABLE
-        && tb[RTA_PRIORITY]
-        && *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1
-       ) {
-               return 0;
+       if (G_filter.oif != 0) {
+               if (!tb[RTA_OIF])
+                       return 0;
+               if (G_filter.oif != *(int*)RTA_DATA(tb[RTA_OIF]))
+                       return 0;
        }
 
        if (G_filter.flushb) {
                struct nlmsghdr *fn;
+
+               /* We are creating route flush commands */
+
+               if (r->rtm_family == AF_INET6
+                && r->rtm_dst_len == 0
+                && r->rtm_type == RTN_UNREACHABLE
+                && tb[RTA_PRIORITY]
+                && *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1
+               ) {
+                       return 0;
+               }
+
                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;
@@ -203,6 +230,8 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
                return 0;
        }
 
+       /* We are printing routes */
+
        if (n->nlmsg_type == RTM_DELROUTE) {
                printf("Deleted ");
        }
@@ -252,10 +281,12 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
                                        RTA_DATA(tb[RTA_GATEWAY]),
                                        abuf, sizeof(abuf)));
        }
-       if (tb[RTA_OIF] && G_filter.oifmask != -1) {
+       if (tb[RTA_OIF]) {
                printf("dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
        }
 
+       /* Todo: parse & show "proto kernel", "scope link" here */
+
        if (tb[RTA_PREFSRC] && /*G_filter.rprefsrc.bitlen - always 0*/ 0 != host_len) {
                /* Do not use format_host(). It is our local addr
                   and symbolic name will not be useful.
@@ -287,7 +318,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM,
                                printf(" error %d", ci->rta_error);
                }
        }
-       if (tb[RTA_IIF] && G_filter.iifmask != -1) {
+       if (tb[RTA_IIF] && G_filter.iif == 0) {
                printf(" iif %s", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_IIF])));
        }
        bb_putchar('\n');
@@ -319,9 +350,9 @@ IF_FEATURE_IP_RULE(ARG_table,)
        };
        struct rtnl_handle rth;
        struct {
-               struct nlmsghdr         n;
-               struct rtmsg            r;
-               char                    buf[1024];
+               struct nlmsghdr n;
+               struct rtmsg    r;
+               char            buf[1024];
        } req;
        char mxbuf[256];
        struct rtattr * mxrta = (void*)mxbuf;
@@ -408,7 +439,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;
@@ -657,12 +689,10 @@ static int iproute_list_or_flush(char **argv, int flush)
                if (id) {
                        idx = xll_name_to_index(id);
                        G_filter.iif = idx;
-                       G_filter.iifmask = -1;
                }
                if (od) {
                        idx = xll_name_to_index(od);
                        G_filter.oif = idx;
-                       G_filter.oifmask = -1;
                }
        }
 
@@ -783,8 +813,8 @@ static int iproute_get(char **argv)
                                }
                                req.r.rtm_dst_len = addr.bitlen;
                        }
-                       argv++;
                }
+               argv++;
        }
 
        if (req.r.rtm_dst_len == 0) {
@@ -838,7 +868,7 @@ static int iproute_get(char **argv)
                        tb[RTA_PREFSRC]->rta_type = RTA_SRC;
                        r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
                } else if (!tb[RTA_SRC]) {
-                       bb_error_msg_and_die("failed to connect the route");
+                       bb_error_msg_and_die("can't connect the route");
                }
                if (!odev && tb[RTA_OIF]) {
                        tb[RTA_OIF]->rta_type = 0;
@@ -861,7 +891,7 @@ static int iproute_get(char **argv)
 }
 
 /* Return value becomes exitcode. It's okay to not return at all */
-int do_iproute(char **argv)
+int FAST_FUNC do_iproute(char **argv)
 {
        static const char ip_route_commands[] ALIGN1 =
        /*0-3*/ "add\0""append\0""change\0""chg\0"