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