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