]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
Update version of IP gre
authorHerbert Xu <herbert@gondor.apana.org.au>
Wed, 7 Jan 2009 02:27:52 +0000 (18:27 -0800)
committerStephen Hemminger <stephen.hemminger@vyatta.com>
Wed, 7 Jan 2009 02:27:52 +0000 (18:27 -0800)
This patch adds support for configuring GRE tunnels using the
new rtnl_link interface.  This only works on kernels that have
the new GRE configuration interface.

This is accessed through the "ip link" command.  The previous
tunnel configuration interface "ip tunnel" remains as it is
and should be retained for compatibility with old kernels.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
ip/link_gre.c

index e92b0d376a3eaa93dc615564faeb0bb4dc1b9c18..9109312beb7a2e6f3a8413aeabe9fd050cd5bbc6 100644 (file)
@@ -41,12 +41,92 @@ static void usage(void)
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                         struct nlmsghdr *n)
 {
+       struct {
+               struct nlmsghdr n;
+               struct ifinfomsg i;
+               char buf[1024];
+       } req;
+       struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
+       struct rtattr *tb[IFLA_MAX + 1];
+       struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+       struct rtattr *greinfo[IFLA_GRE_MAX + 1];
        __u16 iflags = 0;
        __u16 oflags = 0;
        unsigned ikey = 0;
        unsigned okey = 0;
        unsigned saddr = 0;
        unsigned daddr = 0;
+       unsigned link = 0;
+       __u8 pmtudisc = 1;
+       __u8 ttl = 0;
+       __u8 tos = 0;
+       int len;
+
+       if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+               memset(&req, 0, sizeof(req));
+
+               req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
+               req.n.nlmsg_flags = NLM_F_REQUEST;
+               req.n.nlmsg_type = RTM_GETLINK;
+               req.i.ifi_family = preferred_family;
+               req.i.ifi_index = ifi->ifi_index;
+
+               if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
+get_failed:
+                       fprintf(stderr,
+                               "Failed to get existing tunnel info.\n");
+                       return -1;
+               }
+
+               len = req.n.nlmsg_len;
+               len -= NLMSG_LENGTH(sizeof(*ifi));
+               if (len < 0)
+                       goto get_failed;
+
+               parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
+
+               if (!tb[IFLA_LINKINFO])
+                       goto get_failed;
+
+               parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+               if (!linkinfo[IFLA_INFO_DATA])
+                       goto get_failed;
+
+               parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
+                                   linkinfo[IFLA_INFO_DATA]);
+
+               if (greinfo[IFLA_GRE_IKEY])
+                       ikey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_IKEY]);
+
+               if (greinfo[IFLA_GRE_OKEY])
+                       okey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_OKEY]);
+
+               if (greinfo[IFLA_GRE_IFLAGS])
+                       iflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_IFLAGS]);
+
+               if (greinfo[IFLA_GRE_OFLAGS])
+                       oflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_OFLAGS]);
+
+               if (greinfo[IFLA_GRE_LOCAL])
+                       saddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_LOCAL]);
+
+               if (greinfo[IFLA_GRE_REMOTE])
+                       daddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_REMOTE]);
+
+               if (greinfo[IFLA_GRE_PMTUDISC])
+                       pmtudisc = *(__u8 *)RTA_DATA(
+                               greinfo[IFLA_GRE_PMTUDISC]);
+
+               if (greinfo[IFLA_GRE_TTL])
+                       ttl = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TTL]);
+
+               if (greinfo[IFLA_GRE_TOS])
+                       tos = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TOS]);
+
+               if (greinfo[IFLA_GRE_LINK])
+                       link = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_LINK]);
+       }
 
        while (argc > 0) {
                if (!matches(*argv, "key")) {
@@ -112,13 +192,9 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                } else if (!matches(*argv, "ocsum")) {
                        oflags |= GRE_CSUM;
                } else if (!matches(*argv, "nopmtudisc")) {
-                       __u8 val = 0;
-
-                       addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &val, 1);
+                       pmtudisc = 0;
                } else if (!matches(*argv, "pmtudisc")) {
-                       __u8 val = 1;
-
-                       addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &val, 1);
+                       pmtudisc = 1;
                } else if (!matches(*argv, "remote")) {
                        NEXT_ARG();
                        if (strcmp(*argv, "any"))
@@ -128,18 +204,13 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                        if (strcmp(*argv, "any"))
                                saddr = get_addr32(*argv);
                } else if (!matches(*argv, "dev")) {
-                       unsigned link;
-
                        NEXT_ARG();
                        link = tnl_ioctl_get_ifindex(*argv);
                        if (link == 0)
                                exit(-1);
-
-                       addattr32(n, 1024, IFLA_GRE_LINK, link);
                } else if (!matches(*argv, "ttl") ||
                           !matches(*argv, "hoplimit")) {
                        unsigned uval;
-                       __u8 ttl;
 
                        NEXT_ARG();
                        if (strcmp(*argv, "inherit") != 0) {
@@ -148,13 +219,11 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                                if (uval > 255)
                                        invarg("TTL must be <= 255\n", *argv);
                                ttl = uval;
-                               addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
                        }
                } else if (!matches(*argv, "tos") ||
                           !matches(*argv, "tclass") ||
                           !matches(*argv, "dsfield")) {
                        __u32 uval;
-                       __u8 tos;
 
                        NEXT_ARG();
                        if (strcmp(*argv, "inherit") != 0) {
@@ -163,7 +232,6 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
                                tos = uval;
                        } else
                                tos = 1;
-                       addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
                } else 
                        usage();
                argc--; argv++;
@@ -188,6 +256,11 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
        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);
+       addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
+       if (link)
+               addattr32(n, 1024, IFLA_GRE_LINK, link);
+       addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
+       addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
 
        return 0;
 }