]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-netdev-tunnel.c
man: document when the various sd-login.h calls return ENXIO
[thirdparty/systemd.git] / src / network / networkd-netdev-tunnel.c
CommitLineData
7951dea2
SS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
855ee1a1 6 Copyright 2014 Susant Sahani
7951dea2
SS
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
7951dea2
SS
22#include <arpa/inet.h>
23#include <net/if.h>
24#include <linux/ip.h>
25#include <linux/if_tunnel.h>
855ee1a1 26#include <linux/ip6_tunnel.h>
7951dea2
SS
27
28#include "sd-rtnl.h"
3be1d7e0 29#include "networkd-netdev-tunnel.h"
0b1831c2 30#include "networkd-link.h"
7951dea2 31#include "util.h"
81577dc2 32#include "missing.h"
6ef892fc 33#include "conf-parser.h"
7951dea2 34
855ee1a1
SS
35#define DEFAULT_TNL_HOP_LIMIT 64
36
37static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
38 [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
73b23bea 39 [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6",
855ee1a1
SS
40 [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
41};
42
43DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
44DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
45
3be1d7e0 46static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
aa9f1140 47 Tunnel *t = IPIP(netdev);
7951dea2
SS
48 int r;
49
3be1d7e0 50 assert(netdev);
7951dea2 51 assert(link);
7951dea2 52 assert(m);
aa9f1140
TG
53 assert(t);
54 assert(t->family == AF_INET);
7951dea2
SS
55
56 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
57 if (r < 0) {
79008bdd 58 log_netdev_error(netdev,
7951dea2
SS
59 "Could not append IFLA_IPTUN_LINK attribute: %s",
60 strerror(-r));
61 return r;
62 }
63
aa9f1140 64 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
7951dea2 65 if (r < 0) {
79008bdd 66 log_netdev_error(netdev,
7951dea2
SS
67 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
68 strerror(-r));
69 return r;
70 }
71
aa9f1140 72 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
7951dea2 73 if (r < 0) {
79008bdd 74 log_netdev_error(netdev,
7951dea2
SS
75 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
76 strerror(-r));
77 return r;
78 }
79
aa9f1140 80 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
9ae70211 81 if (r < 0) {
79008bdd 82 log_netdev_error(netdev,
9ae70211
SS
83 "Could not append IFLA_IPTUN_TTL attribute: %s",
84 strerror(-r));
85 return r;
86 }
87
9243e967
SS
88 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
89 if (r < 0) {
79008bdd 90 log_netdev_error(netdev,
9243e967
SS
91 "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
92 strerror(-r));
93 return r;
94 }
95
7951dea2
SS
96 return r;
97}
98
3be1d7e0 99static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
aa9f1140 100 Tunnel *t = SIT(netdev);
abf446af
SS
101 int r;
102
3be1d7e0 103 assert(netdev);
abf446af 104 assert(link);
abf446af 105 assert(m);
aa9f1140
TG
106 assert(t);
107 assert(t->family == AF_INET);
abf446af
SS
108
109 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
110 if (r < 0) {
79008bdd 111 log_netdev_error(netdev,
abf446af
SS
112 "Could not append IFLA_IPTUN_LINK attribute: %s",
113 strerror(-r));
114 return r;
115 }
116
aa9f1140 117 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
abf446af 118 if (r < 0) {
79008bdd 119 log_netdev_error(netdev,
abf446af
SS
120 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
121 strerror(-r));
122 return r;
123 }
124
aa9f1140 125 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
abf446af 126 if (r < 0) {
79008bdd 127 log_netdev_error(netdev,
abf446af
SS
128 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
129 strerror(-r));
130 return r;
131 }
132
aa9f1140 133 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
a9f434cf 134 if (r < 0) {
79008bdd 135 log_netdev_error(netdev,
6436165d 136 "Could not append IFLA_IPTUN_TTL attribute: %s",
a9f434cf
SS
137 strerror(-r));
138 return r;
139 }
140
436b910f
SS
141 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
142 if (r < 0) {
79008bdd 143 log_netdev_error(netdev,
436b910f
SS
144 "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
145 strerror(-r));
146 return r;
147 }
148
abf446af
SS
149 return r;
150}
151
3be1d7e0 152static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
1af2536a 153 Tunnel *t;
8bb088c5
SS
154 int r;
155
3be1d7e0 156 assert(netdev);
1af2536a
SS
157
158 if (netdev->kind == NETDEV_KIND_GRE)
159 t = GRE(netdev);
160 else
161 t = GRETAP(netdev);
162
aa9f1140
TG
163 assert(t);
164 assert(t->family == AF_INET);
1af2536a
SS
165 assert(link);
166 assert(m);
8bb088c5
SS
167
168 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
169 if (r < 0) {
79008bdd 170 log_netdev_error(netdev,
8bb088c5
SS
171 "Could not append IFLA_GRE_LINK attribute: %s",
172 strerror(-r));
173 return r;
174 }
175
aa9f1140 176 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
8bb088c5 177 if (r < 0) {
79008bdd 178 log_netdev_error(netdev,
8bb088c5
SS
179 "Could not append IFLA_GRE_LOCAL attribute: %s",
180 strerror(-r));
181 return r;
182 }
183
aa9f1140 184 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
8bb088c5 185 if (r < 0) {
79008bdd 186 log_netdev_error(netdev,
8bb088c5
SS
187 "Could not append IFLA_GRE_REMOTE attribute: %s",
188 strerror(-r));
189 return r;
190 }
191
aa9f1140 192 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
8bb088c5 193 if (r < 0) {
79008bdd 194 log_netdev_error(netdev,
8bb088c5
SS
195 "Could not append IFLA_GRE_TTL attribute: %s",
196 strerror(-r));
197 return r;
198 }
199
aa9f1140 200 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, t->tos);
8bb088c5 201 if (r < 0) {
79008bdd 202 log_netdev_error(netdev,
8bb088c5
SS
203 "Could not append IFLA_GRE_TOS attribute: %s",
204 strerror(-r));
205 return r;
206 }
207
9243e967
SS
208 r = sd_rtnl_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
209 if (r < 0) {
79008bdd 210 log_netdev_error(netdev,
9243e967
SS
211 "Could not append IFLA_GRE_PMTUDISC attribute: %s",
212 strerror(-r));
213 return r;
214 }
215
8bb088c5
SS
216 return r;
217}
218
b16492f8
SS
219static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
220 Tunnel *t;
221 int r;
222
223 assert(netdev);
224
225 if (netdev->kind == NETDEV_KIND_IP6GRE)
226 t = IP6GRE(netdev);
227 else
228 t = IP6GRETAP(netdev);
229
230 assert(t);
231 assert(t->family == AF_INET6);
232 assert(link);
233 assert(m);
234
235 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
236 if (r < 0) {
237 log_netdev_error(netdev,
238 "Could not append IFLA_GRE_LINK attribute: %s",
239 strerror(-r));
240 return r;
241 }
242
243 r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
244 if (r < 0) {
245 log_netdev_error(netdev,
246 "Could not append IFLA_GRE_LOCAL attribute: %s",
247 strerror(-r));
248 return r;
249 }
250
251 r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
252 if (r < 0) {
253 log_netdev_error(netdev,
254 "Could not append IFLA_GRE_REMOTE attribute: %s",
255 strerror(-r));
256 return r;
257 }
258
259 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
260 if (r < 0) {
261 log_netdev_error(netdev,
262 "Could not append IFLA_GRE_TTL attribute: %s",
263 strerror(-r));
264 return r;
265 }
266
267 return r;
268}
269
3be1d7e0 270static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
aa9f1140 271 Tunnel *t = VTI(netdev);
a613382b
SS
272 int r;
273
3be1d7e0 274 assert(netdev);
a613382b 275 assert(link);
a613382b 276 assert(m);
aa9f1140
TG
277 assert(t);
278 assert(t->family == AF_INET);
a613382b
SS
279
280 r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
281 if (r < 0) {
79008bdd 282 log_netdev_error(netdev,
a613382b
SS
283 "Could not append IFLA_IPTUN_LINK attribute: %s",
284 strerror(-r));
285 return r;
286 }
287
aa9f1140 288 r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
a613382b 289 if (r < 0) {
79008bdd 290 log_netdev_error(netdev,
a613382b
SS
291 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
292 strerror(-r));
293 return r;
294 }
295
aa9f1140 296 r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
a613382b 297 if (r < 0) {
79008bdd 298 log_netdev_error(netdev,
a613382b
SS
299 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
300 strerror(-r));
301 return r;
302 }
303
a613382b
SS
304 return r;
305}
8bb088c5 306
855ee1a1
SS
307static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
308 Tunnel *t = IP6TNL(netdev);
309 uint8_t proto;
310 int r;
311
312 assert(netdev);
313 assert(link);
314 assert(m);
315 assert(t);
316 assert(t->family == AF_INET6);
317
318 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
319 if (r < 0) {
320 log_netdev_error(netdev,
321 "Could not append IFLA_IPTUN_LINK attribute: %s",
322 strerror(-r));
323 return r;
324 }
325
326 r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
327 if (r < 0) {
328 log_netdev_error(netdev,
329 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
330 strerror(-r));
331 return r;
332 }
333
334 r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
335 if (r < 0) {
336 log_netdev_error(netdev,
337 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
338 strerror(-r));
339 return r;
340 }
341
342 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
343 if (r < 0) {
344 log_netdev_error(netdev,
345 "Could not append IFLA_IPTUN_TTL attribute: %s",
346 strerror(-r));
347 return r;
348 }
349
350 switch (t->ip6tnl_mode) {
351 case NETDEV_IP6_TNL_MODE_IP6IP6:
352 proto = IPPROTO_IPV6;
353 break;
354 case NETDEV_IP6_TNL_MODE_IPIP6:
355 proto = IPPROTO_IPIP;
356 break;
357 case NETDEV_IP6_TNL_MODE_ANYIP6:
358 default:
359 proto = 0;
360 break;
361 }
362
363 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
364 if (r < 0) {
365 log_netdev_error(netdev,
366 "Could not append IFLA_IPTUN_MODE attribute: %s",
367 strerror(-r));
368 return r;
369 }
370
371 return r;
372}
373
3be1d7e0 374static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
aa9f1140
TG
375 Tunnel *t = NULL;
376
7951dea2 377 assert(netdev);
3be1d7e0 378 assert(filename);
7951dea2 379
aa9f1140
TG
380 switch (netdev->kind) {
381 case NETDEV_KIND_IPIP:
382 t = IPIP(netdev);
383 break;
384 case NETDEV_KIND_SIT:
385 t = SIT(netdev);
386 break;
387 case NETDEV_KIND_GRE:
388 t = GRE(netdev);
389 break;
1af2536a
SS
390 case NETDEV_KIND_GRETAP:
391 t = GRETAP(netdev);
392 break;
b16492f8
SS
393 case NETDEV_KIND_IP6GRE:
394 t = IP6GRE(netdev);
395 break;
396 case NETDEV_KIND_IP6GRETAP:
397 t = IP6GRETAP(netdev);
398 break;
aa9f1140
TG
399 case NETDEV_KIND_VTI:
400 t = VTI(netdev);
401 break;
855ee1a1
SS
402 case NETDEV_KIND_IP6TNL:
403 t = IP6TNL(netdev);
404 break;
aa9f1140
TG
405 default:
406 assert_not_reached("Invalid tunnel kind");
407 }
408
409 assert(t);
410
aa9f1140 411 if (t->remote.in.s_addr == INADDR_ANY) {
3be1d7e0
TG
412 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
413 return -EINVAL;
7951dea2
SS
414 }
415
855ee1a1 416 if (t->family != AF_INET && t->family != AF_INET6) {
3be1d7e0
TG
417 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
418 return -EINVAL;
7951dea2
SS
419 }
420
855ee1a1
SS
421 if (netdev->kind == NETDEV_KIND_IP6TNL) {
422 if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
423 log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename);
424 return -EINVAL;
425 }
426 }
427
7951dea2
SS
428 return 0;
429}
6ef892fc
TG
430
431int config_parse_tunnel_address(const char *unit,
432 const char *filename,
433 unsigned line,
434 const char *section,
435 unsigned section_line,
436 const char *lvalue,
437 int ltype,
438 const char *rvalue,
439 void *data,
440 void *userdata) {
aa9f1140 441 Tunnel *t = userdata;
44e7b949
LP
442 union in_addr_union *addr = data, buffer;
443 int r, f;
6ef892fc
TG
444
445 assert(filename);
446 assert(lvalue);
447 assert(rvalue);
448 assert(data);
449
44e7b949 450 r = in_addr_from_string_auto(rvalue, &f, &buffer);
6ef892fc 451 if (r < 0) {
44e7b949 452 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
6ef892fc
TG
453 return 0;
454 }
455
44e7b949
LP
456 if (t->family != AF_UNSPEC && t->family != f) {
457 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
458 return 0;
459 }
460
461 t->family = f;
462 *addr = buffer;
463
6ef892fc
TG
464 return 0;
465}
3be1d7e0 466
aa9f1140
TG
467static void ipip_init(NetDev *n) {
468 Tunnel *t = IPIP(n);
469
470 assert(n);
471 assert(t);
472
473 t->pmtudisc = true;
474}
475
476static void sit_init(NetDev *n) {
477 Tunnel *t = SIT(n);
478
479 assert(n);
480 assert(t);
481
482 t->pmtudisc = true;
483}
484
485static void vti_init(NetDev *n) {
486 Tunnel *t = VTI(n);
487
488 assert(n);
489 assert(t);
490
491 t->pmtudisc = true;
492}
493
494static void gre_init(NetDev *n) {
1af2536a 495 Tunnel *t;
aa9f1140
TG
496
497 assert(n);
1af2536a
SS
498
499 if (n->kind == NETDEV_KIND_GRE)
500 t = GRE(n);
501 else
502 t = GRETAP(n);
503
aa9f1140
TG
504 assert(t);
505
506 t->pmtudisc = true;
507}
508
b16492f8
SS
509static void ip6gre_init(NetDev *n) {
510 Tunnel *t;
511
512 assert(n);
513
514 if (n->kind == NETDEV_KIND_IP6GRE)
515 t = IP6GRE(n);
516 else
517 t = IP6GRETAP(n);
518
519 assert(t);
520
521 t->ttl = DEFAULT_TNL_HOP_LIMIT;
522}
523
855ee1a1
SS
524static void ip6tnl_init(NetDev *n) {
525 Tunnel *t = IP6TNL(n);
526
527 assert(n);
528 assert(t);
529
530 t->ttl = DEFAULT_TNL_HOP_LIMIT;
531 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
532 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
533}
534
3be1d7e0 535const NetDevVTable ipip_vtable = {
aa9f1140
TG
536 .object_size = sizeof(Tunnel),
537 .init = ipip_init,
538 .sections = "Match\0NetDev\0Tunnel\0",
539 .fill_message_create = netdev_ipip_fill_message_create,
540 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
541 .config_verify = netdev_tunnel_verify,
542};
543
544const NetDevVTable sit_vtable = {
aa9f1140
TG
545 .object_size = sizeof(Tunnel),
546 .init = sit_init,
547 .sections = "Match\0NetDev\0Tunnel\0",
548 .fill_message_create = netdev_sit_fill_message_create,
549 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
550 .config_verify = netdev_tunnel_verify,
551};
552
553const NetDevVTable vti_vtable = {
aa9f1140
TG
554 .object_size = sizeof(Tunnel),
555 .init = vti_init,
556 .sections = "Match\0NetDev\0Tunnel\0",
557 .fill_message_create = netdev_vti_fill_message_create,
558 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
559 .config_verify = netdev_tunnel_verify,
560};
561
562const NetDevVTable gre_vtable = {
aa9f1140
TG
563 .object_size = sizeof(Tunnel),
564 .init = gre_init,
565 .sections = "Match\0NetDev\0Tunnel\0",
566 .fill_message_create = netdev_gre_fill_message_create,
567 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
568 .config_verify = netdev_tunnel_verify,
569};
1af2536a
SS
570
571const NetDevVTable gretap_vtable = {
572 .object_size = sizeof(Tunnel),
573 .init = gre_init,
574 .sections = "Match\0NetDev\0Tunnel\0",
575 .fill_message_create = netdev_gre_fill_message_create,
576 .create_type = NETDEV_CREATE_STACKED,
577 .config_verify = netdev_tunnel_verify,
578};
855ee1a1 579
b16492f8
SS
580const NetDevVTable ip6gre_vtable = {
581 .object_size = sizeof(Tunnel),
582 .init = ip6gre_init,
583 .sections = "Match\0NetDev\0Tunnel\0",
584 .fill_message_create = netdev_ip6gre_fill_message_create,
585 .create_type = NETDEV_CREATE_STACKED,
586 .config_verify = netdev_tunnel_verify,
587};
588
589const NetDevVTable ip6gretap_vtable = {
590 .object_size = sizeof(Tunnel),
591 .init = ip6gre_init,
592 .sections = "Match\0NetDev\0Tunnel\0",
593 .fill_message_create = netdev_ip6gre_fill_message_create,
594 .create_type = NETDEV_CREATE_STACKED,
595 .config_verify = netdev_tunnel_verify,
596};
597
855ee1a1
SS
598const NetDevVTable ip6tnl_vtable = {
599 .object_size = sizeof(Tunnel),
600 .init = ip6tnl_init,
601 .sections = "Match\0NetDev\0Tunnel\0",
602 .fill_message_create = netdev_ip6tnl_fill_message_create,
603 .create_type = NETDEV_CREATE_STACKED,
604 .config_verify = netdev_tunnel_verify,
605};