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,
52 if (!matches(*argv, "key")) {
58 if (strchr(*argv, '.'))
59 uval = get_addr32(*argv);
61 if (get_unsigned(&uval, *argv, 0) < 0) {
63 "Invalid value for \"key\"\n");
70 } else if (!matches(*argv, "ikey")) {
75 if (strchr(*argv, '.'))
76 uval = get_addr32(*argv);
78 if (get_unsigned(&uval, *argv, 0)<0) {
79 fprintf(stderr, "invalid value of \"ikey\"\n");
85 } else if (!matches(*argv, "okey")) {
90 if (strchr(*argv, '.'))
91 uval = get_addr32(*argv);
93 if (get_unsigned(&uval, *argv, 0)<0) {
94 fprintf(stderr, "invalid value of \"okey\"\n");
100 } else if (!matches(*argv, "seq")) {
103 } else if (!matches(*argv, "iseq")) {
105 } else if (!matches(*argv, "oseq")) {
107 } else if (!matches(*argv, "csum")) {
110 } else if (!matches(*argv, "icsum")) {
112 } else if (!matches(*argv, "ocsum")) {
114 } else if (!matches(*argv, "nopmtudisc")) {
117 addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &val, 1);
118 } else if (!matches(*argv, "pmtudisc")) {
121 addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &val, 1);
122 } else if (!matches(*argv, "remote")) {
124 if (strcmp(*argv, "any"))
125 daddr = get_addr32(*argv);
126 } else if (!matches(*argv, "local")) {
128 if (strcmp(*argv, "any"))
129 saddr = get_addr32(*argv);
130 } else if (!matches(*argv, "dev")) {
134 link = tnl_ioctl_get_ifindex(*argv);
138 addattr32(n, 1024, IFLA_GRE_LINK, link);
139 } else if (!matches(*argv, "ttl") ||
140 !matches(*argv, "hoplimit")) {
145 if (strcmp(*argv, "inherit") != 0) {
146 if (get_unsigned(&uval, *argv, 0))
147 invarg("invalid TTL\n", *argv);
149 invarg("TTL must be <= 255\n", *argv);
151 addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
153 } else if (!matches(*argv, "tos") ||
154 !matches(*argv, "tclass") ||
155 !matches(*argv, "dsfield")) {
160 if (strcmp(*argv, "inherit") != 0) {
161 if (rtnl_dsfield_a2n(&uval, *argv))
162 invarg("bad TOS value", *argv);
166 addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
172 if (!ikey && IN_MULTICAST(ntohl(daddr))) {
176 if (!okey && IN_MULTICAST(ntohl(daddr))) {
180 if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
181 fprintf(stderr, "Broadcast tunnel requires a source address.\n");
185 addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
186 addattr32(n, 1024, IFLA_GRE_OKEY, okey);
187 addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
188 addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
189 addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
190 addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
195 static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
199 const char *local = "any";
200 const char *remote = "any";
207 if (tb[IFLA_GRE_REMOTE]) {
208 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_REMOTE]);
211 remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
214 fprintf(f, "remote %s ", remote);
216 if (tb[IFLA_GRE_LOCAL]) {
217 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LOCAL]);
220 local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
223 fprintf(f, "local %s ", local);
225 if (tb[IFLA_GRE_LINK] && *(__u32 *)RTA_DATA(tb[IFLA_GRE_LINK])) {
226 unsigned link = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LINK]);
227 char *n = tnl_ioctl_get_ifname(link);
230 fprintf(f, "dev %s ", n);
232 fprintf(f, "dev %u ", link);
235 if (tb[IFLA_GRE_TTL] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TTL]))
236 fprintf(f, "ttl %d ", *(__u8 *)RTA_DATA(tb[IFLA_GRE_TTL]));
238 fprintf(f, "ttl inherit ");
240 if (tb[IFLA_GRE_TOS] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS])) {
241 int tos = *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS]);
245 fputs("inherit ", f);
247 fprintf(f, "0x%x ", tos);
250 if (tb[IFLA_GRE_PMTUDISC] &&
251 !*(__u8 *)RTA_DATA(tb[IFLA_GRE_PMTUDISC]))
252 fputs("nopmtudisc ", f);
254 if (tb[IFLA_GRE_IFLAGS])
255 iflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_IFLAGS]);
257 if (tb[IFLA_GRE_OFLAGS])
258 oflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_OFLAGS]);
260 if (iflags & GRE_KEY && tb[IFLA_GRE_IKEY] &&
261 *(__u32 *)RTA_DATA(tb[IFLA_GRE_IKEY])) {
262 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
263 fprintf(f, "ikey %s ", s2);
266 if (oflags & GRE_KEY && tb[IFLA_GRE_OKEY] &&
267 *(__u32 *)RTA_DATA(tb[IFLA_GRE_OKEY])) {
268 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
269 fprintf(f, "ikey %s ", s2);
272 if (iflags & GRE_SEQ)
274 if (oflags & GRE_SEQ)
276 if (iflags & GRE_CSUM)
278 if (oflags & GRE_CSUM)
282 struct link_util gre_link_util = {
284 .maxattr = IFLA_GRE_MAX,
285 .parse_opt = gre_parse_opt,
286 .print_opt = gre_print_opt,
289 struct link_util gretap_link_util = {
291 .maxattr = IFLA_GRE_MAX,
292 .parse_opt = gre_parse_opt,
293 .print_opt = gre_print_opt,