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 = tnl_ioctl_get_ifindex(*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
char *n = tnl_ioctl_get_ifname(link);
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,