]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/ipneigh.c
man: tc-taprio.8: fix syntax error
[mirror_iproute2.git] / ip / ipneigh.c
index 5747152251a453ca80414ba611d5dc38faf60b42..88596245a2eda88333dd42d58f24a169c4493743 100644 (file)
@@ -40,6 +40,8 @@ static struct
        int flushp;
        int flushe;
        int master;
+       int protocol;
+       __u8 ndm_flags;
 } filter;
 
 static void usage(void) __attribute__((noreturn));
@@ -48,6 +50,7 @@ static void usage(void)
 {
        fprintf(stderr, "Usage: ip neigh { add | del | change | replace }\n"
                        "                { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]\n");
+       fprintf(stderr, "                [ router ] [ extern_learn ] [ protocol PROTO ]\n\n");
        fprintf(stderr, "       ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n");
        fprintf(stderr, "                                 [ vrf NAME ]\n\n");
        fprintf(stderr, "STATE := { permanent | noarp | stale | reachable | none |\n"
@@ -141,10 +144,20 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
                        req.ndm.ndm_flags |= NTF_PROXY;
                } else if (strcmp(*argv, "router") == 0) {
                        req.ndm.ndm_flags |= NTF_ROUTER;
+               } else if (matches(*argv, "extern_learn") == 0) {
+                       req.ndm.ndm_flags |= NTF_EXT_LEARNED;
                } else if (strcmp(*argv, "dev") == 0) {
                        NEXT_ARG();
                        dev = *argv;
                        dev_ok = 1;
+               } else if (matches(*argv, "protocol") == 0) {
+                       __u32 proto;
+
+                       NEXT_ARG();
+                       if (rtnl_rtprot_a2n(&proto, *argv))
+                               invarg("\"protocol\" value is invalid\n", *argv);
+                       if (addattr8(&req.n, sizeof(req), NDA_PROTOCOL, proto))
+                               return -1;
                } else {
                        if (strcmp(*argv, "to") == 0) {
                                NEXT_ARG();
@@ -234,13 +247,14 @@ static void print_neigh_state(unsigned int nud)
        close_json_array(PRINT_JSON, NULL);
 }
 
-int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int print_neigh(struct nlmsghdr *n, void *arg)
 {
        FILE *fp = (FILE *)arg;
        struct ndmsg *r = NLMSG_DATA(n);
        int len = n->nlmsg_len;
        struct rtattr *tb[NDA_MAX+1];
        static int logit = 1;
+       __u8 protocol = 0;
 
        if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH &&
            n->nlmsg_type != RTM_GETNEIGH) {
@@ -282,6 +296,12 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        if (inet_addr_match_rta(&filter.pfx, tb[NDA_DST]))
                return 0;
 
+       if (tb[NDA_PROTOCOL])
+               protocol = rta_getattr_u8(tb[NDA_PROTOCOL]);
+
+       if (filter.protocol && filter.protocol != protocol)
+               return 0;
+
        if (filter.unused_only && tb[NDA_CACHEINFO]) {
                struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
 
@@ -315,10 +335,18 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 
        if (tb[NDA_DST]) {
                const char *dst;
+               int family = r->ndm_family;
+
+               if (family == AF_BRIDGE) {
+                       if (RTA_PAYLOAD(tb[NDA_DST]) == sizeof(struct in6_addr))
+                               family = AF_INET6;
+                       else
+                               family = AF_INET;
+               }
 
-               dst = format_host_rta(r->ndm_family, tb[NDA_DST]);
+               dst = format_host_rta(family, tb[NDA_DST]);
                print_color_string(PRINT_ANY,
-                                  ifa_family_color(r->ndm_family),
+                                  ifa_family_color(family),
                                   "dst", "%s ", dst);
        }
 
@@ -353,6 +381,9 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        if (r->ndm_flags & NTF_PROXY)
                print_null(PRINT_ANY, "proxy", " %s", "proxy");
 
+       if (r->ndm_flags & NTF_EXT_LEARNED)
+               print_null(PRINT_ANY, "extern_learn", " %s ", "extern_learn");
+
        if (show_stats) {
                if (tb[NDA_CACHEINFO])
                        print_cacheinfo(RTA_DATA(tb[NDA_CACHEINFO]));
@@ -365,6 +396,13 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        if (r->ndm_state)
                print_neigh_state(r->ndm_state);
 
+       if (protocol) {
+               SPRINT_BUF(b1);
+
+               print_string(PRINT_ANY, "protocol", " proto %s ",
+                            rtnl_rtprot_n2a(protocol, b1, sizeof(b1)));
+       }
+
        print_string(PRINT_FP, NULL, "\n", "");
        close_json_object();
        fflush(stdout);
@@ -379,16 +417,29 @@ void ipneigh_reset_filter(int ifindex)
        filter.index = ifindex;
 }
 
+static int ipneigh_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+       struct ndmsg *ndm = NLMSG_DATA(nlh);
+       int err;
+
+       ndm->ndm_flags = filter.ndm_flags;
+
+       if (filter.index) {
+               err = addattr32(nlh, reqlen, NDA_IFINDEX, filter.index);
+               if (err)
+                       return err;
+       }
+       if (filter.master) {
+               err = addattr32(nlh, reqlen, NDA_MASTER, filter.master);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int do_show_or_flush(int argc, char **argv, int flush)
 {
-       struct {
-               struct nlmsghdr n;
-               struct ndmsg            ndm;
-               char                    buf[256];
-       } req = {
-               .n.nlmsg_type = RTM_GETNEIGH,
-               .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
-       };
        char *filter_dev = NULL;
        int state_given = 0;
 
@@ -419,7 +470,6 @@ static int do_show_or_flush(int argc, char **argv, int flush)
                        ifindex = ll_name_to_index(*argv);
                        if (!ifindex)
                                invarg("Device does not exist\n", *argv);
-                       addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
                        filter.master = ifindex;
                } else if (strcmp(*argv, "vrf") == 0) {
                        int ifindex;
@@ -430,7 +480,6 @@ static int do_show_or_flush(int argc, char **argv, int flush)
                                invarg("Not a valid VRF name\n", *argv);
                        if (!name_is_vrf(*argv))
                                invarg("Not a valid VRF name\n", *argv);
-                       addattr32(&req.n, sizeof(req), NDA_MASTER, ifindex);
                        filter.master = ifindex;
                } else if (strcmp(*argv, "unused") == 0) {
                        filter.unused_only = 1;
@@ -452,9 +501,19 @@ static int do_show_or_flush(int argc, char **argv, int flush)
                        if (state == 0)
                                state = 0x100;
                        filter.state |= state;
-               } else if (strcmp(*argv, "proxy") == 0)
-                       req.ndm.ndm_flags = NTF_PROXY;
-               else {
+               } else if (strcmp(*argv, "proxy") == 0) {
+                       filter.ndm_flags = NTF_PROXY;
+               } else if (matches(*argv, "protocol") == 0) {
+                       __u32 prot;
+
+                       NEXT_ARG();
+                       if (rtnl_rtprot_a2n(&prot, *argv)) {
+                               if (strcmp(*argv, "all"))
+                                       invarg("invalid \"protocol\"\n", *argv);
+                               prot = 0;
+                       }
+                       filter.protocol = prot;
+               } else {
                        if (strcmp(*argv, "to") == 0) {
                                NEXT_ARG();
                        }
@@ -474,11 +533,8 @@ static int do_show_or_flush(int argc, char **argv, int flush)
                filter.index = ll_name_to_index(filter_dev);
                if (!filter.index)
                        return nodev(filter_dev);
-               addattr32(&req.n, sizeof(req), NDA_IFINDEX, filter.index);
        }
 
-       req.ndm.ndm_family = filter.family;
-
        if (flush) {
                int round = 0;
                char flushb[4096-512];
@@ -488,7 +544,8 @@ static int do_show_or_flush(int argc, char **argv, int flush)
                filter.flushe = sizeof(flushb);
 
                while (round < MAX_ROUNDS) {
-                       if (rtnl_dump_request_n(&rth, &req.n) < 0) {
+                       if (rtnl_neighdump_req(&rth, filter.family,
+                                              ipneigh_dump_filter) < 0) {
                                perror("Cannot send dump request");
                                exit(1);
                        }
@@ -521,7 +578,7 @@ static int do_show_or_flush(int argc, char **argv, int flush)
                return 1;
        }
 
-       if (rtnl_dump_request_n(&rth, &req.n) < 0) {
+       if (rtnl_neighdump_req(&rth, filter.family, ipneigh_dump_filter) < 0) {
                perror("Cannot send dump request");
                exit(1);
        }