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