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