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