]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/tunnel.c
Merge pull request #16145 from poettering/qrcode-dlopen
[thirdparty/systemd.git] / src / network / netdev / tunnel.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <netinet/in.h>
4 #include <linux/fou.h>
5 #include <linux/ip.h>
6 #include <linux/if_tunnel.h>
7 #include <linux/ip6_tunnel.h>
8
9 #include "conf-parser.h"
10 #include "missing_network.h"
11 #include "netlink-util.h"
12 #include "parse-util.h"
13 #include "string-table.h"
14 #include "string-util.h"
15 #include "tunnel.h"
16 #include "util.h"
17
18 #define DEFAULT_TNL_HOP_LIMIT 64
19 #define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
20 #define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
21
22 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
23 [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
24 [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
25 [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
26 };
27
28 DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
29 DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
30
31 static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
32 Tunnel *t;
33 int r;
34
35 assert(netdev);
36
37 if (netdev->kind == NETDEV_KIND_IPIP)
38 t = IPIP(netdev);
39 else
40 t = SIT(netdev);
41
42 assert(m);
43 assert(t);
44
45 if (link || t->assign_to_loopback) {
46 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
47 if (r < 0)
48 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
49 }
50
51 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
52 if (r < 0)
53 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
54
55 r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
56 if (r < 0)
57 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
58
59 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
60 if (r < 0)
61 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
62
63 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
64 if (r < 0)
65 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
66
67 if (t->fou_tunnel) {
68 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_TYPE, t->fou_encap_type);
69 if (r < 0)
70 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_TYPE attribute: %m");
71
72 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_SPORT, htobe16(t->encap_src_port));
73 if (r < 0)
74 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_SPORT attribute: %m");
75
76 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_DPORT, htobe16(t->fou_destination_port));
77 if (r < 0)
78 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_DPORT attribute: %m");
79 }
80
81 if (netdev->kind == NETDEV_KIND_SIT) {
82 if (t->sixrd_prefixlen > 0) {
83 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &t->sixrd_prefix);
84 if (r < 0)
85 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m");
86
87 /* u16 is deliberate here, even though we're passing a netmask that can never be >128. The kernel is
88 * expecting to receive the prefixlen as a u16.
89 */
90 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, t->sixrd_prefixlen);
91 if (r < 0)
92 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m");
93 }
94
95 if (t->isatap >= 0) {
96 uint16_t flags = 0;
97
98 SET_FLAG(flags, SIT_ISATAP, t->isatap);
99
100 r = sd_netlink_message_append_u16(m, IFLA_IPTUN_FLAGS, flags);
101 if (r < 0)
102 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
103 }
104 }
105
106 return r;
107 }
108
109 static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
110 uint32_t ikey = 0;
111 uint32_t okey = 0;
112 uint16_t iflags = 0;
113 uint16_t oflags = 0;
114 Tunnel *t;
115 int r;
116
117 assert(netdev);
118 assert(m);
119
120 switch (netdev->kind) {
121 case NETDEV_KIND_GRE:
122 t = GRE(netdev);
123 break;
124 case NETDEV_KIND_ERSPAN:
125 t = ERSPAN(netdev);
126 break;
127 case NETDEV_KIND_GRETAP:
128 t = GRETAP(netdev);
129 break;
130 default:
131 assert_not_reached("invalid netdev kind");
132 }
133
134 assert(t);
135
136 if (link || t->assign_to_loopback) {
137 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
138 if (r < 0)
139 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
140 }
141
142 if (netdev->kind == NETDEV_KIND_ERSPAN) {
143 r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index);
144 if (r < 0)
145 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ERSPAN_INDEX attribute: %m");
146 }
147
148 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
149 if (r < 0)
150 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
151
152 r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
153 if (r < 0)
154 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
155
156 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
157 if (r < 0)
158 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
159
160 r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos);
161 if (r < 0)
162 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m");
163
164 r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
165 if (r < 0)
166 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
167
168 if (t->key != 0) {
169 ikey = okey = htobe32(t->key);
170 iflags |= GRE_KEY;
171 oflags |= GRE_KEY;
172 }
173
174 if (t->ikey != 0) {
175 ikey = htobe32(t->ikey);
176 iflags |= GRE_KEY;
177 }
178
179 if (t->okey != 0) {
180 okey = htobe32(t->okey);
181 oflags |= GRE_KEY;
182 }
183
184 if (t->gre_erspan_sequence > 0) {
185 iflags |= GRE_SEQ;
186 oflags |= GRE_SEQ;
187 } else if (t->gre_erspan_sequence == 0) {
188 iflags &= ~GRE_SEQ;
189 oflags &= ~GRE_SEQ;
190 }
191
192 r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey);
193 if (r < 0)
194 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IKEY attribute: %m");
195
196 r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey);
197 if (r < 0)
198 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OKEY attribute: %m");
199
200 r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags);
201 if (r < 0)
202 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IFLAGS attribute: %m");
203
204 r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags);
205 if (r < 0)
206 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m");
207
208 if (t->fou_tunnel) {
209 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_TYPE, t->fou_encap_type);
210 if (r < 0)
211 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_TYPE attribute: %m");
212
213 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_SPORT, htobe16(t->encap_src_port));
214 if (r < 0)
215 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_SPORT attribute: %m");
216
217 r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_DPORT, htobe16(t->fou_destination_port));
218 if (r < 0)
219 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_DPORT attribute: %m");
220 }
221
222 return r;
223 }
224
225 static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
226 uint32_t ikey = 0;
227 uint32_t okey = 0;
228 uint16_t iflags = 0;
229 uint16_t oflags = 0;
230 Tunnel *t;
231 int r;
232
233 assert(netdev);
234
235 if (netdev->kind == NETDEV_KIND_IP6GRE)
236 t = IP6GRE(netdev);
237 else
238 t = IP6GRETAP(netdev);
239
240 assert(t);
241 assert(m);
242
243 if (link || t->assign_to_loopback) {
244 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
245 if (r < 0)
246 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
247 }
248
249 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
250 if (r < 0)
251 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
252
253 r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
254 if (r < 0)
255 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
256
257 r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
258 if (r < 0)
259 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
260
261 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
262 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
263 if (r < 0)
264 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
265 }
266
267 r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
268 if (r < 0)
269 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
270
271 if (t->key != 0) {
272 ikey = okey = htobe32(t->key);
273 iflags |= GRE_KEY;
274 oflags |= GRE_KEY;
275 }
276
277 if (t->ikey != 0) {
278 ikey = htobe32(t->ikey);
279 iflags |= GRE_KEY;
280 }
281
282 if (t->okey != 0) {
283 okey = htobe32(t->okey);
284 oflags |= GRE_KEY;
285 }
286
287 r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey);
288 if (r < 0)
289 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IKEY attribute: %m");
290
291 r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey);
292 if (r < 0)
293 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OKEY attribute: %m");
294
295 r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags);
296 if (r < 0)
297 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IFLAGS attribute: %m");
298
299 r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags);
300 if (r < 0)
301 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m");
302
303 return r;
304 }
305
306 static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
307 uint32_t ikey, okey;
308 Tunnel *t;
309 int r;
310
311 assert(netdev);
312 assert(m);
313
314 if (netdev->kind == NETDEV_KIND_VTI)
315 t = VTI(netdev);
316 else
317 t = VTI6(netdev);
318
319 assert(t);
320
321 if (link || t->assign_to_loopback) {
322 r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
323 if (r < 0)
324 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LINK attribute: %m");
325 }
326
327 if (t->key != 0)
328 ikey = okey = htobe32(t->key);
329 else {
330 ikey = htobe32(t->ikey);
331 okey = htobe32(t->okey);
332 }
333
334 r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey);
335 if (r < 0)
336 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m");
337
338 r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey);
339 if (r < 0)
340 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m");
341
342 r = netlink_message_append_in_addr_union(m, IFLA_VTI_LOCAL, t->family, &t->local);
343 if (r < 0)
344 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LOCAL attribute: %m");
345
346 r = netlink_message_append_in_addr_union(m, IFLA_VTI_REMOTE, t->family, &t->remote);
347 if (r < 0)
348 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_REMOTE attribute: %m");
349
350 return r;
351 }
352
353 static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
354 Tunnel *t = IP6TNL(netdev);
355 uint8_t proto;
356 int r;
357
358 assert(netdev);
359 assert(m);
360 assert(t);
361
362 if (link || t->assign_to_loopback) {
363 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
364 if (r < 0)
365 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
366 }
367
368 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
369 if (r < 0)
370 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
371
372 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
373 if (r < 0)
374 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
375
376 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
377 if (r < 0)
378 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
379
380 if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
381 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
382 if (r < 0)
383 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
384 }
385
386 if (t->copy_dscp)
387 t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
388
389 if (t->allow_localremote >= 0)
390 SET_FLAG(t->flags, IP6_TNL_F_ALLOW_LOCAL_REMOTE, t->allow_localremote);
391
392 if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) {
393 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit);
394 if (r < 0)
395 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m");
396 }
397
398 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
399 if (r < 0)
400 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
401
402 switch (t->ip6tnl_mode) {
403 case NETDEV_IP6_TNL_MODE_IP6IP6:
404 proto = IPPROTO_IPV6;
405 break;
406 case NETDEV_IP6_TNL_MODE_IPIP6:
407 proto = IPPROTO_IPIP;
408 break;
409 case NETDEV_IP6_TNL_MODE_ANYIP6:
410 default:
411 proto = 0;
412 break;
413 }
414
415 r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
416 if (r < 0)
417 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PROTO attribute: %m");
418
419 return r;
420 }
421
422 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
423 Tunnel *t = NULL;
424
425 assert(netdev);
426 assert(filename);
427
428 switch (netdev->kind) {
429 case NETDEV_KIND_IPIP:
430 t = IPIP(netdev);
431 break;
432 case NETDEV_KIND_SIT:
433 t = SIT(netdev);
434 break;
435 case NETDEV_KIND_GRE:
436 t = GRE(netdev);
437 break;
438 case NETDEV_KIND_GRETAP:
439 t = GRETAP(netdev);
440 break;
441 case NETDEV_KIND_IP6GRE:
442 t = IP6GRE(netdev);
443 break;
444 case NETDEV_KIND_IP6GRETAP:
445 t = IP6GRETAP(netdev);
446 break;
447 case NETDEV_KIND_VTI:
448 t = VTI(netdev);
449 break;
450 case NETDEV_KIND_VTI6:
451 t = VTI6(netdev);
452 break;
453 case NETDEV_KIND_IP6TNL:
454 t = IP6TNL(netdev);
455 break;
456 case NETDEV_KIND_ERSPAN:
457 t = ERSPAN(netdev);
458 break;
459 default:
460 assert_not_reached("Invalid tunnel kind");
461 }
462
463 assert(t);
464
465 if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_SIT, NETDEV_KIND_GRE) &&
466 !IN_SET(t->family, AF_UNSPEC, AF_INET))
467 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
468 "vti/ipip/sit/gre tunnel without a local/remote IPv4 address configured in %s. Ignoring", filename);
469
470 if (IN_SET(netdev->kind, NETDEV_KIND_GRETAP, NETDEV_KIND_ERSPAN) &&
471 (t->family != AF_INET || in_addr_is_null(t->family, &t->remote)))
472 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
473 "gretap/erspan tunnel without a remote IPv4 address configured in %s. Ignoring", filename);
474
475 if ((IN_SET(netdev->kind, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL) && t->family != AF_INET6) ||
476 (netdev->kind == NETDEV_KIND_IP6GRE && !IN_SET(t->family, AF_UNSPEC, AF_INET6)))
477 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
478 "vti6/ip6tnl/ip6gre tunnel without a local/remote IPv6 address configured in %s. Ignoring", filename);
479
480 if (netdev->kind == NETDEV_KIND_IP6GRETAP &&
481 (t->family != AF_INET6 || in_addr_is_null(t->family, &t->remote)))
482 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
483 "ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename);
484
485 if (netdev->kind == NETDEV_KIND_IP6TNL &&
486 t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
487 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
488 "ip6tnl without mode configured in %s. Ignoring", filename);
489
490 if (t->fou_tunnel && t->fou_destination_port <= 0)
491 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
492 "FooOverUDP missing port configured in %s. Ignoring", filename);
493
494 if (netdev->kind == NETDEV_KIND_ERSPAN && (t->erspan_index >= (1 << 20) || t->erspan_index == 0))
495 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Invalid erspan index %d. Ignoring", t->erspan_index);
496
497 /* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */
498 if (netdev->kind == NETDEV_KIND_VTI)
499 t->family = AF_INET;
500
501 return 0;
502 }
503
504 int config_parse_tunnel_address(const char *unit,
505 const char *filename,
506 unsigned line,
507 const char *section,
508 unsigned section_line,
509 const char *lvalue,
510 int ltype,
511 const char *rvalue,
512 void *data,
513 void *userdata) {
514 Tunnel *t = userdata;
515 union in_addr_union *addr = data, buffer;
516 int r, f;
517
518 assert(filename);
519 assert(lvalue);
520 assert(rvalue);
521 assert(data);
522
523 /* This is used to parse addresses on both local and remote ends of the tunnel.
524 * Address families must match.
525 *
526 * "any" is a special value which means that the address is unspecified.
527 */
528
529 if (streq(rvalue, "any")) {
530 *addr = IN_ADDR_NULL;
531
532 /* As a special case, if both the local and remote addresses are
533 * unspecified, also clear the address family.
534 */
535 if (t->family != AF_UNSPEC &&
536 in_addr_is_null(t->family, &t->local) != 0 &&
537 in_addr_is_null(t->family, &t->remote) != 0)
538 t->family = AF_UNSPEC;
539 return 0;
540 }
541
542 r = in_addr_from_string_auto(rvalue, &f, &buffer);
543 if (r < 0) {
544 log_syntax(unit, LOG_WARNING, filename, line, r,
545 "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
546 return 0;
547 }
548
549 if (t->family != AF_UNSPEC && t->family != f) {
550 log_syntax(unit, LOG_WARNING, filename, line, 0,
551 "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
552 return 0;
553 }
554
555 t->family = f;
556 *addr = buffer;
557 return 0;
558 }
559
560 int config_parse_tunnel_key(const char *unit,
561 const char *filename,
562 unsigned line,
563 const char *section,
564 unsigned section_line,
565 const char *lvalue,
566 int ltype,
567 const char *rvalue,
568 void *data,
569 void *userdata) {
570 union in_addr_union buffer;
571 Tunnel *t = userdata;
572 uint32_t k;
573 int r;
574
575 assert(filename);
576 assert(lvalue);
577 assert(rvalue);
578 assert(data);
579
580 r = in_addr_from_string(AF_INET, rvalue, &buffer);
581 if (r < 0) {
582 r = safe_atou32(rvalue, &k);
583 if (r < 0) {
584 log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue);
585 return 0;
586 }
587 } else
588 k = be32toh(buffer.in.s_addr);
589
590 if (streq(lvalue, "Key"))
591 t->key = k;
592 else if (streq(lvalue, "InputKey"))
593 t->ikey = k;
594 else
595 t->okey = k;
596
597 return 0;
598 }
599
600 int config_parse_ipv6_flowlabel(const char* unit,
601 const char *filename,
602 unsigned line,
603 const char *section,
604 unsigned section_line,
605 const char *lvalue,
606 int ltype,
607 const char *rvalue,
608 void *data,
609 void *userdata) {
610 IPv6FlowLabel *ipv6_flowlabel = data;
611 Tunnel *t = userdata;
612 int k = 0;
613 int r;
614
615 assert(filename);
616 assert(lvalue);
617 assert(rvalue);
618 assert(ipv6_flowlabel);
619
620 if (streq(rvalue, "inherit")) {
621 *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
622 t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
623 } else {
624 r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
625 if (r < 0)
626 return r;
627
628 if (k > 0xFFFFF)
629 log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
630 else {
631 *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
632 t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
633 }
634 }
635
636 return 0;
637 }
638
639 int config_parse_encap_limit(const char* unit,
640 const char *filename,
641 unsigned line,
642 const char *section,
643 unsigned section_line,
644 const char *lvalue,
645 int ltype,
646 const char *rvalue,
647 void *data,
648 void *userdata) {
649 Tunnel *t = userdata;
650 int k = 0;
651 int r;
652
653 assert(filename);
654 assert(lvalue);
655 assert(rvalue);
656
657 if (streq(rvalue, "none"))
658 t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
659 else {
660 r = safe_atoi(rvalue, &k);
661 if (r < 0) {
662 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue);
663 return 0;
664 }
665
666 if (k > 255 || k < 0)
667 log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k);
668 else {
669 t->encap_limit = k;
670 t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
671 }
672 }
673
674 return 0;
675 }
676
677 int config_parse_6rd_prefix(const char* unit,
678 const char *filename,
679 unsigned line,
680 const char *section,
681 unsigned section_line,
682 const char *lvalue,
683 int ltype,
684 const char *rvalue,
685 void *data,
686 void *userdata) {
687 Tunnel *t = userdata;
688
689 assert(filename);
690 assert(lvalue);
691 assert(rvalue);
692
693 union in_addr_union p;
694 uint8_t l;
695 int r;
696
697 r = in_addr_prefix_from_string(rvalue, AF_INET6, &p, &l);
698 if (r < 0) {
699 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse 6rd prefix \"%s\", ignoring: %m", rvalue);
700 return 0;
701 }
702 if (l == 0) {
703 log_syntax(unit, LOG_WARNING, filename, line, 0, "6rd prefix length of \"%s\" must be greater than zero, ignoring", rvalue);
704 return 0;
705 }
706
707 t->sixrd_prefix = p.in6;
708 t->sixrd_prefixlen = l;
709
710 return 0;
711 }
712
713 static void ipip_sit_init(NetDev *n) {
714 Tunnel *t;
715
716 assert(n);
717
718 switch (n->kind) {
719 case NETDEV_KIND_IPIP:
720 t = IPIP(n);
721 break;
722 case NETDEV_KIND_SIT:
723 t = SIT(n);
724 break;
725 default:
726 assert_not_reached("invalid netdev kind");
727 }
728
729 assert(t);
730
731 t->pmtudisc = true;
732 t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT;
733 t->isatap = -1;
734 }
735
736 static void vti_init(NetDev *n) {
737 Tunnel *t;
738
739 assert(n);
740
741 if (n->kind == NETDEV_KIND_VTI)
742 t = VTI(n);
743 else
744 t = VTI6(n);
745
746 assert(t);
747
748 t->pmtudisc = true;
749 }
750
751 static void gre_erspan_init(NetDev *n) {
752 Tunnel *t;
753
754 assert(n);
755
756 switch (n->kind) {
757 case NETDEV_KIND_GRE:
758 t = GRE(n);
759 break;
760 case NETDEV_KIND_ERSPAN:
761 t = ERSPAN(n);
762 break;
763 case NETDEV_KIND_GRETAP:
764 t = GRETAP(n);
765 break;
766 default:
767 assert_not_reached("invalid netdev kind");
768 }
769
770 assert(t);
771
772 t->pmtudisc = true;
773 t->gre_erspan_sequence = -1;
774 t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT;
775 }
776
777 static void ip6gre_init(NetDev *n) {
778 Tunnel *t;
779
780 assert(n);
781
782 if (n->kind == NETDEV_KIND_IP6GRE)
783 t = IP6GRE(n);
784 else
785 t = IP6GRETAP(n);
786
787 assert(t);
788
789 t->ttl = DEFAULT_TNL_HOP_LIMIT;
790 }
791
792 static void ip6tnl_init(NetDev *n) {
793 Tunnel *t = IP6TNL(n);
794
795 assert(n);
796 assert(t);
797
798 t->ttl = DEFAULT_TNL_HOP_LIMIT;
799 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
800 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
801 t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
802 t->allow_localremote = -1;
803 }
804
805 const NetDevVTable ipip_vtable = {
806 .object_size = sizeof(Tunnel),
807 .init = ipip_sit_init,
808 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
809 .fill_message_create = netdev_ipip_sit_fill_message_create,
810 .create_type = NETDEV_CREATE_STACKED,
811 .config_verify = netdev_tunnel_verify,
812 .generate_mac = true,
813 };
814
815 const NetDevVTable sit_vtable = {
816 .object_size = sizeof(Tunnel),
817 .init = ipip_sit_init,
818 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
819 .fill_message_create = netdev_ipip_sit_fill_message_create,
820 .create_type = NETDEV_CREATE_STACKED,
821 .config_verify = netdev_tunnel_verify,
822 .generate_mac = true,
823 };
824
825 const NetDevVTable vti_vtable = {
826 .object_size = sizeof(Tunnel),
827 .init = vti_init,
828 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
829 .fill_message_create = netdev_vti_fill_message_create,
830 .create_type = NETDEV_CREATE_STACKED,
831 .config_verify = netdev_tunnel_verify,
832 .generate_mac = true,
833 };
834
835 const NetDevVTable vti6_vtable = {
836 .object_size = sizeof(Tunnel),
837 .init = vti_init,
838 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
839 .fill_message_create = netdev_vti_fill_message_create,
840 .create_type = NETDEV_CREATE_STACKED,
841 .config_verify = netdev_tunnel_verify,
842 .generate_mac = true,
843 };
844
845 const NetDevVTable gre_vtable = {
846 .object_size = sizeof(Tunnel),
847 .init = gre_erspan_init,
848 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
849 .fill_message_create = netdev_gre_erspan_fill_message_create,
850 .create_type = NETDEV_CREATE_STACKED,
851 .config_verify = netdev_tunnel_verify,
852 .generate_mac = true,
853 };
854
855 const NetDevVTable gretap_vtable = {
856 .object_size = sizeof(Tunnel),
857 .init = gre_erspan_init,
858 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
859 .fill_message_create = netdev_gre_erspan_fill_message_create,
860 .create_type = NETDEV_CREATE_STACKED,
861 .config_verify = netdev_tunnel_verify,
862 .generate_mac = true,
863 };
864
865 const NetDevVTable ip6gre_vtable = {
866 .object_size = sizeof(Tunnel),
867 .init = ip6gre_init,
868 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
869 .fill_message_create = netdev_ip6gre_fill_message_create,
870 .create_type = NETDEV_CREATE_STACKED,
871 .config_verify = netdev_tunnel_verify,
872 .generate_mac = true,
873 };
874
875 const NetDevVTable ip6gretap_vtable = {
876 .object_size = sizeof(Tunnel),
877 .init = ip6gre_init,
878 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
879 .fill_message_create = netdev_ip6gre_fill_message_create,
880 .create_type = NETDEV_CREATE_STACKED,
881 .config_verify = netdev_tunnel_verify,
882 .generate_mac = true,
883 };
884
885 const NetDevVTable ip6tnl_vtable = {
886 .object_size = sizeof(Tunnel),
887 .init = ip6tnl_init,
888 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
889 .fill_message_create = netdev_ip6tnl_fill_message_create,
890 .create_type = NETDEV_CREATE_STACKED,
891 .config_verify = netdev_tunnel_verify,
892 .generate_mac = true,
893 };
894
895 const NetDevVTable erspan_vtable = {
896 .object_size = sizeof(Tunnel),
897 .init = gre_erspan_init,
898 .sections = NETDEV_COMMON_SECTIONS "Tunnel\0",
899 .fill_message_create = netdev_gre_erspan_fill_message_create,
900 .create_type = NETDEV_CREATE_STACKED,
901 .config_verify = netdev_tunnel_verify,
902 .generate_mac = true,
903 };