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