]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/link_gre.c
bridge: fdb: add support for src_vni option
[mirror_iproute2.git] / ip / link_gre.c
index e3e5323935adf6ad060b9ae3bcdafd6b2b5e7484..d754fa9a3425fa89e992b53e571b12c243147a18 100644 (file)
@@ -31,9 +31,9 @@ static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
        );
        fprintf(f,
                "                     [ local ADDR ]\n"
-               "                     [ [i|o]seq ]\n"
-               "                     [ [i|o]key KEY ]\n"
-               "                     [ [i|o]csum ]\n"
+               "                     [ [no][i|o]seq ]\n"
+               "                     [ [i|o]key KEY | no[i|o]key ]\n"
+               "                     [ [no][i|o]csum ]\n"
                "                     [ ttl TTL ]\n"
                "                     [ tos TOS ]\n"
                "                     [ [no]pmtudisc ]\n"
@@ -86,8 +86,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
        __u16 oflags = 0;
        __be32 ikey = 0;
        __be32 okey = 0;
-       unsigned int saddr = 0;
-       unsigned int daddr = 0;
+       inet_prefix saddr, daddr;
        __u8 pmtudisc = 1;
        __u8 ignore_df = 0;
        __u8 tos = 0;
@@ -104,7 +103,12 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
        __u8 erspan_dir = 0;
        __u16 erspan_hwid = 0;
 
+       inet_prefix_reset(&saddr);
+       inet_prefix_reset(&daddr);
+
        if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+               const struct rtattr *rta;
+
                if (rtnl_talk(&rth, &req.n, &answer) < 0) {
 get_failed:
                        fprintf(stderr,
@@ -130,6 +134,14 @@ get_failed:
                parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
                                    linkinfo[IFLA_INFO_DATA]);
 
+               rta = greinfo[IFLA_GRE_LOCAL];
+               if (rta && get_addr_rta(&saddr, rta, AF_INET))
+                       goto get_failed;
+
+               rta = greinfo[IFLA_GRE_REMOTE];
+               if (rta && get_addr_rta(&daddr, rta, AF_INET))
+                       goto get_failed;
+
                if (greinfo[IFLA_GRE_IKEY])
                        ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]);
 
@@ -142,12 +154,6 @@ get_failed:
                if (greinfo[IFLA_GRE_OFLAGS])
                        oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]);
 
-               if (greinfo[IFLA_GRE_LOCAL])
-                       saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]);
-
-               if (greinfo[IFLA_GRE_REMOTE])
-                       daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]);
-
                if (greinfo[IFLA_GRE_PMTUDISC])
                        pmtudisc = rta_getattr_u8(
                                greinfo[IFLA_GRE_PMTUDISC]);
@@ -204,46 +210,67 @@ get_failed:
                        iflags |= GRE_KEY;
                        oflags |= GRE_KEY;
                        ikey = okey = tnl_parse_key("key", *argv);
