]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: link - serialize routes
[thirdparty/systemd.git] / src / network / networkd-link.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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
22#include <netinet/ether.h>
23#include <linux/if.h>
4cc7a82c 24#include <unistd.h>
f579559b 25
b5efdb8a 26#include "alloc-util.h"
1346b1f0 27#include "bus-util.h"
bd91b83e 28#include "dhcp-lease-internal.h"
3ffd4af2 29#include "fd-util.h"
cf1d700d
TG
30#include "fileio.h"
31#include "netlink-util.h"
c6f7c917 32#include "network-internal.h"
3ffd4af2
LP
33#include "networkd-link.h"
34#include "networkd-netdev.h"
cf1d700d
TG
35#include "set.h"
36#include "socket-util.h"
15a5e950 37#include "stdio-util.h"
8b43440b 38#include "string-table.h"
cf1d700d
TG
39#include "udev-util.h"
40#include "util.h"
41#include "virt.h"
fc2f9534 42
a97dcc12 43bool link_dhcp6_enabled(Link *link) {
78c958f8
TG
44 if (link->flags & IFF_LOOPBACK)
45 return false;
46
47 if (!link->network)
48 return false;
49
e0ee46f2 50 return link->network->dhcp & ADDRESS_FAMILY_IPV6;
78c958f8
TG
51}
52
a97dcc12 53bool link_dhcp4_enabled(Link *link) {
78c958f8
TG
54 if (link->flags & IFF_LOOPBACK)
55 return false;
56
57 if (!link->network)
58 return false;
59
e0ee46f2 60 return link->network->dhcp & ADDRESS_FAMILY_IPV4;
78c958f8
TG
61}
62
a97dcc12 63bool link_dhcp4_server_enabled(Link *link) {
78c958f8
TG
64 if (link->flags & IFF_LOOPBACK)
65 return false;
66
67 if (!link->network)
68 return false;
69
70 return link->network->dhcp_server;
71}
72
a97dcc12 73bool link_ipv4ll_enabled(Link *link) {
78c958f8
TG
74 if (link->flags & IFF_LOOPBACK)
75 return false;
76
77 if (!link->network)
78 return false;
79
e0ee46f2 80 return link->network->link_local & ADDRESS_FAMILY_IPV4;
d0d6a4cd
TG
81}
82
83bool link_ipv6ll_enabled(Link *link) {
84 if (link->flags & IFF_LOOPBACK)
85 return false;
86
87 if (!link->network)
88 return false;
89
e0ee46f2 90 return link->network->link_local & ADDRESS_FAMILY_IPV6;
78c958f8
TG
91}
92
a97dcc12 93bool link_lldp_enabled(Link *link) {
ce43e484
SS
94 if (link->flags & IFF_LOOPBACK)
95 return false;
96
97 if (!link->network)
98 return false;
99
5a8bcb67 100 if (link->network->bridge)
ce43e484
SS
101 return false;
102
103 return link->network->lldp;
104}
105
769d324c 106static bool link_ipv4_forward_enabled(Link *link) {
5a8bcb67
LP
107 if (link->flags & IFF_LOOPBACK)
108 return false;
109
110 if (!link->network)
111 return false;
112
e0ee46f2 113 return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
769d324c
LP
114}
115
116static bool link_ipv6_forward_enabled(Link *link) {
117 if (link->flags & IFF_LOOPBACK)
118 return false;
119
120 if (!link->network)
121 return false;
122
e0ee46f2 123 return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
5a8bcb67
LP
124}
125
1f0d9695 126static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
49092e22 127 if (link->flags & IFF_LOOPBACK)
1f0d9695 128 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
49092e22
SS
129
130 if (!link->network)
1f0d9695 131 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
49092e22
SS
132
133 return link->network->ipv6_privacy_extensions;
134}
135
84de38c5
TG
136void link_update_operstate(Link *link) {
137 LinkOperationalState operstate;
138 assert(link);
139
140 if (link->kernel_operstate == IF_OPER_DORMANT)
141 operstate = LINK_OPERSTATE_DORMANT;
142 else if (link_has_carrier(link)) {
143 Address *address;
144 uint8_t scope = RT_SCOPE_NOWHERE;
145 Iterator i;
146
147 /* if we have carrier, check what addresses we have */
148 SET_FOREACH(address, link->addresses, i) {
149 if (!address_is_ready(address))
150 continue;
151
152 if (address->scope < scope)
153 scope = address->scope;
154 }
155
156 /* for operstate we also take foreign addresses into account */
157 SET_FOREACH(address, link->addresses_foreign, i) {
158 if (!address_is_ready(address))
159 continue;
160
161 if (address->scope < scope)
162 scope = address->scope;
163 }
164
165 if (scope < RT_SCOPE_SITE)
166 /* universally accessible addresses found */
167 operstate = LINK_OPERSTATE_ROUTABLE;
168 else if (scope < RT_SCOPE_HOST)
169 /* only link or site local addresses found */
170 operstate = LINK_OPERSTATE_DEGRADED;
171 else
172 /* no useful addresses found */
173 operstate = LINK_OPERSTATE_CARRIER;
174 } else if (link->flags & IFF_UP)
175 operstate = LINK_OPERSTATE_NO_CARRIER;
176 else
177 operstate = LINK_OPERSTATE_OFF;
178
179 if (link->operstate != operstate) {
180 link->operstate = operstate;
181 link_send_changed(link, "OperationalState", NULL);
182 link_dirty(link);
183 manager_dirty(link->manager);
184 }
185}
186
51d18171
TG
187#define FLAG_STRING(string, flag, old, new) \
188 (((old ^ new) & flag) \
189 ? ((old & flag) ? (" -" string) : (" +" string)) \
190 : "")
191
1c4baffc 192static int link_update_flags(Link *link, sd_netlink_message *m) {
51d18171
TG
193 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
194 uint8_t operstate;
195 int r;
196
197 assert(link);
198
199 r = sd_rtnl_message_link_get_flags(m, &flags);
6a7a4e4d
LP
200 if (r < 0)
201 return log_link_warning_errno(link, r, "Could not get link flags: %m");
51d18171 202
1c4baffc 203 r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate);
51d18171
TG
204 if (r < 0)
205 /* if we got a message without operstate, take it to mean
206 the state was unchanged */
207 operstate = link->kernel_operstate;
208
209 if ((link->flags == flags) && (link->kernel_operstate == operstate))
210 return 0;
211
212 if (link->flags != flags) {
6a7a4e4d 213 log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
51d18171
TG
214 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
215 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
216 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
217 FLAG_STRING("UP", IFF_UP, link->flags, flags),
218 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
219 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
220 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
221 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
222 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
223 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
224 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
225 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
226 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
227 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
228 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
229 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
230 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
231 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
232 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
233
234 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
235 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
236 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
237 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
238 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
239 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
240 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
241 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
242
243 /* link flags are currently at most 18 bits, let's align to
244 * printing 20 */
245 if (unknown_flags_added)
79008bdd 246 log_link_debug(link,
6a7a4e4d 247 "Unknown link flags gained: %#.5x (ignoring)",
51d18171
TG
248 unknown_flags_added);
249
250 if (unknown_flags_removed)
79008bdd 251 log_link_debug(link,
6a7a4e4d 252 "Unknown link flags lost: %#.5x (ignoring)",
51d18171
TG
253 unknown_flags_removed);
254 }
255
256 link->flags = flags;
257 link->kernel_operstate = operstate;
258
84de38c5 259 link_update_operstate(link);
51d18171
TG
260
261 return 0;
262}
263
1c4baffc 264static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
14b746f7 265 _cleanup_link_unref_ Link *link = NULL;
505f8da7 266 uint16_t type;
ca4e095a 267 const char *ifname;
505f8da7 268 int r, ifindex;
f579559b 269
0c2f9b84 270 assert(manager);
505f8da7 271 assert(message);
f579559b
TG
272 assert(ret);
273
1c4baffc 274 r = sd_netlink_message_get_type(message, &type);
505f8da7
TG
275 if (r < 0)
276 return r;
277 else if (type != RTM_NEWLINK)
278 return -EINVAL;
279
280 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
281 if (r < 0)
282 return r;
283 else if (ifindex <= 0)
284 return -EINVAL;
285
1c4baffc 286 r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
505f8da7
TG
287 if (r < 0)
288 return r;
289
f579559b
TG
290 link = new0(Link, 1);
291 if (!link)
292 return -ENOMEM;
293
14b746f7 294 link->n_ref = 1;
5a3eb5a7 295 link->manager = manager;
8434fd5c 296 link->state = LINK_STATE_PENDING;
be3a09b7 297 link->rtnl_extended_attrs = true;
505f8da7
TG
298 link->ifindex = ifindex;
299 link->ifname = strdup(ifname);
300 if (!link->ifname)
301 return -ENOMEM;
f579559b 302
1c4baffc 303 r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
512922f8 304 if (r < 0)
79008bdd 305 log_link_debug(link, "MAC address not found for new device, continuing without");
512922f8 306
3c9b8860
TG
307 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
308 link->ifindex);
fe8db0c5 309 if (r < 0)
315db1a8 310 return -ENOMEM;
fe8db0c5 311
3c9b8860
TG
312 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
313 link->ifindex);
68a8723c
TG
314 if (r < 0)
315 return -ENOMEM;
316
49699bac
SS
317 r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
318 link->ifindex);
319 if (r < 0)
320 return -ENOMEM;
321
322
d5099efc 323 r = hashmap_ensure_allocated(&manager->links, NULL);
ae06ab10
TG
324 if (r < 0)
325 return r;
326
327 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
f579559b
TG
328 if (r < 0)
329 return r;
330
51d18171
TG
331 r = link_update_flags(link, message);
332 if (r < 0)
333 return r;
334
f579559b
TG
335 *ret = link;
336 link = NULL;
337
338 return 0;
339}
340
14b746f7 341static void link_free(Link *link) {
428fd0a7 342 Address *address;
0d4ad91d
AR
343 Iterator i;
344 Link *carrier;
428fd0a7 345
f579559b
TG
346 if (!link)
347 return;
348
cf1d700d
TG
349 while (!set_isempty(link->addresses))
350 address_free(set_first(link->addresses));
351
352 set_free(link->addresses);
428fd0a7 353
adda1ed9
TG
354 while (!set_isempty(link->addresses_foreign))
355 address_free(set_first(link->addresses_foreign));
356
357 set_free(link->addresses_foreign);
358
11bf3cce
LP
359 while ((address = link->pool_addresses)) {
360 LIST_REMOVE(addresses, link->pool_addresses, address);
361 address_free(address);
362 }
363
bfcdba8d 364 sd_dhcp_server_unref(link->dhcp_server);
e5b04c8d 365 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 366 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 367
68a8723c
TG
368 free(link->lease_file);
369
07e10d1a
TG
370 sd_lldp_free(link->lldp);
371
49699bac
SS
372 free(link->lldp_file);
373
56cd007a 374 sd_ipv4ll_unref(link->ipv4ll);
4138fb2c 375 sd_dhcp6_client_unref(link->dhcp6_client);
de1e9928 376 sd_ndisc_unref(link->ndisc_router_discovery);
4138fb2c 377
28aeb07f 378 if (link->manager)
ae06ab10 379 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
f579559b 380
c166a070 381 free(link->ifname);
68a8723c 382
84de38c5 383 (void)unlink(link->state_file);
fe8db0c5 384 free(link->state_file);
c166a070 385
b5db00e5
UTL
386 udev_device_unref(link->udev_device);
387
0d4ad91d
AR
388 HASHMAP_FOREACH (carrier, link->bound_to_links, i)
389 hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
390 hashmap_free(link->bound_to_links);
391
392 HASHMAP_FOREACH (carrier, link->bound_by_links, i)
393 hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
394 hashmap_free(link->bound_by_links);
395
f579559b
TG
396 free(link);
397}
398
14b746f7 399Link *link_unref(Link *link) {
957325b7
TG
400 if (!link)
401 return NULL;
402
403 assert(link->n_ref > 0);
404
405 link->n_ref --;
406
407 if (link->n_ref > 0)
408 return NULL;
409
410 link_free(link);
14b746f7
TG
411
412 return NULL;
413}
414
415Link *link_ref(Link *link) {
957325b7
TG
416 if (!link)
417 return NULL;
418
419 assert(link->n_ref > 0);
420
421 link->n_ref ++;
14b746f7
TG
422
423 return link;
424}
425
11a7f229
TG
426int link_get(Manager *m, int ifindex, Link **ret) {
427 Link *link;
11a7f229
TG
428
429 assert(m);
11a7f229
TG
430 assert(ifindex);
431 assert(ret);
432
ae06ab10 433 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
11a7f229
TG
434 if (!link)
435 return -ENODEV;
436
437 *ret = link;
438
439 return 0;
440}
441
e331e246
TG
442static void link_set_state(Link *link, LinkState state) {
443 assert(link);
444
445 if (link->state == state)
446 return;
447
448 link->state = state;
449
450 link_send_changed(link, "AdministrativeState", NULL);
451
452 return;
453}
454
57bd6899
TG
455static void link_enter_unmanaged(Link *link) {
456 assert(link);
457
6a7a4e4d 458 log_link_debug(link, "Unmanaged");
57bd6899 459
e331e246 460 link_set_state(link, LINK_STATE_UNMANAGED);
57bd6899 461
84de38c5 462 link_dirty(link);
57bd6899
TG
463}
464
111bb8f9
TG
465static int link_stop_clients(Link *link) {
466 int r = 0, k;
467
468 assert(link);
469 assert(link->manager);
470 assert(link->manager->event);
471
472 if (!link->network)
473 return 0;
474
ba179154 475 if (link->dhcp_client) {
111bb8f9 476 k = sd_dhcp_client_stop(link->dhcp_client);
6a7a4e4d
LP
477 if (k < 0)
478 r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
111bb8f9
TG
479 }
480
ba179154 481 if (link->ipv4ll) {
111bb8f9 482 k = sd_ipv4ll_stop(link->ipv4ll);
6a7a4e4d
LP
483 if (k < 0)
484 r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
dd43110f
TG
485 }
486
de1e9928 487 if(link->ndisc_router_discovery) {
1873a3d3
PF
488 if (link->dhcp6_client) {
489 k = sd_dhcp6_client_stop(link->dhcp6_client);
6a7a4e4d
LP
490 if (k < 0)
491 r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
1873a3d3 492 }
4138fb2c 493
de1e9928 494 k = sd_ndisc_stop(link->ndisc_router_discovery);
6a7a4e4d 495 if (k < 0)
ceabaf0f 496 r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
4138fb2c
PF
497 }
498
ce43e484 499 if (link->lldp) {
ce43e484 500 k = sd_lldp_stop(link->lldp);
6a7a4e4d
LP
501 if (k < 0)
502 r = log_link_warning_errno(link, r, "Could not stop LLDP: %m");
ce43e484
SS
503 }
504
111bb8f9
TG
505 return r;
506}
507
b22d8a00 508void link_enter_failed(Link *link) {
ef1ba606 509 assert(link);
f882c247 510
370e9930 511 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
512 return;
513
6a7a4e4d 514 log_link_warning(link, "Failed");
449f7554 515
e331e246 516 link_set_state(link, LINK_STATE_FAILED);
fe8db0c5 517
111bb8f9
TG
518 link_stop_clients(link);
519
84de38c5 520 link_dirty(link);
f882c247
TG
521}
522
4f434938
LP
523static Address* link_find_dhcp_server_address(Link *link) {
524 Address *address;
525
526 assert(link);
527 assert(link->network);
528
d4cdbea5 529 /* The first statically configured address if there is any */
4f434938
LP
530 LIST_FOREACH(addresses, address, link->network->static_addresses) {
531
532 if (address->family != AF_INET)
533 continue;
534
af93291c 535 if (in_addr_is_null(address->family, &address->in_addr))
4f434938
LP
536 continue;
537
538 return address;
539 }
540
541 /* If that didn't work, find a suitable address we got from the pool */
542 LIST_FOREACH(addresses, address, link->pool_addresses) {
543 if (address->family != AF_INET)
544 continue;
545
546 return address;
547 }
548
549 return NULL;
550}
551
dd43110f 552static int link_enter_configured(Link *link) {
dd43110f
TG
553 assert(link);
554 assert(link->network);
555 assert(link->state == LINK_STATE_SETTING_ROUTES);
556
6a7a4e4d 557 log_link_info(link, "Configured");
dd43110f 558
e331e246 559 link_set_state(link, LINK_STATE_CONFIGURED);
dd43110f 560
84de38c5 561 link_dirty(link);
dd43110f
TG
562
563 return 0;
564}
565
8012cd39
TG
566void link_check_ready(Link *link) {
567 Address *a;
568 Iterator i;
569
3c9b8860 570 assert(link);
adda1ed9
TG
571
572 if (!link->network)
573 return;
3c9b8860
TG
574
575 if (!link->static_configured)
576 return;
577
78c958f8 578 if (link_ipv4ll_enabled(link))
3c9b8860
TG
579 if (!link->ipv4ll_address ||
580 !link->ipv4ll_route)
581 return;
582
3ada37a2
PF
583 if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
584 !link->dhcp4_configured) ||
585 (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
586 !link->dhcp6_configured) ||
587 (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
588 !link->dhcp4_configured && !link->dhcp6_configured))
18d29550
PF
589 return;
590
8012cd39
TG
591 SET_FOREACH(a, link->addresses, i)
592 if (!address_is_ready(a))
593 return;
594
9fdaa992
TG
595 if (link->state != LINK_STATE_CONFIGURED)
596 link_enter_configured(link);
3c9b8860
TG
597
598 return;
599}
600
1c4baffc 601static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 602 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
603 int r;
604
3c9b8860 605 assert(link->link_messages > 0);
370e9930
TG
606 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
607 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
608 LINK_STATE_LINGER));
f882c247 609
3c9b8860 610 link->link_messages --;
f882c247 611
77a008c0 612 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
613 return 1;
614
1c4baffc 615 r = sd_netlink_message_get_errno(m);
c166a070 616 if (r < 0 && r != -EEXIST)
a2fae7bb 617 log_link_warning_errno(link, r, "Could not set route: %m");
f882c247 618
3c9b8860 619 if (link->link_messages == 0) {
6a7a4e4d 620 log_link_debug(link, "Routes set");
3c9b8860 621 link->static_configured = true;
8012cd39 622 link_check_ready(link);
dd3efc09 623 }
f882c247
TG
624
625 return 1;
626}
627
628static int link_enter_set_routes(Link *link) {
a6cc569e 629 Route *rt;
f882c247
TG
630 int r;
631
632 assert(link);
633 assert(link->network);
ef1ba606 634 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 635
e331e246 636 link_set_state(link, LINK_STATE_SETTING_ROUTES);
f882c247 637
3d3d4255 638 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 639 r = route_configure(rt, link, &route_handler);
dd3efc09 640 if (r < 0) {
6a7a4e4d 641 log_link_warning_errno(link, r, "Could not set routes: %m");
3c9b8860 642 link_enter_failed(link);
a6cc569e
TG
643 return r;
644 }
645
3c9b8860 646 link->link_messages ++;
8ddbeaa2 647 }
f5be5601 648
3c9b8860
TG
649 if (link->link_messages == 0) {
650 link->static_configured = true;
8012cd39 651 link_check_ready(link);
431ca2ce 652 } else
6a7a4e4d 653 log_link_debug(link, "Setting routes");
f882c247
TG
654
655 return 0;
656}
657
91b5f997 658int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 659 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
660 int r;
661
662 assert(m);
663 assert(link);
664 assert(link->ifname);
665
5da8149f 666 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
667 return 1;
668
1c4baffc 669 r = sd_netlink_message_get_errno(m);
b90b025a 670 if (r < 0 && r != -ESRCH)
a2fae7bb 671 log_link_warning_errno(link, r, "Could not drop route: %m");
5c1d3fc9 672
5bdd314c 673 return 1;
5c1d3fc9
UTL
674}
675
1c4baffc 676static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 677 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
678 int r;
679
4958aee4 680 assert(rtnl);
f5be5601
TG
681 assert(m);
682 assert(link);
683 assert(link->ifname);
3c9b8860 684 assert(link->link_messages > 0);
370e9930
TG
685 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
686 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 687
3c9b8860 688 link->link_messages --;
f882c247 689
5da8149f 690 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
691 return 1;
692
1c4baffc 693 r = sd_netlink_message_get_errno(m);
c166a070 694 if (r < 0 && r != -EEXIST)
a2fae7bb 695 log_link_warning_errno(link, r, "could not set address: %m");
45af44d4 696 else if (r >= 0)
200a0868 697 manager_rtnl_process_address(rtnl, m, link->manager);
f882c247 698
3c9b8860 699 if (link->link_messages == 0) {
6a7a4e4d 700 log_link_debug(link, "Addresses set");
ef1ba606 701 link_enter_set_routes(link);
dd3efc09 702 }
f882c247
TG
703
704 return 1;
705}
706
4f5f911e
LP
707static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
708 _cleanup_free_ struct in_addr *addresses = NULL;
709 size_t n_addresses = 0, n_allocated = 0;
710 char **a;
711
712 log_debug("Copying DNS server information from %s", link->ifname);
713
714 if (!link->network)
715 return 0;
716
717 STRV_FOREACH(a, link->network->dns) {
718 struct in_addr ia;
719
720 /* Only look for IPv4 addresses */
721 if (inet_pton(AF_INET, *a, &ia) <= 0)
722 continue;
723
724 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
725 return log_oom();
726
727 addresses[n_addresses++] = ia;
728 }
729
730 if (link->network->dhcp_dns &&
731 link->dhcp_lease) {
732 const struct in_addr *da = NULL;
733 int n;
734
735 n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
736 if (n > 0) {
737
738 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
739 return log_oom();
740
741 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
742 n_addresses += n;
743 }
744 }
745
746 if (n_addresses <= 0)
747 return 0;
748
749 return sd_dhcp_server_set_dns(s, addresses, n_addresses);
750}
751
752static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
753 _cleanup_free_ struct in_addr *addresses = NULL;
754 size_t n_addresses = 0, n_allocated = 0;
755 char **a;
756
757 if (!link->network)
758 return 0;
759
760 log_debug("Copying NTP server information from %s", link->ifname);
761
762 STRV_FOREACH(a, link->network->ntp) {
763 struct in_addr ia;
764
765 /* Only look for IPv4 addresses */
766 if (inet_pton(AF_INET, *a, &ia) <= 0)
767 continue;
768
769 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
770 return log_oom();
771
772 addresses[n_addresses++] = ia;
773 }
774
775 if (link->network->dhcp_ntp &&
776 link->dhcp_lease) {
777 const struct in_addr *da = NULL;
778 int n;
779
780 n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
781 if (n > 0) {
782
783 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
784 return log_oom();
785
786 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
787 n_addresses += n;
788 }
789 }
790
791 if (n_addresses <= 0)
792 return 0;
793
794 return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
795}
796
f882c247 797static int link_enter_set_addresses(Link *link) {
a6cc569e 798 Address *ad;
f882c247
TG
799 int r;
800
801 assert(link);
802 assert(link->network);
f5be5601 803 assert(link->state != _LINK_STATE_INVALID);
f882c247 804
e331e246 805 link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
f882c247 806
3d3d4255 807 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
66669078 808 r = address_configure(ad, link, &address_handler, false);
dd3efc09 809 if (r < 0) {
5a8bcb67 810 log_link_warning_errno(link, r, "Could not set addresses: %m");
f5be5601
TG
811 link_enter_failed(link);
812 return r;
813 }
814
3c9b8860 815 link->link_messages ++;
f882c247
TG
816 }
817
d4cdbea5
TG
818 /* now that we can figure out a default address for the dhcp server,
819 start it */
820 if (link_dhcp4_server_enabled(link)) {
d4cdbea5 821 Address *address;
4f5f911e
LP
822 Link *uplink = NULL;
823 bool acquired_uplink = false;
d4cdbea5
TG
824
825 address = link_find_dhcp_server_address(link);
826 if (!address) {
6a7a4e4d 827 log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
d4cdbea5
TG
828 link_enter_failed(link);
829 return 0;
830 }
831
61986155 832 /* use the server address' subnet as the pool */
9b3a67c5
TG
833 r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
834 link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
d4cdbea5
TG
835 if (r < 0)
836 return r;
837
838 /* TODO:
839 r = sd_dhcp_server_set_router(link->dhcp_server,
840 &main_address->in_addr.in);
841 if (r < 0)
842 return r;
d4cdbea5
TG
843 */
844
586ac6f7
LP
845 if (link->network->dhcp_server_max_lease_time_usec > 0) {
846 r = sd_dhcp_server_set_max_lease_time(
847 link->dhcp_server,
848 DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
849 if (r < 0)
850 return r;
851 }
852
853 if (link->network->dhcp_server_default_lease_time_usec > 0) {
854 r = sd_dhcp_server_set_default_lease_time(
855 link->dhcp_server,
856 DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
857 if (r < 0)
858 return r;
859 }
860
1a04db0f
LP
861 if (link->network->dhcp_server_emit_dns) {
862
4f5f911e 863 if (link->network->n_dhcp_server_dns > 0)
1a04db0f 864 r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
4f5f911e
LP
865 else {
866 uplink = manager_find_uplink(link->manager, link);
867 acquired_uplink = true;
868
869 if (!uplink) {
870 log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
871 r = 0;
872 } else
873 r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
874 }
875 if (r < 0)
876 log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
1a04db0f
LP
877 }
878
879
880 if (link->network->dhcp_server_emit_ntp) {
881
4f5f911e 882 if (link->network->n_dhcp_server_ntp > 0)
1a04db0f 883 r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
4f5f911e
LP
884 else {
885 if (!acquired_uplink)
886 uplink = manager_find_uplink(link->manager, link);
887
888 if (!uplink) {
889 log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
890 r = 0;
891 } else
892 r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
893
894 }
895 if (r < 0)
896 log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
1a04db0f
LP
897 }
898
8eb9058d
LP
899 if (link->network->dhcp_server_emit_timezone) {
900 _cleanup_free_ char *buffer = NULL;
0ab8a1b6 901 const char *tz = NULL;
8eb9058d
LP
902
903 if (link->network->dhcp_server_timezone)
904 tz = link->network->dhcp_server_timezone;
905 else {
906 r = get_timezone(&buffer);
907 if (r < 0)
908 log_warning_errno(r, "Failed to determine timezone: %m");
909 else
910 tz = buffer;
911 }
912
913 if (tz) {
914 r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
915 if (r < 0)
916 return r;
917 }
918 }
919
d4cdbea5
TG
920 r = sd_dhcp_server_start(link->dhcp_server);
921 if (r < 0) {
6a7a4e4d 922 log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
d4cdbea5
TG
923
924 link_enter_failed(link);
925
926 return 0;
927 }
928
6a7a4e4d 929 log_link_debug(link, "Offering DHCPv4 leases");
d4cdbea5
TG
930 }
931
6a7a4e4d 932 if (link->link_messages == 0)
431ca2ce 933 link_enter_set_routes(link);
6a7a4e4d
LP
934 else
935 log_link_debug(link, "Setting addresses");
431ca2ce 936
f882c247
TG
937 return 0;
938}
939
91b5f997 940int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 941 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
942 int r;
943
944 assert(m);
945 assert(link);
946 assert(link->ifname);
947
5da8149f 948 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
949 return 1;
950
1c4baffc 951 r = sd_netlink_message_get_errno(m);
b90b025a 952 if (r < 0 && r != -EADDRNOTAVAIL)
a2fae7bb 953 log_link_warning_errno(link, r, "Could not drop address: %m");
ff254138 954
5bdd314c 955 return 1;
ff254138
TG
956}
957
a245ced0 958static int link_set_bridge_fdb(Link *const link) {
b98b483b
AR
959 FdbEntry *fdb_entry;
960 int r = 0;
961
962 LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
ea6ec096 963 r = fdb_entry_configure(link, fdb_entry);
b98b483b 964 if(r < 0) {
6a7a4e4d 965 log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
b98b483b
AR
966 break;
967 }
968 }
969
970 return r;
971}
972
1c4baffc 973static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
e1853b00
SS
974 _cleanup_link_unref_ Link *link = userdata;
975 int r;
976
6a7a4e4d 977 log_link_debug(link, "Set link");
e1853b00 978
1c4baffc 979 r = sd_netlink_message_get_errno(m);
e1853b00 980 if (r < 0 && r != -EEXIST) {
f2341e0a 981 log_link_error_errno(link, r, "Could not join netdev: %m");
e1853b00
SS
982 link_enter_failed(link);
983 return 1;
984 }
985
986 return 0;
987}
988
19070062 989static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
5da8149f 990 _cleanup_link_unref_ Link *link = userdata;
21b80ad1 991 const sd_bus_error *e;
1346b1f0 992
19070062 993 assert(m);
b226d99b
TG
994 assert(link);
995
5da8149f 996 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 997 return 1;
370e9930 998
21b80ad1
LP
999 e = sd_bus_message_get_error(m);
1000 if (e)
1001 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
1346b1f0
TG
1002
1003 return 1;
1004}
1005
3c9b8860 1006int link_set_hostname(Link *link, const char *hostname) {
21b80ad1 1007 int r;
1346b1f0 1008
b226d99b
TG
1009 assert(link);
1010 assert(link->manager);
1346b1f0 1011
dce391e7 1012 log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
1346b1f0 1013
3c9b8860
TG
1014 if (!link->manager->bus) {
1015 /* TODO: replace by assert when we can rely on kdbus */
6a7a4e4d 1016 log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
1017 return 0;
1018 }
1019
9c34154a 1020 r = sd_bus_call_method_async(
b226d99b 1021 link->manager->bus,
9c34154a 1022 NULL,
1346b1f0
TG
1023 "org.freedesktop.hostname1",
1024 "/org/freedesktop/hostname1",
1025 "org.freedesktop.hostname1",
9c34154a
UTL
1026 "SetHostname",
1027 set_hostname_handler,
1028 link,
1029 "sb",
1030 hostname,
1031 false);
1346b1f0 1032
6a7a4e4d
LP
1033 if (r < 0)
1034 return log_link_error_errno(link, r, "Could not set transient hostname: %m");
b226d99b
TG
1035
1036 link_ref(link);
1346b1f0 1037
5da8149f 1038 return 0;
1346b1f0
TG
1039}
1040
21b80ad1
LP
1041static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
1042 _cleanup_link_unref_ Link *link = userdata;
1043 const sd_bus_error *e;
1044
1045 assert(m);
1046 assert(link);
1047
1048 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1049 return 1;
1050
1051 e = sd_bus_message_get_error(m);
1052 if (e)
1053 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
1054
1055 return 1;
1056}
1057
64d6c229 1058int link_set_timezone(Link *link, const char *tz) {
21b80ad1
LP
1059 int r;
1060
1061 assert(link);
1062 assert(link->manager);
64d6c229 1063 assert(tz);
21b80ad1 1064
64d6c229 1065 log_link_debug(link, "Setting system timezone: '%s'", tz);
21b80ad1
LP
1066
1067 if (!link->manager->bus) {
1068 log_link_info(link, "Not connected to system bus, ignoring timezone.");
1069 return 0;
1070 }
1071
1072 r = sd_bus_call_method_async(
1073 link->manager->bus,
1074 NULL,
1075 "org.freedesktop.timedate1",
1076 "/org/freedesktop/timedate1",
1077 "org.freedesktop.timedate1",
1078 "SetTimezone",
1079 set_timezone_handler,
1080 link,
1081 "sb",
64d6c229 1082 tz,
21b80ad1
LP
1083 false);
1084 if (r < 0)
1085 return log_link_error_errno(link, r, "Could not set timezone: %m");
1086
1087 link_ref(link);
1088
1089 return 0;
1090}
1091
1c4baffc 1092static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1093 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
1094 int r;
1095
1096 assert(m);
1097 assert(link);
1098 assert(link->ifname);
1099
5da8149f 1100 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
1101 return 1;
1102
1c4baffc 1103 r = sd_netlink_message_get_errno(m);
c9ccc19f 1104 if (r < 0)
a2fae7bb 1105 log_link_warning_errno(link, r, "Could not set MTU: %m");
4f882b2a
TG
1106
1107 return 1;
1108}
1109
3c9b8860 1110int link_set_mtu(Link *link, uint32_t mtu) {
1c4baffc 1111 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f882b2a
TG
1112 int r;
1113
1114 assert(link);
1115 assert(link->manager);
1116 assert(link->manager->rtnl);
1117
6a7a4e4d 1118 log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
4f882b2a 1119
6a7a4e4d
LP
1120 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1121 if (r < 0)
1122 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
4f882b2a 1123
1c4baffc 1124 r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
6a7a4e4d
LP
1125 if (r < 0)
1126 return log_link_error_errno(link, r, "Could not append MTU: %m");
4f882b2a 1127
1c4baffc 1128 r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
6a7a4e4d
LP
1129 if (r < 0)
1130 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
4f882b2a 1131
ae941762 1132 link_ref(link);
b226d99b 1133
4f882b2a
TG
1134 return 0;
1135}
1136
e1853b00 1137static int link_set_bridge(Link *link) {
1c4baffc 1138 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
e1853b00
SS
1139 int r;
1140
1141 assert(link);
1142 assert(link->network);
1143
6a7a4e4d
LP
1144 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1145 if (r < 0)
1146 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
e1853b00
SS
1147
1148 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
6a7a4e4d
LP
1149 if (r < 0)
1150 return log_link_error_errno(link, r, "Could not set message family: %m");
e1853b00 1151
1c4baffc 1152 r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
6a7a4e4d
LP
1153 if (r < 0)
1154 return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
e1853b00 1155
84c34096 1156 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
eb7ff4dd
SS
1157 if (r < 0)
1158 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
1159
1160 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
1161 if (r < 0)
1162 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
1163
1164 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
1165 if (r < 0)
1166 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
1167
23da66bb 1168 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
eb7ff4dd
SS
1169 if (r < 0)
1170 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
1171
1172 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
1173 if (r < 0)
1174 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
1175
e1853b00 1176 if(link->network->cost != 0) {
1c4baffc 1177 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
6a7a4e4d
LP
1178 if (r < 0)
1179 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
e1853b00
SS
1180 }
1181
1c4baffc 1182 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1183 if (r < 0)
1184 return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
e1853b00 1185
1c4baffc 1186 r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
6a7a4e4d
LP
1187 if (r < 0)
1188 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
e1853b00
SS
1189
1190 link_ref(link);
1191
1192 return r;
1193}
1194
49699bac
SS
1195static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
1196 Link *link = userdata;
1197 int r;
1198
1199 assert(link);
1200 assert(link->network);
1201 assert(link->manager);
1202
9ef61f2e
DH
1203 switch (event) {
1204 case SD_LLDP_EVENT_UPDATE_INFO:
1205 r = sd_lldp_save(link->lldp, link->lldp_file);
1206 if (r < 0)
1207 log_link_warning_errno(link, r, "Could not save LLDP: %m");
49699bac 1208
9ef61f2e
DH
1209 break;
1210 default:
1211 break;
1212 }
49699bac
SS
1213}
1214
ff254138
TG
1215static int link_acquire_conf(Link *link) {
1216 int r;
1217
1218 assert(link);
1219 assert(link->network);
ff254138
TG
1220 assert(link->manager);
1221 assert(link->manager->event);
1222
78c958f8 1223 if (link_ipv4ll_enabled(link)) {
eb34d4af 1224 assert(link->ipv4ll);
ff254138 1225
6a7a4e4d 1226 log_link_debug(link, "Acquiring IPv4 link-local address");
5c1d3fc9
UTL
1227
1228 r = sd_ipv4ll_start(link->ipv4ll);
6a7a4e4d
LP
1229 if (r < 0)
1230 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
5c1d3fc9
UTL
1231 }
1232
78c958f8 1233 if (link_dhcp4_enabled(link)) {
eb34d4af 1234 assert(link->dhcp_client);
ff254138 1235
6a7a4e4d 1236 log_link_debug(link, "Acquiring DHCPv4 lease");
ab47d620 1237
5c1d3fc9 1238 r = sd_dhcp_client_start(link->dhcp_client);
6a7a4e4d
LP
1239 if (r < 0)
1240 return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
5c1d3fc9 1241 }
ff254138 1242
78c958f8 1243 if (link_dhcp6_enabled(link)) {
de1e9928 1244 assert(link->ndisc_router_discovery);
4138fb2c 1245
6a7a4e4d 1246 log_link_debug(link, "Discovering IPv6 routers");
4138fb2c 1247
de1e9928 1248 r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
6a7a4e4d 1249 if (r < 0)
ceabaf0f 1250 return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
4138fb2c
PF
1251 }
1252
ce43e484
SS
1253 if (link_lldp_enabled(link)) {
1254 assert(link->lldp);
1255
1256 log_link_debug(link, "Starting LLDP");
1257
1258 r = sd_lldp_start(link->lldp);
6a7a4e4d
LP
1259 if (r < 0)
1260 return log_link_warning_errno(link, r, "Could not start LLDP: %m");
ce43e484
SS
1261 }
1262
ff254138
TG
1263 return 0;
1264}
1265
a61bb41c 1266bool link_has_carrier(Link *link) {
deb2e523
TG
1267 /* see Documentation/networking/operstates.txt in the kernel sources */
1268
a61bb41c 1269 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1270 return true;
1271
a61bb41c 1272 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1273 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1274 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1275 return true;
1276
1277 return false;
1278}
1279
1c4baffc 1280static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1281 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1282 int r;
1283
1746cf2a
TG
1284 assert(link);
1285
5da8149f 1286 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1287 return 1;
1288
1c4baffc 1289 r = sd_netlink_message_get_errno(m);
6a7a4e4d
LP
1290 if (r < 0)
1291 /* we warn but don't fail the link, as it may be
1292 brought up later */
a2fae7bb 1293 log_link_warning_errno(link, r, "Could not bring up interface: %m");
45ad2c13 1294
f882c247
TG
1295 return 1;
1296}
1297
1298static int link_up(Link *link) {
1c4baffc 1299 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
5c3072ea 1300 uint8_t ipv6ll_mode;
f579559b
TG
1301 int r;
1302
f882c247 1303 assert(link);
c106cc36 1304 assert(link->network);
f882c247
TG
1305 assert(link->manager);
1306 assert(link->manager->rtnl);
1307
6a7a4e4d 1308 log_link_debug(link, "Bringing link up");
449f7554 1309
6a7a4e4d
LP
1310 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1311 if (r < 0)
1312 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
f579559b 1313
5d4795f3 1314 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
6a7a4e4d
LP
1315 if (r < 0)
1316 return log_link_error_errno(link, r, "Could not set link flags: %m");
fc25d7f8 1317
c106cc36 1318 if (link->network->mac) {
1c4baffc 1319 r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
6a7a4e4d
LP
1320 if (r < 0)
1321 return log_link_error_errno(link, r, "Could not set MAC address: %m");
c106cc36
TG
1322 }
1323
1324 if (link->network->mtu) {
1c4baffc 1325 r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
6a7a4e4d
LP
1326 if (r < 0)
1327 return log_link_error_errno(link, r, "Could not set MTU: %m");
c106cc36
TG
1328 }
1329
1c4baffc 1330 r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
6a7a4e4d
LP
1331 if (r < 0)
1332 return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
d0d6a4cd 1333
01d28f81
TG
1334 if (socket_ipv6_is_supported()) {
1335 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
1c4baffc 1336 r = sd_netlink_message_open_container(req, AF_INET6);
01d28f81
TG
1337 if (r < 0)
1338 return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
d0d6a4cd 1339
01d28f81 1340 ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
1c4baffc 1341 r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
01d28f81
TG
1342 if (r < 0)
1343 return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
d0d6a4cd 1344
01d28f81 1345 if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
1c4baffc 1346 r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
01d28f81
TG
1347 if (r < 0)
1348 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
1349 }
1350
1c4baffc 1351 r = sd_netlink_message_close_container(req);
6a7a4e4d 1352 if (r < 0)
01d28f81 1353 return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
7f77697a 1354 }
d0d6a4cd 1355
1c4baffc 1356 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1357 if (r < 0)
1358 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
d0d6a4cd 1359
1c4baffc 1360 r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
6a7a4e4d
LP
1361 if (r < 0)
1362 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
f579559b 1363
b226d99b
TG
1364 link_ref(link);
1365
f882c247
TG
1366 return 0;
1367}
1368
1c4baffc 1369static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
0d4ad91d
AR
1370 _cleanup_link_unref_ Link *link = userdata;
1371 int r;
1372
1373 assert(link);
1374
1375 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1376 return 1;
1377
1c4baffc 1378 r = sd_netlink_message_get_errno(m);
0d4ad91d 1379 if (r < 0)
a2fae7bb 1380 log_link_warning_errno(link, r, "Could not bring down interface: %m");
0d4ad91d
AR
1381
1382 return 1;
1383}
1384
1385static int link_down(Link *link) {
1c4baffc 1386 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
0d4ad91d
AR
1387 int r;
1388
1389 assert(link);
1390 assert(link->manager);
1391 assert(link->manager->rtnl);
1392
6a7a4e4d 1393 log_link_debug(link, "Bringing link down");
0d4ad91d
AR
1394
1395 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1396 RTM_SETLINK, link->ifindex);
6a7a4e4d
LP
1397 if (r < 0)
1398 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
0d4ad91d
AR
1399
1400 r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
6a7a4e4d
LP
1401 if (r < 0)
1402 return log_link_error_errno(link, r, "Could not set link flags: %m");
0d4ad91d 1403
1c4baffc 1404 r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
6a7a4e4d
LP
1405 if (r < 0)
1406 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
0d4ad91d
AR
1407
1408 link_ref(link);
1409
1410 return 0;
1411}
1412
1413static int link_handle_bound_to_list(Link *link) {
1414 Link *l;
1415 Iterator i;
1416 int r;
1417 bool required_up = false;
1418 bool link_is_up = false;
1419
1420 assert(link);
1421
1422 if (hashmap_isempty(link->bound_to_links))
1423 return 0;
1424
1425 if (link->flags & IFF_UP)
1426 link_is_up = true;
1427
1428 HASHMAP_FOREACH (l, link->bound_to_links, i)
1429 if (link_has_carrier(l)) {
1430 required_up = true;
1431 break;
1432 }
1433
1434 if (!required_up && link_is_up) {
1435 r = link_down(link);
1436 if (r < 0)
1437 return r;
1438 } else if (required_up && !link_is_up) {
1439 r = link_up(link);
1440 if (r < 0)
1441 return r;
1442 }
1443
1444 return 0;
1445}
1446
1447static int link_handle_bound_by_list(Link *link) {
1448 Iterator i;
1449 Link *l;
1450 int r;
1451
1452 assert(link);
1453
1454 if (hashmap_isempty(link->bound_by_links))
1455 return 0;
1456
1457 HASHMAP_FOREACH (l, link->bound_by_links, i) {
1458 r = link_handle_bound_to_list(l);
1459 if (r < 0)
1460 return r;
1461 }
1462
1463 return 0;
1464}
1465
1466static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
1467 int r;
1468
1469 assert(link);
1470 assert(carrier);
1471
1472 if (link == carrier)
1473 return 0;
1474
1475 if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
1476 return 0;
1477
1478 r = hashmap_ensure_allocated(h, NULL);
1479 if (r < 0)
1480 return r;
1481
1482 r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
1483 if (r < 0)
1484 return r;
1485
1486 return 0;
1487}
1488
1489static int link_new_bound_by_list(Link *link) {
1490 Manager *m;
1491 Link *carrier;
1492 Iterator i;
1493 int r;
1494 bool list_updated = false;
1495
1496 assert(link);
1497 assert(link->manager);
1498
1499 m = link->manager;
1500
1501 HASHMAP_FOREACH (carrier, m->links, i) {
1502 if (!carrier->network)
1503 continue;
1504
1505 if (strv_isempty(carrier->network->bind_carrier))
1506 continue;
1507
1508 if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
1509 r = link_put_carrier(link, carrier, &link->bound_by_links);
1510 if (r < 0)
1511 return r;
1512
1513 list_updated = true;
1514 }
1515 }
1516
1517 if (list_updated)
84de38c5 1518 link_dirty(link);
0d4ad91d
AR
1519
1520 HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
1521 r = link_put_carrier(carrier, link, &carrier->bound_to_links);
1522 if (r < 0)
1523 return r;
1524
84de38c5 1525 link_dirty(carrier);
0d4ad91d
AR
1526 }
1527
1528 return 0;
1529}
1530
1531static int link_new_bound_to_list(Link *link) {
1532 Manager *m;
1533 Link *carrier;
1534 Iterator i;
1535 int r;
1536 bool list_updated = false;
1537
1538 assert(link);
1539 assert(link->manager);
1540
1541 if (!link->network)
1542 return 0;
1543
1544 if (strv_isempty(link->network->bind_carrier))
1545 return 0;
1546
1547 m = link->manager;
1548
1549 HASHMAP_FOREACH (carrier, m->links, i) {
1550 if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
1551 r = link_put_carrier(link, carrier, &link->bound_to_links);
1552 if (r < 0)
1553 return r;
1554
1555 list_updated = true;
1556 }
1557 }
1558
1559 if (list_updated)
84de38c5 1560 link_dirty(link);
0d4ad91d
AR
1561
1562 HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
1563 r = link_put_carrier(carrier, link, &carrier->bound_by_links);
1564 if (r < 0)
1565 return r;
1566
84de38c5 1567 link_dirty(carrier);
0d4ad91d
AR
1568 }
1569
1570 return 0;
1571}
1572
1573static int link_new_carrier_maps(Link *link) {
1574 int r;
1575
1576 r = link_new_bound_by_list(link);
1577 if (r < 0)
1578 return r;
1579
1580 r = link_handle_bound_by_list(link);
1581 if (r < 0)
1582 return r;
1583
1584 r = link_new_bound_to_list(link);
1585 if (r < 0)
1586 return r;
1587
1588 r = link_handle_bound_to_list(link);
1589 if (r < 0)
1590 return r;
1591
1592 return 0;
1593}
1594
1595static void link_free_bound_to_list(Link *link) {
1596 Link *bound_to;
1597 Iterator i;
1598
1599 HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
1600 hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
1601
1602 if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
84de38c5 1603 link_dirty(bound_to);
0d4ad91d
AR
1604 }
1605
1606 return;
1607}
1608
1609static void link_free_bound_by_list(Link *link) {
1610 Link *bound_by;
1611 Iterator i;
1612
1613 HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
1614 hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
1615
1616 if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
84de38c5 1617 link_dirty(bound_by);
0d4ad91d
AR
1618 link_handle_bound_to_list(bound_by);
1619 }
1620 }
1621
1622 return;
1623}
1624
1625static void link_free_carrier_maps(Link *link) {
1626 bool list_updated = false;
1627
1628 assert(link);
1629
1630 if (!hashmap_isempty(link->bound_to_links)) {
1631 link_free_bound_to_list(link);
1632 list_updated = true;
1633 }
1634
1635 if (!hashmap_isempty(link->bound_by_links)) {
1636 link_free_bound_by_list(link);
1637 list_updated = true;
1638 }
1639
1640 if (list_updated)
84de38c5 1641 link_dirty(link);
0d4ad91d
AR
1642
1643 return;
1644}
1645
1646void link_drop(Link *link) {
1647 if (!link || link->state == LINK_STATE_LINGER)
1648 return;
1649
1650 link_set_state(link, LINK_STATE_LINGER);
1651
1652 link_free_carrier_maps(link);
1653
6a7a4e4d 1654 log_link_debug(link, "Link removed");
0d4ad91d 1655
84de38c5 1656 (void)unlink(link->state_file);
0d4ad91d
AR
1657 link_unref(link);
1658
1659 return;
1660}
1661
3f265037 1662static int link_joined(Link *link) {
f882c247
TG
1663 int r;
1664
ef1ba606 1665 assert(link);
f5be5601 1666 assert(link->network);
dd3efc09 1667
0d4ad91d
AR
1668 if (!hashmap_isempty(link->bound_to_links)) {
1669 r = link_handle_bound_to_list(link);
1670 if (r < 0)
1671 return r;
1672 } else if (!(link->flags & IFF_UP)) {
505f8da7
TG
1673 r = link_up(link);
1674 if (r < 0) {
1675 link_enter_failed(link);
1676 return r;
1677 }
ef1ba606 1678 }
f882c247 1679
e1853b00
SS
1680 if(link->network->bridge) {
1681 r = link_set_bridge(link);
6a7a4e4d
LP
1682 if (r < 0)
1683 log_link_error_errno(link, r, "Could not set bridge message: %m");
e1853b00
SS
1684 }
1685
fb6730c4 1686 return link_enter_set_addresses(link);
02b59d57
TG
1687}
1688
62e2d5bb 1689static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1690 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1691 int r;
1692
1746cf2a 1693 assert(link);
ef1ba606 1694 assert(link->network);
02b59d57 1695
52433f6b
TG
1696 link->enslaving --;
1697
5da8149f 1698 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1699 return 1;
1700
1c4baffc 1701 r = sd_netlink_message_get_errno(m);
856f962c 1702 if (r < 0 && r != -EEXIST) {
a2fae7bb 1703 log_link_error_errno(link, r, "Could not join netdev: %m");
ef1ba606
TG
1704 link_enter_failed(link);
1705 return 1;
ba179154 1706 } else
6a7a4e4d 1707 log_link_debug(link, "Joined netdev");
02b59d57 1708
856f962c 1709 if (link->enslaving <= 0)
3f265037 1710 link_joined(link);
02b59d57
TG
1711
1712 return 1;
1713}
1714
3f265037 1715static int link_enter_join_netdev(Link *link) {
6a0a2f86 1716 NetDev *netdev;
672682a6 1717 Iterator i;
02b59d57
TG
1718 int r;
1719
1720 assert(link);
1721 assert(link->network);
8434fd5c 1722 assert(link->state == LINK_STATE_PENDING);
02b59d57 1723
e331e246 1724 link_set_state(link, LINK_STATE_ENSLAVING);
02b59d57 1725
84de38c5 1726 link_dirty(link);
fe8db0c5 1727
7951dea2
SS
1728 if (!link->network->bridge &&
1729 !link->network->bond &&
6a0a2f86 1730 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1731 return link_joined(link);
02b59d57 1732
d9c67ea1 1733 if (link->network->bond) {
f2341e0a
LP
1734 log_struct(LOG_DEBUG,
1735 LOG_LINK_INTERFACE(link),
1736 LOG_NETDEV_INTERFACE(link->network->bond),
1737 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
1738 NULL);
1739
1740 r = netdev_join(link->network->bond, link, netdev_join_handler);
52433f6b 1741 if (r < 0) {
f2341e0a
LP
1742 log_struct_errno(LOG_WARNING, r,
1743 LOG_LINK_INTERFACE(link),
1744 LOG_NETDEV_INTERFACE(link->network->bond),
1745 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
1746 NULL);
1747
52433f6b
TG
1748 link_enter_failed(link);
1749 return r;
1750 }
1751
0ad6148e
MO
1752 link->enslaving ++;
1753 }
1754
d9c67ea1 1755 if (link->network->bridge) {
f2341e0a
LP
1756 log_struct(LOG_DEBUG,
1757 LOG_LINK_INTERFACE(link),
1758 LOG_NETDEV_INTERFACE(link->network->bridge),
1759 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
1760 NULL);
1761
1762 r = netdev_join(link->network->bridge, link, netdev_join_handler);
0ad6148e 1763 if (r < 0) {
f2341e0a
LP
1764 log_struct_errno(LOG_WARNING, r,
1765 LOG_LINK_INTERFACE(link),
1766 LOG_NETDEV_INTERFACE(link->network->bridge),
1767 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
1768 NULL),
0ad6148e
MO
1769 link_enter_failed(link);
1770 return r;
1771 }
1772
52433f6b
TG
1773 link->enslaving ++;
1774 }
1775
6a0a2f86 1776 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1777
f2341e0a
LP
1778 log_struct(LOG_DEBUG,
1779 LOG_LINK_INTERFACE(link),
1780 LOG_NETDEV_INTERFACE(netdev),
1781 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
1782 NULL);
1783
1784 r = netdev_join(netdev, link, netdev_join_handler);
7951dea2 1785 if (r < 0) {
f2341e0a
LP
1786 log_struct_errno(LOG_WARNING, r,
1787 LOG_LINK_INTERFACE(link),
1788 LOG_NETDEV_INTERFACE(netdev),
1789 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
1790 NULL);
326cb406
SS
1791 link_enter_failed(link);
1792 return r;
1793 }
1794
326cb406
SS
1795 link->enslaving ++;
1796 }
1797
ef1ba606
TG
1798 return 0;
1799}
1800
769d324c 1801static int link_set_ipv4_forward(Link *link) {
15dee3f0 1802 const char *p = NULL, *v;
5a8bcb67
LP
1803 int r;
1804
15dee3f0
LP
1805 if (link->flags & IFF_LOOPBACK)
1806 return 0;
1807
8add5f79
NO
1808 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1809 return 0;
1810
63c372cb 1811 p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1812 v = one_zero(link_ipv4_forward_enabled(link));
1813
4c1fc3e4 1814 r = write_string_file(p, v, 0);
15dee3f0
LP
1815 if (r < 0) {
1816 /* If the right value is set anyway, don't complain */
1817 if (verify_one_line_file(p, v) > 0)
1818 return 0;
1819
43c6d5ab 1820 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
15dee3f0 1821 }
43c6d5ab 1822
769d324c
LP
1823 return 0;
1824}
1825
1826static int link_set_ipv6_forward(Link *link) {
15dee3f0 1827 const char *p = NULL, *v = NULL;
769d324c
LP
1828 int r;
1829
fe027299
LP
1830 /* Make this a NOP if IPv6 is not available */
1831 if (!socket_ipv6_is_supported())
1832 return 0;
1833
15dee3f0
LP
1834 if (link->flags & IFF_LOOPBACK)
1835 return 0;
1836
8add5f79
NO
1837 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1838 return 0;
1839
63c372cb 1840 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1841 v = one_zero(link_ipv6_forward_enabled(link));
1842
4c1fc3e4 1843 r = write_string_file(p, v, 0);
15dee3f0
LP
1844 if (r < 0) {
1845 /* If the right value is set anyway, don't complain */
1846 if (verify_one_line_file(p, v) > 0)
1847 return 0;
1848
769d324c 1849 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
15dee3f0 1850 }
5a8bcb67
LP
1851
1852 return 0;
1853}
1854
49092e22 1855static int link_set_ipv6_privacy_extensions(Link *link) {
1f0d9695
LP
1856 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1857 IPv6PrivacyExtensions s;
49092e22
SS
1858 const char *p = NULL;
1859 int r;
1860
1861 /* Make this a NOP if IPv6 is not available */
1862 if (!socket_ipv6_is_supported())
1863 return 0;
1864
1f0d9695
LP
1865 s = link_ipv6_privacy_extensions(link);
1866 if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
49092e22
SS
1867 return 0;
1868
1869 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
1870 xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
1871
4c1fc3e4 1872 r = write_string_file(p, buf, 0);
1f0d9695
LP
1873 if (r < 0) {
1874 /* If the right value is set anyway, don't complain */
1875 if (verify_one_line_file(p, buf) > 0)
1876 return 0;
1877
49092e22 1878 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
1f0d9695 1879 }
49092e22
SS
1880
1881 return 0;
1882}
1883
4f2e437a
SS
1884static int link_set_ipv6_accept_ra(Link *link) {
1885 const char *p = NULL, *v = NULL;
4f2e437a
SS
1886 int r;
1887
1888 /* Make this a NOP if IPv6 is not available */
1889 if (!socket_ipv6_is_supported())
1890 return 0;
1891
1892 if (link->flags & IFF_LOOPBACK)
1893 return 0;
1894
6a512301
GM
1895 /* If unset use system default (enabled if local forwarding is disabled.
1896 * disabled if local forwarding is enabled).
1897 * If set, ignore or enforce RA independent of local forwarding state.
4f2e437a 1898 */
ebf98081 1899 if (link->network->ipv6_accept_ra < 0)
6a512301
GM
1900 /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
1901 v = "1";
ebf98081 1902 else if (link->network->ipv6_accept_ra > 0)
6a512301
GM
1903 /* "2" means accept RA even if ip_forward is enabled */
1904 v = "2";
ebf98081 1905 else
6a512301
GM
1906 /* "0" means ignore RA */
1907 v = "0";
ebf98081 1908
4f2e437a 1909 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
4f2e437a
SS
1910
1911 r = write_string_file(p, v, 0);
1912 if (r < 0) {
1913 /* If the right value is set anyway, don't complain */
1914 if (verify_one_line_file(p, v) > 0)
1915 return 0;
1916
1917 log_link_warning_errno(link, r, "Cannot configure IPv6 accept_ra for interface: %m");
1918 }
1919
1920 return 0;
1921}
1922
8749cbcd
SS
1923static int link_set_ipv6_dad_transmits(Link *link) {
1924 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1925 const char *p = NULL;
1926 int r;
1927
1928 /* Make this a NOP if IPv6 is not available */
1929 if (!socket_ipv6_is_supported())
1930 return 0;
1931
1932 if (link->flags & IFF_LOOPBACK)
1933 return 0;
1934
1935 if (link->network->ipv6_dad_transmits < 0)
1936 return 0;
1937
1938 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
1939
1940 xsprintf(buf, "%u", link->network->ipv6_dad_transmits);
1941
1942 r = write_string_file(p, buf, 0);
1943 if (r < 0) {
1944 /* If the right value is set anyway, don't complain */
1945 if (verify_one_line_file(p, buf) > 0)
1946 return 0;
1947
1948 log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
1949 }
1950
1951 return 0;
1952}
1953
a748b692 1954static int link_configure(Link *link) {
02b59d57
TG
1955 int r;
1956
ef1ba606 1957 assert(link);
b22d8a00 1958 assert(link->network);
8434fd5c 1959 assert(link->state == LINK_STATE_PENDING);
a748b692 1960
b98b483b
AR
1961 r = link_set_bridge_fdb(link);
1962 if (r < 0)
1963 return r;
1964
769d324c
LP
1965 r = link_set_ipv4_forward(link);
1966 if (r < 0)
1967 return r;
1968
1969 r = link_set_ipv6_forward(link);
5a8bcb67
LP
1970 if (r < 0)
1971 return r;
1972
49092e22
SS
1973 r = link_set_ipv6_privacy_extensions(link);
1974 if (r < 0)
1975 return r;
1976
4f2e437a
SS
1977 r = link_set_ipv6_accept_ra(link);
1978 if (r < 0)
1979 return r;
1980
8749cbcd
SS
1981 r = link_set_ipv6_dad_transmits(link);
1982 if (r < 0)
1983 return r;
1984
78c958f8 1985 if (link_ipv4ll_enabled(link)) {
b22d8a00 1986 r = ipv4ll_configure(link);
eb34d4af
TG
1987 if (r < 0)
1988 return r;
1989 }
1990
78c958f8 1991 if (link_dhcp4_enabled(link)) {
3c9b8860 1992 r = dhcp4_configure(link);
eb34d4af
TG
1993 if (r < 0)
1994 return r;
eb34d4af
TG
1995 }
1996
78c958f8 1997 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1998 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1999 if (r < 0)
2000 return r;
2001
2002 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
2003 if (r < 0)
2004 return r;
dd43110f
TG
2005 }
2006
78c958f8 2007 if (link_dhcp6_enabled(link)) {
de1e9928 2008 r = ndisc_configure(link);
4138fb2c
PF
2009 if (r < 0)
2010 return r;
2011 }
2012
ce43e484
SS
2013 if (link_lldp_enabled(link)) {
2014 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
2015 if (r < 0)
2016 return r;
2017
2018 r = sd_lldp_attach_event(link->lldp, NULL, 0);
2019 if (r < 0)
2020 return r;
49699bac
SS
2021
2022 r = sd_lldp_set_callback(link->lldp,
2023 lldp_handler, link);
2024 if (r < 0)
2025 return r;
ce43e484
SS
2026 }
2027
a61bb41c 2028 if (link_has_carrier(link)) {
1e9be60b
TG
2029 r = link_acquire_conf(link);
2030 if (r < 0)
2031 return r;
cc544d5f 2032 }
1e9be60b 2033
3f265037 2034 return link_enter_join_netdev(link);
505f8da7
TG
2035}
2036
1c4baffc 2037static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860 2038 void *userdata) {
5da8149f 2039 _cleanup_link_unref_ Link *link = userdata;
505f8da7 2040 Network *network;
505f8da7
TG
2041 int r;
2042
2043 assert(link);
2044 assert(link->ifname);
2045 assert(link->manager);
2046
8434fd5c 2047 if (link->state != LINK_STATE_PENDING)
5da8149f 2048 return 1;
505f8da7 2049
6a7a4e4d 2050 log_link_debug(link, "Link state is up-to-date");
505f8da7 2051
0d4ad91d
AR
2052 r = link_new_bound_by_list(link);
2053 if (r < 0)
2054 return r;
2055
2056 r = link_handle_bound_by_list(link);
2057 if (r < 0)
2058 return r;
2059
3c9b8860
TG
2060 r = network_get(link->manager, link->udev_device, link->ifname,
2061 &link->mac, &network);
57bd6899
TG
2062 if (r == -ENOENT) {
2063 link_enter_unmanaged(link);
5da8149f 2064 return 1;
57bd6899
TG
2065 } else if (r < 0)
2066 return r;
505f8da7 2067
bd2efe92 2068 if (link->flags & IFF_LOOPBACK) {
d0d6a4cd 2069 if (network->link_local != ADDRESS_FAMILY_NO)
6a7a4e4d 2070 log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
78c958f8 2071
cb9fc36a 2072 if (network->dhcp != ADDRESS_FAMILY_NO)
6a7a4e4d 2073 log_link_debug(link, "Ignoring DHCP clients for loopback link");
78c958f8
TG
2074
2075 if (network->dhcp_server)
6a7a4e4d 2076 log_link_debug(link, "Ignoring DHCP server for loopback link");
bd2efe92
TG
2077 }
2078
505f8da7
TG
2079 r = network_apply(link->manager, network, link);
2080 if (r < 0)
2081 return r;
2082
0d4ad91d
AR
2083 r = link_new_bound_to_list(link);
2084 if (r < 0)
2085 return r;
2086
a748b692
TG
2087 r = link_configure(link);
2088 if (r < 0)
2089 return r;
2090
5da8149f 2091 return 1;
505f8da7
TG
2092}
2093
4f561e8e 2094int link_initialized(Link *link, struct udev_device *device) {
1c4baffc 2095 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f561e8e
TG
2096 int r;
2097
2098 assert(link);
2099 assert(link->manager);
2100 assert(link->manager->rtnl);
2101 assert(device);
2102
8434fd5c 2103 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
2104 return 0;
2105
679b3605
TG
2106 if (link->udev_device)
2107 return 0;
2108
79008bdd 2109 log_link_debug(link, "udev initialized link");
4f561e8e
TG
2110
2111 link->udev_device = udev_device_ref(device);
2112
3c9b8860
TG
2113 /* udev has initialized the link, but we don't know if we have yet
2114 * processed the NEWLINK messages with the latest state. Do a GETLINK,
2115 * when it returns we know that the pending NEWLINKs have already been
2116 * processed and that we are up-to-date */
4f561e8e 2117
3c9b8860
TG
2118 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
2119 link->ifindex);
4f561e8e
TG
2120 if (r < 0)
2121 return r;
2122
1c4baffc 2123 r = sd_netlink_call_async(link->manager->rtnl, req,
3c9b8860 2124 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
2125 if (r < 0)
2126 return r;
2127
5da8149f
TG
2128 link_ref(link);
2129
4f561e8e
TG
2130 return 0;
2131}
2132
1c4baffc 2133int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
505f8da7
TG
2134 Link *link;
2135 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2136 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2137 int r;
2138
2139 assert(m);
fbbeb65a 2140 assert(m->rtnl);
505f8da7
TG
2141 assert(message);
2142 assert(ret);
2143
2144 r = link_new(m, message, ret);
2145 if (r < 0)
2146 return r;
2147
2148 link = *ret;
2149
6a7a4e4d 2150 log_link_debug(link, "Link %d added", link->ifindex);
505f8da7 2151
75f86906 2152 if (detect_container() <= 0) {
505f8da7 2153 /* not in a container, udev will be around */
ae06ab10 2154 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7 2155 device = udev_device_new_from_device_id(m->udev, ifindex_str);
5c416fc4
TG
2156 if (!device) {
2157 r = log_link_warning_errno(link, errno, "Could not find udev device: %m");
2158 goto failed;
2159 }
505f8da7 2160
3c4cb064 2161 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 2162 /* not yet ready */
79008bdd 2163 log_link_debug(link, "link pending udev initialization...");
505f8da7 2164 return 0;
3c4cb064 2165 }
505f8da7 2166
4f561e8e
TG
2167 r = link_initialized(link, device);
2168 if (r < 0)
5c416fc4 2169 goto failed;
4f561e8e 2170 } else {
5da8149f
TG
2171 /* we are calling a callback directly, so must take a ref */
2172 link_ref(link);
2173
4f561e8e
TG
2174 r = link_initialized_and_synced(m->rtnl, NULL, link);
2175 if (r < 0)
5c416fc4 2176 goto failed;
4f561e8e 2177 }
505f8da7 2178
a748b692 2179 return 0;
5c416fc4
TG
2180failed:
2181 link_enter_failed(link);
2182 return r;
a748b692
TG
2183}
2184
9c0a72f9
TG
2185static int link_carrier_gained(Link *link) {
2186 int r;
2187
2188 assert(link);
2189
2190 if (link->network) {
2191 r = link_acquire_conf(link);
2192 if (r < 0) {
2193 link_enter_failed(link);
2194 return r;
2195 }
2196 }
2197
0d4ad91d
AR
2198 r = link_handle_bound_by_list(link);
2199 if (r < 0)
2200 return r;
2201
9c0a72f9
TG
2202 return 0;
2203}
2204
2205static int link_carrier_lost(Link *link) {
2206 int r;
2207
2208 assert(link);
2209
2210 r = link_stop_clients(link);
2211 if (r < 0) {
2212 link_enter_failed(link);
2213 return r;
2214 }
2215
0d4ad91d
AR
2216 r = link_handle_bound_by_list(link);
2217 if (r < 0)
2218 return r;
2219
9c0a72f9
TG
2220 return 0;
2221}
2222
2223int link_carrier_reset(Link *link) {
2224 int r;
2225
2226 assert(link);
2227
2228 if (link_has_carrier(link)) {
2229 r = link_carrier_lost(link);
2230 if (r < 0)
2231 return r;
2232
2233 r = link_carrier_gained(link);
2234 if (r < 0)
2235 return r;
2236
6a7a4e4d 2237 log_link_info(link, "Reset carrier");
9c0a72f9
TG
2238 }
2239
2240 return 0;
2241}
2242
2243
1c4baffc 2244int link_update(Link *link, sd_netlink_message *m) {
c49b33ac 2245 struct ether_addr mac;
ca4e095a 2246 const char *ifname;
afe7fd56 2247 uint32_t mtu;
a61bb41c 2248 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
2249 int r;
2250
dd3efc09 2251 assert(link);
b8941f74 2252 assert(link->ifname);
22936833
TG
2253 assert(m);
2254
7619683b
TG
2255 if (link->state == LINK_STATE_LINGER) {
2256 link_ref(link);
6a7a4e4d 2257 log_link_info(link, "Link readded");
e331e246 2258 link_set_state(link, LINK_STATE_ENSLAVING);
0d4ad91d
AR
2259
2260 r = link_new_carrier_maps(link);
2261 if (r < 0)
2262 return r;
7619683b
TG
2263 }
2264
1c4baffc 2265 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
b8941f74 2266 if (r >= 0 && !streq(ifname, link->ifname)) {
6a7a4e4d 2267 log_link_info(link, "Renamed to %s", ifname);
b8941f74 2268
0d4ad91d
AR
2269 link_free_carrier_maps(link);
2270
2fc09a9c
DM
2271 r = free_and_strdup(&link->ifname, ifname);
2272 if (r < 0)
2273 return r;
0d4ad91d
AR
2274
2275 r = link_new_carrier_maps(link);
2276 if (r < 0)
2277 return r;
b8941f74
TG
2278 }
2279
1c4baffc 2280 r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
afe7fd56
TG
2281 if (r >= 0 && mtu > 0) {
2282 link->mtu = mtu;
2283 if (!link->original_mtu) {
2284 link->original_mtu = mtu;
6a7a4e4d 2285 log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
afe7fd56
TG
2286 }
2287
2288 if (link->dhcp_client) {
3c9b8860
TG
2289 r = sd_dhcp_client_set_mtu(link->dhcp_client,
2290 link->mtu);
afe7fd56 2291 if (r < 0) {
6a7a4e4d 2292 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
afe7fd56
TG
2293 return r;
2294 }
2295 }
9842de0d 2296 }
69629de9 2297
e9189a1f
TG
2298 /* The kernel may broadcast NEWLINK messages without the MAC address
2299 set, simply ignore them. */
1c4baffc 2300 r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 2301 if (r >= 0) {
3c9b8860
TG
2302 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
2303 ETH_ALEN)) {
c49b33ac 2304
3c9b8860
TG
2305 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
2306 ETH_ALEN);
c49b33ac 2307
79008bdd 2308 log_link_debug(link, "MAC address: "
20861203
TG
2309 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2310 mac.ether_addr_octet[0],
2311 mac.ether_addr_octet[1],
2312 mac.ether_addr_octet[2],
2313 mac.ether_addr_octet[3],
2314 mac.ether_addr_octet[4],
2315 mac.ether_addr_octet[5]);
c49b33ac 2316
20861203
TG
2317 if (link->ipv4ll) {
2318 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
6a7a4e4d
LP
2319 if (r < 0)
2320 return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
c49b33ac 2321 }
c49b33ac 2322
20861203 2323 if (link->dhcp_client) {
3c9b8860 2324 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
2325 (const uint8_t *) &link->mac,
2326 sizeof (link->mac),
2327 ARPHRD_ETHER);
6a7a4e4d
LP
2328 if (r < 0)
2329 return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
c49b33ac 2330 }
4138fb2c
PF
2331
2332 if (link->dhcp6_client) {
2333 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
2334 (const uint8_t *) &link->mac,
2335 sizeof (link->mac),
2336 ARPHRD_ETHER);
6a7a4e4d
LP
2337 if (r < 0)
2338 return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
4138fb2c 2339 }
c49b33ac 2340 }
4f882b2a
TG
2341 }
2342
a61bb41c
TG
2343 had_carrier = link_has_carrier(link);
2344
2345 r = link_update_flags(link, m);
2346 if (r < 0)
2347 return r;
2348
2349 carrier_gained = !had_carrier && link_has_carrier(link);
2350 carrier_lost = had_carrier && !link_has_carrier(link);
2351
2352 if (carrier_gained) {
6a7a4e4d 2353 log_link_info(link, "Gained carrier");
a61bb41c 2354
9c0a72f9
TG
2355 r = link_carrier_gained(link);
2356 if (r < 0)
2357 return r;
a61bb41c 2358 } else if (carrier_lost) {
6a7a4e4d 2359 log_link_info(link, "Lost carrier");
a61bb41c 2360
9c0a72f9
TG
2361 r = link_carrier_lost(link);
2362 if (r < 0)
a61bb41c 2363 return r;
9c0a72f9 2364
a61bb41c
TG
2365 }
2366
2367 return 0;
dd3efc09 2368}
fe8db0c5
TG
2369
2370int link_save(Link *link) {
68a8723c 2371 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2372 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2373 const char *admin_state, *oper_state;
e7780c8d 2374 Address *a;
c1eb9872 2375 Route *route;
e7780c8d 2376 Iterator i;
fe8db0c5
TG
2377 int r;
2378
2379 assert(link);
2380 assert(link->state_file);
68a8723c 2381 assert(link->lease_file);
bbf7c048
TG
2382 assert(link->manager);
2383
370e9930
TG
2384 if (link->state == LINK_STATE_LINGER) {
2385 unlink(link->state_file);
2386 return 0;
2387 }
2388
deb2e523
TG
2389 admin_state = link_state_to_string(link->state);
2390 assert(admin_state);
2391
e375dcde
TG
2392 oper_state = link_operstate_to_string(link->operstate);
2393 assert(oper_state);
deb2e523 2394
fe8db0c5
TG
2395 r = fopen_temporary(link->state_file, &f, &temp_path);
2396 if (r < 0)
6a7a4e4d 2397 goto fail;
fe8db0c5
TG
2398
2399 fchmod(fileno(f), 0644);
2400
2401 fprintf(f,
2402 "# This is private data. Do not parse.\n"
deb2e523 2403 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
2404 "OPER_STATE=%s\n",
2405 admin_state, oper_state);
fe8db0c5 2406
bcb7a07e 2407 if (link->network) {
ea352b40
LP
2408 char **address, **domain;
2409 bool space;
07bdc70d
PF
2410 sd_dhcp6_lease *dhcp6_lease = NULL;
2411
2412 if (link->dhcp6_client) {
2413 r = sd_dhcp6_client_get_lease(link->dhcp6_client,
2414 &dhcp6_lease);
2415 if (r < 0)
2416 log_link_debug(link, "No DHCPv6 lease");
2417 }
b0e39c82 2418
adc5b2e2
TG
2419 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
2420
b0e39c82 2421 fputs("DNS=", f);
ea352b40
LP
2422 space = false;
2423 STRV_FOREACH(address, link->network->dns) {
2424 if (space)
2425 fputc(' ', f);
2426 fputs(*address, f);
2427 space = true;
2428 }
d5314fff 2429
b0e39c82
TG
2430 if (link->network->dhcp_dns &&
2431 link->dhcp_lease) {
2432 const struct in_addr *addresses;
2433
2434 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2435 if (r > 0) {
ea352b40
LP
2436 if (space)
2437 fputc(' ', f);
b0e39c82 2438 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2439 space = true;
2440 }
2441 }
2442
2443 if (link->network->dhcp_dns && dhcp6_lease) {
2444 struct in6_addr *in6_addrs;
2445
2446 r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
2447 if (r > 0) {
2448 if (space)
2449 fputc(' ', f);
2450 serialize_in6_addrs(f, in6_addrs, r);
b0e39c82
TG
2451 }
2452 }
2453
2ce40956 2454 fputc('\n', f);
b0e39c82 2455
2ce40956 2456 fputs("NTP=", f);
ea352b40
LP
2457 space = false;
2458 STRV_FOREACH(address, link->network->ntp) {
2459 if (space)
2460 fputc(' ', f);
2461 fputs(*address, f);
2462 space = true;
2463 }
d5314fff 2464
b0e39c82
TG
2465 if (link->network->dhcp_ntp &&
2466 link->dhcp_lease) {
2467 const struct in_addr *addresses;
2468
2469 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2470 if (r > 0) {
ea352b40
LP
2471 if (space)
2472 fputc(' ', f);
b0e39c82 2473 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2474 space = true;
2475 }
2476 }
2477
2478 if (link->network->dhcp_ntp && dhcp6_lease) {
2479 struct in6_addr *in6_addrs;
2480 char **hosts;
2481 char **hostname;
2482
2483 r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
2484 &in6_addrs);
2485 if (r > 0) {
2486 if (space)
2487 fputc(' ', f);
2488 serialize_in6_addrs(f, in6_addrs, r);
2489 space = true;
2490 }
2491
2492 r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
2493 if (r > 0) {
2494 STRV_FOREACH(hostname, hosts) {
2495 if (space)
2496 fputc(' ', f);
2497 fputs(*hostname, f);
2498 space = true;
2499 }
b0e39c82
TG
2500 }
2501 }
2502
2ce40956 2503 fputc('\n', f);
bd8f6538 2504
2ce40956 2505 fputs("DOMAINS=", f);
ea352b40
LP
2506 space = false;
2507 STRV_FOREACH(domain, link->network->domains) {
2508 if (space)
2509 fputc(' ', f);
2510 fputs(*domain, f);
2511 space = true;
2512 }
d5314fff 2513
ad0734e8 2514 if (link->network->dhcp_domains &&
9b4d1882
TG
2515 link->dhcp_lease) {
2516 const char *domainname;
2517
2518 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 2519 if (r >= 0) {
ea352b40
LP
2520 if (space)
2521 fputc(' ', f);
6192b846 2522 fputs(domainname, f);
07bdc70d
PF
2523 space = true;
2524 }
2525 }
2526
2527 if (link->network->dhcp_domains && dhcp6_lease) {
2528 char **domains;
2529
2530 r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
2531 if (r >= 0) {
2532 STRV_FOREACH(domain, domains) {
2533 if (space)
2534 fputc(' ', f);
2535 fputs(*domain, f);
2536 space = true;
2537 }
6192b846 2538 }
9b4d1882
TG
2539 }
2540
2ce40956 2541 fputc('\n', f);
6192b846 2542
67272d15
TG
2543 fprintf(f, "WILDCARD_DOMAIN=%s\n",
2544 yes_no(link->network->wildcard_domain));
2545
3c9b8860 2546 fprintf(f, "LLMNR=%s\n",
a7e5da6e 2547 resolve_support_to_string(link->network->llmnr));
e7780c8d 2548
2ce40956 2549 fputs("ADDRESSES=", f);
e7780c8d
TG
2550 space = false;
2551 SET_FOREACH(a, link->addresses, i) {
2552 _cleanup_free_ char *address_str = NULL;
2553
2554 r = in_addr_to_string(a->family, &a->in_addr, &address_str);
2555 if (r < 0)
2556 goto fail;
2557
e7780c8d
TG
2558 fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
2559 space = true;
2560 }
2561
2ce40956 2562 fputc('\n', f);
c1eb9872
TG
2563
2564 fputs("ROUTES=", f);
2565 space = false;
2566 SET_FOREACH(route, link->routes, i) {
2567 _cleanup_free_ char *route_str = NULL;
2568
2569 r = in_addr_to_string(route->family, &route->dst, &route_str);
2570 if (r < 0)
2571 goto fail;
2572
2573 fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu", space ? " " : "", route_str,
2574 route->dst_prefixlen, route->tos, route->priority, route->table);
2575 space = true;
2576 }
2577
2578 fputc('\n', f);
bcb7a07e 2579 }
7374f9d8 2580
0d4ad91d
AR
2581 if (!hashmap_isempty(link->bound_to_links)) {
2582 Link *carrier;
0d4ad91d
AR
2583 bool space = false;
2584
2585 fputs("CARRIER_BOUND_TO=", f);
2586 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
2587 if (space)
2588 fputc(' ', f);
2589 fputs(carrier->ifname, f);
2590 space = true;
2591 }
2592
2ce40956 2593 fputc('\n', f);
0d4ad91d
AR
2594 }
2595
2596 if (!hashmap_isempty(link->bound_by_links)) {
2597 Link *carrier;
0d4ad91d
AR
2598 bool space = false;
2599
2600 fputs("CARRIER_BOUND_BY=", f);
0d4ad91d
AR
2601 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
2602 if (space)
2603 fputc(' ', f);
2604 fputs(carrier->ifname, f);
2605 space = true;
2606 }
2607
2ce40956 2608 fputc('\n', f);
0d4ad91d
AR
2609 }
2610
8eb9058d
LP
2611 if (link->dhcp_lease) {
2612 const char *tz = NULL;
2613
2614 r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
2615 if (r >= 0)
2616 fprintf(f, "TIMEZONE=%s\n", tz);
2617 }
2618
fe8db0c5 2619 if (link->dhcp_lease) {
d9876a52
TG
2620 assert(link->network);
2621
bd91b83e 2622 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 2623 if (r < 0)
c2d6bd61 2624 goto fail;
fe8db0c5 2625
7374f9d8 2626 fprintf(f,
b0e39c82
TG
2627 "DHCP_LEASE=%s\n",
2628 link->lease_file);
deb2e523 2629 } else
68a8723c 2630 unlink(link->lease_file);
fe8db0c5 2631
49699bac
SS
2632 if (link->lldp) {
2633 assert(link->network);
2634
2635 r = sd_lldp_save(link->lldp, link->lldp_file);
2636 if (r < 0)
2637 goto fail;
2638
2639 fprintf(f,
2640 "LLDP_FILE=%s\n",
2641 link->lldp_file);
2642 } else
2643 unlink(link->lldp_file);
2644
c2d6bd61
LP
2645 r = fflush_and_check(f);
2646 if (r < 0)
2647 goto fail;
fe8db0c5 2648
c2d6bd61 2649 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 2650 r = -errno;
c2d6bd61 2651 goto fail;
fe8db0c5
TG
2652 }
2653
c2d6bd61 2654 return 0;
dacd6cee 2655
c2d6bd61 2656fail:
6a7a4e4d 2657 (void) unlink(link->state_file);
6a7a4e4d
LP
2658 if (temp_path)
2659 (void) unlink(temp_path);
2660
dacd6cee 2661 return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
fe8db0c5
TG
2662}
2663
84de38c5
TG
2664/* The serialized state in /run is no longer up-to-date. */
2665void link_dirty(Link *link) {
2666 int r;
2667
2668 assert(link);
2669
2670 r = set_ensure_allocated(&link->manager->dirty_links, NULL);
2671 if (r < 0)
2672 /* allocation errors are ignored */
2673 return;
2674
2675 r = set_put(link->manager->dirty_links, link);
2676 if (r < 0)
2677 /* allocation errors are ignored */
2678 return;
2679
2680 link_ref(link);
2681}
2682
2683/* The serialized state in /run is up-to-date */
2684void link_clean(Link *link) {
2685 assert(link);
2686 assert(link->manager);
2687
2688 set_remove(link->manager->dirty_links, link);
2689 link_unref(link);
2690}
2691
fe8db0c5 2692static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 2693 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
2694 [LINK_STATE_ENSLAVING] = "configuring",
2695 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
2696 [LINK_STATE_SETTING_ROUTES] = "configuring",
2697 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2698 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2699 [LINK_STATE_FAILED] = "failed",
370e9930 2700 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2701};
2702
2703DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2704
2705static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
2706 [LINK_OPERSTATE_OFF] = "off",
2707 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
2708 [LINK_OPERSTATE_DORMANT] = "dormant",
2709 [LINK_OPERSTATE_CARRIER] = "carrier",
2710 [LINK_OPERSTATE_DEGRADED] = "degraded",
2711 [LINK_OPERSTATE_ROUTABLE] = "routable",
2712};
2713
2714DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);