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