+               } else if (!matches(*argv, "nokey")) {
+                       iflags &= ~GRE_KEY;
+                       oflags &= ~GRE_KEY;
+                       ikey = okey = 0;
                } else if (!matches(*argv, "ikey")) {
                        NEXT_ARG();
                        iflags |= GRE_KEY;
                        ikey = tnl_parse_key("ikey", *argv);
+               } else if (!matches(*argv, "noikey")) {
+                       iflags &= ~GRE_KEY;
+                       ikey = 0;
                } else if (!matches(*argv, "okey")) {
                        NEXT_ARG();
                        oflags |= GRE_KEY;
                        okey = tnl_parse_key("okey", *argv);
+               } else if (!matches(*argv, "nookey")) {
+                       oflags &= ~GRE_KEY;
+                       okey = 0;
                } else if (!matches(*argv, "seq")) {
                        iflags |= GRE_SEQ;
                        oflags |= GRE_SEQ;
+               } else if (!matches(*argv, "noseq")) {
+                       iflags &= ~GRE_SEQ;
+                       oflags &= ~GRE_SEQ;
                } else if (!matches(*argv, "iseq")) {
                        iflags |= GRE_SEQ;
+               } else if (!matches(*argv, "noiseq")) {
+                       iflags &= ~GRE_SEQ;
                } else if (!matches(*argv, "oseq")) {
                        oflags |= GRE_SEQ;
+               } else if (!matches(*argv, "nooseq")) {
+                       oflags &= ~GRE_SEQ;
                } else if (!matches(*argv, "csum")) {
                        iflags |= GRE_CSUM;
                        oflags |= GRE_CSUM;
+               } else if (!matches(*argv, "nocsum")) {
+                       iflags &= ~GRE_CSUM;
+                       oflags &= ~GRE_CSUM;
                } else if (!matches(*argv, "icsum")) {
                        iflags |= GRE_CSUM;
+               } else if (!matches(*argv, "noicsum")) {
+                       iflags &= ~GRE_CSUM;
                } else if (!matches(*argv, "ocsum")) {
                        oflags |= GRE_CSUM;
+               } else if (!matches(*argv, "noocsum")) {
+                       oflags &= ~GRE_CSUM;
                } else if (!matches(*argv, "nopmtudisc")) {
                        pmtudisc = 0;
                } else if (!matches(*argv, "pmtudisc")) {
                        pmtudisc = 1;
                } else if (!matches(*argv, "remote")) {
                        NEXT_ARG();
-                       daddr = get_addr32(*argv);
+                       get_addr(&daddr, *argv, AF_INET);
                } else if (!matches(*argv, "local")) {
                        NEXT_ARG();
-                       saddr = get_addr32(*argv);
+                       get_addr(&saddr, *argv, AF_INET);
                } else if (!matches(*argv, "dev")) {
                        NEXT_ARG();
                        link = ll_name_to_index(*argv);
-                       if (link == 0) {
-                               fprintf(stderr, "Cannot find device \"%s\"\n",
-                                       *argv);
-                               exit(-1);
-                       }
+                       if (!link)
+                               exit(nodev(*argv));
                } else if (!matches(*argv, "ttl") ||
                           !matches(*argv, "hoplimit") ||
                           !matches(*argv, "hlim")) {
@@ -343,17 +370,20 @@ get_failed:
                argc--; argv++;
        }
 
-       if (!ikey && IN_MULTICAST(ntohl(daddr))) {
-               ikey = daddr;
-               iflags |= GRE_KEY;
-       }
-       if (!okey && IN_MULTICAST(ntohl(daddr))) {
-               okey = daddr;
-               oflags |= GRE_KEY;
-       }
-       if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
-               fprintf(stderr, "A broadcast tunnel requires a source address.\n");
-               return -1;
+       if (is_addrtype_inet_multi(&daddr)) {
+               if (!ikey) {
+                       ikey = daddr.data[0];
+                       iflags |= GRE_KEY;
+               }
+               if (!okey) {
+                       okey = daddr.data[0];
+                       oflags |= GRE_KEY;
+               }
+               if (!is_addrtype_inet_not_unspec(&saddr)) {
+                       fprintf(stderr,
+                               "A broadcast tunnel requires a source address.\n");
+                       return -1;
+               }
        }
 
        if (metadata) {
@@ -365,8 +395,10 @@ get_failed:
        addattr32(n, 1024, IFLA_GRE_OKEY, okey);
        addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
        addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
-       addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
-       addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
+       if (is_addrtype_inet_not_unspec(&saddr))
+               addattr_l(n, 1024, IFLA_GRE_LOCAL, saddr.data, saddr.bytelen);
+       if (is_addrtype_inet_not_unspec(&daddr))
+               addattr_l(n, 1024, IFLA_GRE_REMOTE, daddr.data, daddr.bytelen);
        addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
        if (ignore_df)
                addattr8(n, 1024, IFLA_GRE_IGNORE_DF, ignore_df & 1);
@@ -431,7 +463,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
                tos = rta_getattr_u8(tb[IFLA_GRE_TOS]);
        if (tos) {
                if (is_json_context() || tos != 1)
-                       print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos);
+                       print_0xhex(PRINT_ANY, "tos", "tos %#llx ", tos);
                else
                        print_string(PRINT_FP, NULL, "tos %s ", "inherit");
        }
@@ -476,7 +508,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 
                if (fwmark) {
                        print_0xhex(PRINT_ANY,
-                                   "fwmark", "fwmark 0x%x ", fwmark);
+                                   "fwmark", "fwmark %#llx ", fwmark);
                }
        }
 
@@ -509,7 +541,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
                __u16 erspan_hwid = rta_getattr_u16(tb[IFLA_GRE_ERSPAN_HWID]);
 
                print_0xhex(PRINT_ANY,
-                           "erspan_hwid", "erspan_hwid 0x%x ", erspan_hwid);
+                           "erspan_hwid", "erspan_hwid %#llx ", erspan_hwid);
        }
 
        tnl_print_encap(tb,