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