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