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