]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/ipmroute.c
mroute: fix up family handling
[mirror_iproute2.git] / ip / ipmroute.c
index 453a6cf62e71172d34156a902acff994286217b1..b8f0bc49b92e31aec527a515670cedbca58ad5e4 100644 (file)
@@ -13,7 +13,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <syslog.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <sys/ioctl.h>
@@ -30,6 +29,7 @@
 #include <rt_names.h>
 #include "utils.h"
 #include "ip_common.h"
+#include "json_print.h"
 
 static void usage(void) __attribute__((noreturn));
 
@@ -52,15 +52,14 @@ struct rtfilter {
        inet_prefix msrc;
 } filter;
 
-int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_mroute(struct nlmsghdr *n, void *arg)
 {
-       FILE *fp = (FILE *)arg;
        struct rtmsg *r = NLMSG_DATA(n);
        int len = n->nlmsg_len;
        struct rtattr *tb[RTA_MAX+1];
-       char obuf[256];
-
+       const char *src, *dst;
        SPRINT_BUF(b1);
+       SPRINT_BUF(b2);
        __u32 table;
        int iif = 0;
        int family;
@@ -76,10 +75,11 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
                return -1;
        }
+
        if (r->rtm_type != RTN_MULTICAST) {
-               fprintf(stderr, "Not a multicast route (type: %s)\n",
-                       rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1)));
-               return 0;
+               fprintf(stderr,
+                       "Non multicast route received, kernel does support IP multicast?\n");
+               return -1;
        }
 
        parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
@@ -96,48 +96,52 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        if (filter.af && filter.af != r->rtm_family)
                return 0;
 
-       if (tb[RTA_DST] && filter.mdst.bitlen > 0) {
-               inet_prefix dst = { .family = r->rtm_family };
-
-               memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), RTA_PAYLOAD(tb[RTA_DST]));
-               if (inet_addr_match(&dst, &filter.mdst, filter.mdst.bitlen))
-                       return 0;
-       }
-
-       if (tb[RTA_SRC] && filter.msrc.bitlen > 0) {
-               inet_prefix src = { .family = r->rtm_family };
+       if (inet_addr_match_rta(&filter.mdst, tb[RTA_DST]))
+               return 0;
 
-               memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), RTA_PAYLOAD(tb[RTA_SRC]));
-               if (inet_addr_match(&src, &filter.msrc, filter.msrc.bitlen))
-                       return 0;
-       }
+       if (inet_addr_match_rta(&filter.msrc, tb[RTA_SRC]))
+               return 0;
 
        family = get_real_family(r->rtm_type, r->rtm_family);
 
+       open_json_object(NULL);
        if (n->nlmsg_type == RTM_DELROUTE)
-               fprintf(fp, "Deleted ");
+               print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 
        if (tb[RTA_SRC])
-               len = snprintf(obuf, sizeof(obuf),
-                              "(%s, ", rt_addr_n2a_rta(family, tb[RTA_SRC]));
+               src = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_SRC]),
+                                   RTA_DATA(tb[RTA_SRC]), b1, sizeof(b1));
        else
-               len = sprintf(obuf, "(unknown, ");
+               src = "unknown";
+
        if (tb[RTA_DST])
-               snprintf(obuf + len, sizeof(obuf) - len,
-                        "%s)", rt_addr_n2a_rta(family, tb[RTA_DST]));
+               dst = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_DST]),
+                                   RTA_DATA(tb[RTA_DST]), b2, sizeof(b2));
        else
-               snprintf(obuf + len, sizeof(obuf) - len, "unknown) ");
+               dst = "unknown";
+
+       if (is_json_context()) {
+               print_string(PRINT_JSON, "src", NULL, src);
+               print_string(PRINT_JSON, "dst", NULL, dst);
+       } else {
+               char obuf[256];
+
+               snprintf(obuf, sizeof(obuf), "(%s,%s)", src, dst);
+               print_string(PRINT_FP, NULL,
+                            "%-32s Iif: ", obuf);
+       }
 
-       fprintf(fp, "%-32s Iif: ", obuf);
        if (iif)
-               fprintf(fp, "%-10s ", ll_index_to_name(iif));
+               print_color_string(PRINT_ANY, COLOR_IFNAME,
+                                  "iif", "%-10s ", ll_index_to_name(iif));
        else
-               fprintf(fp, "unresolved ");
+               print_string(PRINT_ANY,"iif", "%s ", "unresolved");
 
        if (tb[RTA_MULTIPATH]) {
                struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]);
                int first = 1;
 
+               open_json_array(PRINT_JSON, "multipath");
                len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
 
                for (;;) {
@@ -146,47 +150,65 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
                        if (nh->rtnh_len > len)
                                break;
 
+                       open_json_object(NULL);
                        if (first) {
-                               fprintf(fp, "Oifs: ");
+                               print_string(PRINT_FP, NULL, "Oifs: ", NULL);
                                first = 0;
                        }
-                       fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex));
+
+                       print_color_string(PRINT_ANY, COLOR_IFNAME,
+                                          "oif", "%s", ll_index_to_name(nh->rtnh_ifindex));
+
                        if (nh->rtnh_hops > 1)
-                               fprintf(fp, "(ttl %d) ", nh->rtnh_hops);
+                               print_uint(PRINT_ANY,
+                                          "ttl", "(ttl %u) ", nh->rtnh_hops);
                        else
-                               fprintf(fp, " ");
+                               print_string(PRINT_FP, NULL, " ", NULL);
+
+                       close_json_object();
                        len -= NLMSG_ALIGN(nh->rtnh_len);
                        nh = RTNH_NEXT(nh);
                }
