]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
test-dhcp6-client: Add a simple Information Request test case
[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
0b1831c2 26#include "networkd-link.h"
3be1d7e0 27#include "networkd-netdev.h"
f579559b 28#include "libudev-private.h"
505f8da7 29#include "udev-util.h"
f579559b 30#include "util.h"
505f8da7 31#include "virt.h"
1346b1f0 32#include "bus-util.h"
c6f7c917 33#include "network-internal.h"
ed942a9e 34#include "conf-parser.h"
f579559b 35
fe8db0c5
TG
36#include "dhcp-lease-internal.h"
37
78c958f8
TG
38static bool link_dhcp6_enabled(Link *link) {
39 if (link->flags & IFF_LOOPBACK)
40 return false;
41
42 if (!link->network)
43 return false;
44
45 return IN_SET(link->network->dhcp, DHCP_SUPPORT_V6, DHCP_SUPPORT_BOTH);
46}
47
48static bool link_dhcp4_enabled(Link *link) {
49 if (link->flags & IFF_LOOPBACK)
50 return false;
51
52 if (!link->network)
53 return false;
54
55 return IN_SET(link->network->dhcp, DHCP_SUPPORT_V4, DHCP_SUPPORT_BOTH);
56}
57
58static bool link_dhcp4_server_enabled(Link *link) {
59 if (link->flags & IFF_LOOPBACK)
60 return false;
61
62 if (!link->network)
63 return false;
64
65 return link->network->dhcp_server;
66}
67
68static bool link_ipv4ll_enabled(Link *link) {
69 if (link->flags & IFF_LOOPBACK)
70 return false;
71
72 if (!link->network)
73 return false;
74
75 return link->network->ipv4ll;
76}
77
51d18171
TG
78#define FLAG_STRING(string, flag, old, new) \
79 (((old ^ new) & flag) \
80 ? ((old & flag) ? (" -" string) : (" +" string)) \
81 : "")
82
83static int link_update_flags(Link *link, sd_rtnl_message *m) {
84 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
85 uint8_t operstate;
86 int r;
87
88 assert(link);
89
90 r = sd_rtnl_message_link_get_flags(m, &flags);
91 if (r < 0) {
79008bdd 92 log_link_warning(link, "Could not get link flags");
51d18171
TG
93 return r;
94 }
95
96 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
97 if (r < 0)
98 /* if we got a message without operstate, take it to mean
99 the state was unchanged */
100 operstate = link->kernel_operstate;
101
102 if ((link->flags == flags) && (link->kernel_operstate == operstate))
103 return 0;
104
105 if (link->flags != flags) {
79008bdd 106 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
107 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
108 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
109 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
110 FLAG_STRING("UP", IFF_UP, link->flags, flags),
111 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
112 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
113 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
114 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
115 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
116 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
117 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
118 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
119 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
120 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
121 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
122 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
123 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
124 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
125 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
126
127 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
128 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
129 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
130 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
131 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
132 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
133 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
134 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
135
136 /* link flags are currently at most 18 bits, let's align to
137 * printing 20 */
138 if (unknown_flags_added)
79008bdd 139 log_link_debug(link,
51d18171
TG
140 "unknown link flags gained: %#.5x (ignoring)",
141 unknown_flags_added);
142
143 if (unknown_flags_removed)
79008bdd 144 log_link_debug(link,
51d18171
TG
145 "unknown link flags lost: %#.5x (ignoring)",
146 unknown_flags_removed);
147 }
148
149 link->flags = flags;
150 link->kernel_operstate = operstate;
151
152 link_save(link);
153
154 return 0;
155}
156
505f8da7 157static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
14b746f7 158 _cleanup_link_unref_ Link *link = NULL;
505f8da7 159 uint16_t type;
ca4e095a 160 const char *ifname;
505f8da7 161 int r, ifindex;
f579559b 162
0c2f9b84 163 assert(manager);
505f8da7 164 assert(message);
f579559b
TG
165 assert(ret);
166
505f8da7
TG
167 r = sd_rtnl_message_get_type(message, &type);
168 if (r < 0)
169 return r;
170 else if (type != RTM_NEWLINK)
171 return -EINVAL;
172
173 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
174 if (r < 0)
175 return r;
176 else if (ifindex <= 0)
177 return -EINVAL;
178
179 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &ifname);
180 if (r < 0)
181 return r;
182
f579559b
TG
183 link = new0(Link, 1);
184 if (!link)
185 return -ENOMEM;
186
14b746f7 187 link->n_ref = 1;
5a3eb5a7 188 link->manager = manager;
8434fd5c 189 link->state = LINK_STATE_PENDING;
505f8da7
TG
190 link->ifindex = ifindex;
191 link->ifname = strdup(ifname);
192 if (!link->ifname)
193 return -ENOMEM;
f579559b 194
512922f8
TG
195 r = sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
196 if (r < 0)
79008bdd 197 log_link_debug(link, "MAC address not found for new device, continuing without");
512922f8 198
3c9b8860
TG
199 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
200 link->ifindex);
fe8db0c5 201 if (r < 0)
315db1a8 202 return -ENOMEM;
fe8db0c5 203
3c9b8860
TG
204 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
205 link->ifindex);
68a8723c
TG
206 if (r < 0)
207 return -ENOMEM;
208
d5099efc 209 r = hashmap_ensure_allocated(&manager->links, NULL);
ae06ab10
TG
210 if (r < 0)
211 return r;
212
213 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
f579559b
TG
214 if (r < 0)
215 return r;
216
51d18171
TG
217 r = link_update_flags(link, message);
218 if (r < 0)
219 return r;
220
f579559b
TG
221 *ret = link;
222 link = NULL;
223
224 return 0;
225}
226
14b746f7 227static void link_free(Link *link) {
428fd0a7
TG
228 Address *address;
229
f579559b
TG
230 if (!link)
231 return;
232
428fd0a7
TG
233 while ((address = link->addresses)) {
234 LIST_REMOVE(addresses, link->addresses, address);
235 address_free(address);
236 }
237
11bf3cce
LP
238 while ((address = link->pool_addresses)) {
239 LIST_REMOVE(addresses, link->pool_addresses, address);
240 address_free(address);
241 }
242
e5b04c8d 243 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 244 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 245
68a8723c
TG
246 unlink(link->lease_file);
247 free(link->lease_file);
248
56cd007a 249 sd_ipv4ll_unref(link->ipv4ll);
4138fb2c 250 sd_dhcp6_client_unref(link->dhcp6_client);
6b66097b 251 sd_icmp6_nd_unref(link->icmp6_router_discovery);
4138fb2c 252
28aeb07f 253 if (link->manager)
ae06ab10 254 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
f579559b 255
c166a070 256 free(link->ifname);
68a8723c
TG
257
258 unlink(link->state_file);
fe8db0c5 259 free(link->state_file);
c166a070 260
b5db00e5
UTL
261 udev_device_unref(link->udev_device);
262
f579559b
TG
263 free(link);
264}
265
14b746f7
TG
266Link *link_unref(Link *link) {
267 if (link && (-- link->n_ref <= 0))
268 link_free(link);
269
270 return NULL;
271}
272
273Link *link_ref(Link *link) {
274 if (link)
275 assert_se(++ link->n_ref >= 2);
276
277 return link;
278}
279
11a7f229
TG
280int link_get(Manager *m, int ifindex, Link **ret) {
281 Link *link;
11a7f229
TG
282
283 assert(m);
11a7f229
TG
284 assert(ifindex);
285 assert(ret);
286
ae06ab10 287 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
11a7f229
TG
288 if (!link)
289 return -ENODEV;
290
291 *ret = link;
292
293 return 0;
294}
295
370e9930
TG
296void link_drop(Link *link) {
297 if (!link || link->state == LINK_STATE_LINGER)
298 return;
299
300 link->state = LINK_STATE_LINGER;
301
79008bdd 302 log_link_debug(link, "link removed");
370e9930
TG
303
304 link_unref(link);
305
306 return;
307}
308
57bd6899
TG
309static void link_enter_unmanaged(Link *link) {
310 assert(link);
311
79008bdd 312 log_link_debug(link, "unmanaged");
57bd6899
TG
313
314 link->state = LINK_STATE_UNMANAGED;
315
316 link_save(link);
317}
318
111bb8f9
TG
319static int link_stop_clients(Link *link) {
320 int r = 0, k;
321
322 assert(link);
323 assert(link->manager);
324 assert(link->manager->event);
325
326 if (!link->network)
327 return 0;
328
ba179154 329 if (link->dhcp_client) {
111bb8f9
TG
330 k = sd_dhcp_client_stop(link->dhcp_client);
331 if (k < 0) {
79008bdd 332 log_link_warning(link, "Could not stop DHCPv4 client: %s",
3c9b8860 333 strerror(-r));
111bb8f9
TG
334 r = k;
335 }
336 }
337
ba179154 338 if (link->ipv4ll) {
111bb8f9
TG
339 k = sd_ipv4ll_stop(link->ipv4ll);
340 if (k < 0) {
79008bdd 341 log_link_warning(link, "Could not stop IPv4 link-local: %s",
3c9b8860 342 strerror(-r));
111bb8f9 343 r = k;
dd43110f
TG
344 }
345 }
346
ba179154 347 if(link->icmp6_router_discovery) {
1873a3d3
PF
348
349 if (link->dhcp6_client) {
350 k = sd_dhcp6_client_stop(link->dhcp6_client);
351 if (k < 0) {
79008bdd 352 log_link_warning(link, "Could not stop DHCPv6 client: %s",
3c9b8860 353 strerror(-r));
1873a3d3
PF
354 r = k;
355 }
356 }
4138fb2c 357
1873a3d3 358 k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
4138fb2c 359 if (k < 0) {
79008bdd 360 log_link_warning(link,
3c9b8860
TG
361 "Could not stop ICMPv6 router discovery: %s",
362 strerror(-r));
4138fb2c
PF
363 r = k;
364 }
365 }
366
111bb8f9
TG
367 return r;
368}
369
b22d8a00 370void link_enter_failed(Link *link) {
ef1ba606 371 assert(link);
f882c247 372
370e9930 373 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
374 return;
375
79008bdd 376 log_link_warning(link, "failed");
449f7554 377
ef1ba606 378 link->state = LINK_STATE_FAILED;
fe8db0c5 379
111bb8f9
TG
380 link_stop_clients(link);
381
fe8db0c5 382 link_save(link);
f882c247
TG
383}
384
4f434938
LP
385static Address* link_find_dhcp_server_address(Link *link) {
386 Address *address;
387
388 assert(link);
389 assert(link->network);
390
391 /* The the first statically configured address if there is any */
392 LIST_FOREACH(addresses, address, link->network->static_addresses) {
393
394 if (address->family != AF_INET)
395 continue;
396
af93291c 397 if (in_addr_is_null(address->family, &address->in_addr))
4f434938
LP
398 continue;
399
400 return address;
401 }
402
403 /* If that didn't work, find a suitable address we got from the pool */
404 LIST_FOREACH(addresses, address, link->pool_addresses) {
405 if (address->family != AF_INET)
406 continue;
407
408 return address;
409 }
410
411 return NULL;
412}
413
dd43110f
TG
414static int link_enter_configured(Link *link) {
415 int r;
416
417 assert(link);
418 assert(link->network);
419 assert(link->state == LINK_STATE_SETTING_ROUTES);
420
78c958f8 421 if (link_dhcp4_server_enabled(link) &&
7c16313f 422 !sd_dhcp_server_is_running(link->dhcp_server)) {
4f434938
LP
423 struct in_addr pool_start;
424 Address *address;
425
426 address = link_find_dhcp_server_address(link);
427 if (!address) {
79008bdd 428 log_link_warning(link,
3c9b8860 429 "Failed to find suitable address for DHCPv4 server instance.");
4f434938
LP
430 link_enter_failed(link);
431 return 0;
432 }
433
79008bdd 434 log_link_debug(link, "offering DHCPv4 leases");
dd43110f 435
3c9b8860
TG
436 r = sd_dhcp_server_set_address(link->dhcp_server,
437 &address->in_addr.in,
438 address->prefixlen);
4f434938
LP
439 if (r < 0)
440 return r;
441
442 /* offer 32 addresses starting from the address following the server address */
443 pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1);
444 r = sd_dhcp_server_set_lease_pool(link->dhcp_server,
445 &pool_start, 32);
446 if (r < 0)
447 return r;
448
449 /* TODO:
450 r = sd_dhcp_server_set_router(link->dhcp_server,
451 &main_address->in_addr.in);
452 if (r < 0)
453 return r;
454
455 r = sd_dhcp_server_set_prefixlen(link->dhcp_server,
456 main_address->prefixlen);
457 if (r < 0)
458 return r;
459 */
460
dd43110f
TG
461 r = sd_dhcp_server_start(link->dhcp_server);
462 if (r < 0) {
79008bdd 463 log_link_warning(link, "could not start DHCPv4 server "
dd43110f
TG
464 "instance: %s", strerror(-r));
465
466 link_enter_failed(link);
467
468 return 0;
469 }
470 }
471
79008bdd 472 log_link_info(link, "link configured");
dd43110f
TG
473
474 link->state = LINK_STATE_CONFIGURED;
475
476 link_save(link);
477
478 return 0;
479}
480
3c9b8860
TG
481void link_client_handler(Link *link) {
482 assert(link);
483 assert(link->network);
484
485 if (!link->static_configured)
486 return;
487
78c958f8 488 if (link_ipv4ll_enabled(link))
3c9b8860
TG
489 if (!link->ipv4ll_address ||
490 !link->ipv4ll_route)
491 return;
492
78c958f8 493 if (link_dhcp4_enabled(link) && !link->dhcp4_configured)
3c9b8860
TG
494 return;
495
9fdaa992
TG
496 if (link->state != LINK_STATE_CONFIGURED)
497 link_enter_configured(link);
3c9b8860
TG
498
499 return;
500}
501
f882c247 502static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 503 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
504 int r;
505
3c9b8860 506 assert(link->link_messages > 0);
370e9930
TG
507 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
508 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
509 LINK_STATE_LINGER));
f882c247 510
3c9b8860 511 link->link_messages --;
f882c247 512
77a008c0 513 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
514 return 1;
515
516 r = sd_rtnl_message_get_errno(m);
c166a070 517 if (r < 0 && r != -EEXIST)
6c861f0a 518 log_link_warning_errno(link, -r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
f882c247 519
3c9b8860 520 if (link->link_messages == 0) {
79008bdd 521 log_link_debug(link, "routes set");
3c9b8860
TG
522 link->static_configured = true;
523 link_client_handler(link);
dd3efc09 524 }
f882c247
TG
525
526 return 1;
527}
528
529static int link_enter_set_routes(Link *link) {
a6cc569e 530 Route *rt;
f882c247
TG
531 int r;
532
533 assert(link);
534 assert(link->network);
ef1ba606 535 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 536
ef1ba606 537 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 538
3d3d4255 539 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 540 r = route_configure(rt, link, &route_handler);
dd3efc09 541 if (r < 0) {
79008bdd 542 log_link_warning(link,
3c9b8860 543 "could not set routes: %s",
b1666580 544 strerror(-r));
3c9b8860 545 link_enter_failed(link);
a6cc569e
TG
546 return r;
547 }
548
3c9b8860 549 link->link_messages ++;
8ddbeaa2 550 }
f5be5601 551
3c9b8860
TG
552 if (link->link_messages == 0) {
553 link->static_configured = true;
554 link_client_handler(link);
431ca2ce 555 } else
79008bdd 556 log_link_debug(link, "setting routes");
f882c247
TG
557
558 return 0;
559}
560
b22d8a00 561int link_route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 562 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
563 int r;
564
565 assert(m);
566 assert(link);
567 assert(link->ifname);
568
5da8149f 569 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
570 return 1;
571
572 r = sd_rtnl_message_get_errno(m);
b90b025a 573 if (r < 0 && r != -ESRCH)
6c861f0a 574 log_link_warning_errno(link, -r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
5c1d3fc9 575
5bdd314c 576 return 1;
5c1d3fc9
UTL
577}
578
f882c247 579static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 580 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
581 int r;
582
4958aee4 583 assert(rtnl);
f5be5601
TG
584 assert(m);
585 assert(link);
586 assert(link->ifname);
3c9b8860 587 assert(link->link_messages > 0);
370e9930
TG
588 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
589 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 590
3c9b8860 591 link->link_messages --;
f882c247 592
5da8149f 593 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
594 return 1;
595
596 r = sd_rtnl_message_get_errno(m);
c166a070 597 if (r < 0 && r != -EEXIST)
6c861f0a 598 log_link_warning_errno(link, -r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
45af44d4
TG
599 else if (r >= 0)
600 link_rtnl_process_address(rtnl, m, link->manager);
f882c247 601
3c9b8860 602 if (link->link_messages == 0) {
79008bdd 603 log_link_debug(link, "addresses set");
ef1ba606 604 link_enter_set_routes(link);
dd3efc09 605 }
f882c247
TG
606
607 return 1;
608}
609
610static int link_enter_set_addresses(Link *link) {
a6cc569e 611 Address *ad;
f882c247
TG
612 int r;
613
614 assert(link);
615 assert(link->network);
f5be5601 616 assert(link->state != _LINK_STATE_INVALID);
f882c247 617
ef1ba606 618 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 619
3d3d4255 620 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 621 r = address_configure(ad, link, &address_handler);
dd3efc09 622 if (r < 0) {
79008bdd 623 log_link_warning(link,
3c9b8860 624 "could not set addresses: %s",
a6cc569e 625 strerror(-r));
f5be5601
TG
626 link_enter_failed(link);
627 return r;
628 }
629
3c9b8860 630 link->link_messages ++;
f882c247
TG
631 }
632
3c9b8860 633 if (link->link_messages == 0) {
431ca2ce
TG
634 link_enter_set_routes(link);
635 } else
79008bdd 636 log_link_debug(link, "setting addresses");
431ca2ce 637
f882c247
TG
638 return 0;
639}
640
b22d8a00 641int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 642 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
643 int r;
644
645 assert(m);
646 assert(link);
647 assert(link->ifname);
648
5da8149f 649 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
650 return 1;
651
652 r = sd_rtnl_message_get_errno(m);
b90b025a 653 if (r < 0 && r != -EADDRNOTAVAIL)
6c861f0a 654 log_link_warning_errno(link, -r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
ff254138 655
5bdd314c 656 return 1;
ff254138
TG
657}
658
e1853b00
SS
659static int link_set_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
660 _cleanup_link_unref_ Link *link = userdata;
661 int r;
662
00e8d83a 663 log_link_debug(link, "set link");
e1853b00
SS
664
665 r = sd_rtnl_message_get_errno(m);
666 if (r < 0 && r != -EEXIST) {
00e8d83a 667 log_link_struct(link, LOG_ERR,
e1853b00
SS
668 "MESSAGE=%-*s: could not join netdev: %s",
669 IFNAMSIZ,
670 link->ifname, strerror(-r),
671 "ERRNO=%d", -r,
672 NULL);
673 link_enter_failed(link);
674 return 1;
675 }
676
677 return 0;
678}
679
3c9b8860
TG
680static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata,
681 sd_bus_error *ret_error) {
5da8149f 682 _cleanup_link_unref_ Link *link = userdata;
1346b1f0
TG
683 int r;
684
b226d99b
TG
685 assert(link);
686
5da8149f 687 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 688 return 1;
370e9930 689
1346b1f0 690 r = sd_bus_message_get_errno(m);
70b34f5d 691 if (r > 0)
79008bdd 692 log_link_warning(link, "Could not set hostname: %s",
3c9b8860 693 strerror(r));
1346b1f0
TG
694
695 return 1;
696}
697
3c9b8860 698int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
699 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
700 int r = 0;
701
b226d99b
TG
702 assert(link);
703 assert(link->manager);
1346b1f0
TG
704 assert(hostname);
705
79008bdd 706 log_link_debug(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 707
3c9b8860
TG
708 if (!link->manager->bus) {
709 /* TODO: replace by assert when we can rely on kdbus */
79008bdd 710 log_link_info(link,
3c9b8860 711 "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
712 return 0;
713 }
714
1346b1f0 715 r = sd_bus_message_new_method_call(
b226d99b 716 link->manager->bus,
151b9b96 717 &m,
1346b1f0
TG
718 "org.freedesktop.hostname1",
719 "/org/freedesktop/hostname1",
720 "org.freedesktop.hostname1",
151b9b96 721 "SetHostname");
1346b1f0
TG
722 if (r < 0)
723 return r;
724
725 r = sd_bus_message_append(m, "sb", hostname, false);
726 if (r < 0)
727 return r;
728
3c9b8860
TG
729 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler,
730 link, 0);
5da8149f 731 if (r < 0) {
79008bdd 732 log_link_error(link, "Could not set transient hostname: %s",
3c9b8860 733 strerror(-r));
5da8149f
TG
734 return r;
735 }
b226d99b
TG
736
737 link_ref(link);
1346b1f0 738
5da8149f 739 return 0;
1346b1f0
TG
740}
741
4f882b2a 742static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 743 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
744 int r;
745
746 assert(m);
747 assert(link);
748 assert(link->ifname);
749
5da8149f 750 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
751 return 1;
752
753 r = sd_rtnl_message_get_errno(m);
c9ccc19f 754 if (r < 0)
6c861f0a 755 log_link_warning_errno(link, -r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
4f882b2a
TG
756
757 return 1;
758}
759
3c9b8860 760int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 761 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
762 int r;
763
764 assert(link);
765 assert(link->manager);
766 assert(link->manager->rtnl);
767
79008bdd 768 log_link_debug(link, "setting MTU: %" PRIu32, mtu);
4f882b2a 769
151b9b96
LP
770 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
771 RTM_SETLINK, link->ifindex);
4f882b2a 772 if (r < 0) {
79008bdd 773 log_link_error(link, "Could not allocate RTM_SETLINK message");
4f882b2a
TG
774 return r;
775 }
776
777 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
778 if (r < 0) {
79008bdd 779 log_link_error(link, "Could not append MTU: %s", strerror(-r));
4f882b2a
TG
780 return r;
781 }
782
3c9b8860
TG
783 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link,
784 0, NULL);
4f882b2a 785 if (r < 0) {
79008bdd 786 log_link_error(link,
3c9b8860
TG
787 "Could not send rtnetlink message: %s",
788 strerror(-r));
4f882b2a
TG
789 return r;
790 }
791
ae941762 792 link_ref(link);
b226d99b 793
4f882b2a
TG
794 return 0;
795}
796
e1853b00
SS
797static int link_set_bridge(Link *link) {
798 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
799 int r;
800
801 assert(link);
802 assert(link->network);
803
804 if(link->network->cost == 0)
805 return 0;
806
807 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
808 RTM_SETLINK, link->ifindex);
809 if (r < 0) {
00e8d83a 810 log_link_error(link, "Could not allocate RTM_SETLINK message");
e1853b00
SS
811 return r;
812 }
813
814 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
815 if (r < 0) {
00e8d83a 816 log_link_error(link,
e1853b00
SS
817 "Could not set message family %s", strerror(-r));
818 return r;
819 }
820
821 r = sd_rtnl_message_open_container(req, IFLA_PROTINFO);
822 if (r < 0) {
00e8d83a 823 log_link_error(link,
e1853b00
SS
824 "Could not append IFLA_PROTINFO attribute: %s",
825 strerror(-r));
826 return r;
827 }
828
829 if(link->network->cost != 0) {
830 r = sd_rtnl_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
831 if (r < 0) {
00e8d83a 832 log_link_error(link,
e1853b00
SS
833 "Could not append IFLA_BRPORT_COST attribute: %s",
834 strerror(-r));
835 return r;
836 }
837 }
838
839 r = sd_rtnl_message_close_container(req);
840 if (r < 0) {
00e8d83a 841 log_link_error(link,
e1853b00
SS
842 "Could not append IFLA_LINKINFO attribute: %s",
843 strerror(-r));
844 return r;
845 }
846
847 r = sd_rtnl_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
848 if (r < 0) {
00e8d83a 849 log_link_error(link,
e1853b00
SS
850 "Could not send rtnetlink message: %s",
851 strerror(-r));
852 return r;
853 }
854
855 link_ref(link);
856
857 return r;
858}
859
4138fb2c
PF
860static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
861 Link *link = userdata;
862
863 assert(link);
864 assert(link->network);
865 assert(link->manager);
866
867 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
868 return;
869
870 switch(event) {
871 case DHCP6_EVENT_STOP:
872 case DHCP6_EVENT_RESEND_EXPIRE:
873 case DHCP6_EVENT_RETRANS_MAX:
874 case DHCP6_EVENT_IP_ACQUIRE:
79008bdd 875 log_link_debug(link, "DHCPv6 event %d", event);
4138fb2c
PF
876
877 break;
878
879 default:
880 if (event < 0)
79008bdd 881 log_link_warning(link, "DHCPv6 error: %s",
4138fb2c
PF
882 strerror(-event));
883 else
79008bdd 884 log_link_warning(link, "DHCPv6 unknown event: %d",
4138fb2c
PF
885 event);
886 return;
887 }
888}
889
890static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
891 Link *link = userdata;
892 int r;
893
894 assert(link);
895 assert(link->network);
896 assert(link->manager);
897
898 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
899 return;
900
901 switch(event) {
902 case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
903 case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
904 return;
905
906 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
907 case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
908 break;
909
910 default:
911 if (event < 0)
79008bdd 912 log_link_warning(link, "ICMPv6 error: %s",
4138fb2c
PF
913 strerror(-event));
914 else
79008bdd 915 log_link_warning(link, "ICMPv6 unknown event: %d",
4138fb2c
PF
916 event);
917
918 return;
919 }
920
921 if (link->dhcp6_client)
922 return;
923
924 r = sd_dhcp6_client_new(&link->dhcp6_client);
925 if (r < 0)
926 return;
927
928 r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
929 if (r < 0) {
930 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
931 return;
932 }
933
76253e73
DW
934 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
935 (const uint8_t *) &link->mac,
936 sizeof (link->mac), ARPHRD_ETHER);
4138fb2c
PF
937 if (r < 0) {
938 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
939 return;
940 }
941
942 r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
943 if (r < 0) {
944 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
945 return;
946 }
947
948 r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
949 link);
950 if (r < 0) {
951 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
952 return;
953 }
954
955 r = sd_dhcp6_client_start(link->dhcp6_client);
956 if (r < 0)
957 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
958}
959
ff254138
TG
960static int link_acquire_conf(Link *link) {
961 int r;
962
963 assert(link);
964 assert(link->network);
ff254138
TG
965 assert(link->manager);
966 assert(link->manager->event);
967
78c958f8 968 if (link_ipv4ll_enabled(link)) {
eb34d4af 969 assert(link->ipv4ll);
ff254138 970
79008bdd 971 log_link_debug(link, "acquiring IPv4 link-local address");
5c1d3fc9
UTL
972
973 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6 974 if (r < 0) {
79008bdd 975 log_link_warning(link, "could not acquire IPv4 "
124fa2c6 976 "link-local address");
ff254138 977 return r;
124fa2c6 978 }
5c1d3fc9
UTL
979 }
980
78c958f8 981 if (link_dhcp4_enabled(link)) {
eb34d4af 982 assert(link->dhcp_client);
ff254138 983
79008bdd 984 log_link_debug(link, "acquiring DHCPv4 lease");
ab47d620 985
5c1d3fc9 986 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6 987 if (r < 0) {
79008bdd 988 log_link_warning(link, "could not acquire DHCPv4 "
124fa2c6 989 "lease");
5c1d3fc9 990 return r;
124fa2c6 991 }
5c1d3fc9 992 }
ff254138 993
78c958f8 994 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
995 assert(link->icmp6_router_discovery);
996
79008bdd 997 log_link_debug(link, "discovering IPv6 routers");
4138fb2c
PF
998
999 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
1000 if (r < 0) {
79008bdd 1001 log_link_warning(link,
3c9b8860 1002 "could not start IPv6 router discovery");
4138fb2c
PF
1003 return r;
1004 }
1005 }
1006
ff254138
TG
1007 return 0;
1008}
1009
a61bb41c 1010bool link_has_carrier(Link *link) {
deb2e523
TG
1011 /* see Documentation/networking/operstates.txt in the kernel sources */
1012
a61bb41c 1013 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1014 return true;
1015
a61bb41c 1016 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1017 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1018 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1019 return true;
1020
1021 return false;
1022}
1023
dd3efc09 1024static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 1025 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1026 int r;
1027
1746cf2a
TG
1028 assert(link);
1029
5da8149f 1030 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1031 return 1;
1032
dd3efc09 1033 r = sd_rtnl_message_get_errno(m);
45ad2c13 1034 if (r < 0) {
9b86b393
TG
1035 /* we warn but don't fail the link, as it may
1036 be brought up later */
6c861f0a 1037 log_link_warning_errno(link, -r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
45ad2c13
TG
1038 }
1039
f882c247
TG
1040 return 1;
1041}
1042
1043static int link_up(Link *link) {
cf6a8911 1044 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1045 int r;
1046
f882c247 1047 assert(link);
c106cc36 1048 assert(link->network);
f882c247
TG
1049 assert(link->manager);
1050 assert(link->manager->rtnl);
1051
79008bdd 1052 log_link_debug(link, "bringing link up");
449f7554 1053
151b9b96
LP
1054 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1055 RTM_SETLINK, link->ifindex);
f579559b 1056 if (r < 0) {
79008bdd 1057 log_link_error(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1058 return r;
1059 }
1060
5d4795f3 1061 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1062 if (r < 0) {
79008bdd 1063 log_link_error(link, "Could not set link flags: %s",
3c9b8860 1064 strerror(-r));
fc25d7f8
TG
1065 return r;
1066 }
1067
c106cc36
TG
1068 if (link->network->mac) {
1069 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
1070 if (r < 0) {
1071 log_link_error(link, "Could not set MAC address: %s", strerror(-r));
1072 return r;
1073 }
1074 }
1075
1076 if (link->network->mtu) {
1077 r = sd_rtnl_message_append_u32(req, IFLA_MTU, link->network->mtu);
1078 if (r < 0) {
1079 log_link_error(link, "Could not set MTU: %s", strerror(-r));
1080 return r;
1081 }
1082 }
1083
3c9b8860
TG
1084 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1085 0, NULL);
f579559b 1086 if (r < 0) {
79008bdd 1087 log_link_error(link,
3c9b8860
TG
1088 "Could not send rtnetlink message: %s",
1089 strerror(-r));
f579559b
TG
1090 return r;
1091 }
1092
b226d99b
TG
1093 link_ref(link);
1094
f882c247
TG
1095 return 0;
1096}
1097
3f265037 1098static int link_joined(Link *link) {
f882c247
TG
1099 int r;
1100
ef1ba606 1101 assert(link);
f5be5601 1102 assert(link->network);
dd3efc09 1103
505f8da7
TG
1104 if (!(link->flags & IFF_UP)) {
1105 r = link_up(link);
1106 if (r < 0) {
1107 link_enter_failed(link);
1108 return r;
1109 }
ef1ba606 1110 }
f882c247 1111
e1853b00
SS
1112 if(link->network->bridge) {
1113 r = link_set_bridge(link);
1114 if (r < 0) {
00e8d83a 1115 log_link_error(link,
e1853b00
SS
1116 "Could not set bridge message: %s",
1117 strerror(-r));
1118 }
1119 }
1120
fb6730c4 1121 return link_enter_set_addresses(link);
02b59d57
TG
1122}
1123
3c9b8860
TG
1124static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1125 void *userdata) {
5da8149f 1126 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1127 int r;
1128
1746cf2a 1129 assert(link);
ef1ba606 1130 assert(link->network);
02b59d57 1131
52433f6b
TG
1132 link->enslaving --;
1133
5da8149f 1134 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1135 return 1;
1136
1137 r = sd_rtnl_message_get_errno(m);
856f962c 1138 if (r < 0 && r != -EEXIST) {
6c861f0a 1139 log_link_error_errno(link, -r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1140 link_enter_failed(link);
1141 return 1;
ba179154 1142 } else
79008bdd 1143 log_link_debug(link, "joined netdev");
02b59d57 1144
856f962c 1145 if (link->enslaving <= 0)
3f265037 1146 link_joined(link);
02b59d57
TG
1147
1148 return 1;
1149}
1150
3f265037 1151static int link_enter_join_netdev(Link *link) {
6a0a2f86 1152 NetDev *netdev;
672682a6 1153 Iterator i;
02b59d57
TG
1154 int r;
1155
1156 assert(link);
1157 assert(link->network);
8434fd5c 1158 assert(link->state == LINK_STATE_PENDING);
02b59d57 1159
52433f6b 1160 link->state = LINK_STATE_ENSLAVING;
02b59d57 1161
fe8db0c5
TG
1162 link_save(link);
1163
7951dea2
SS
1164 if (!link->network->bridge &&
1165 !link->network->bond &&
6a0a2f86 1166 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1167 return link_joined(link);
02b59d57 1168
d9c67ea1 1169 if (link->network->bond) {
6c861f0a 1170 log_link_struct(link, LOG_DEBUG,
97578344 1171 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1172 IFNAMSIZ,
af4e9e2c 1173 link->ifname, link->network->bond->ifname,
aa9f1140 1174 NETDEVIF(link->network->bond),
52433f6b 1175 NULL);
449f7554 1176
3f265037 1177 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b 1178 if (r < 0) {
6c861f0a 1179 log_link_struct(link, LOG_WARNING,
3f265037 1180 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1181 IFNAMSIZ,
3c9b8860
TG
1182 link->ifname, link->network->bond->ifname,
1183 strerror(-r),
aa9f1140 1184 NETDEVIF(link->network->bond),
52433f6b
TG
1185 NULL);
1186 link_enter_failed(link);
1187 return r;
1188 }
1189
0ad6148e
MO
1190 link->enslaving ++;
1191 }
1192
d9c67ea1 1193 if (link->network->bridge) {
6c861f0a 1194 log_link_struct(link, LOG_DEBUG,
97578344 1195 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1196 IFNAMSIZ,
af4e9e2c 1197 link->ifname, link->network->bridge->ifname,
aa9f1140 1198 NETDEVIF(link->network->bridge),
0ad6148e
MO
1199 NULL);
1200
3c9b8860
TG
1201 r = netdev_join(link->network->bridge, link,
1202 &netdev_join_handler);
0ad6148e 1203 if (r < 0) {
6c861f0a 1204 log_link_struct(link, LOG_WARNING,
3f265037 1205 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1206 IFNAMSIZ,
3c9b8860
TG
1207 link->ifname, link->network->bridge->ifname,
1208 strerror(-r),
aa9f1140 1209 NETDEVIF(link->network->bridge),
0ad6148e
MO
1210 NULL);
1211 link_enter_failed(link);
1212 return r;
1213 }
1214
52433f6b
TG
1215 link->enslaving ++;
1216 }
1217
6a0a2f86 1218 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
6c861f0a 1219 log_link_struct(link, LOG_DEBUG,
97578344 1220 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1221 IFNAMSIZ,
3c9b8860
TG
1222 link->ifname, netdev->ifname, NETDEVIF(netdev),
1223 NULL);
7951dea2 1224
6a0a2f86 1225 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2 1226 if (r < 0) {
6c861f0a 1227 log_link_struct(link, LOG_WARNING,
3f265037 1228 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1229 IFNAMSIZ,
3c9b8860
TG
1230 link->ifname, netdev->ifname,
1231 strerror(-r),
6a0a2f86 1232 NETDEVIF(netdev), NULL);
326cb406
SS
1233 link_enter_failed(link);
1234 return r;
1235 }
1236
326cb406
SS
1237 link->enslaving ++;
1238 }
1239
ef1ba606
TG
1240 return 0;
1241}
1242
a748b692 1243static int link_configure(Link *link) {
02b59d57
TG
1244 int r;
1245
ef1ba606 1246 assert(link);
b22d8a00 1247 assert(link->network);
8434fd5c 1248 assert(link->state == LINK_STATE_PENDING);
a748b692 1249
78c958f8 1250 if (link_ipv4ll_enabled(link)) {
b22d8a00 1251 r = ipv4ll_configure(link);
eb34d4af
TG
1252 if (r < 0)
1253 return r;
1254 }
1255
78c958f8 1256 if (link_dhcp4_enabled(link)) {
3c9b8860 1257 r = dhcp4_configure(link);
eb34d4af
TG
1258 if (r < 0)
1259 return r;
eb34d4af
TG
1260 }
1261
78c958f8 1262 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1263 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1264 if (r < 0)
1265 return r;
1266
1267 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1268 if (r < 0)
1269 return r;
dd43110f
TG
1270 }
1271
78c958f8 1272 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1273 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1274 if (r < 0)
1275 return r;
1276
1277 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1278 NULL, 0);
1279 if (r < 0)
1280 return r;
1281
1282 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1283 &link->mac);
1284 if (r < 0)
1285 return r;
1286
1287 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1288 link->ifindex);
1289 if (r < 0)
1290 return r;
1291
1292 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1293 icmp6_router_handler, link);
1294 if (r < 0)
1295 return r;
1296 }
1297
a61bb41c 1298 if (link_has_carrier(link)) {
1e9be60b
TG
1299 r = link_acquire_conf(link);
1300 if (r < 0)
1301 return r;
cc544d5f 1302 }
1e9be60b 1303
3f265037 1304 return link_enter_join_netdev(link);
505f8da7
TG
1305}
1306
3c9b8860
TG
1307static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1308 void *userdata) {
5da8149f 1309 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1310 Network *network;
505f8da7
TG
1311 int r;
1312
1313 assert(link);
1314 assert(link->ifname);
1315 assert(link->manager);
1316
8434fd5c 1317 if (link->state != LINK_STATE_PENDING)
5da8149f 1318 return 1;
505f8da7 1319
79008bdd 1320 log_link_debug(link, "link state is up-to-date");
505f8da7 1321
3c9b8860
TG
1322 r = network_get(link->manager, link->udev_device, link->ifname,
1323 &link->mac, &network);
57bd6899
TG
1324 if (r == -ENOENT) {
1325 link_enter_unmanaged(link);
5da8149f 1326 return 1;
57bd6899
TG
1327 } else if (r < 0)
1328 return r;
505f8da7 1329
bd2efe92 1330 if (link->flags & IFF_LOOPBACK) {
78c958f8 1331 if (network->ipv4ll)
79008bdd 1332 log_link_debug(link, "ignoring IPv4LL for loopback link");
78c958f8
TG
1333
1334 if (network->dhcp != DHCP_SUPPORT_NONE)
79008bdd 1335 log_link_debug(link, "ignoring DHCP clients for loopback link");
78c958f8
TG
1336
1337 if (network->dhcp_server)
79008bdd 1338 log_link_debug(link, "ignoring DHCP server for loopback link");
bd2efe92
TG
1339 }
1340
505f8da7
TG
1341 r = network_apply(link->manager, network, link);
1342 if (r < 0)
1343 return r;
1344
a748b692
TG
1345 r = link_configure(link);
1346 if (r < 0)
1347 return r;
1348
5da8149f 1349 return 1;
505f8da7
TG
1350}
1351
4f561e8e
TG
1352int link_initialized(Link *link, struct udev_device *device) {
1353 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1354 int r;
1355
1356 assert(link);
1357 assert(link->manager);
1358 assert(link->manager->rtnl);
1359 assert(device);
1360
8434fd5c 1361 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1362 return 0;
1363
679b3605
TG
1364 if (link->udev_device)
1365 return 0;
1366
79008bdd 1367 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1368
1369 link->udev_device = udev_device_ref(device);
1370
3c9b8860
TG
1371 /* udev has initialized the link, but we don't know if we have yet
1372 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1373 * when it returns we know that the pending NEWLINKs have already been
1374 * processed and that we are up-to-date */
4f561e8e 1375
3c9b8860
TG
1376 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1377 link->ifindex);
4f561e8e
TG
1378 if (r < 0)
1379 return r;
1380
3c9b8860
TG
1381 r = sd_rtnl_call_async(link->manager->rtnl, req,
1382 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1383 if (r < 0)
1384 return r;
1385
5da8149f
TG
1386 link_ref(link);
1387
4f561e8e
TG
1388 return 0;
1389}
1390
45af44d4 1391int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
fbbeb65a
TG
1392 Manager *m = userdata;
1393 Link *link = NULL;
1394 uint16_t type;
1395 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1396 Address *ad;
fbbeb65a 1397 char buf[INET6_ADDRSTRLEN];
c6d3b303
TG
1398 char valid_buf[FORMAT_TIMESPAN_MAX];
1399 const char *valid_str = NULL;
428fd0a7 1400 bool address_dropped = false;
fbbeb65a
TG
1401 int r, ifindex;
1402
1403 assert(rtnl);
1404 assert(message);
1405 assert(m);
1406
45af44d4
TG
1407 if (sd_rtnl_message_is_error(message)) {
1408 r = sd_rtnl_message_get_errno(message);
1409 if (r < 0)
1410 log_warning_errno(r, "rtnl: failed to receive address: %m");
1411
1412 return 0;
1413 }
1414
fbbeb65a
TG
1415 r = sd_rtnl_message_get_type(message, &type);
1416 if (r < 0) {
1417 log_warning("rtnl: could not get message type");
1418 return 0;
1419 }
1420
1421 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
45af44d4
TG
1422 if (r < 0) {
1423 log_warning_errno(r, "rtnl: could not get ifindex: %m");
1424 return 0;
1425 } else if (ifindex <= 0) {
1426 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
fbbeb65a
TG
1427 return 0;
1428 } else {
1429 r = link_get(m, ifindex, &link);
1430 if (r < 0 || !link) {
1e19f352 1431 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
1432 return 0;
1433 }
1434 }
1435
1436 r = address_new_dynamic(&address);
1437 if (r < 0)
393c0c5e 1438 return r;
fbbeb65a
TG
1439
1440 r = sd_rtnl_message_addr_get_family(message, &address->family);
1441 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
79008bdd 1442 log_link_warning(link,
3c9b8860 1443 "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1444 return 0;
1445 }
1446
1447 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1448 if (r < 0) {
79008bdd 1449 log_link_warning(link,
3c9b8860 1450 "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1451 return 0;
1452 }
1453
1454 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1455 if (r < 0) {
79008bdd 1456 log_link_warning(link,
3c9b8860 1457 "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1458 return 0;
1459 }
1460
81163121
TG
1461 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1462 if (r < 0) {
79008bdd 1463 log_link_warning(link,
81163121
TG
1464 "rtnl: received address with invalid flags, ignoring");
1465 return 0;
1466 }
1467
fbbeb65a
TG
1468 switch (address->family) {
1469 case AF_INET:
3c9b8860
TG
1470 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL,
1471 &address->in_addr.in);
fbbeb65a 1472 if (r < 0) {
79008bdd 1473 log_link_warning(link,
3c9b8860 1474 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1475 return 0;
1476 }
1477
1478 break;
1479
1480 case AF_INET6:
3c9b8860
TG
1481 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS,
1482 &address->in_addr.in6);
fbbeb65a 1483 if (r < 0) {
79008bdd 1484 log_link_warning(link,
3c9b8860 1485 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1486 return 0;
1487 }
1488
1489 break;
1490
1491 default:
1492 assert_not_reached("invalid address family");
1493 }
1494
3c9b8860
TG
1495 if (!inet_ntop(address->family, &address->in_addr, buf,
1496 INET6_ADDRSTRLEN)) {
79008bdd 1497 log_link_warning(link, "could not print address");
fbbeb65a
TG
1498 return 0;
1499 }
1500
c6d3b303
TG
1501 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO,
1502 &address->cinfo);
1503 if (r >= 0) {
1504 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1505 valid_str = "ever";
1506 else
1507 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1508 address->cinfo.ifa_valid * USEC_PER_SEC,
1509 USEC_PER_SEC);
1510 }
1511
428fd0a7
TG
1512 LIST_FOREACH(addresses, ad, link->addresses) {
1513 if (address_equal(ad, address)) {
1514 LIST_REMOVE(addresses, link->addresses, ad);
1515
1516 address_free(ad);
1517
1518 address_dropped = true;
1519
1520 break;
1521 }
1522 }
1523
fbbeb65a
TG
1524 switch (type) {
1525 case RTM_NEWADDR:
428fd0a7 1526 if (!address_dropped)
79008bdd 1527 log_link_debug(link, "added address: %s/%u (valid for %s)",
b1d6dcf5 1528 buf, address->prefixlen, valid_str);
393c0c5e 1529 else
79008bdd 1530 log_link_debug(link, "updated address: %s/%u (valid for %s)",
b1d6dcf5 1531 buf, address->prefixlen, valid_str);
fbbeb65a 1532
428fd0a7
TG
1533 LIST_PREPEND(addresses, link->addresses, address);
1534 address = NULL;
1535
f5602be9
TG
1536 link_save(link);
1537
428fd0a7 1538 break;
fbbeb65a 1539 case RTM_DELADDR:
f5602be9 1540 if (address_dropped) {
79008bdd 1541 log_link_debug(link, "removed address: %s/%u (valid for %s)",
b1d6dcf5 1542 buf, address->prefixlen, valid_str);
428fd0a7 1543
f5602be9 1544 link_save(link);
393c0c5e 1545 } else
79008bdd 1546 log_link_warning(link,
c6d3b303 1547 "removing non-existent address: %s/%u (valid for %s)",
b1d6dcf5 1548 buf, address->prefixlen, valid_str);
f5602be9 1549
fbbeb65a
TG
1550 break;
1551 default:
1552 assert_not_reached("Received invalid RTNL message type");
1553 }
1554
1555 return 1;
1556}
1557
505f8da7
TG
1558int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1559 Link *link;
1560 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1561 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1562 int r;
1563
1564 assert(m);
fbbeb65a 1565 assert(m->rtnl);
505f8da7
TG
1566 assert(message);
1567 assert(ret);
1568
1569 r = link_new(m, message, ret);
1570 if (r < 0)
1571 return r;
1572
1573 link = *ret;
1574
79008bdd 1575 log_link_debug(link, "link %d added", link->ifindex);
505f8da7
TG
1576
1577 if (detect_container(NULL) <= 0) {
1578 /* not in a container, udev will be around */
ae06ab10 1579 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1580 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1581 if (!device) {
79008bdd 1582 log_link_warning(link,
3c9b8860 1583 "could not find udev device: %m");
9fecce80 1584 return -errno;
505f8da7
TG
1585 }
1586
3c4cb064 1587 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1588 /* not yet ready */
79008bdd 1589 log_link_debug(link, "link pending udev initialization...");
505f8da7 1590 return 0;
3c4cb064 1591 }
505f8da7 1592
4f561e8e
TG
1593 r = link_initialized(link, device);
1594 if (r < 0)
1595 return r;
1596 } else {
5da8149f
TG
1597 /* we are calling a callback directly, so must take a ref */
1598 link_ref(link);
1599
4f561e8e
TG
1600 r = link_initialized_and_synced(m->rtnl, NULL, link);
1601 if (r < 0)
1602 return r;
1603 }
505f8da7 1604
a748b692
TG
1605 return 0;
1606}
1607
22936833 1608int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1609 struct ether_addr mac;
ca4e095a 1610 const char *ifname;
afe7fd56 1611 uint32_t mtu;
a61bb41c 1612 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
1613 int r;
1614
dd3efc09 1615 assert(link);
b8941f74 1616 assert(link->ifname);
22936833
TG
1617 assert(m);
1618
7619683b
TG
1619 if (link->state == LINK_STATE_LINGER) {
1620 link_ref(link);
79008bdd 1621 log_link_info(link, "link readded");
7619683b
TG
1622 link->state = LINK_STATE_ENSLAVING;
1623 }
1624
b8941f74
TG
1625 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1626 if (r >= 0 && !streq(ifname, link->ifname)) {
79008bdd 1627 log_link_info(link, "renamed to %s", ifname);
b8941f74
TG
1628
1629 free(link->ifname);
1630 link->ifname = strdup(ifname);
1631 if (!link->ifname)
1632 return -ENOMEM;
1633 }
1634
afe7fd56
TG
1635 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1636 if (r >= 0 && mtu > 0) {
1637 link->mtu = mtu;
1638 if (!link->original_mtu) {
1639 link->original_mtu = mtu;
79008bdd 1640 log_link_debug(link, "saved original MTU: %"
afe7fd56
TG
1641 PRIu32, link->original_mtu);
1642 }
1643
1644 if (link->dhcp_client) {
3c9b8860
TG
1645 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1646 link->mtu);
afe7fd56 1647 if (r < 0) {
79008bdd 1648 log_link_warning(link,
3c9b8860 1649 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1650 strerror(-r));
1651 return r;
1652 }
1653 }
9842de0d 1654 }
69629de9 1655
e9189a1f
TG
1656 /* The kernel may broadcast NEWLINK messages without the MAC address
1657 set, simply ignore them. */
c49b33ac 1658 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1659 if (r >= 0) {
3c9b8860
TG
1660 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1661 ETH_ALEN)) {
c49b33ac 1662
3c9b8860
TG
1663 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1664 ETH_ALEN);
c49b33ac 1665
79008bdd 1666 log_link_debug(link, "MAC address: "
20861203
TG
1667 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1668 mac.ether_addr_octet[0],
1669 mac.ether_addr_octet[1],
1670 mac.ether_addr_octet[2],
1671 mac.ether_addr_octet[3],
1672 mac.ether_addr_octet[4],
1673 mac.ether_addr_octet[5]);
c49b33ac 1674
20861203
TG
1675 if (link->ipv4ll) {
1676 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1677 if (r < 0) {
79008bdd 1678 log_link_warning(link,
3c9b8860 1679 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1680 strerror(-r));
1681 return r;
1682 }
c49b33ac 1683 }
c49b33ac 1684
20861203 1685 if (link->dhcp_client) {
3c9b8860 1686 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
1687 (const uint8_t *) &link->mac,
1688 sizeof (link->mac),
1689 ARPHRD_ETHER);
20861203 1690 if (r < 0) {
79008bdd 1691 log_link_warning(link,
3c9b8860 1692 "Could not update MAC address in DHCP client: %s",
20861203
TG
1693 strerror(-r));
1694 return r;
1695 }
c49b33ac 1696 }
4138fb2c
PF
1697
1698 if (link->dhcp6_client) {
1699 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
1700 (const uint8_t *) &link->mac,
1701 sizeof (link->mac),
1702 ARPHRD_ETHER);
4138fb2c 1703 if (r < 0) {
79008bdd 1704 log_link_warning(link,
3c9b8860 1705 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1706 strerror(-r));
1707 return r;
1708 }
1709 }
c49b33ac 1710 }
4f882b2a
TG
1711 }
1712
a61bb41c
TG
1713 had_carrier = link_has_carrier(link);
1714
1715 r = link_update_flags(link, m);
1716 if (r < 0)
1717 return r;
1718
1719 carrier_gained = !had_carrier && link_has_carrier(link);
1720 carrier_lost = had_carrier && !link_has_carrier(link);
1721
1722 if (carrier_gained) {
79008bdd 1723 log_link_info(link, "gained carrier");
a61bb41c
TG
1724
1725 if (link->network) {
1726 r = link_acquire_conf(link);
1727 if (r < 0) {
1728 link_enter_failed(link);
1729 return r;
1730 }
1731 }
1732 } else if (carrier_lost) {
79008bdd 1733 log_link_info(link, "lost carrier");
a61bb41c
TG
1734
1735 r = link_stop_clients(link);
1736 if (r < 0) {
1737 link_enter_failed(link);
1738 return r;
1739 }
1740 }
1741
1742 return 0;
dd3efc09 1743}
fe8db0c5 1744
e375dcde
TG
1745static void link_update_operstate(Link *link) {
1746
1747 assert(link);
1748
1749 if (link->kernel_operstate == IF_OPER_DORMANT)
1750 link->operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 1751 else if (link_has_carrier(link)) {
e375dcde
TG
1752 Address *address;
1753 uint8_t scope = RT_SCOPE_NOWHERE;
1754
1755 /* if we have carrier, check what addresses we have */
1756 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
1757 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
1758 continue;
1759
e375dcde
TG
1760 if (address->scope < scope)
1761 scope = address->scope;
1762 }
1763
1764 if (scope < RT_SCOPE_SITE)
1765 /* universally accessible addresses found */
1766 link->operstate = LINK_OPERSTATE_ROUTABLE;
1767 else if (scope < RT_SCOPE_HOST)
1768 /* only link or site local addresses found */
1769 link->operstate = LINK_OPERSTATE_DEGRADED;
1770 else
1771 /* no useful addresses found */
1772 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1773 } else if (link->flags & IFF_UP)
d3df0e39 1774 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1775 else
d3df0e39 1776 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1777}
1778
fe8db0c5 1779int link_save(Link *link) {
68a8723c 1780 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1781 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1782 const char *admin_state, *oper_state;
fe8db0c5
TG
1783 int r;
1784
1785 assert(link);
1786 assert(link->state_file);
68a8723c 1787 assert(link->lease_file);
bbf7c048
TG
1788 assert(link->manager);
1789
e375dcde
TG
1790 link_update_operstate(link);
1791
bbf7c048
TG
1792 r = manager_save(link->manager);
1793 if (r < 0)
1794 return r;
fe8db0c5 1795
370e9930
TG
1796 if (link->state == LINK_STATE_LINGER) {
1797 unlink(link->state_file);
1798 return 0;
1799 }
1800
deb2e523
TG
1801 admin_state = link_state_to_string(link->state);
1802 assert(admin_state);
1803
e375dcde
TG
1804 oper_state = link_operstate_to_string(link->operstate);
1805 assert(oper_state);
deb2e523 1806
fe8db0c5
TG
1807 r = fopen_temporary(link->state_file, &f, &temp_path);
1808 if (r < 0)
c2d6bd61 1809 return r;
fe8db0c5
TG
1810
1811 fchmod(fileno(f), 0644);
1812
1813 fprintf(f,
1814 "# This is private data. Do not parse.\n"
deb2e523 1815 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1816 "OPER_STATE=%s\n",
1817 admin_state, oper_state);
fe8db0c5 1818
bcb7a07e 1819 if (link->network) {
ea352b40
LP
1820 char **address, **domain;
1821 bool space;
b0e39c82 1822
adc5b2e2
TG
1823 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
1824
b0e39c82 1825 fputs("DNS=", f);
ea352b40
LP
1826 space = false;
1827 STRV_FOREACH(address, link->network->dns) {
1828 if (space)
1829 fputc(' ', f);
1830 fputs(*address, f);
1831 space = true;
1832 }
d5314fff 1833
b0e39c82
TG
1834 if (link->network->dhcp_dns &&
1835 link->dhcp_lease) {
1836 const struct in_addr *addresses;
1837
1838 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1839 if (r > 0) {
ea352b40
LP
1840 if (space)
1841 fputc(' ', f);
b0e39c82 1842 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1843 }
1844 }
1845
b0e39c82
TG
1846 fputs("\n", f);
1847
1848 fprintf(f, "NTP=");
ea352b40
LP
1849 space = false;
1850 STRV_FOREACH(address, link->network->ntp) {
1851 if (space)
1852 fputc(' ', f);
1853 fputs(*address, f);
1854 space = true;
1855 }
d5314fff 1856
b0e39c82
TG
1857 if (link->network->dhcp_ntp &&
1858 link->dhcp_lease) {
1859 const struct in_addr *addresses;
1860
1861 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1862 if (r > 0) {
ea352b40
LP
1863 if (space)
1864 fputc(' ', f);
b0e39c82 1865 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1866 }
1867 }
1868
b0e39c82 1869 fputs("\n", f);
bd8f6538 1870
6192b846 1871 fprintf(f, "DOMAINS=");
ea352b40
LP
1872 space = false;
1873 STRV_FOREACH(domain, link->network->domains) {
1874 if (space)
1875 fputc(' ', f);
1876 fputs(*domain, f);
1877 space = true;
1878 }
d5314fff 1879
ad0734e8 1880 if (link->network->dhcp_domains &&
9b4d1882
TG
1881 link->dhcp_lease) {
1882 const char *domainname;
1883
1884 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 1885 if (r >= 0) {
ea352b40
LP
1886 if (space)
1887 fputc(' ', f);
6192b846 1888 fputs(domainname, f);
6192b846 1889 }
9b4d1882
TG
1890 }
1891
6192b846
TG
1892 fputs("\n", f);
1893
67272d15
TG
1894 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1895 yes_no(link->network->wildcard_domain));
1896
3c9b8860
TG
1897 fprintf(f, "LLMNR=%s\n",
1898 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1899 }
7374f9d8 1900
fe8db0c5 1901 if (link->dhcp_lease) {
d9876a52
TG
1902 assert(link->network);
1903
1dc24d5f 1904 r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1905 if (r < 0)
c2d6bd61 1906 goto fail;
fe8db0c5 1907
7374f9d8 1908 fprintf(f,
b0e39c82
TG
1909 "DHCP_LEASE=%s\n",
1910 link->lease_file);
deb2e523 1911 } else
68a8723c 1912 unlink(link->lease_file);
fe8db0c5 1913
c2d6bd61
LP
1914 r = fflush_and_check(f);
1915 if (r < 0)
1916 goto fail;
fe8db0c5 1917
c2d6bd61 1918 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1919 r = -errno;
c2d6bd61 1920 goto fail;
fe8db0c5
TG
1921 }
1922
c2d6bd61 1923 return 0;
c2d6bd61 1924fail:
79008bdd 1925 log_link_error(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
c2d6bd61
LP
1926 unlink(link->state_file);
1927 unlink(temp_path);
fe8db0c5
TG
1928 return r;
1929}
1930
1931static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1932 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1933 [LINK_STATE_ENSLAVING] = "configuring",
1934 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1935 [LINK_STATE_SETTING_ROUTES] = "configuring",
1936 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1937 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1938 [LINK_STATE_FAILED] = "failed",
370e9930 1939 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1940};
1941
1942DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1943
1944static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1945 [LINK_OPERSTATE_OFF] = "off",
1946 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1947 [LINK_OPERSTATE_DORMANT] = "dormant",
1948 [LINK_OPERSTATE_CARRIER] = "carrier",
1949 [LINK_OPERSTATE_DEGRADED] = "degraded",
1950 [LINK_OPERSTATE_ROUTABLE] = "routable",
1951};
1952
1953DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);