2 * link_gre.c gre driver module
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Herbert Xu <herbert@gondor.apana.org.au>
15 #include <linux/if_tunnel.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <arpa/inet.h>
22 #include "ip_common.h"
25 static void usage(void) __attribute__((noreturn));
26 static void usage(void)
28 fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
29 fprintf(stderr, " type { gre | gretap } [ remote ADDR ] [ local ADDR ]\n");
30 fprintf(stderr, " [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n");
31 fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
32 fprintf(stderr, "\n");
33 fprintf(stderr, "Where: NAME := STRING\n");
34 fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
35 fprintf(stderr, " TOS := { NUMBER | inherit }\n");
36 fprintf(stderr, " TTL := { 1..255 | inherit }\n");
37 fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n");
41 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
49 struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
50 struct rtattr *tb[IFLA_MAX + 1];
51 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
52 struct rtattr *greinfo[IFLA_GRE_MAX + 1];
65 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
66 memset(&req, 0, sizeof(req));
68 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
69 req.n.nlmsg_flags = NLM_F_REQUEST;
70 req.n.nlmsg_type = RTM_GETLINK;
71 req.i.ifi_family = preferred_family;
72 req.i.ifi_index = ifi->ifi_index;
74 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
77 "Failed to get existing tunnel info.\n");
81 len = req.n.nlmsg_len;
82 len -= NLMSG_LENGTH(sizeof(*ifi));
86 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
88 if (!tb[IFLA_LINKINFO])
91 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
93 if (!linkinfo[IFLA_INFO_DATA])
96 parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
97 linkinfo[IFLA_INFO_DATA]);
99 if (greinfo[IFLA_GRE_IKEY])
100 ikey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_IKEY]);
102 if (greinfo[IFLA_GRE_OKEY])
103 okey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_OKEY]);
105 if (greinfo[IFLA_GRE_IFLAGS])
106 iflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_IFLAGS]);
108 if (greinfo[IFLA_GRE_OFLAGS])
109 oflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_OFLAGS]);
111 if (greinfo[IFLA_GRE_LOCAL])
112 saddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_LOCAL]);
114 if (greinfo[IFLA_GRE_REMOTE])
115 daddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_REMOTE]);
117 if (greinfo[IFLA_GRE_PMTUDISC])
118 pmtudisc = *(__u8 *)RTA_DATA(
119 greinfo[IFLA_GRE_PMTUDISC]);
121 if (greinfo[IFLA_GRE_TTL])
122 ttl = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TTL]);
124 if (greinfo[IFLA_GRE_TOS])
125 tos = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TOS]);
127 if (greinfo[IFLA_GRE_LINK])
128 link = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_LINK]);
132 if (!matches(*argv, "key")) {
138 if (strchr(*argv, '.'))
139 uval = get_addr32(*argv);
141 if (get_unsigned(&uval, *argv, 0) < 0) {
143 "Invalid value for \"key\"\n");
150 } else if (!matches(*argv, "ikey")) {
155 if (strchr(*argv, '.'))
156 uval = get_addr32(*argv);
158 if (get_unsigned(&uval, *argv, 0)<0) {
159 fprintf(stderr, "invalid value of \"ikey\"\n");
165 } else if (!matches(*argv, "okey")) {
170 if (strchr(*argv, '.'))
171 uval = get_addr32(*argv);
173 if (get_unsigned(&uval, *argv, 0)<0) {
174 fprintf(stderr, "invalid value of \"okey\"\n");
180 } else if (!matches(*argv, "seq")) {
183 } else if (!matches(*argv, "iseq")) {
185 } else if (!matches(*argv, "oseq")) {
187 } else if (!matches(*argv, "csum")) {
190 } else if (!matches(*argv, "icsum")) {
192 } else if (!matches(*argv, "ocsum")) {
194 } else if (!matches(*argv, "nopmtudisc")) {
196 } else if (!matches(*argv, "pmtudisc")) {
198 } else if (!matches(*argv, "remote")) {
200 if (strcmp(*argv, "any"))
201 daddr = get_addr32(*argv);
202 } else if (!matches(*argv, "local")) {
204 if (strcmp(*argv, "any"))
205 saddr = get_addr32(*argv);
206 } else if (!matches(*argv, "dev")) {
208 link = tnl_ioctl_get_ifindex(*argv);
211 } else if (!matches(*argv, "ttl") ||
212 !matches(*argv, "hoplimit")) {
216 if (strcmp(*argv, "inherit") != 0) {
217 if (get_unsigned(&uval, *argv, 0))
218 invarg("invalid TTL\n", *argv);
220 invarg("TTL must be <= 255\n", *argv);
223 } else if (!matches(*argv, "tos") ||
224 !matches(*argv, "tclass") ||
225 !matches(*argv, "dsfield")) {
229 if (strcmp(*argv, "inherit") != 0) {
230 if (rtnl_dsfield_a2n(&uval, *argv))
231 invarg("bad TOS value", *argv);
240 if (!ikey && IN_MULTICAST(ntohl(daddr))) {
244 if (!okey && IN_MULTICAST(ntohl(daddr))) {
248 if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
249 fprintf(stderr, "Broadcast tunnel requires a source address.\n");
253 addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
254 addattr32(n, 1024, IFLA_GRE_OKEY, okey);
255 addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
256 addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
257 addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
258 addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
259 addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
261 addattr32(n, 1024, IFLA_GRE_LINK, link);
262 addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
263 addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
268 static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
272 const char *local = "any";
273 const char *remote = "any";
280 if (tb[IFLA_GRE_REMOTE]) {
281 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_REMOTE]);
284 remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
287 fprintf(f, "remote %s ", remote);
289 if (tb[IFLA_GRE_LOCAL]) {
290 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LOCAL]);
293 local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
296 fprintf(f, "local %s ", local);
298 if (tb[IFLA_GRE_LINK] && *(__u32 *)RTA_DATA(tb[IFLA_GRE_LINK])) {
299 unsigned link = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LINK]);
300 char *n = tnl_ioctl_get_ifname(link);
303 fprintf(f, "dev %s ", n);
305 fprintf(f, "dev %u ", link);
308 if (tb[IFLA_GRE_TTL] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TTL]))
309 fprintf(f, "ttl %d ", *(__u8 *)RTA_DATA(tb[IFLA_GRE_TTL]));
311 fprintf(f, "ttl inherit ");
313 if (tb[IFLA_GRE_TOS] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS])) {
314 int tos = *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS]);
318 fputs("inherit ", f);
320 fprintf(f, "0x%x ", tos);
323 if (tb[IFLA_GRE_PMTUDISC] &&
324 !*(__u8 *)RTA_DATA(tb[IFLA_GRE_PMTUDISC]))
325 fputs("nopmtudisc ", f);
327 if (tb[IFLA_GRE_IFLAGS])
328 iflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_IFLAGS]);
330 if (tb[IFLA_GRE_OFLAGS])
331 oflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_OFLAGS]);
333 if (iflags & GRE_KEY && tb[IFLA_GRE_IKEY] &&
334 *(__u32 *)RTA_DATA(tb[IFLA_GRE_IKEY])) {
335 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
336 fprintf(f, "ikey %s ", s2);
339 if (oflags & GRE_KEY && tb[IFLA_GRE_OKEY] &&
340 *(__u32 *)RTA_DATA(tb[IFLA_GRE_OKEY])) {
341 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
342 fprintf(f, "ikey %s ", s2);
345 if (iflags & GRE_SEQ)
347 if (oflags & GRE_SEQ)
349 if (iflags & GRE_CSUM)
351 if (oflags & GRE_CSUM)
355 struct link_util gre_link_util = {
357 .maxattr = IFLA_GRE_MAX,
358 .parse_opt = gre_parse_opt,
359 .print_opt = gre_print_opt,
362 struct link_util gretap_link_util = {
364 .maxattr = IFLA_GRE_MAX,
365 .parse_opt = gre_parse_opt,
366 .print_opt = gre_print_opt,