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")) {
} 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"))
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) {
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) {
tos = uval;
} else
tos = 1;
- addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
} else
usage();
argc--; 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;
}