From: Herbert Xu Date: Wed, 7 Jan 2009 02:27:52 +0000 (-0800) Subject: Update version of IP gre X-Git-Tag: v2.6.28~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72c771b20e38eaabb7699625fcdc144a51771f9c;p=thirdparty%2Fiproute2.git Update version of IP gre 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 --- diff --git a/ip/link_gre.c b/ip/link_gre.c index e92b0d376..9109312be 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -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; }