]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
gitignore: ignore generated systemd-bootchart.service
[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
b22d8a00 579int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
4958aee4
TG
580 _cleanup_link_unref_ Link *link = userdata;
581 int r;
582
583 assert(rtnl);
584 assert(m);
585 assert(link);
586 assert(link->manager);
587
588 for (; m; m = sd_rtnl_message_next(m)) {
589 r = sd_rtnl_message_get_errno(m);
590 if (r < 0) {
79008bdd 591 log_link_debug(link, "getting address failed: %s",
3c9b8860 592 strerror(-r));
4958aee4
TG
593 continue;
594 }
595
596 r = link_rtnl_process_address(rtnl, m, link->manager);
597 if (r < 0)
79008bdd 598 log_link_warning(link, "could not process address: %s",
3c9b8860 599 strerror(-r));
4958aee4
TG
600 }
601
602 return 1;
603}
604
f882c247 605static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 606 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
607 int r;
608
4958aee4 609 assert(rtnl);
f5be5601
TG
610 assert(m);
611 assert(link);
612 assert(link->ifname);
3c9b8860 613 assert(link->link_messages > 0);
370e9930
TG
614 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
615 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 616
3c9b8860 617 link->link_messages --;
f882c247 618
5da8149f 619 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
620 return 1;
621
622 r = sd_rtnl_message_get_errno(m);
c166a070 623 if (r < 0 && r != -EEXIST)
6c861f0a 624 log_link_warning_errno(link, -r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
5bdd314c 625 else if (r >= 0) {
4958aee4
TG
626 /* calling handler directly so take a ref */
627 link_ref(link);
628 link_get_address_handler(rtnl, m, link);
629 }
f882c247 630
3c9b8860 631 if (link->link_messages == 0) {
79008bdd 632 log_link_debug(link, "addresses set");
ef1ba606 633 link_enter_set_routes(link);
dd3efc09 634 }
f882c247
TG
635
636 return 1;
637}
638
639static int link_enter_set_addresses(Link *link) {
a6cc569e 640 Address *ad;
f882c247
TG
641 int r;
642
643 assert(link);
644 assert(link->network);
f5be5601 645 assert(link->state != _LINK_STATE_INVALID);
f882c247 646
ef1ba606 647 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 648
3d3d4255 649 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 650 r = address_configure(ad, link, &address_handler);
dd3efc09 651 if (r < 0) {
79008bdd 652 log_link_warning(link,
3c9b8860 653 "could not set addresses: %s",
a6cc569e 654 strerror(-r));
f5be5601
TG
655 link_enter_failed(link);
656 return r;
657 }
658
3c9b8860 659 link->link_messages ++;
f882c247
TG
660 }
661
3c9b8860 662 if (link->link_messages == 0) {
431ca2ce
TG
663 link_enter_set_routes(link);
664 } else
79008bdd 665 log_link_debug(link, "setting addresses");
431ca2ce 666
f882c247
TG
667 return 0;
668}
669
b22d8a00 670int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 671 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
672 int r;
673
674 assert(m);
675 assert(link);
676 assert(link->ifname);
677
5da8149f 678 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
679 return 1;
680
681 r = sd_rtnl_message_get_errno(m);
b90b025a 682 if (r < 0 && r != -EADDRNOTAVAIL)
6c861f0a 683 log_link_warning_errno(link, -r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
ff254138 684
5bdd314c 685 return 1;
ff254138
TG
686}
687
e1853b00
SS
688static int link_set_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
689 _cleanup_link_unref_ Link *link = userdata;
690 int r;
691
00e8d83a 692 log_link_debug(link, "set link");
e1853b00
SS
693
694 r = sd_rtnl_message_get_errno(m);
695 if (r < 0 && r != -EEXIST) {
00e8d83a 696 log_link_struct(link, LOG_ERR,
e1853b00
SS
697 "MESSAGE=%-*s: could not join netdev: %s",
698 IFNAMSIZ,
699 link->ifname, strerror(-r),
700 "ERRNO=%d", -r,
701 NULL);
702 link_enter_failed(link);
703 return 1;
704 }
705
706 return 0;
707}
708
3c9b8860
TG
709static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata,
710 sd_bus_error *ret_error) {
5da8149f 711 _cleanup_link_unref_ Link *link = userdata;
1346b1f0
TG
712 int r;
713
b226d99b
TG
714 assert(link);
715
5da8149f 716 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 717 return 1;
370e9930 718
1346b1f0 719 r = sd_bus_message_get_errno(m);
70b34f5d 720 if (r > 0)
79008bdd 721 log_link_warning(link, "Could not set hostname: %s",
3c9b8860 722 strerror(r));
1346b1f0
TG
723
724 return 1;
725}
726
3c9b8860 727int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
728 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
729 int r = 0;
730
b226d99b
TG
731 assert(link);
732 assert(link->manager);
1346b1f0
TG
733 assert(hostname);
734
79008bdd 735 log_link_debug(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 736
3c9b8860
TG
737 if (!link->manager->bus) {
738 /* TODO: replace by assert when we can rely on kdbus */
79008bdd 739 log_link_info(link,
3c9b8860 740 "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
741 return 0;
742 }
743
1346b1f0 744 r = sd_bus_message_new_method_call(
b226d99b 745 link->manager->bus,
151b9b96 746 &m,
1346b1f0
TG
747 "org.freedesktop.hostname1",
748 "/org/freedesktop/hostname1",
749 "org.freedesktop.hostname1",
151b9b96 750 "SetHostname");
1346b1f0
TG
751 if (r < 0)
752 return r;
753
754 r = sd_bus_message_append(m, "sb", hostname, false);
755 if (r < 0)
756 return r;
757
3c9b8860
TG
758 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler,
759 link, 0);
5da8149f 760 if (r < 0) {
79008bdd 761 log_link_error(link, "Could not set transient hostname: %s",
3c9b8860 762 strerror(-r));
5da8149f
TG
763 return r;
764 }
b226d99b
TG
765
766 link_ref(link);
1346b1f0 767
5da8149f 768 return 0;
1346b1f0
TG
769}
770
4f882b2a 771static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 772 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
773 int r;
774
775 assert(m);
776 assert(link);
777 assert(link->ifname);
778
5da8149f 779 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
780 return 1;
781
782 r = sd_rtnl_message_get_errno(m);
c9ccc19f 783 if (r < 0)
6c861f0a 784 log_link_warning_errno(link, -r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
4f882b2a
TG
785
786 return 1;
787}
788
3c9b8860 789int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 790 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
791 int r;
792
793 assert(link);
794 assert(link->manager);
795 assert(link->manager->rtnl);
796
79008bdd 797 log_link_debug(link, "setting MTU: %" PRIu32, mtu);
4f882b2a 798
151b9b96
LP
799 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
800 RTM_SETLINK, link->ifindex);
4f882b2a 801 if (r < 0) {
79008bdd 802 log_link_error(link, "Could not allocate RTM_SETLINK message");
4f882b2a
TG
803 return r;
804 }
805
806 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
807 if (r < 0) {
79008bdd 808 log_link_error(link, "Could not append MTU: %s", strerror(-r));
4f882b2a
TG
809 return r;
810 }
811
3c9b8860
TG
812 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link,
813 0, NULL);
4f882b2a 814 if (r < 0) {
79008bdd 815 log_link_error(link,
3c9b8860
TG
816 "Could not send rtnetlink message: %s",
817 strerror(-r));
4f882b2a
TG
818 return r;
819 }
820
ae941762 821 link_ref(link);
b226d99b 822
4f882b2a
TG
823 return 0;
824}
825
e1853b00
SS
826static int link_set_bridge(Link *link) {
827 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
828 int r;
829
830 assert(link);
831 assert(link->network);
832
833 if(link->network->cost == 0)
834 return 0;
835
836 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
837 RTM_SETLINK, link->ifindex);
838 if (r < 0) {
00e8d83a 839 log_link_error(link, "Could not allocate RTM_SETLINK message");
e1853b00
SS
840 return r;
841 }
842
843 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
844 if (r < 0) {
00e8d83a 845 log_link_error(link,
e1853b00
SS
846 "Could not set message family %s", strerror(-r));
847 return r;
848 }
849
850 r = sd_rtnl_message_open_container(req, IFLA_PROTINFO);
851 if (r < 0) {
00e8d83a 852 log_link_error(link,
e1853b00
SS
853 "Could not append IFLA_PROTINFO attribute: %s",
854 strerror(-r));
855 return r;
856 }
857
858 if(link->network->cost != 0) {
859 r = sd_rtnl_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
860 if (r < 0) {
00e8d83a 861 log_link_error(link,
e1853b00
SS
862 "Could not append IFLA_BRPORT_COST attribute: %s",
863 strerror(-r));
864 return r;
865 }
866 }
867
868 r = sd_rtnl_message_close_container(req);
869 if (r < 0) {
00e8d83a 870 log_link_error(link,
e1853b00
SS
871 "Could not append IFLA_LINKINFO attribute: %s",
872 strerror(-r));
873 return r;
874 }
875
876 r = sd_rtnl_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
877 if (r < 0) {
00e8d83a 878 log_link_error(link,
e1853b00
SS
879 "Could not send rtnetlink message: %s",
880 strerror(-r));
881 return r;
882 }
883
884 link_ref(link);
885
886 return r;
887}
888
4138fb2c
PF
889static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
890 Link *link = userdata;
891
892 assert(link);
893 assert(link->network);
894 assert(link->manager);
895
896 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
897 return;
898
899 switch(event) {
900 case DHCP6_EVENT_STOP:
901 case DHCP6_EVENT_RESEND_EXPIRE:
902 case DHCP6_EVENT_RETRANS_MAX:
903 case DHCP6_EVENT_IP_ACQUIRE:
79008bdd 904 log_link_debug(link, "DHCPv6 event %d", event);
4138fb2c
PF
905
906 break;
907
908 default:
909 if (event < 0)
79008bdd 910 log_link_warning(link, "DHCPv6 error: %s",
4138fb2c
PF
911 strerror(-event));
912 else
79008bdd 913 log_link_warning(link, "DHCPv6 unknown event: %d",
4138fb2c
PF
914 event);
915 return;
916 }
917}
918
919static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
920 Link *link = userdata;
921 int r;
922
923 assert(link);
924 assert(link->network);
925 assert(link->manager);
926
927 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
928 return;
929
930 switch(event) {
931 case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
932 case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
933 return;
934
935 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
936 case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
937 break;
938
939 default:
940 if (event < 0)
79008bdd 941 log_link_warning(link, "ICMPv6 error: %s",
4138fb2c
PF
942 strerror(-event));
943 else
79008bdd 944 log_link_warning(link, "ICMPv6 unknown event: %d",
4138fb2c
PF
945 event);
946
947 return;
948 }
949
950 if (link->dhcp6_client)
951 return;
952
953 r = sd_dhcp6_client_new(&link->dhcp6_client);
954 if (r < 0)
955 return;
956
957 r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
958 if (r < 0) {
959 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
960 return;
961 }
962
76253e73
DW
963 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
964 (const uint8_t *) &link->mac,
965 sizeof (link->mac), ARPHRD_ETHER);
4138fb2c
PF
966 if (r < 0) {
967 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
968 return;
969 }
970
971 r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
972 if (r < 0) {
973 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
974 return;
975 }
976
977 r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
978 link);
979 if (r < 0) {
980 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
981 return;
982 }
983
984 r = sd_dhcp6_client_start(link->dhcp6_client);
985 if (r < 0)
986 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
987}
988
ff254138
TG
989static int link_acquire_conf(Link *link) {
990 int r;
991
992 assert(link);
993 assert(link->network);
ff254138
TG
994 assert(link->manager);
995 assert(link->manager->event);
996
78c958f8 997 if (link_ipv4ll_enabled(link)) {
eb34d4af 998 assert(link->ipv4ll);
ff254138 999
79008bdd 1000 log_link_debug(link, "acquiring IPv4 link-local address");
5c1d3fc9
UTL
1001
1002 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6 1003 if (r < 0) {
79008bdd 1004 log_link_warning(link, "could not acquire IPv4 "
124fa2c6 1005 "link-local address");
ff254138 1006 return r;
124fa2c6 1007 }
5c1d3fc9
UTL
1008 }
1009
78c958f8 1010 if (link_dhcp4_enabled(link)) {
eb34d4af 1011 assert(link->dhcp_client);
ff254138 1012
79008bdd 1013 log_link_debug(link, "acquiring DHCPv4 lease");
ab47d620 1014
5c1d3fc9 1015 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6 1016 if (r < 0) {
79008bdd 1017 log_link_warning(link, "could not acquire DHCPv4 "
124fa2c6 1018 "lease");
5c1d3fc9 1019 return r;
124fa2c6 1020 }
5c1d3fc9 1021 }
ff254138 1022
78c958f8 1023 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1024 assert(link->icmp6_router_discovery);
1025
79008bdd 1026 log_link_debug(link, "discovering IPv6 routers");
4138fb2c
PF
1027
1028 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
1029 if (r < 0) {
79008bdd 1030 log_link_warning(link,
3c9b8860 1031 "could not start IPv6 router discovery");
4138fb2c
PF
1032 return r;
1033 }
1034 }
1035
ff254138
TG
1036 return 0;
1037}
1038
a61bb41c 1039bool link_has_carrier(Link *link) {
deb2e523
TG
1040 /* see Documentation/networking/operstates.txt in the kernel sources */
1041
a61bb41c 1042 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1043 return true;
1044
a61bb41c 1045 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1046 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1047 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1048 return true;
1049
1050 return false;
1051}
1052
dd3efc09 1053static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 1054 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1055 int r;
1056
1746cf2a
TG
1057 assert(link);
1058
5da8149f 1059 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1060 return 1;
1061
dd3efc09 1062 r = sd_rtnl_message_get_errno(m);
45ad2c13 1063 if (r < 0) {
9b86b393
TG
1064 /* we warn but don't fail the link, as it may
1065 be brought up later */
6c861f0a 1066 log_link_warning_errno(link, -r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
45ad2c13
TG
1067 }
1068
f882c247
TG
1069 return 1;
1070}
1071
1072static int link_up(Link *link) {
cf6a8911 1073 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1074 int r;
1075
f882c247
TG
1076 assert(link);
1077 assert(link->manager);
1078 assert(link->manager->rtnl);
1079
79008bdd 1080 log_link_debug(link, "bringing link up");
449f7554 1081
151b9b96
LP
1082 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1083 RTM_SETLINK, link->ifindex);
f579559b 1084 if (r < 0) {
79008bdd 1085 log_link_error(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1086 return r;
1087 }
1088
5d4795f3 1089 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1090 if (r < 0) {
79008bdd 1091 log_link_error(link, "Could not set link flags: %s",
3c9b8860 1092 strerror(-r));
fc25d7f8
TG
1093 return r;
1094 }
1095
3c9b8860
TG
1096 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1097 0, NULL);
f579559b 1098 if (r < 0) {
79008bdd 1099 log_link_error(link,
3c9b8860
TG
1100 "Could not send rtnetlink message: %s",
1101 strerror(-r));
f579559b
TG
1102 return r;
1103 }
1104
b226d99b
TG
1105 link_ref(link);
1106
f882c247
TG
1107 return 0;
1108}
1109
3f265037 1110static int link_joined(Link *link) {
f882c247
TG
1111 int r;
1112
ef1ba606 1113 assert(link);
f5be5601 1114 assert(link->network);
dd3efc09 1115
505f8da7
TG
1116 if (!(link->flags & IFF_UP)) {
1117 r = link_up(link);
1118 if (r < 0) {
1119 link_enter_failed(link);
1120 return r;
1121 }
ef1ba606 1122 }
f882c247 1123
e1853b00
SS
1124 if(link->network->bridge) {
1125 r = link_set_bridge(link);
1126 if (r < 0) {
00e8d83a 1127 log_link_error(link,
e1853b00
SS
1128 "Could not set bridge message: %s",
1129 strerror(-r));
1130 }
1131 }
1132
fb6730c4 1133 return link_enter_set_addresses(link);
02b59d57
TG
1134}
1135
3c9b8860
TG
1136static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1137 void *userdata) {
5da8149f 1138 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1139 int r;
1140
1746cf2a 1141 assert(link);
ef1ba606 1142 assert(link->network);
02b59d57 1143
52433f6b
TG
1144 link->enslaving --;
1145
5da8149f 1146 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1147 return 1;
1148
1149 r = sd_rtnl_message_get_errno(m);
856f962c 1150 if (r < 0 && r != -EEXIST) {
6c861f0a 1151 log_link_error_errno(link, -r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1152 link_enter_failed(link);
1153 return 1;
ba179154 1154 } else
79008bdd 1155 log_link_debug(link, "joined netdev");
02b59d57 1156
856f962c 1157 if (link->enslaving <= 0)
3f265037 1158 link_joined(link);
02b59d57
TG
1159
1160 return 1;
1161}
1162
3f265037 1163static int link_enter_join_netdev(Link *link) {
6a0a2f86 1164 NetDev *netdev;
672682a6 1165 Iterator i;
02b59d57
TG
1166 int r;
1167
1168 assert(link);
1169 assert(link->network);
8434fd5c 1170 assert(link->state == LINK_STATE_PENDING);
02b59d57 1171
52433f6b 1172 link->state = LINK_STATE_ENSLAVING;
02b59d57 1173
fe8db0c5
TG
1174 link_save(link);
1175
7951dea2
SS
1176 if (!link->network->bridge &&
1177 !link->network->bond &&
6a0a2f86 1178 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1179 return link_joined(link);
02b59d57 1180
d9c67ea1 1181 if (link->network->bond) {
6c861f0a 1182 log_link_struct(link, LOG_DEBUG,
97578344 1183 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1184 IFNAMSIZ,
af4e9e2c 1185 link->ifname, link->network->bond->ifname,
aa9f1140 1186 NETDEVIF(link->network->bond),
52433f6b 1187 NULL);
449f7554 1188
3f265037 1189 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b 1190 if (r < 0) {
6c861f0a 1191 log_link_struct(link, LOG_WARNING,
3f265037 1192 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1193 IFNAMSIZ,
3c9b8860
TG
1194 link->ifname, link->network->bond->ifname,
1195 strerror(-r),
aa9f1140 1196 NETDEVIF(link->network->bond),
52433f6b
TG
1197 NULL);
1198 link_enter_failed(link);
1199 return r;
1200 }
1201
0ad6148e
MO
1202 link->enslaving ++;
1203 }
1204
d9c67ea1 1205 if (link->network->bridge) {
6c861f0a 1206 log_link_struct(link, LOG_DEBUG,
97578344 1207 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1208 IFNAMSIZ,
af4e9e2c 1209 link->ifname, link->network->bridge->ifname,
aa9f1140 1210 NETDEVIF(link->network->bridge),
0ad6148e
MO
1211 NULL);
1212
3c9b8860
TG
1213 r = netdev_join(link->network->bridge, link,
1214 &netdev_join_handler);
0ad6148e 1215 if (r < 0) {
6c861f0a 1216 log_link_struct(link, LOG_WARNING,
3f265037 1217 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1218 IFNAMSIZ,
3c9b8860
TG
1219 link->ifname, link->network->bridge->ifname,
1220 strerror(-r),
aa9f1140 1221 NETDEVIF(link->network->bridge),
0ad6148e
MO
1222 NULL);
1223 link_enter_failed(link);
1224 return r;
1225 }
1226
52433f6b
TG
1227 link->enslaving ++;
1228 }
1229
6a0a2f86 1230 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
6c861f0a 1231 log_link_struct(link, LOG_DEBUG,
97578344 1232 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1233 IFNAMSIZ,
3c9b8860
TG
1234 link->ifname, netdev->ifname, NETDEVIF(netdev),
1235 NULL);
7951dea2 1236
6a0a2f86 1237 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2 1238 if (r < 0) {
6c861f0a 1239 log_link_struct(link, LOG_WARNING,
3f265037 1240 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1241 IFNAMSIZ,
3c9b8860
TG
1242 link->ifname, netdev->ifname,
1243 strerror(-r),
6a0a2f86 1244 NETDEVIF(netdev), NULL);
326cb406
SS
1245 link_enter_failed(link);
1246 return r;
1247 }
1248
326cb406
SS
1249 link->enslaving ++;
1250 }
1251
ef1ba606
TG
1252 return 0;
1253}
1254
a748b692 1255static int link_configure(Link *link) {
02b59d57
TG
1256 int r;
1257
ef1ba606 1258 assert(link);
b22d8a00 1259 assert(link->network);
8434fd5c 1260 assert(link->state == LINK_STATE_PENDING);
a748b692 1261
78c958f8 1262 if (link_ipv4ll_enabled(link)) {
b22d8a00 1263 r = ipv4ll_configure(link);
eb34d4af
TG
1264 if (r < 0)
1265 return r;
1266 }
1267
78c958f8 1268 if (link_dhcp4_enabled(link)) {
3c9b8860 1269 r = dhcp4_configure(link);
eb34d4af
TG
1270 if (r < 0)
1271 return r;
eb34d4af
TG
1272 }
1273
78c958f8 1274 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1275 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1276 if (r < 0)
1277 return r;
1278
1279 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1280 if (r < 0)
1281 return r;
dd43110f
TG
1282 }
1283
78c958f8 1284 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1285 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1286 if (r < 0)
1287 return r;
1288
1289 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1290 NULL, 0);
1291 if (r < 0)
1292 return r;
1293
1294 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1295 &link->mac);
1296 if (r < 0)
1297 return r;
1298
1299 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1300 link->ifindex);
1301 if (r < 0)
1302 return r;
1303
1304 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1305 icmp6_router_handler, link);
1306 if (r < 0)
1307 return r;
1308 }
1309
a61bb41c 1310 if (link_has_carrier(link)) {
1e9be60b
TG
1311 r = link_acquire_conf(link);
1312 if (r < 0)
1313 return r;
cc544d5f 1314 }
1e9be60b 1315
3f265037 1316 return link_enter_join_netdev(link);
505f8da7
TG
1317}
1318
3c9b8860
TG
1319static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1320 void *userdata) {
5da8149f 1321 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1322 Network *network;
505f8da7
TG
1323 int r;
1324
1325 assert(link);
1326 assert(link->ifname);
1327 assert(link->manager);
1328
8434fd5c 1329 if (link->state != LINK_STATE_PENDING)
5da8149f 1330 return 1;
505f8da7 1331
79008bdd 1332 log_link_debug(link, "link state is up-to-date");
505f8da7 1333
3c9b8860
TG
1334 r = network_get(link->manager, link->udev_device, link->ifname,
1335 &link->mac, &network);
57bd6899
TG
1336 if (r == -ENOENT) {
1337 link_enter_unmanaged(link);
5da8149f 1338 return 1;
57bd6899
TG
1339 } else if (r < 0)
1340 return r;
505f8da7 1341
bd2efe92 1342 if (link->flags & IFF_LOOPBACK) {
78c958f8 1343 if (network->ipv4ll)
79008bdd 1344 log_link_debug(link, "ignoring IPv4LL for loopback link");
78c958f8
TG
1345
1346 if (network->dhcp != DHCP_SUPPORT_NONE)
79008bdd 1347 log_link_debug(link, "ignoring DHCP clients for loopback link");
78c958f8
TG
1348
1349 if (network->dhcp_server)
79008bdd 1350 log_link_debug(link, "ignoring DHCP server for loopback link");
bd2efe92
TG
1351 }
1352
505f8da7
TG
1353 r = network_apply(link->manager, network, link);
1354 if (r < 0)
1355 return r;
1356
a748b692
TG
1357 r = link_configure(link);
1358 if (r < 0)
1359 return r;
1360
5da8149f 1361 return 1;
505f8da7
TG
1362}
1363
4f561e8e
TG
1364int link_initialized(Link *link, struct udev_device *device) {
1365 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1366 int r;
1367
1368 assert(link);
1369 assert(link->manager);
1370 assert(link->manager->rtnl);
1371 assert(device);
1372
8434fd5c 1373 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1374 return 0;
1375
679b3605
TG
1376 if (link->udev_device)
1377 return 0;
1378
79008bdd 1379 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1380
1381 link->udev_device = udev_device_ref(device);
1382
3c9b8860
TG
1383 /* udev has initialized the link, but we don't know if we have yet
1384 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1385 * when it returns we know that the pending NEWLINKs have already been
1386 * processed and that we are up-to-date */
4f561e8e 1387
3c9b8860
TG
1388 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1389 link->ifindex);
4f561e8e
TG
1390 if (r < 0)
1391 return r;
1392
3c9b8860
TG
1393 r = sd_rtnl_call_async(link->manager->rtnl, req,
1394 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1395 if (r < 0)
1396 return r;
1397
5da8149f
TG
1398 link_ref(link);
1399
4f561e8e
TG
1400 return 0;
1401}
1402
3c9b8860
TG
1403int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message,
1404 void *userdata) {
fbbeb65a
TG
1405 Manager *m = userdata;
1406 Link *link = NULL;
1407 uint16_t type;
1408 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1409 Address *ad;
fbbeb65a 1410 char buf[INET6_ADDRSTRLEN];
c6d3b303
TG
1411 char valid_buf[FORMAT_TIMESPAN_MAX];
1412 const char *valid_str = NULL;
428fd0a7 1413 bool address_dropped = false;
fbbeb65a
TG
1414 int r, ifindex;
1415
1416 assert(rtnl);
1417 assert(message);
1418 assert(m);
1419
1420 r = sd_rtnl_message_get_type(message, &type);
1421 if (r < 0) {
1422 log_warning("rtnl: could not get message type");
1423 return 0;
1424 }
1425
1426 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1427 if (r < 0 || ifindex <= 0) {
5ea846cc 1428 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1429 return 0;
1430 } else {
1431 r = link_get(m, ifindex, &link);
1432 if (r < 0 || !link) {
a821cbb0 1433 log_warning("rtnl: received address for a nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
1434 return 0;
1435 }
1436 }
1437
1438 r = address_new_dynamic(&address);
1439 if (r < 0)
393c0c5e 1440 return r;
fbbeb65a
TG
1441
1442 r = sd_rtnl_message_addr_get_family(message, &address->family);
1443 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
79008bdd 1444 log_link_warning(link,
3c9b8860 1445 "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1446 return 0;
1447 }
1448
1449 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1450 if (r < 0) {
79008bdd 1451 log_link_warning(link,
3c9b8860 1452 "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1453 return 0;
1454 }
1455
1456 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1457 if (r < 0) {
79008bdd 1458 log_link_warning(link,
3c9b8860 1459 "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1460 return 0;
1461 }
1462
81163121
TG
1463 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1464 if (r < 0) {
79008bdd 1465 log_link_warning(link,
81163121
TG
1466 "rtnl: received address with invalid flags, ignoring");
1467 return 0;
1468 }
1469
fbbeb65a
TG
1470 switch (address->family) {
1471 case AF_INET:
3c9b8860
TG
1472 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL,
1473 &address->in_addr.in);
fbbeb65a 1474 if (r < 0) {
79008bdd 1475 log_link_warning(link,
3c9b8860 1476 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1477 return 0;
1478 }
1479
1480 break;
1481
1482 case AF_INET6:
3c9b8860
TG
1483 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS,
1484 &address->in_addr.in6);
fbbeb65a 1485 if (r < 0) {
79008bdd 1486 log_link_warning(link,
3c9b8860 1487 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1488 return 0;
1489 }
1490
1491 break;
1492
1493 default:
1494 assert_not_reached("invalid address family");
1495 }
1496
3c9b8860
TG
1497 if (!inet_ntop(address->family, &address->in_addr, buf,
1498 INET6_ADDRSTRLEN)) {
79008bdd 1499 log_link_warning(link, "could not print address");
fbbeb65a
TG
1500 return 0;
1501 }
1502
c6d3b303
TG
1503 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO,
1504 &address->cinfo);
1505 if (r >= 0) {
1506 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1507 valid_str = "ever";
1508 else
1509 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1510 address->cinfo.ifa_valid * USEC_PER_SEC,
1511 USEC_PER_SEC);
1512 }
1513
428fd0a7
TG
1514 LIST_FOREACH(addresses, ad, link->addresses) {
1515 if (address_equal(ad, address)) {
1516 LIST_REMOVE(addresses, link->addresses, ad);
1517
1518 address_free(ad);
1519
1520 address_dropped = true;
1521
1522 break;
1523 }
1524 }
1525
fbbeb65a
TG
1526 switch (type) {
1527 case RTM_NEWADDR:
428fd0a7 1528 if (!address_dropped)
79008bdd 1529 log_link_debug(link, "added address: %s/%u (valid for %s)",
b1d6dcf5 1530 buf, address->prefixlen, valid_str);
393c0c5e 1531 else
79008bdd 1532 log_link_debug(link, "updated address: %s/%u (valid for %s)",
b1d6dcf5 1533 buf, address->prefixlen, valid_str);
fbbeb65a 1534
428fd0a7
TG
1535 LIST_PREPEND(addresses, link->addresses, address);
1536 address = NULL;
1537
f5602be9
TG
1538 link_save(link);
1539
428fd0a7 1540 break;
fbbeb65a 1541 case RTM_DELADDR:
f5602be9 1542 if (address_dropped) {
79008bdd 1543 log_link_debug(link, "removed address: %s/%u (valid for %s)",
b1d6dcf5 1544 buf, address->prefixlen, valid_str);
428fd0a7 1545
f5602be9 1546 link_save(link);
393c0c5e 1547 } else
79008bdd 1548 log_link_warning(link,
c6d3b303 1549 "removing non-existent address: %s/%u (valid for %s)",
b1d6dcf5 1550 buf, address->prefixlen, valid_str);
f5602be9 1551
fbbeb65a
TG
1552 break;
1553 default:
1554 assert_not_reached("Received invalid RTNL message type");
1555 }
1556
1557 return 1;
1558}
1559
505f8da7
TG
1560int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1561 Link *link;
fbbeb65a 1562 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1563 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1564 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1565 int r;
1566
1567 assert(m);
fbbeb65a 1568 assert(m->rtnl);
505f8da7
TG
1569 assert(message);
1570 assert(ret);
1571
1572 r = link_new(m, message, ret);
1573 if (r < 0)
1574 return r;
1575
1576 link = *ret;
1577
79008bdd 1578 log_link_debug(link, "link %d added", link->ifindex);
505f8da7 1579
3c9b8860
TG
1580 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex,
1581 0);
fbbeb65a
TG
1582 if (r < 0)
1583 return r;
1584
3c9b8860
TG
1585 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0,
1586 NULL);
fbbeb65a
TG
1587 if (r < 0)
1588 return r;
1589
5da8149f
TG
1590 link_ref(link);
1591
505f8da7
TG
1592 if (detect_container(NULL) <= 0) {
1593 /* not in a container, udev will be around */
ae06ab10 1594 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1595 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1596 if (!device) {
79008bdd 1597 log_link_warning(link,
3c9b8860 1598 "could not find udev device: %m");
9fecce80 1599 return -errno;
505f8da7
TG
1600 }
1601
3c4cb064 1602 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1603 /* not yet ready */
79008bdd 1604 log_link_debug(link, "link pending udev initialization...");
505f8da7 1605 return 0;
3c4cb064 1606 }
505f8da7 1607
4f561e8e
TG
1608 r = link_initialized(link, device);
1609 if (r < 0)
1610 return r;
1611 } else {
5da8149f
TG
1612 /* we are calling a callback directly, so must take a ref */
1613 link_ref(link);
1614
4f561e8e
TG
1615 r = link_initialized_and_synced(m->rtnl, NULL, link);
1616 if (r < 0)
1617 return r;
1618 }
505f8da7 1619
a748b692
TG
1620 return 0;
1621}
1622
22936833 1623int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1624 struct ether_addr mac;
ca4e095a 1625 const char *ifname;
afe7fd56 1626 uint32_t mtu;
a61bb41c 1627 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
1628 int r;
1629
dd3efc09 1630 assert(link);
b8941f74 1631 assert(link->ifname);
22936833
TG
1632 assert(m);
1633
7619683b
TG
1634 if (link->state == LINK_STATE_LINGER) {
1635 link_ref(link);
79008bdd 1636 log_link_info(link, "link readded");
7619683b
TG
1637 link->state = LINK_STATE_ENSLAVING;
1638 }
1639
b8941f74
TG
1640 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1641 if (r >= 0 && !streq(ifname, link->ifname)) {
79008bdd 1642 log_link_info(link, "renamed to %s", ifname);
b8941f74
TG
1643
1644 free(link->ifname);
1645 link->ifname = strdup(ifname);
1646 if (!link->ifname)
1647 return -ENOMEM;
1648 }
1649
afe7fd56
TG
1650 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1651 if (r >= 0 && mtu > 0) {
1652 link->mtu = mtu;
1653 if (!link->original_mtu) {
1654 link->original_mtu = mtu;
79008bdd 1655 log_link_debug(link, "saved original MTU: %"
afe7fd56
TG
1656 PRIu32, link->original_mtu);
1657 }
1658
1659 if (link->dhcp_client) {
3c9b8860
TG
1660 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1661 link->mtu);
afe7fd56 1662 if (r < 0) {
79008bdd 1663 log_link_warning(link,
3c9b8860 1664 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1665 strerror(-r));
1666 return r;
1667 }
1668 }
9842de0d 1669 }
69629de9 1670
e9189a1f
TG
1671 /* The kernel may broadcast NEWLINK messages without the MAC address
1672 set, simply ignore them. */
c49b33ac 1673 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1674 if (r >= 0) {
3c9b8860
TG
1675 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1676 ETH_ALEN)) {
c49b33ac 1677
3c9b8860
TG
1678 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1679 ETH_ALEN);
c49b33ac 1680
79008bdd 1681 log_link_debug(link, "MAC address: "
20861203
TG
1682 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1683 mac.ether_addr_octet[0],
1684 mac.ether_addr_octet[1],
1685 mac.ether_addr_octet[2],
1686 mac.ether_addr_octet[3],
1687 mac.ether_addr_octet[4],
1688 mac.ether_addr_octet[5]);
c49b33ac 1689
20861203
TG
1690 if (link->ipv4ll) {
1691 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1692 if (r < 0) {
79008bdd 1693 log_link_warning(link,
3c9b8860 1694 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1695 strerror(-r));
1696 return r;
1697 }
c49b33ac 1698 }
c49b33ac 1699
20861203 1700 if (link->dhcp_client) {
3c9b8860 1701 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
1702 (const uint8_t *) &link->mac,
1703 sizeof (link->mac),
1704 ARPHRD_ETHER);
20861203 1705 if (r < 0) {
79008bdd 1706 log_link_warning(link,
3c9b8860 1707 "Could not update MAC address in DHCP client: %s",
20861203
TG
1708 strerror(-r));
1709 return r;
1710 }
c49b33ac 1711 }
4138fb2c
PF
1712
1713 if (link->dhcp6_client) {
1714 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
1715 (const uint8_t *) &link->mac,
1716 sizeof (link->mac),
1717 ARPHRD_ETHER);
4138fb2c 1718 if (r < 0) {
79008bdd 1719 log_link_warning(link,
3c9b8860 1720 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1721 strerror(-r));
1722 return r;
1723 }
1724 }
c49b33ac 1725 }
4f882b2a
TG
1726 }
1727
a61bb41c
TG
1728 had_carrier = link_has_carrier(link);
1729
1730 r = link_update_flags(link, m);
1731 if (r < 0)
1732 return r;
1733
1734 carrier_gained = !had_carrier && link_has_carrier(link);
1735 carrier_lost = had_carrier && !link_has_carrier(link);
1736
1737 if (carrier_gained) {
79008bdd 1738 log_link_info(link, "gained carrier");
a61bb41c
TG
1739
1740 if (link->network) {
1741 r = link_acquire_conf(link);
1742 if (r < 0) {
1743 link_enter_failed(link);
1744 return r;
1745 }
1746 }
1747 } else if (carrier_lost) {
79008bdd 1748 log_link_info(link, "lost carrier");
a61bb41c
TG
1749
1750 r = link_stop_clients(link);
1751 if (r < 0) {
1752 link_enter_failed(link);
1753 return r;
1754 }
1755 }
1756
1757 return 0;
dd3efc09 1758}
fe8db0c5 1759
e375dcde
TG
1760static void link_update_operstate(Link *link) {
1761
1762 assert(link);
1763
1764 if (link->kernel_operstate == IF_OPER_DORMANT)
1765 link->operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 1766 else if (link_has_carrier(link)) {
e375dcde
TG
1767 Address *address;
1768 uint8_t scope = RT_SCOPE_NOWHERE;
1769
1770 /* if we have carrier, check what addresses we have */
1771 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
1772 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
1773 continue;
1774
e375dcde
TG
1775 if (address->scope < scope)
1776 scope = address->scope;
1777 }
1778
1779 if (scope < RT_SCOPE_SITE)
1780 /* universally accessible addresses found */
1781 link->operstate = LINK_OPERSTATE_ROUTABLE;
1782 else if (scope < RT_SCOPE_HOST)
1783 /* only link or site local addresses found */
1784 link->operstate = LINK_OPERSTATE_DEGRADED;
1785 else
1786 /* no useful addresses found */
1787 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1788 } else if (link->flags & IFF_UP)
d3df0e39 1789 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1790 else
d3df0e39 1791 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1792}
1793
fe8db0c5 1794int link_save(Link *link) {
68a8723c 1795 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1796 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1797 const char *admin_state, *oper_state;
fe8db0c5
TG
1798 int r;
1799
1800 assert(link);
1801 assert(link->state_file);
68a8723c 1802 assert(link->lease_file);
bbf7c048
TG
1803 assert(link->manager);
1804
e375dcde
TG
1805 link_update_operstate(link);
1806
bbf7c048
TG
1807 r = manager_save(link->manager);
1808 if (r < 0)
1809 return r;
fe8db0c5 1810
370e9930
TG
1811 if (link->state == LINK_STATE_LINGER) {
1812 unlink(link->state_file);
1813 return 0;
1814 }
1815
deb2e523
TG
1816 admin_state = link_state_to_string(link->state);
1817 assert(admin_state);
1818
e375dcde
TG
1819 oper_state = link_operstate_to_string(link->operstate);
1820 assert(oper_state);
deb2e523 1821
fe8db0c5
TG
1822 r = fopen_temporary(link->state_file, &f, &temp_path);
1823 if (r < 0)
c2d6bd61 1824 return r;
fe8db0c5
TG
1825
1826 fchmod(fileno(f), 0644);
1827
1828 fprintf(f,
1829 "# This is private data. Do not parse.\n"
deb2e523 1830 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1831 "OPER_STATE=%s\n",
1832 admin_state, oper_state);
fe8db0c5 1833
bcb7a07e 1834 if (link->network) {
ea352b40
LP
1835 char **address, **domain;
1836 bool space;
b0e39c82 1837
adc5b2e2
TG
1838 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
1839
b0e39c82 1840 fputs("DNS=", f);
ea352b40
LP
1841 space = false;
1842 STRV_FOREACH(address, link->network->dns) {
1843 if (space)
1844 fputc(' ', f);
1845 fputs(*address, f);
1846 space = true;
1847 }
d5314fff 1848
b0e39c82
TG
1849 if (link->network->dhcp_dns &&
1850 link->dhcp_lease) {
1851 const struct in_addr *addresses;
1852
1853 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1854 if (r > 0) {
ea352b40
LP
1855 if (space)
1856 fputc(' ', f);
b0e39c82 1857 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1858 }
1859 }
1860
b0e39c82
TG
1861 fputs("\n", f);
1862
1863 fprintf(f, "NTP=");
ea352b40
LP
1864 space = false;
1865 STRV_FOREACH(address, link->network->ntp) {
1866 if (space)
1867 fputc(' ', f);
1868 fputs(*address, f);
1869 space = true;
1870 }
d5314fff 1871
b0e39c82
TG
1872 if (link->network->dhcp_ntp &&
1873 link->dhcp_lease) {
1874 const struct in_addr *addresses;
1875
1876 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1877 if (r > 0) {
ea352b40
LP
1878 if (space)
1879 fputc(' ', f);
b0e39c82 1880 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1881 }
1882 }
1883
b0e39c82 1884 fputs("\n", f);
bd8f6538 1885
6192b846 1886 fprintf(f, "DOMAINS=");
ea352b40
LP
1887 space = false;
1888 STRV_FOREACH(domain, link->network->domains) {
1889 if (space)
1890 fputc(' ', f);
1891 fputs(*domain, f);
1892 space = true;
1893 }
d5314fff 1894
ad0734e8 1895 if (link->network->dhcp_domains &&
9b4d1882
TG
1896 link->dhcp_lease) {
1897 const char *domainname;
1898
1899 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 1900 if (r >= 0) {
ea352b40
LP
1901 if (space)
1902 fputc(' ', f);
6192b846 1903 fputs(domainname, f);
6192b846 1904 }
9b4d1882
TG
1905 }
1906
6192b846
TG
1907 fputs("\n", f);
1908
67272d15
TG
1909 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1910 yes_no(link->network->wildcard_domain));
1911
3c9b8860
TG
1912 fprintf(f, "LLMNR=%s\n",
1913 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1914 }
7374f9d8 1915
fe8db0c5 1916 if (link->dhcp_lease) {
d9876a52
TG
1917 assert(link->network);
1918
1dc24d5f 1919 r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1920 if (r < 0)
c2d6bd61 1921 goto fail;
fe8db0c5 1922
7374f9d8 1923 fprintf(f,
b0e39c82
TG
1924 "DHCP_LEASE=%s\n",
1925 link->lease_file);
deb2e523 1926 } else
68a8723c 1927 unlink(link->lease_file);
fe8db0c5 1928
c2d6bd61
LP
1929 r = fflush_and_check(f);
1930 if (r < 0)
1931 goto fail;
fe8db0c5 1932
c2d6bd61 1933 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1934 r = -errno;
c2d6bd61 1935 goto fail;
fe8db0c5
TG
1936 }
1937
c2d6bd61 1938 return 0;
c2d6bd61 1939fail:
79008bdd 1940 log_link_error(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
c2d6bd61
LP
1941 unlink(link->state_file);
1942 unlink(temp_path);
fe8db0c5
TG
1943 return r;
1944}
1945
1946static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1947 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1948 [LINK_STATE_ENSLAVING] = "configuring",
1949 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1950 [LINK_STATE_SETTING_ROUTES] = "configuring",
1951 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1952 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1953 [LINK_STATE_FAILED] = "failed",
370e9930 1954 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1955};
1956
1957DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1958
1959static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1960 [LINK_OPERSTATE_OFF] = "off",
1961 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1962 [LINK_OPERSTATE_DORMANT] = "dormant",
1963 [LINK_OPERSTATE_CARRIER] = "carrier",
1964 [LINK_OPERSTATE_DEGRADED] = "degraded",
1965 [LINK_OPERSTATE_ROUTABLE] = "routable",
1966};
1967
1968DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);