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