]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/link_gre.c
tests: Check existing of /proc/config.gz before use it
[mirror_iproute2.git] / ip / link_gre.c
CommitLineData
237d9e82
HX
1/*
2 * link_gre.c gre driver module
3 *
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.
8 *
9 * Authors: Herbert Xu <herbert@gondor.apana.org.au>
10 *
11 */
12
13#include <string.h>
14#include <net/if.h>
237d9e82
HX
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <arpa/inet.h>
18
1957a322
SH
19#include <linux/ip.h>
20#include <linux/if_tunnel.h>
237d9e82
HX
21#include "rt_names.h"
22#include "utils.h"
23#include "ip_common.h"
24#include "tunnel.h"
25
26static void usage(void) __attribute__((noreturn));
27static void usage(void)
28{
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");
39 exit(-1);
40}
41
42static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
43 struct nlmsghdr *n)
44{
72c771b2
HX
45 struct {
46 struct nlmsghdr n;
47 struct ifinfomsg i;
48 char buf[1024];
49 } req;
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];
237d9e82
HX
54 __u16 iflags = 0;
55 __u16 oflags = 0;
56 unsigned ikey = 0;
57 unsigned okey = 0;
58 unsigned saddr = 0;
59 unsigned daddr = 0;
72c771b2
HX
60 unsigned link = 0;
61 __u8 pmtudisc = 1;
62 __u8 ttl = 0;
63 __u8 tos = 0;
64 int len;
65
66 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
67 memset(&req, 0, sizeof(req));
68
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;
74
cd70f3f5 75 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
72c771b2
HX
76get_failed:
77 fprintf(stderr,
78 "Failed to get existing tunnel info.\n");
79 return -1;
80 }
81
82 len = req.n.nlmsg_len;
83 len -= NLMSG_LENGTH(sizeof(*ifi));
84 if (len < 0)
85 goto get_failed;
86
87 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
88
89 if (!tb[IFLA_LINKINFO])
90 goto get_failed;
91
92 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
93
94 if (!linkinfo[IFLA_INFO_DATA])
95 goto get_failed;
96
97 parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
98 linkinfo[IFLA_INFO_DATA]);
99
100 if (greinfo[IFLA_GRE_IKEY])
ff24746c 101 ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]);
72c771b2
HX
102
103 if (greinfo[IFLA_GRE_OKEY])
ff24746c 104 okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]);
72c771b2
HX
105
106 if (greinfo[IFLA_GRE_IFLAGS])
ff24746c 107 iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]);
72c771b2
HX
108
109 if (greinfo[IFLA_GRE_OFLAGS])
ff24746c 110 oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]);
72c771b2
HX
111
112 if (greinfo[IFLA_GRE_LOCAL])
ff24746c 113 saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]);
72c771b2
HX
114
115 if (greinfo[IFLA_GRE_REMOTE])
ff24746c 116 daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]);
72c771b2
HX
117
118 if (greinfo[IFLA_GRE_PMTUDISC])
ff24746c 119 pmtudisc = rta_getattr_u8(
72c771b2
HX
120 greinfo[IFLA_GRE_PMTUDISC]);
121
122 if (greinfo[IFLA_GRE_TTL])
ff24746c 123 ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]);
72c771b2
HX
124
125 if (greinfo[IFLA_GRE_TOS])
ff24746c 126 tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]);
72c771b2
HX
127
128 if (greinfo[IFLA_GRE_LINK])
ff24746c 129 link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]);
72c771b2 130 }
237d9e82
HX
131
132 while (argc > 0) {
133 if (!matches(*argv, "key")) {
134 unsigned uval;
135
136 NEXT_ARG();
137 iflags |= GRE_KEY;
138 oflags |= GRE_KEY;
139 if (strchr(*argv, '.'))
140 uval = get_addr32(*argv);
141 else {
142 if (get_unsigned(&uval, *argv, 0) < 0) {
143 fprintf(stderr,
14645ec2 144 "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
237d9e82
HX
145 exit(-1);
146 }
147 uval = htonl(uval);
148 }
149
150 ikey = okey = uval;
151 } else if (!matches(*argv, "ikey")) {
152 unsigned uval;
153
154 NEXT_ARG();
155 iflags |= GRE_KEY;
156 if (strchr(*argv, '.'))
157 uval = get_addr32(*argv);
158 else {
159 if (get_unsigned(&uval, *argv, 0)<0) {
14645ec2 160 fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
237d9e82
HX
161 exit(-1);
162 }
163 uval = htonl(uval);
164 }
165 ikey = uval;
166 } else if (!matches(*argv, "okey")) {
167 unsigned uval;
168
169 NEXT_ARG();
170 oflags |= GRE_KEY;
171 if (strchr(*argv, '.'))
172 uval = get_addr32(*argv);
173 else {
174 if (get_unsigned(&uval, *argv, 0)<0) {
14645ec2 175 fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
237d9e82
HX
176 exit(-1);
177 }
178 uval = htonl(uval);
179 }
180 okey = uval;
181 } else if (!matches(*argv, "seq")) {
182 iflags |= GRE_SEQ;
183 oflags |= GRE_SEQ;
184 } else if (!matches(*argv, "iseq")) {
185 iflags |= GRE_SEQ;
186 } else if (!matches(*argv, "oseq")) {
187 oflags |= GRE_SEQ;
188 } else if (!matches(*argv, "csum")) {
189 iflags |= GRE_CSUM;
190 oflags |= GRE_CSUM;
191 } else if (!matches(*argv, "icsum")) {
192 iflags |= GRE_CSUM;
193 } else if (!matches(*argv, "ocsum")) {
194 oflags |= GRE_CSUM;
195 } else if (!matches(*argv, "nopmtudisc")) {
72c771b2 196 pmtudisc = 0;
237d9e82 197 } else if (!matches(*argv, "pmtudisc")) {
72c771b2 198 pmtudisc = 1;
237d9e82
HX
199 } else if (!matches(*argv, "remote")) {
200 NEXT_ARG();
201 if (strcmp(*argv, "any"))
202 daddr = get_addr32(*argv);
203 } else if (!matches(*argv, "local")) {
204 NEXT_ARG();
205 if (strcmp(*argv, "any"))
206 saddr = get_addr32(*argv);
207 } else if (!matches(*argv, "dev")) {
237d9e82 208 NEXT_ARG();
ea71beac 209 link = if_nametoindex(*argv);
0cb6bb51
CW
210 if (link == 0) {
211 fprintf(stderr, "Cannot find device \"%s\"\n",
212 *argv);
237d9e82 213 exit(-1);
0cb6bb51 214 }
237d9e82
HX
215 } else if (!matches(*argv, "ttl") ||
216 !matches(*argv, "hoplimit")) {
217 unsigned uval;
237d9e82
HX
218
219 NEXT_ARG();
220 if (strcmp(*argv, "inherit") != 0) {
221 if (get_unsigned(&uval, *argv, 0))
222 invarg("invalid TTL\n", *argv);
223 if (uval > 255)
224 invarg("TTL must be <= 255\n", *argv);
225 ttl = uval;
237d9e82
HX
226 }
227 } else if (!matches(*argv, "tos") ||
228 !matches(*argv, "tclass") ||
229 !matches(*argv, "dsfield")) {
230 __u32 uval;
237d9e82
HX
231
232 NEXT_ARG();
233 if (strcmp(*argv, "inherit") != 0) {
234 if (rtnl_dsfield_a2n(&uval, *argv))
235 invarg("bad TOS value", *argv);
236 tos = uval;
237 } else
238 tos = 1;
0612519e 239 } else
237d9e82
HX
240 usage();
241 argc--; argv++;
242 }
243
244 if (!ikey && IN_MULTICAST(ntohl(daddr))) {
245 ikey = daddr;
246 iflags |= GRE_KEY;
247 }
248 if (!okey && IN_MULTICAST(ntohl(daddr))) {
249 okey = daddr;
250 oflags |= GRE_KEY;
251 }
252 if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
14645ec2 253 fprintf(stderr, "A broadcast tunnel requires a source address.\n");
237d9e82
HX
254 return -1;
255 }
256
257 addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
258 addattr32(n, 1024, IFLA_GRE_OKEY, okey);
259 addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
260 addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
261 addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
262 addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
72c771b2
HX
263 addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
264 if (link)
265 addattr32(n, 1024, IFLA_GRE_LINK, link);
266 addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
267 addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
237d9e82
HX
268
269 return 0;
270}
271
272static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
273{
274 char s1[1024];
275 char s2[64];
276 const char *local = "any";
277 const char *remote = "any";
278 unsigned iflags = 0;
279 unsigned oflags = 0;
280
281 if (!tb)
282 return;
283
284 if (tb[IFLA_GRE_REMOTE]) {
ff24746c 285 unsigned addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]);
237d9e82
HX
286
287 if (addr)
288 remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
289 }
290
291 fprintf(f, "remote %s ", remote);
292
293 if (tb[IFLA_GRE_LOCAL]) {
ff24746c 294 unsigned addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]);
237d9e82
HX
295
296 if (addr)
297 local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
298 }
299
300 fprintf(f, "local %s ", local);
301
ff24746c
SH
302 if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) {
303 unsigned link = rta_getattr_u32(tb[IFLA_GRE_LINK]);
ea71beac 304 const char *n = if_indextoname(link, s2);
237d9e82
HX
305
306 if (n)
307 fprintf(f, "dev %s ", n);
308 else
309 fprintf(f, "dev %u ", link);
310 }
311
ff24746c
SH
312 if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL]))
313 fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_GRE_TTL]));
237d9e82
HX
314 else
315 fprintf(f, "ttl inherit ");
316
ff24746c
SH
317 if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) {
318 int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]);
237d9e82
HX
319
320 fputs("tos ", f);
321 if (tos == 1)
322 fputs("inherit ", f);
323 else
324 fprintf(f, "0x%x ", tos);
325 }
326
327 if (tb[IFLA_GRE_PMTUDISC] &&
ff24746c 328 !rta_getattr_u8(tb[IFLA_GRE_PMTUDISC]))
237d9e82
HX
329 fputs("nopmtudisc ", f);
330
331 if (tb[IFLA_GRE_IFLAGS])
ff24746c 332 iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]);
237d9e82
HX
333
334 if (tb[IFLA_GRE_OFLAGS])
ff24746c 335 oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]);
237d9e82 336
71816553 337 if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) {
237d9e82
HX
338 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
339 fprintf(f, "ikey %s ", s2);
340 }
341
71816553 342 if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) {
237d9e82 343 inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
71816553 344 fprintf(f, "okey %s ", s2);
237d9e82
HX
345 }
346
347 if (iflags & GRE_SEQ)
348 fputs("iseq ", f);
349 if (oflags & GRE_SEQ)
350 fputs("oseq ", f);
351 if (iflags & GRE_CSUM)
352 fputs("icsum ", f);
353 if (oflags & GRE_CSUM)
354 fputs("ocsum ", f);
355}
356
357struct link_util gre_link_util = {
358 .id = "gre",
359 .maxattr = IFLA_GRE_MAX,
360 .parse_opt = gre_parse_opt,
361 .print_opt = gre_print_opt,
362};
363
364struct link_util gretap_link_util = {
365 .id = "gretap",
366 .maxattr = IFLA_GRE_MAX,
367 .parse_opt = gre_parse_opt,
368 .print_opt = gre_print_opt,
369};