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 <sys/types.h>
16 #include <sys/socket.h>
17 #include <arpa/inet.h>
20 #include <linux/if_tunnel.h>
23 #include "ip_common.h"
26 static void usage(void) __attribute__((noreturn));
27 static void usage(void)
29 fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
30 fprintf(stderr, " type { gre | gretap } [ remote ADDR ] [ local ADDR ]\n");
31 fprintf(stderr, " [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n");
32 fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
33 fprintf(stderr, "\n");
34 fprintf(stderr, "Where: NAME := STRING\n");
35 fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
36 fprintf(stderr, " TOS := { NUMBER | inherit }\n");
37 fprintf(stderr, " TTL := { 1..255 | inherit }\n");
38 fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n");
42 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
50 struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
51 struct rtattr *tb[IFLA_MAX + 1];
52 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
53 struct rtattr *greinfo[IFLA_GRE_MAX + 1];
66 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
67 memset(&req, 0, sizeof(req));
69 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
70 req.n.nlmsg_flags = NLM_F_REQUEST;
71 req.n.nlmsg_type = RTM_GETLINK;
72 req.i.ifi_family = preferred_family;
73 req.i.ifi_index = ifi->ifi_index;
75 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) {
78 "Failed to get existing tunnel info.\n");
82 len = req.n.nlmsg_len;
83 len -= NLMSG_LENGTH(sizeof(*ifi));
87 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
89 if (!tb[IFLA_LINKINFO])
92 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
94 if (!linkinfo[IFLA_INFO_DATA])
97 parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
98 linkinfo[IFLA_INFO_DATA]);
100 if (greinfo[IFLA_GRE_IKEY])
101 ikey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_IKEY]);
103 if (greinfo[IFLA_GRE_OKEY])
104 okey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_OKEY]);
106 if (greinfo[IFLA_GRE_IFLAGS])
107 iflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_IFLAGS]);
109 if (greinfo[IFLA_GRE_OFLAGS])
110 oflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_OFLAGS]);
112 if (greinfo[IFLA_GRE_LOCAL])
113 saddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_LOCAL]);
115 if (greinfo[IFLA_GRE_REMOTE])
116 daddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_REMOTE]);
118 if (greinfo[IFLA_GRE_PMTUDISC])
119 pmtudisc = *(__u8 *)RTA_DATA(
120 greinfo[IFLA_GRE_PMTUDISC]);
122 if (greinfo[IFLA_GRE_TTL])
123 ttl = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TTL]);
125 if (greinfo[IFLA_GRE_TOS])
126 tos = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TOS]);
128 if (greinfo[IFLA_GRE_LINK])
129 link = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_LINK]);
133 if (!matches(*argv, "key")) {
139 if (strchr(*argv, '.'))
140 uval = get_addr32(*argv);
142 if (get_unsigned(&uval, *argv, 0) < 0) {
144 "Invalid value for \"key\"\n");
151 } else if (!matches(*argv, "ikey")) {
156 if (strchr(*argv, '.'))
157 uval = get_addr32(*argv);
159 if (get_unsigned(&uval, *argv, 0)<0) {
160 fprintf(stderr, "invalid value of \"ikey\"\n");
166 } else if (!matches(*argv, "okey")) {
171 if (strchr(*argv, '.'))
172 uval = get_addr32(*argv);
174 if (get_unsigned(&uval, *argv, 0)<0) {
175 fprintf(stderr, "invalid value of \"okey\"\n");
181 } else if (!matches(*argv, "seq")) {
184 } else if (!matches(*argv, "iseq")) {
186 } else if (!matches(*argv, "oseq")) {
188 } else if (!matches(*argv, "csum")) {
191 } else if (!matches(*argv, "icsum")) {
193 } else if (!matches(*argv, "ocsum")) {
195 } else if (!matches(*argv, "nopmtudisc")) {
197 } else if (!matches(*argv, "pmtudisc")) {
199 } else if (!matches(*argv, "remote")) {
201 if (strcmp(*argv, "any"))
202 daddr = get_addr32(*argv);
203 } else if (!matches(*argv, "local")) {
205 if (strcmp(*argv, "any"))
206 saddr = get_addr32(*argv);
207 } else if (!matches(*argv, "dev")) {
209 link = if_nametoindex(*argv);
212 } else if (!matches(*argv, "ttl") ||
213 !matches(*argv, "hoplimit")) {
217 if (strcmp(*argv, "inherit") != 0) {
218 if (get_unsigned(&uval, *argv, 0))
219 invarg("invalid TTL\n", *argv);
221 invarg("TTL must be <= 255\n", *argv);
224 } else if (!matches(*argv, "tos") ||
225 !matches(*argv, "tclass") ||
226 !matches(*argv, "dsfield")) {
230 if (strcmp(*argv, "inherit") != 0) {
231 if (rtnl_dsfield_a2n(&uval, *argv))
232 invarg("bad TOS value", *argv);
241 if (!ikey && IN_MULTICAST(ntohl(daddr))) {
245 if (!okey && IN_MULTICAST(ntohl(daddr))) {
249 if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
250 fprintf(stderr, "Broadcast tunnel requires a source address.\n");
254 addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
255 addattr32(n, 1024, IFLA_GRE_OKEY, okey);
256 addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
257 addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
258 addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
259 addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
260 addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
262 addattr32(n, 1024, IFLA_GRE_LINK, link);
263 addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
264 addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
269 static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
273 const char *local = "any";
274 const char *remote = "any";
281 if (tb[IFLA_GRE_REMOTE]) {
282 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_REMOTE]);
285 remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
288 fprintf(f, "remote %s ", remote);
290 if (tb[IFLA_GRE_LOCAL]) {
291 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LOCAL]);
294 local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
297 fprintf(f, "local %s ", local);
299 if (tb[IFLA_GRE_LINK] && *(__u32 *)RTA_DATA(tb[IFLA_GRE_LINK])) {
300 unsigned link = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LINK]);
301 const char *n = if_indextoname(link, s2);
304 fprintf(f, "dev %s ", n);
306 fprintf(f, "dev %u ", link);
309 if (tb[IFLA_GRE_TTL] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TTL]))
310 fprintf(f, "ttl %d ", *(__u8 *)RTA_DATA(tb[IFLA_GRE_TTL]));
312 fprintf(f, "ttl inherit ");
314 if (tb[IFLA_GRE_TOS] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS])) {
315 int tos = *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS]);
319 fputs("inherit ", f);
321 fprintf(f, "0x%x ", tos);
324 if (tb[IFLA_GRE_PMTUDISC] &&
325 !*(__u8 *)RTA_DATA(tb[IFLA_GRE_PMTUDISC]))
326 fputs("nopmtudisc ", f);
328 if (tb[IFLA_GRE_IFLAGS])
329 iflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_IFLAGS]);
331 if (tb[IFLA_GRE_OFLAGS])
332 oflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_OFLAGS]);
334 if (iflags & GRE_KEY && tb[IFLA_GRE_IKEY] &&
335 *(__u32 *)RTA_DATA(tb[IFLA_GRE_IKEY])) {
336 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
337 fprintf(f, "ikey %s ", s2);
340 if (oflags & GRE_KEY && tb[IFLA_GRE_OKEY] &&
341 *(__u32 *)RTA_DATA(tb[IFLA_GRE_OKEY])) {
342 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
343 fprintf(f, "ikey %s ", s2);
346 if (iflags & GRE_SEQ)
348 if (oflags & GRE_SEQ)
350 if (iflags & GRE_CSUM)
352 if (oflags & GRE_CSUM)
356 struct link_util gre_link_util = {
358 .maxattr = IFLA_GRE_MAX,
359 .parse_opt = gre_parse_opt,
360 .print_opt = gre_print_opt,
363 struct link_util gretap_link_util = {
365 .maxattr = IFLA_GRE_MAX,
366 .parse_opt = gre_parse_opt,
367 .print_opt = gre_print_opt,