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