]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: fix a couple of format string types
[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
eb3da901
LP
1862 r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1863 if (r < 0)
43c6d5ab
LP
1864 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
1865
769d324c
LP
1866 return 0;
1867}
1868
1869static int link_set_ipv6_forward(Link *link) {
15dee3f0 1870 const char *p = NULL, *v = NULL;
769d324c
LP
1871 int r;
1872
fe027299
LP
1873 /* Make this a NOP if IPv6 is not available */
1874 if (!socket_ipv6_is_supported())
1875 return 0;
1876
15dee3f0
LP
1877 if (link->flags & IFF_LOOPBACK)
1878 return 0;
1879
8add5f79
NO
1880 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1881 return 0;
1882
63c372cb 1883 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1884 v = one_zero(link_ipv6_forward_enabled(link));
1885
eb3da901
LP
1886 r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1887 if (r < 0)
769d324c 1888 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
5a8bcb67
LP
1889
1890 return 0;
1891}
1892
49092e22 1893static int link_set_ipv6_privacy_extensions(Link *link) {
1f0d9695
LP
1894 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1895 IPv6PrivacyExtensions s;
49092e22
SS
1896 const char *p = NULL;
1897 int r;
1898
1899 /* Make this a NOP if IPv6 is not available */
1900 if (!socket_ipv6_is_supported())
1901 return 0;
1902
1f0d9695 1903 s = link_ipv6_privacy_extensions(link);
66a6bd68 1904 if (s < 0)
49092e22
SS
1905 return 0;
1906
1907 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
66a6bd68 1908 xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
49092e22 1909
eb3da901
LP
1910 r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1911 if (r < 0)
49092e22
SS
1912 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
1913
1914 return 0;
1915}
1916
4f2e437a 1917static int link_set_ipv6_accept_ra(Link *link) {
3b015d40 1918 const char *p = NULL;
4f2e437a
SS
1919 int r;
1920
1921 /* Make this a NOP if IPv6 is not available */
1922 if (!socket_ipv6_is_supported())
1923 return 0;
1924
1925 if (link->flags & IFF_LOOPBACK)
1926 return 0;
1927
4f2e437a 1928 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
4f2e437a 1929
66a6bd68 1930 /* We handle router advertisments ourselves, tell the kernel to GTFO */
eb3da901
LP
1931 r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1932 if (r < 0)
3b015d40 1933 log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
4f2e437a
SS
1934
1935 return 0;
1936}
1937
8749cbcd 1938static int link_set_ipv6_dad_transmits(Link *link) {
66a6bd68 1939 char buf[DECIMAL_STR_MAX(int) + 1];
8749cbcd
SS
1940 const char *p = NULL;
1941 int r;
1942
1943 /* Make this a NOP if IPv6 is not available */
1944 if (!socket_ipv6_is_supported())
1945 return 0;
1946
1947 if (link->flags & IFF_LOOPBACK)
1948 return 0;
1949
1950 if (link->network->ipv6_dad_transmits < 0)
1951 return 0;
1952
1953 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
66a6bd68 1954 xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
8749cbcd 1955
eb3da901
LP
1956 r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1957 if (r < 0)
8749cbcd 1958 log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
8749cbcd
SS
1959
1960 return 0;
1961}
1962
b69c3180 1963static int link_set_ipv6_hop_limit(Link *link) {
66a6bd68 1964 char buf[DECIMAL_STR_MAX(int) + 1];
b69c3180
SS
1965 const char *p = NULL;
1966 int r;
1967
1968 /* Make this a NOP if IPv6 is not available */
1969 if (!socket_ipv6_is_supported())
1970 return 0;
1971
1972 if (link->flags & IFF_LOOPBACK)
1973 return 0;
1974
1975 if (link->network->ipv6_hop_limit < 0)
1976 return 0;
1977
1978 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
66a6bd68 1979 xsprintf(buf, "%i", link->network->ipv6_hop_limit);
b69c3180 1980
eb3da901
LP
1981 r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
1982 if (r < 0)
b69c3180 1983 log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
b69c3180
SS
1984
1985 return 0;
1986}
1987
5e5b137a
TG
1988static int link_drop_foreign_config(Link *link) {
1989 Address *address;
1990 Route *route;
1991 Iterator i;
1992 int r;
1993
1994 SET_FOREACH(address, link->addresses_foreign, i) {
1995 /* we consider IPv6LL addresses to be managed by the kernel */
1996 if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1)
1997 continue;
1998
1999 r = address_remove(address, link, link_address_remove_handler);
2000 if (r < 0)
2001 return r;
2002 }
2003
2004 SET_FOREACH(route, link->routes_foreign, i) {
2005 /* do not touch routes managed by the kernel */
2006 if (route->protocol == RTPROT_KERNEL)
2007 continue;
2008
2009 r = route_remove(route, link, link_address_remove_handler);
2010 if (r < 0)
2011 return r;
2012 }
2013
2014 return 0;
2015}
2016
a748b692 2017static int link_configure(Link *link) {
02b59d57
TG
2018 int r;
2019
ef1ba606 2020 assert(link);
b22d8a00 2021 assert(link->network);
8434fd5c 2022 assert(link->state == LINK_STATE_PENDING);
a748b692 2023
5e5b137a
TG
2024 r = link_drop_foreign_config(link);
2025 if (r < 0)
2026 return r;
2027
b98b483b
AR
2028 r = link_set_bridge_fdb(link);
2029 if (r < 0)
2030 return r;
2031
769d324c
LP
2032 r = link_set_ipv4_forward(link);
2033 if (r < 0)
2034 return r;
2035
2036 r = link_set_ipv6_forward(link);
5a8bcb67
LP
2037 if (r < 0)
2038 return r;
2039
49092e22
SS
2040 r = link_set_ipv6_privacy_extensions(link);
2041 if (r < 0)
2042 return r;
2043
4f2e437a
SS
2044 r = link_set_ipv6_accept_ra(link);
2045 if (r < 0)
2046 return r;
2047
8749cbcd
SS
2048 r = link_set_ipv6_dad_transmits(link);
2049 if (r < 0)
2050 return r;
b69c3180
SS
2051
2052 r = link_set_ipv6_hop_limit(link);
2053 if (r < 0)
2054 return r;
8749cbcd 2055
78c958f8 2056 if (link_ipv4ll_enabled(link)) {
b22d8a00 2057 r = ipv4ll_configure(link);
eb34d4af
TG
2058 if (r < 0)
2059 return r;
2060 }
2061
78c958f8 2062 if (link_dhcp4_enabled(link)) {
3c9b8860 2063 r = dhcp4_configure(link);
eb34d4af
TG
2064 if (r < 0)
2065 return r;
eb34d4af
TG
2066 }
2067
78c958f8 2068 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
2069 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
2070 if (r < 0)
2071 return r;
2072
2073 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
2074 if (r < 0)
2075 return r;
dd43110f
TG
2076 }
2077
78c958f8 2078 if (link_dhcp6_enabled(link)) {
f5a8c43f
TG
2079 r = dhcp6_configure(link);
2080 if (r < 0)
2081 return r;
2082 }
2083
2084 if (link_ipv6_accept_ra_enabled(link)) {
de1e9928 2085 r = ndisc_configure(link);
4138fb2c
PF
2086 if (r < 0)
2087 return r;
2088 }
2089
ce43e484
SS
2090 if (link_lldp_enabled(link)) {
2091 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
2092 if (r < 0)
2093 return r;
2094
2095 r = sd_lldp_attach_event(link->lldp, NULL, 0);
2096 if (r < 0)
2097 return r;
49699bac
SS
2098
2099 r = sd_lldp_set_callback(link->lldp,
2100 lldp_handler, link);
2101 if (r < 0)
2102 return r;
ce43e484
SS
2103 }
2104
a61bb41c 2105 if (link_has_carrier(link)) {
1e9be60b
TG
2106 r = link_acquire_conf(link);
2107 if (r < 0)
2108 return r;
e7ab854c
TG
2109
2110 if (link->ipv6ll_address) {
2111 r = link_acquire_ipv6_conf(link);
2112 if (r < 0)
2113 return r;
2114 }
cc544d5f 2115 }
1e9be60b 2116
3f265037 2117 return link_enter_join_netdev(link);
505f8da7
TG
2118}
2119
1c4baffc 2120static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860 2121 void *userdata) {
5da8149f 2122 _cleanup_link_unref_ Link *link = userdata;
505f8da7 2123 Network *network;
505f8da7
TG
2124 int r;
2125
2126 assert(link);
2127 assert(link->ifname);
2128 assert(link->manager);
2129
8434fd5c 2130 if (link->state != LINK_STATE_PENDING)
5da8149f 2131 return 1;
505f8da7 2132
6a7a4e4d 2133 log_link_debug(link, "Link state is up-to-date");
505f8da7 2134
0d4ad91d
AR
2135 r = link_new_bound_by_list(link);
2136 if (r < 0)
2137 return r;
2138
2139 r = link_handle_bound_by_list(link);
2140 if (r < 0)
2141 return r;
2142
c4a03a56
TG
2143 if (!link->network) {
2144 r = network_get(link->manager, link->udev_device, link->ifname,
2145 &link->mac, &network);
2146 if (r == -ENOENT) {
2147 link_enter_unmanaged(link);
2148 return 1;
2149 } else if (r < 0)
2150 return r;
505f8da7 2151
c4a03a56
TG
2152 if (link->flags & IFF_LOOPBACK) {
2153 if (network->link_local != ADDRESS_FAMILY_NO)
2154 log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
78c958f8 2155
c4a03a56
TG
2156 if (network->dhcp != ADDRESS_FAMILY_NO)
2157 log_link_debug(link, "Ignoring DHCP clients for loopback link");
78c958f8 2158
c4a03a56
TG
2159 if (network->dhcp_server)
2160 log_link_debug(link, "Ignoring DHCP server for loopback link");
2161 }
bd2efe92 2162
c4a03a56
TG
2163 r = network_apply(link->manager, network, link);
2164 if (r < 0)
2165 return r;
2166 }
505f8da7 2167
0d4ad91d
AR
2168 r = link_new_bound_to_list(link);
2169 if (r < 0)
2170 return r;
2171
a748b692
TG
2172 r = link_configure(link);
2173 if (r < 0)
2174 return r;
2175
5da8149f 2176 return 1;
505f8da7
TG
2177}
2178
4f561e8e 2179int link_initialized(Link *link, struct udev_device *device) {
1c4baffc 2180 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f561e8e
TG
2181 int r;
2182
2183 assert(link);
2184 assert(link->manager);
2185 assert(link->manager->rtnl);
2186 assert(device);
2187
8434fd5c 2188 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
2189 return 0;
2190
679b3605
TG
2191 if (link->udev_device)
2192 return 0;
2193
79008bdd 2194 log_link_debug(link, "udev initialized link");
4f561e8e
TG
2195
2196 link->udev_device = udev_device_ref(device);
2197
3c9b8860
TG
2198 /* udev has initialized the link, but we don't know if we have yet
2199 * processed the NEWLINK messages with the latest state. Do a GETLINK,
2200 * when it returns we know that the pending NEWLINKs have already been
2201 * processed and that we are up-to-date */
4f561e8e 2202
3c9b8860
TG
2203 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
2204 link->ifindex);
4f561e8e
TG
2205 if (r < 0)
2206 return r;
2207
1c4baffc 2208 r = sd_netlink_call_async(link->manager->rtnl, req,
3c9b8860 2209 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
2210 if (r < 0)
2211 return r;
2212
5da8149f
TG
2213 link_ref(link);
2214
4f561e8e
TG
2215 return 0;
2216}
2217
c4a03a56 2218static int link_load(Link *link) {
0bc70f1d
TG
2219 _cleanup_free_ char *network_file = NULL,
2220 *addresses = NULL,
f703cc2c 2221 *routes = NULL,
0bc70f1d
TG
2222 *dhcp4_address = NULL,
2223 *ipv4ll_address = NULL;
2224 union in_addr_union address;
f703cc2c 2225 union in_addr_union route_dst;
c598ac76 2226 const char *p;
c4a03a56
TG
2227 int r;
2228
2229 assert(link);
2230
2231 r = parse_env_file(link->state_file, NEWLINE,
2232 "NETWORK_FILE", &network_file,
2233 "ADDRESSES", &addresses,
f703cc2c 2234 "ROUTES", &routes,
0bc70f1d
TG
2235 "DHCP4_ADDRESS", &dhcp4_address,
2236 "IPV4LL_ADDRESS", &ipv4ll_address,
c4a03a56
TG
2237 NULL);
2238 if (r < 0 && r != -ENOENT)
2239 return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file);
2240
2241 if (network_file) {
2242 Network *network;
2243 char *suffix;
2244
2245 /* drop suffix */
2246 suffix = strrchr(network_file, '.');
2247 if (!suffix) {
2248 log_link_debug(link, "Failed to get network name from %s", network_file);
2249 goto network_file_fail;
2250 }
2251 *suffix = '\0';
2252
2253 r = network_get_by_name(link->manager, basename(network_file), &network);
2254 if (r < 0) {
2255 log_link_debug_errno(link, r, "Failed to get network %s: %m", basename(network_file));
2256 goto network_file_fail;
2257 }
2258
2259 r = network_apply(link->manager, network, link);
2260 if (r < 0)
2261 return log_link_error_errno(link, r, "Failed to apply network %s: %m", basename(network_file));
2262 }
2263
2264network_file_fail:
2265
2266 if (addresses) {
c598ac76 2267 p = addresses;
c4a03a56 2268
c598ac76
TG
2269 for (;;) {
2270 _cleanup_free_ char *address_str = NULL;
c4a03a56
TG
2271 char *prefixlen_str;
2272 int family;
2273 unsigned char prefixlen;
c4a03a56 2274
c598ac76
TG
2275 r = extract_first_word(&p, &address_str, NULL, 0);
2276 if (r < 0) {
2277 log_link_debug_errno(link, r, "Failed to extract next address string: %m");
2278 continue;
2279 } if (r == 0)
2280 break;
2281
2282 prefixlen_str = strchr(address_str, '/');
c4a03a56 2283 if (!prefixlen_str) {
c598ac76 2284 log_link_debug(link, "Failed to parse address and prefix length %s", address_str);
c4a03a56
TG
2285 continue;
2286 }
2287
2288 *prefixlen_str ++ = '\0';
2289
2290 r = sscanf(prefixlen_str, "%hhu", &prefixlen);
2291 if (r != 1) {
2292 log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str);
2293 continue;
2294 }
2295
c598ac76 2296 r = in_addr_from_string_auto(address_str, &family, &address);
c4a03a56 2297 if (r < 0) {
c598ac76 2298 log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str);
c4a03a56
TG
2299 continue;
2300 }
2301
2302 r = address_add(link, family, &address, prefixlen, NULL);
2303 if (r < 0)
2304 return log_link_error_errno(link, r, "Failed to add address: %m");
2305 }
2306 }
2307
f703cc2c 2308 if (routes) {
c598ac76 2309 for (;;) {
f833694d 2310 Route *route;
c598ac76 2311 _cleanup_free_ char *route_str = NULL;
f833694d
TG
2312 _cleanup_event_source_unref_ sd_event_source *expire = NULL;
2313 usec_t lifetime;
f703cc2c
TG
2314 char *prefixlen_str;
2315 int family;
2316 unsigned char prefixlen, tos, table;
2317 uint32_t priority;
2318
c598ac76
TG
2319 r = extract_first_word(&p, &route_str, NULL, 0);
2320 if (r < 0) {
2321 log_link_debug_errno(link, r, "Failed to extract next route string: %m");
2322 continue;
2323 } if (r == 0)
2324 break;
2325
2326 prefixlen_str = strchr(route_str, '/');
f703cc2c 2327 if (!prefixlen_str) {
c598ac76 2328 log_link_debug(link, "Failed to parse route %s", route_str);
f703cc2c
TG
2329 continue;
2330 }
2331
2332 *prefixlen_str ++ = '\0';
2333
f833694d
TG
2334 r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime);
2335 if (r != 5) {
2336 log_link_debug(link,
2337 "Failed to parse destination prefix length, tos, priority, table or expiration %s",
2338 prefixlen_str);
f703cc2c
TG
2339 continue;
2340 }
2341
c598ac76 2342 r = in_addr_from_string_auto(route_str, &family, &route_dst);
f703cc2c 2343 if (r < 0) {
c598ac76 2344 log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str);
f703cc2c
TG
2345 continue;
2346 }
2347
f833694d 2348 r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route);
f703cc2c
TG
2349 if (r < 0)
2350 return log_link_error_errno(link, r, "Failed to add route: %m");
f833694d
TG
2351
2352 if (lifetime != USEC_INFINITY) {
2353 r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime,
2354 0, route_expire_handler, route);
2355 if (r < 0)
2356 log_link_warning_errno(link, r, "Could not arm route expiration handler: %m");
2357 }
2358
2359 route->lifetime = lifetime;
2360 sd_event_source_unref(route->expire);
2361 route->expire = expire;
2362 expire = NULL;
f703cc2c
TG
2363 }
2364 }
2365
0bc70f1d
TG
2366 if (dhcp4_address) {
2367 r = in_addr_from_string(AF_INET, dhcp4_address, &address);
2368 if (r < 0) {
2369 log_link_debug_errno(link, r, "Falied to parse DHCPv4 address %s: %m", dhcp4_address);
2370 goto dhcp4_address_fail;
2371 }
2372
2373 r = sd_dhcp_client_new(&link->dhcp_client);
2374 if (r < 0)
2375 return log_link_error_errno(link, r, "Falied to create DHCPv4 client: %m");
2376
2377 r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
2378 if (r < 0)
2379 return log_link_error_errno(link, r, "Falied to set inital DHCPv4 address %s: %m", dhcp4_address);
2380 }
2381
2382dhcp4_address_fail:
2383
2384 if (ipv4ll_address) {
2385 r = in_addr_from_string(AF_INET, ipv4ll_address, &address);
2386 if (r < 0) {
2387 log_link_debug_errno(link, r, "Falied to parse IPv4LL address %s: %m", ipv4ll_address);
2388 goto ipv4ll_address_fail;
2389 }
2390
2391 r = sd_ipv4ll_new(&link->ipv4ll);
2392 if (r < 0)
2393 return log_link_error_errno(link, r, "Falied to create IPv4LL client: %m");
2394
2395 r = sd_ipv4ll_set_address(link->ipv4ll, &address.in);
2396 if (r < 0)
2397 return log_link_error_errno(link, r, "Falied to set inital IPv4LL address %s: %m", ipv4ll_address);
2398 }
2399
2400ipv4ll_address_fail:
2401
c4a03a56
TG
2402 return 0;
2403}
2404
1c4baffc 2405int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
505f8da7
TG
2406 Link *link;
2407 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2408 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2409 int r;
2410
2411 assert(m);
fbbeb65a 2412 assert(m->rtnl);
505f8da7
TG
2413 assert(message);
2414 assert(ret);
2415
2416 r = link_new(m, message, ret);
2417 if (r < 0)
2418 return r;
2419
2420 link = *ret;
2421
6a7a4e4d 2422 log_link_debug(link, "Link %d added", link->ifindex);
505f8da7 2423
c4a03a56
TG
2424 r = link_load(link);
2425 if (r < 0)
2426 return r;
2427
75f86906 2428 if (detect_container() <= 0) {
505f8da7 2429 /* not in a container, udev will be around */
ae06ab10 2430 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7 2431 device = udev_device_new_from_device_id(m->udev, ifindex_str);
5c416fc4
TG
2432 if (!device) {
2433 r = log_link_warning_errno(link, errno, "Could not find udev device: %m");
2434 goto failed;
2435 }
505f8da7 2436
3c4cb064 2437 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 2438 /* not yet ready */
79008bdd 2439 log_link_debug(link, "link pending udev initialization...");
505f8da7 2440 return 0;
3c4cb064 2441 }
505f8da7 2442
4f561e8e
TG
2443 r = link_initialized(link, device);
2444 if (r < 0)
5c416fc4 2445 goto failed;
4f561e8e 2446 } else {
5da8149f
TG
2447 /* we are calling a callback directly, so must take a ref */
2448 link_ref(link);
2449
4f561e8e
TG
2450 r = link_initialized_and_synced(m->rtnl, NULL, link);
2451 if (r < 0)
5c416fc4 2452 goto failed;
4f561e8e 2453 }
505f8da7 2454
a748b692 2455 return 0;
5c416fc4
TG
2456failed:
2457 link_enter_failed(link);
2458 return r;
a748b692
TG
2459}
2460
e7ab854c
TG
2461int link_ipv6ll_gained(Link *link) {
2462 int r;
2463
2464 assert(link);
2465
2466 log_link_info(link, "Gained IPv6LL");
2467
2468 link->ipv6ll_address = true;
2469 link_check_ready(link);
2470
2471 if (link->network) {
2472 r = link_acquire_ipv6_conf(link);
2473 if (r < 0) {
2474 link_enter_failed(link);
2475 return r;
2476 }
2477 }
2478
2479 return 0;
2480}
2481
9c0a72f9
TG
2482static int link_carrier_gained(Link *link) {
2483 int r;
2484
2485 assert(link);
2486
2487 if (link->network) {
2488 r = link_acquire_conf(link);
2489 if (r < 0) {
2490 link_enter_failed(link);
2491 return r;
2492 }
2493 }
2494
0d4ad91d
AR
2495 r = link_handle_bound_by_list(link);
2496 if (r < 0)
2497 return r;
2498
9c0a72f9
TG
2499 return 0;
2500}
2501
2502static int link_carrier_lost(Link *link) {
2503 int r;
2504
2505 assert(link);
2506
2507 r = link_stop_clients(link);
2508 if (r < 0) {
2509 link_enter_failed(link);
2510 return r;
2511 }
2512
0d4ad91d
AR
2513 r = link_handle_bound_by_list(link);
2514 if (r < 0)
2515 return r;
2516
9c0a72f9
TG
2517 return 0;
2518}
2519
2520int link_carrier_reset(Link *link) {
2521 int r;
2522
2523 assert(link);
2524
2525 if (link_has_carrier(link)) {
2526 r = link_carrier_lost(link);
2527 if (r < 0)
2528 return r;
2529
2530 r = link_carrier_gained(link);
2531 if (r < 0)
2532 return r;
2533
6a7a4e4d 2534 log_link_info(link, "Reset carrier");
9c0a72f9
TG
2535 }
2536
2537 return 0;
2538}
2539
2540
1c4baffc 2541int link_update(Link *link, sd_netlink_message *m) {
c49b33ac 2542 struct ether_addr mac;
ca4e095a 2543 const char *ifname;
afe7fd56 2544 uint32_t mtu;
a61bb41c 2545 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
2546 int r;
2547
dd3efc09 2548 assert(link);
b8941f74 2549 assert(link->ifname);
22936833
TG
2550 assert(m);
2551
7619683b
TG
2552 if (link->state == LINK_STATE_LINGER) {
2553 link_ref(link);
6a7a4e4d 2554 log_link_info(link, "Link readded");
e331e246 2555 link_set_state(link, LINK_STATE_ENSLAVING);
0d4ad91d
AR
2556
2557 r = link_new_carrier_maps(link);
2558 if (r < 0)
2559 return r;
7619683b
TG
2560 }
2561
1c4baffc 2562 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
b8941f74 2563 if (r >= 0 && !streq(ifname, link->ifname)) {
6a7a4e4d 2564 log_link_info(link, "Renamed to %s", ifname);
b8941f74 2565
0d4ad91d
AR
2566 link_free_carrier_maps(link);
2567
2fc09a9c
DM
2568 r = free_and_strdup(&link->ifname, ifname);
2569 if (r < 0)
2570 return r;
0d4ad91d
AR
2571
2572 r = link_new_carrier_maps(link);
2573 if (r < 0)
2574 return r;
b8941f74
TG
2575 }
2576
1c4baffc 2577 r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
afe7fd56
TG
2578 if (r >= 0 && mtu > 0) {
2579 link->mtu = mtu;
2580 if (!link->original_mtu) {
2581 link->original_mtu = mtu;
6a7a4e4d 2582 log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
afe7fd56
TG
2583 }
2584
2585 if (link->dhcp_client) {
3c9b8860
TG
2586 r = sd_dhcp_client_set_mtu(link->dhcp_client,
2587 link->mtu);
afe7fd56 2588 if (r < 0) {
6a7a4e4d 2589 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
afe7fd56
TG
2590 return r;
2591 }
2592 }
9842de0d 2593 }
69629de9 2594
e9189a1f
TG
2595 /* The kernel may broadcast NEWLINK messages without the MAC address
2596 set, simply ignore them. */
1c4baffc 2597 r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 2598 if (r >= 0) {
3c9b8860
TG
2599 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
2600 ETH_ALEN)) {
c49b33ac 2601
3c9b8860
TG
2602 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
2603 ETH_ALEN);
c49b33ac 2604
79008bdd 2605 log_link_debug(link, "MAC address: "
20861203
TG
2606 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2607 mac.ether_addr_octet[0],
2608 mac.ether_addr_octet[1],
2609 mac.ether_addr_octet[2],
2610 mac.ether_addr_octet[3],
2611 mac.ether_addr_octet[4],
2612 mac.ether_addr_octet[5]);
c49b33ac 2613
20861203
TG
2614 if (link->ipv4ll) {
2615 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
6a7a4e4d
LP
2616 if (r < 0)
2617 return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
c49b33ac 2618 }
c49b33ac 2619
20861203 2620 if (link->dhcp_client) {
3c9b8860 2621 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
2622 (const uint8_t *) &link->mac,
2623 sizeof (link->mac),
2624 ARPHRD_ETHER);
6a7a4e4d
LP
2625 if (r < 0)
2626 return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
c49b33ac 2627 }
4138fb2c
PF
2628
2629 if (link->dhcp6_client) {
2630 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
2631 (const uint8_t *) &link->mac,
2632 sizeof (link->mac),
2633 ARPHRD_ETHER);
6a7a4e4d
LP
2634 if (r < 0)
2635 return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
4138fb2c 2636 }
c49b33ac 2637 }
4f882b2a
TG
2638 }
2639
a61bb41c
TG
2640 had_carrier = link_has_carrier(link);
2641
2642 r = link_update_flags(link, m);
2643 if (r < 0)
2644 return r;
2645
2646 carrier_gained = !had_carrier && link_has_carrier(link);
2647 carrier_lost = had_carrier && !link_has_carrier(link);
2648
2649 if (carrier_gained) {
6a7a4e4d 2650 log_link_info(link, "Gained carrier");
a61bb41c 2651
9c0a72f9
TG
2652 r = link_carrier_gained(link);
2653 if (r < 0)
2654 return r;
a61bb41c 2655 } else if (carrier_lost) {
6a7a4e4d 2656 log_link_info(link, "Lost carrier");
a61bb41c 2657
9c0a72f9
TG
2658 r = link_carrier_lost(link);
2659 if (r < 0)
a61bb41c 2660 return r;
9c0a72f9 2661
a61bb41c
TG
2662 }
2663
2664 return 0;
dd3efc09 2665}
fe8db0c5
TG
2666
2667int link_save(Link *link) {
68a8723c 2668 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2669 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2670 const char *admin_state, *oper_state;
e7780c8d 2671 Address *a;
c1eb9872 2672 Route *route;
e7780c8d 2673 Iterator i;
fe8db0c5
TG
2674 int r;
2675
2676 assert(link);
2677 assert(link->state_file);
68a8723c 2678 assert(link->lease_file);
bbf7c048
TG
2679 assert(link->manager);
2680
370e9930
TG
2681 if (link->state == LINK_STATE_LINGER) {
2682 unlink(link->state_file);
2683 return 0;
2684 }
2685
deb2e523
TG
2686 admin_state = link_state_to_string(link->state);
2687 assert(admin_state);
2688
e375dcde
TG
2689 oper_state = link_operstate_to_string(link->operstate);
2690 assert(oper_state);
deb2e523 2691
fe8db0c5
TG
2692 r = fopen_temporary(link->state_file, &f, &temp_path);
2693 if (r < 0)
6a7a4e4d 2694 goto fail;
fe8db0c5
TG
2695
2696 fchmod(fileno(f), 0644);
2697
2698 fprintf(f,
2699 "# This is private data. Do not parse.\n"
deb2e523 2700 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
2701 "OPER_STATE=%s\n",
2702 admin_state, oper_state);
fe8db0c5 2703
bcb7a07e 2704 if (link->network) {
ea352b40
LP
2705 char **address, **domain;
2706 bool space;
07bdc70d
PF
2707 sd_dhcp6_lease *dhcp6_lease = NULL;
2708
2709 if (link->dhcp6_client) {
4058d339
TG
2710 r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
2711 if (r < 0 && r != -ENOMSG)
07bdc70d
PF
2712 log_link_debug(link, "No DHCPv6 lease");
2713 }
b0e39c82 2714
adc5b2e2
TG
2715 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
2716
b0e39c82 2717 fputs("DNS=", f);
ea352b40
LP
2718 space = false;
2719 STRV_FOREACH(address, link->network->dns) {
2720 if (space)
2721 fputc(' ', f);
2722 fputs(*address, f);
2723 space = true;
2724 }
d5314fff 2725
b0e39c82
TG
2726 if (link->network->dhcp_dns &&
2727 link->dhcp_lease) {
2728 const struct in_addr *addresses;
2729
2730 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2731 if (r > 0) {
ea352b40
LP
2732 if (space)
2733 fputc(' ', f);
b0e39c82 2734 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2735 space = true;
2736 }
2737 }
2738
2739 if (link->network->dhcp_dns && dhcp6_lease) {
2740 struct in6_addr *in6_addrs;
2741
2742 r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
2743 if (r > 0) {
2744 if (space)
2745 fputc(' ', f);
2746 serialize_in6_addrs(f, in6_addrs, r);
b0e39c82
TG
2747 }
2748 }
2749
2ce40956 2750 fputc('\n', f);
b0e39c82 2751
2ce40956 2752 fputs("NTP=", f);
ea352b40
LP
2753 space = false;
2754 STRV_FOREACH(address, link->network->ntp) {
2755 if (space)
2756 fputc(' ', f);
2757 fputs(*address, f);
2758 space = true;
2759 }
d5314fff 2760
b0e39c82
TG
2761 if (link->network->dhcp_ntp &&
2762 link->dhcp_lease) {
2763 const struct in_addr *addresses;
2764
2765 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2766 if (r > 0) {
ea352b40
LP
2767 if (space)
2768 fputc(' ', f);
b0e39c82 2769 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2770 space = true;
2771 }
2772 }
2773
2774 if (link->network->dhcp_ntp && dhcp6_lease) {
2775 struct in6_addr *in6_addrs;
2776 char **hosts;
2777 char **hostname;
2778
2779 r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
2780 &in6_addrs);
2781 if (r > 0) {
2782 if (space)
2783 fputc(' ', f);
2784 serialize_in6_addrs(f, in6_addrs, r);
2785 space = true;
2786 }
2787
2788 r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
2789 if (r > 0) {
2790 STRV_FOREACH(hostname, hosts) {
2791 if (space)
2792 fputc(' ', f);
2793 fputs(*hostname, f);
2794 space = true;
2795 }
b0e39c82
TG
2796 }
2797 }
2798
2ce40956 2799 fputc('\n', f);
bd8f6538 2800
2ce40956 2801 fputs("DOMAINS=", f);
ea352b40
LP
2802 space = false;
2803 STRV_FOREACH(domain, link->network->domains) {
2804 if (space)
2805 fputc(' ', f);
2806 fputs(*domain, f);
2807 space = true;
2808 }
d5314fff 2809
ad0734e8 2810 if (link->network->dhcp_domains &&
9b4d1882
TG
2811 link->dhcp_lease) {
2812 const char *domainname;
2813
2814 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 2815 if (r >= 0) {
ea352b40
LP
2816 if (space)
2817 fputc(' ', f);
6192b846 2818 fputs(domainname, f);
07bdc70d
PF
2819 space = true;
2820 }
2821 }
2822
2823 if (link->network->dhcp_domains && dhcp6_lease) {
2824 char **domains;
2825
2826 r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
2827 if (r >= 0) {
2828 STRV_FOREACH(domain, domains) {
2829 if (space)
2830 fputc(' ', f);
2831 fputs(*domain, f);
2832 space = true;
2833 }
6192b846 2834 }
9b4d1882
TG
2835 }
2836
2ce40956 2837 fputc('\n', f);
6192b846 2838
67272d15
TG
2839 fprintf(f, "WILDCARD_DOMAIN=%s\n",
2840 yes_no(link->network->wildcard_domain));
2841
3c9b8860 2842 fprintf(f, "LLMNR=%s\n",
a7e5da6e 2843 resolve_support_to_string(link->network->llmnr));
e7780c8d 2844
2ce40956 2845 fputs("ADDRESSES=", f);
e7780c8d
TG
2846 space = false;
2847 SET_FOREACH(a, link->addresses, i) {
2848 _cleanup_free_ char *address_str = NULL;
2849
2850 r = in_addr_to_string(a->family, &a->in_addr, &address_str);
2851 if (r < 0)
2852 goto fail;
2853
e7780c8d
TG
2854 fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen);
2855 space = true;
2856 }
2857
2ce40956 2858 fputc('\n', f);
c1eb9872
TG
2859
2860 fputs("ROUTES=", f);
2861 space = false;
2862 SET_FOREACH(route, link->routes, i) {
2863 _cleanup_free_ char *route_str = NULL;
2864
2865 r = in_addr_to_string(route->family, &route->dst, &route_str);
2866 if (r < 0)
2867 goto fail;
2868
f833694d
TG
2869 fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str,
2870 route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime);
c1eb9872
TG
2871 space = true;
2872 }
2873
2874 fputc('\n', f);
bcb7a07e 2875 }
7374f9d8 2876
0d4ad91d
AR
2877 if (!hashmap_isempty(link->bound_to_links)) {
2878 Link *carrier;
0d4ad91d
AR
2879 bool space = false;
2880
2881 fputs("CARRIER_BOUND_TO=", f);
2882 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
2883 if (space)
2884 fputc(' ', f);
2885 fputs(carrier->ifname, f);
2886 space = true;
2887 }
2888
2ce40956 2889 fputc('\n', f);
0d4ad91d
AR
2890 }
2891
2892 if (!hashmap_isempty(link->bound_by_links)) {
2893 Link *carrier;
0d4ad91d
AR
2894 bool space = false;
2895
2896 fputs("CARRIER_BOUND_BY=", f);
0d4ad91d
AR
2897 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
2898 if (space)
2899 fputc(' ', f);
2900 fputs(carrier->ifname, f);
2901 space = true;
2902 }
2903
2ce40956 2904 fputc('\n', f);
0d4ad91d
AR
2905 }
2906
8eb9058d 2907 if (link->dhcp_lease) {
0bc70f1d 2908 struct in_addr address;
8eb9058d
LP
2909 const char *tz = NULL;
2910
0bc70f1d
TG
2911 assert(link->network);
2912
8eb9058d
LP
2913 r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
2914 if (r >= 0)
2915 fprintf(f, "TIMEZONE=%s\n", tz);
8eb9058d 2916
0bc70f1d
TG
2917 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
2918 if (r >= 0) {
2919 fputs("DHCP4_ADDRESS=", f);
2920 serialize_in_addrs(f, &address, 1);
2921 fputc('\n', f);
2922 }
d9876a52 2923
bd91b83e 2924 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 2925 if (r < 0)
c2d6bd61 2926 goto fail;
fe8db0c5 2927
7374f9d8 2928 fprintf(f,
b0e39c82
TG
2929 "DHCP_LEASE=%s\n",
2930 link->lease_file);
deb2e523 2931 } else
68a8723c 2932 unlink(link->lease_file);
fe8db0c5 2933
0bc70f1d
TG
2934 if (link->ipv4ll) {
2935 struct in_addr address;
2936
2937 r = sd_ipv4ll_get_address(link->ipv4ll, &address);
2938 if (r >= 0) {
2939 fputs("IPV4LL_ADDRESS=", f);
2940 serialize_in_addrs(f, &address, 1);
2941 fputc('\n', f);
2942 }
2943 }
2944
49699bac
SS
2945 if (link->lldp) {
2946 assert(link->network);
2947
2948 r = sd_lldp_save(link->lldp, link->lldp_file);
2949 if (r < 0)
2950 goto fail;
2951
2952 fprintf(f,
2953 "LLDP_FILE=%s\n",
2954 link->lldp_file);
2955 } else
2956 unlink(link->lldp_file);
2957
c2d6bd61
LP
2958 r = fflush_and_check(f);
2959 if (r < 0)
2960 goto fail;
fe8db0c5 2961
c2d6bd61 2962 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 2963 r = -errno;
c2d6bd61 2964 goto fail;
fe8db0c5
TG
2965 }
2966
c2d6bd61 2967 return 0;
dacd6cee 2968
c2d6bd61 2969fail:
6a7a4e4d 2970 (void) unlink(link->state_file);
6a7a4e4d
LP
2971 if (temp_path)
2972 (void) unlink(temp_path);
2973
dacd6cee 2974 return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
fe8db0c5
TG
2975}
2976
84de38c5
TG
2977/* The serialized state in /run is no longer up-to-date. */
2978void link_dirty(Link *link) {
2979 int r;
2980
2981 assert(link);
2982
2983 r = set_ensure_allocated(&link->manager->dirty_links, NULL);
2984 if (r < 0)
2985 /* allocation errors are ignored */
2986 return;
2987
2988 r = set_put(link->manager->dirty_links, link);
2989 if (r < 0)
2990 /* allocation errors are ignored */
2991 return;
2992
2993 link_ref(link);
2994}
2995
2996/* The serialized state in /run is up-to-date */
2997void link_clean(Link *link) {
2998 assert(link);
2999 assert(link->manager);
3000
3001 set_remove(link->manager->dirty_links, link);
3002 link_unref(link);
3003}
3004
fe8db0c5 3005static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 3006 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
3007 [LINK_STATE_ENSLAVING] = "configuring",
3008 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
3009 [LINK_STATE_SETTING_ROUTES] = "configuring",
3010 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 3011 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 3012 [LINK_STATE_FAILED] = "failed",
370e9930 3013 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
3014};
3015
3016DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
3017
3018static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
3019 [LINK_OPERSTATE_OFF] = "off",
3020 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
3021 [LINK_OPERSTATE_DORMANT] = "dormant",
3022 [LINK_OPERSTATE_CARRIER] = "carrier",
3023 [LINK_OPERSTATE_DEGRADED] = "degraded",
3024 [LINK_OPERSTATE_ROUTABLE] = "routable",
3025};
3026
3027DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);