]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-netdev-tunnel.c
networkd: tunnel improve logging
[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);
5289f3ff
SS
57 if (r < 0)
58 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
7951dea2 59
aa9f1140 60 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
5289f3ff
SS
61 if (r < 0)
62 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
7951dea2 63
aa9f1140 64 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
5289f3ff
SS
65 if (r < 0)
66 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
7951dea2 67
aa9f1140 68 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
5289f3ff
SS
69 if (r < 0)
70 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
9ae70211 71
9243e967 72 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
5289f3ff
SS
73 if (r < 0)
74 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
9243e967 75
7951dea2
SS
76 return r;
77}
78
3be1d7e0 79static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
aa9f1140 80 Tunnel *t = SIT(netdev);
abf446af
SS
81 int r;
82
3be1d7e0 83 assert(netdev);
abf446af 84 assert(link);
abf446af 85 assert(m);
aa9f1140
TG
86 assert(t);
87 assert(t->family == AF_INET);
abf446af
SS
88
89 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
5289f3ff
SS
90 if (r < 0)
91 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
abf446af 92
aa9f1140 93 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
5289f3ff
SS
94 if (r < 0)
95 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
abf446af 96
aa9f1140 97 r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
5289f3ff
SS
98 if (r < 0)
99 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
abf446af 100
aa9f1140 101 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
5289f3ff
SS
102 if (r < 0)
103 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
a9f434cf 104
436b910f 105 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc);
5289f3ff
SS
106 if (r < 0)
107 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
436b910f 108
abf446af
SS
109 return r;
110}
111
3be1d7e0 112static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
1af2536a 113 Tunnel *t;
8bb088c5
SS
114 int r;
115
3be1d7e0 116 assert(netdev);
1af2536a
SS
117
118 if (netdev->kind == NETDEV_KIND_GRE)
5289f3ff 119 t = GRE(netdev);
1af2536a 120 else
5289f3ff 121 t = GRETAP(netdev);
1af2536a 122
aa9f1140
TG
123 assert(t);
124 assert(t->family == AF_INET);
1af2536a
SS
125 assert(link);
126 assert(m);
8bb088c5
SS
127
128 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
5289f3ff
SS
129 if (r < 0)
130 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
8bb088c5 131
aa9f1140 132 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
5289f3ff
SS
133 if (r < 0)
134 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
8bb088c5 135
aa9f1140 136 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
5289f3ff
SS
137 if (r < 0)
138 log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
8bb088c5 139
aa9f1140 140 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
5289f3ff
SS
141 if (r < 0)
142 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
8bb088c5 143
aa9f1140 144 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, t->tos);
5289f3ff
SS
145 if (r < 0)
146 log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m");
8bb088c5 147
9243e967 148 r = sd_rtnl_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc);
5289f3ff
SS
149 if (r < 0)
150 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m");
9243e967 151
8bb088c5
SS
152 return r;
153}
154
b16492f8
SS
155static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
156 Tunnel *t;
157 int r;
158
159 assert(netdev);
160
161 if (netdev->kind == NETDEV_KIND_IP6GRE)
5289f3ff 162 t = IP6GRE(netdev);
b16492f8 163 else
5289f3ff 164 t = IP6GRETAP(netdev);
b16492f8
SS
165
166 assert(t);
167 assert(t->family == AF_INET6);
168 assert(link);
169 assert(m);
170
171 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
5289f3ff
SS
172 if (r < 0)
173 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m");
b16492f8
SS
174
175 r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
5289f3ff
SS
176 if (r < 0)
177 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m");
b16492f8
SS
178
179 r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
5289f3ff
SS
180 if (r < 0)
181 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m");
b16492f8
SS
182
183 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
5289f3ff
SS
184 if (r < 0)
185 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
b16492f8
SS
186
187 return r;
188}
189
3be1d7e0 190static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
aa9f1140 191 Tunnel *t = VTI(netdev);
a613382b
SS
192 int r;
193
3be1d7e0 194 assert(netdev);
a613382b 195 assert(link);
a613382b 196 assert(m);
aa9f1140
TG
197 assert(t);
198 assert(t->family == AF_INET);
a613382b
SS
199
200 r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
5289f3ff
SS
201 if (r < 0)
202 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
a613382b 203
aa9f1140 204 r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
5289f3ff
SS
205 if (r < 0)
206 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
a613382b 207
aa9f1140 208 r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
5289f3ff
SS
209 if (r < 0)
210 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
a613382b 211
a613382b
SS
212 return r;
213}
8bb088c5 214
855ee1a1
SS
215static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
216 Tunnel *t = IP6TNL(netdev);
217 uint8_t proto;
218 int r;
219
220 assert(netdev);
221 assert(link);
222 assert(m);
223 assert(t);
224 assert(t->family == AF_INET6);
225
226 r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
5289f3ff
SS
227 if (r < 0)
228 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
855ee1a1
SS
229
230 r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
5289f3ff
SS
231 if (r < 0)
232 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
855ee1a1
SS
233
234 r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
5289f3ff
SS
235 if (r < 0)
236 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m");
855ee1a1
SS
237
238 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
5289f3ff
SS
239 if (r < 0)
240 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
855ee1a1
SS
241
242 switch (t->ip6tnl_mode) {
243 case NETDEV_IP6_TNL_MODE_IP6IP6:
244 proto = IPPROTO_IPV6;
245 break;
246 case NETDEV_IP6_TNL_MODE_IPIP6:
247 proto = IPPROTO_IPIP;
248 break;
249 case NETDEV_IP6_TNL_MODE_ANYIP6:
250 default:
251 proto = 0;
252 break;
253 }
254
255 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
5289f3ff
SS
256 if (r < 0)
257 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m");
855ee1a1
SS
258
259 return r;
260}
261
3be1d7e0 262static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
aa9f1140
TG
263 Tunnel *t = NULL;
264
7951dea2 265 assert(netdev);
3be1d7e0 266 assert(filename);
7951dea2 267
aa9f1140
TG
268 switch (netdev->kind) {
269 case NETDEV_KIND_IPIP:
270 t = IPIP(netdev);
271 break;
272 case NETDEV_KIND_SIT:
273 t = SIT(netdev);
274 break;
275 case NETDEV_KIND_GRE:
276 t = GRE(netdev);
277 break;
1af2536a
SS
278 case NETDEV_KIND_GRETAP:
279 t = GRETAP(netdev);
280 break;
b16492f8
SS
281 case NETDEV_KIND_IP6GRE:
282 t = IP6GRE(netdev);
283 break;
284 case NETDEV_KIND_IP6GRETAP:
285 t = IP6GRETAP(netdev);
286 break;
aa9f1140
TG
287 case NETDEV_KIND_VTI:
288 t = VTI(netdev);
289 break;
855ee1a1
SS
290 case NETDEV_KIND_IP6TNL:
291 t = IP6TNL(netdev);
292 break;
aa9f1140
TG
293 default:
294 assert_not_reached("Invalid tunnel kind");
295 }
296
297 assert(t);
298
aa9f1140 299 if (t->remote.in.s_addr == INADDR_ANY) {
5289f3ff
SS
300 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
301 return -EINVAL;
7951dea2
SS
302 }
303
855ee1a1 304 if (t->family != AF_INET && t->family != AF_INET6) {
5289f3ff
SS
305 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
306 return -EINVAL;
7951dea2
SS
307 }
308
855ee1a1
SS
309 if (netdev->kind == NETDEV_KIND_IP6TNL) {
310 if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
311 log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename);
312 return -EINVAL;
313 }
314 }
315
7951dea2
SS
316 return 0;
317}
6ef892fc
TG
318
319int config_parse_tunnel_address(const char *unit,
320 const char *filename,
321 unsigned line,
322 const char *section,
323 unsigned section_line,
324 const char *lvalue,
325 int ltype,
326 const char *rvalue,
327 void *data,
328 void *userdata) {
aa9f1140 329 Tunnel *t = userdata;
44e7b949
LP
330 union in_addr_union *addr = data, buffer;
331 int r, f;
6ef892fc
TG
332
333 assert(filename);
334 assert(lvalue);
335 assert(rvalue);
336 assert(data);
337
44e7b949 338 r = in_addr_from_string_auto(rvalue, &f, &buffer);
6ef892fc 339 if (r < 0) {
44e7b949 340 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
6ef892fc
TG
341 return 0;
342 }
343
44e7b949
LP
344 if (t->family != AF_UNSPEC && t->family != f) {
345 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
346 return 0;
347 }
348
349 t->family = f;
350 *addr = buffer;
351
6ef892fc
TG
352 return 0;
353}
3be1d7e0 354
aa9f1140
TG
355static void ipip_init(NetDev *n) {
356 Tunnel *t = IPIP(n);
357
358 assert(n);
359 assert(t);
360
361 t->pmtudisc = true;
362}
363
364static void sit_init(NetDev *n) {
365 Tunnel *t = SIT(n);
366
367 assert(n);
368 assert(t);
369
370 t->pmtudisc = true;
371}
372
373static void vti_init(NetDev *n) {
374 Tunnel *t = VTI(n);
375
376 assert(n);
377 assert(t);
378
379 t->pmtudisc = true;
380}
381
382static void gre_init(NetDev *n) {
1af2536a 383 Tunnel *t;
aa9f1140
TG
384
385 assert(n);
1af2536a
SS
386
387 if (n->kind == NETDEV_KIND_GRE)
388 t = GRE(n);
389 else
390 t = GRETAP(n);
391
aa9f1140
TG
392 assert(t);
393
394 t->pmtudisc = true;
395}
396
b16492f8
SS
397static void ip6gre_init(NetDev *n) {
398 Tunnel *t;
399
400 assert(n);
401
402 if (n->kind == NETDEV_KIND_IP6GRE)
403 t = IP6GRE(n);
404 else
405 t = IP6GRETAP(n);
406
407 assert(t);
408
409 t->ttl = DEFAULT_TNL_HOP_LIMIT;
410}
411
855ee1a1
SS
412static void ip6tnl_init(NetDev *n) {
413 Tunnel *t = IP6TNL(n);
414
415 assert(n);
416 assert(t);
417
418 t->ttl = DEFAULT_TNL_HOP_LIMIT;
419 t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
420 t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
421}
422
3be1d7e0 423const NetDevVTable ipip_vtable = {
aa9f1140
TG
424 .object_size = sizeof(Tunnel),
425 .init = ipip_init,
426 .sections = "Match\0NetDev\0Tunnel\0",
427 .fill_message_create = netdev_ipip_fill_message_create,
428 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
429 .config_verify = netdev_tunnel_verify,
430};
431
432const NetDevVTable sit_vtable = {
aa9f1140
TG
433 .object_size = sizeof(Tunnel),
434 .init = sit_init,
435 .sections = "Match\0NetDev\0Tunnel\0",
436 .fill_message_create = netdev_sit_fill_message_create,
437 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
438 .config_verify = netdev_tunnel_verify,
439};
440
441const NetDevVTable vti_vtable = {
aa9f1140
TG
442 .object_size = sizeof(Tunnel),
443 .init = vti_init,
444 .sections = "Match\0NetDev\0Tunnel\0",
445 .fill_message_create = netdev_vti_fill_message_create,
446 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
447 .config_verify = netdev_tunnel_verify,
448};
449
450const NetDevVTable gre_vtable = {
aa9f1140
TG
451 .object_size = sizeof(Tunnel),
452 .init = gre_init,
453 .sections = "Match\0NetDev\0Tunnel\0",
454 .fill_message_create = netdev_gre_fill_message_create,
455 .create_type = NETDEV_CREATE_STACKED,
3be1d7e0
TG
456 .config_verify = netdev_tunnel_verify,
457};
1af2536a
SS
458
459const NetDevVTable gretap_vtable = {
460 .object_size = sizeof(Tunnel),
461 .init = gre_init,
462 .sections = "Match\0NetDev\0Tunnel\0",
463 .fill_message_create = netdev_gre_fill_message_create,
464 .create_type = NETDEV_CREATE_STACKED,
465 .config_verify = netdev_tunnel_verify,
466};
855ee1a1 467
b16492f8
SS
468const NetDevVTable ip6gre_vtable = {
469 .object_size = sizeof(Tunnel),
470 .init = ip6gre_init,
471 .sections = "Match\0NetDev\0Tunnel\0",
472 .fill_message_create = netdev_ip6gre_fill_message_create,
473 .create_type = NETDEV_CREATE_STACKED,
474 .config_verify = netdev_tunnel_verify,
475};
476
477const NetDevVTable ip6gretap_vtable = {
478 .object_size = sizeof(Tunnel),
479 .init = ip6gre_init,
480 .sections = "Match\0NetDev\0Tunnel\0",
481 .fill_message_create = netdev_ip6gre_fill_message_create,
482 .create_type = NETDEV_CREATE_STACKED,
483 .config_verify = netdev_tunnel_verify,
484};
485
855ee1a1
SS
486const NetDevVTable ip6tnl_vtable = {
487 .object_size = sizeof(Tunnel),
488 .init = ip6tnl_init,
489 .sections = "Match\0NetDev\0Tunnel\0",
490 .fill_message_create = netdev_ip6tnl_fill_message_create,
491 .create_type = NETDEV_CREATE_STACKED,
492 .config_verify = netdev_tunnel_verify,
493};