+               close_json_array(PRINT_JSON, NULL);
        }
-       fprintf(fp, " State: %s",
-               r->rtm_flags & RTNH_F_UNRESOLVED ? "unresolved" : "resolved");
+
+       print_string(PRINT_ANY, "state", " State: %s",
+                    (r->rtm_flags & RTNH_F_UNRESOLVED) ? "unresolved" : "resolved");
+
        if (r->rtm_flags & RTNH_F_OFFLOAD)
-               fprintf(fp, " offload");
+               print_null(PRINT_ANY, "offload", " offload", NULL);
+
        if (show_stats && tb[RTA_MFC_STATS]) {
                struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]);
 
-               fprintf(fp, "%s  %"PRIu64" packets, %"PRIu64" bytes", _SL_,
-                       (uint64_t)mfcs->mfcs_packets,
-                       (uint64_t)mfcs->mfcs_bytes);
+               print_nl();
+               print_u64(PRINT_ANY, "packets", "  %"PRIu64" packets,",
+                          mfcs->mfcs_packets);
+               print_u64(PRINT_ANY, "bytes", " %"PRIu64" bytes", mfcs->mfcs_bytes);
+
                if (mfcs->mfcs_wrong_if)
-                       fprintf(fp, ", %"PRIu64" arrived on wrong iif.",
-                               (uint64_t)mfcs->mfcs_wrong_if);
+                       print_u64(PRINT_ANY, "wrong_if",
+                                  ", %"PRIu64" arrived on wrong iif.",
+                                  mfcs->mfcs_wrong_if);
        }
+
        if (show_stats && tb[RTA_EXPIRES]) {
                struct timeval tv;
+               double age;
 
                __jiffies_to_tv(&tv, rta_getattr_u64(tb[RTA_EXPIRES]));
-               fprintf(fp, ", Age %4i.%.2i", (int)tv.tv_sec,
-                       (int)tv.tv_usec/10000);
+               age = tv.tv_sec;
+               age += tv.tv_usec / 1000000.;
+               print_float(PRINT_ANY, "expires",
+                           ", Age %.2f", age);
        }
 
        if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
-               fprintf(fp, " Table: %s",
-                       rtnl_rttable_n2a(table, b1, sizeof(b1)));
+               print_string(PRINT_ANY, "table", " Table: %s",
+                            rtnl_rttable_n2a(table, b1, sizeof(b1)));
 
-       fprintf(fp, "\n");
-       fflush(fp);
+       print_string(PRINT_FP, NULL, "\n", NULL);
+       close_json_object();
        return 0;
 }
 
@@ -201,18 +223,22 @@ void ipmroute_reset_filter(int ifindex)
 static int mroute_list(int argc, char **argv)
 {
        char *id = NULL;
-       int family;
+       int family = preferred_family;
 
        ipmroute_reset_filter(0);
-       if (preferred_family == AF_UNSPEC)
-               family = AF_INET;
-       else
-               family = AF_INET6;
-       if (family == AF_INET) {
+       if (family == AF_INET || family == AF_UNSPEC) {
+               family = RTNL_FAMILY_IPMR;
                filter.af = RTNL_FAMILY_IPMR;
                filter.tb = RT_TABLE_DEFAULT;  /* for backward compatibility */
-       } else
+       } else if (family == AF_INET6) {
+               family = RTNL_FAMILY_IP6MR;
                filter.af = RTNL_FAMILY_IP6MR;
+       } else {
+               /* family does not have multicast routing */
+               return 0;
+       }
+
+       filter.msrc.family = filter.mdst.family = family;
 
        while (argc > 0) {
                if (matches(*argv, "table") == 0) {
@@ -234,14 +260,16 @@ static int mroute_list(int argc, char **argv)
                        id = *argv;
                } else if (matches(*argv, "from") == 0) {
                        NEXT_ARG();
-                       get_prefix(&filter.msrc, *argv, family);
+                       if (get_prefix(&filter.msrc, *argv, family))
+                               invarg("from value is invalid\n", *argv);
                } else {
                        if (strcmp(*argv, "to") == 0) {
                                NEXT_ARG();
                        }
                        if (matches(*argv, "help") == 0)
                                usage();
-                       get_prefix(&filter.mdst, *argv, family);
+                       if (get_prefix(&filter.mdst, *argv, family))
+                               invarg("to value is invalid\n", *argv);
                }
                argc--; argv++;
        }
@@ -251,24 +279,26 @@ static int mroute_list(int argc, char **argv)
        if (id)  {
                int idx;
 
-               if ((idx = ll_name_to_index(id)) == 0) {
-                       fprintf(stderr, "Cannot find device \"%s\"\n", id);
-                       return -1;
-               }
+               idx = ll_name_to_index(id);
+               if (!idx)
+                       return nodev(id);
                filter.iif = idx;
        }
 
-       if (rtnl_wilddump_request(&rth, filter.af, RTM_GETROUTE) < 0) {
+       if (rtnl_routedump_req(&rth, filter.af, NULL) < 0) {
                perror("Cannot send dump request");
                return 1;
        }
 
+       new_json_obj(json);
        if (rtnl_dump_filter(&rth, print_mroute, stdout) < 0) {
+               delete_json_obj();
                fprintf(stderr, "Dump terminated\n");
                exit(1);
        }
+       delete_json_obj();
 
-       exit(0);
+       return 0;
 }
 
 int do_multiroute(int argc, char **argv)