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