]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
journal: Fix navigating backwards missing entries
[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 1076 assert(link);
c106cc36 1077 assert(link->network);
f882c247
TG
1078 assert(link->manager);
1079 assert(link->manager->rtnl);
1080
79008bdd 1081 log_link_debug(link, "bringing link up");
449f7554 1082
151b9b96
LP
1083 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1084 RTM_SETLINK, link->ifindex);
f579559b 1085 if (r < 0) {
79008bdd 1086 log_link_error(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1087 return r;
1088 }
1089
5d4795f3 1090 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1091 if (r < 0) {
79008bdd 1092 log_link_error(link, "Could not set link flags: %s",
3c9b8860 1093 strerror(-r));
fc25d7f8
TG
1094 return r;
1095 }
1096
c106cc36
TG
1097 if (link->network->mac) {
1098 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
1099 if (r < 0) {
1100 log_link_error(link, "Could not set MAC address: %s", strerror(-r));
1101 return r;
1102 }
1103 }
1104
1105 if (link->network->mtu) {
1106 r = sd_rtnl_message_append_u32(req, IFLA_MTU, link->network->mtu);
1107 if (r < 0) {
1108 log_link_error(link, "Could not set MTU: %s", strerror(-r));
1109 return r;
1110 }
1111 }
1112
3c9b8860
TG
1113 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1114 0, NULL);
f579559b 1115 if (r < 0) {
79008bdd 1116 log_link_error(link,
3c9b8860
TG
1117 "Could not send rtnetlink message: %s",
1118 strerror(-r));
f579559b
TG
1119 return r;
1120 }
1121
b226d99b
TG
1122 link_ref(link);
1123
f882c247
TG
1124 return 0;
1125}
1126
3f265037 1127static int link_joined(Link *link) {
f882c247
TG
1128 int r;
1129
ef1ba606 1130 assert(link);
f5be5601 1131 assert(link->network);
dd3efc09 1132
505f8da7
TG
1133 if (!(link->flags & IFF_UP)) {
1134 r = link_up(link);
1135 if (r < 0) {
1136 link_enter_failed(link);
1137 return r;
1138 }
ef1ba606 1139 }
f882c247 1140
e1853b00
SS
1141 if(link->network->bridge) {
1142 r = link_set_bridge(link);
1143 if (r < 0) {
00e8d83a 1144 log_link_error(link,
e1853b00
SS
1145 "Could not set bridge message: %s",
1146 strerror(-r));
1147 }
1148 }
1149
fb6730c4 1150 return link_enter_set_addresses(link);
02b59d57
TG
1151}
1152
3c9b8860
TG
1153static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1154 void *userdata) {
5da8149f 1155 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1156 int r;
1157
1746cf2a 1158 assert(link);
ef1ba606 1159 assert(link->network);
02b59d57 1160
52433f6b
TG
1161 link->enslaving --;
1162
5da8149f 1163 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1164 return 1;
1165
1166 r = sd_rtnl_message_get_errno(m);
856f962c 1167 if (r < 0 && r != -EEXIST) {
6c861f0a 1168 log_link_error_errno(link, -r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1169 link_enter_failed(link);
1170 return 1;
ba179154 1171 } else
79008bdd 1172 log_link_debug(link, "joined netdev");
02b59d57 1173
856f962c 1174 if (link->enslaving <= 0)
3f265037 1175 link_joined(link);
02b59d57
TG
1176
1177 return 1;
1178}
1179
3f265037 1180static int link_enter_join_netdev(Link *link) {
6a0a2f86 1181 NetDev *netdev;
672682a6 1182 Iterator i;
02b59d57
TG
1183 int r;
1184
1185 assert(link);
1186 assert(link->network);
8434fd5c 1187 assert(link->state == LINK_STATE_PENDING);
02b59d57 1188
52433f6b 1189 link->state = LINK_STATE_ENSLAVING;
02b59d57 1190
fe8db0c5
TG
1191 link_save(link);
1192
7951dea2
SS
1193 if (!link->network->bridge &&
1194 !link->network->bond &&
6a0a2f86 1195 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1196 return link_joined(link);
02b59d57 1197
d9c67ea1 1198 if (link->network->bond) {
6c861f0a 1199 log_link_struct(link, LOG_DEBUG,
97578344 1200 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1201 IFNAMSIZ,
af4e9e2c 1202 link->ifname, link->network->bond->ifname,
aa9f1140 1203 NETDEVIF(link->network->bond),
52433f6b 1204 NULL);
449f7554 1205
3f265037 1206 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b 1207 if (r < 0) {
6c861f0a 1208 log_link_struct(link, LOG_WARNING,
3f265037 1209 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1210 IFNAMSIZ,
3c9b8860
TG
1211 link->ifname, link->network->bond->ifname,
1212 strerror(-r),
aa9f1140 1213 NETDEVIF(link->network->bond),
52433f6b
TG
1214 NULL);
1215 link_enter_failed(link);
1216 return r;
1217 }
1218
0ad6148e
MO
1219 link->enslaving ++;
1220 }
1221
d9c67ea1 1222 if (link->network->bridge) {
6c861f0a 1223 log_link_struct(link, LOG_DEBUG,
97578344 1224 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1225 IFNAMSIZ,
af4e9e2c 1226 link->ifname, link->network->bridge->ifname,
aa9f1140 1227 NETDEVIF(link->network->bridge),
0ad6148e
MO
1228 NULL);
1229
3c9b8860
TG
1230 r = netdev_join(link->network->bridge, link,
1231 &netdev_join_handler);
0ad6148e 1232 if (r < 0) {
6c861f0a 1233 log_link_struct(link, LOG_WARNING,
3f265037 1234 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1235 IFNAMSIZ,
3c9b8860
TG
1236 link->ifname, link->network->bridge->ifname,
1237 strerror(-r),
aa9f1140 1238 NETDEVIF(link->network->bridge),
0ad6148e
MO
1239 NULL);
1240 link_enter_failed(link);
1241 return r;
1242 }
1243
52433f6b
TG
1244 link->enslaving ++;
1245 }
1246
6a0a2f86 1247 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
6c861f0a 1248 log_link_struct(link, LOG_DEBUG,
97578344 1249 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1250 IFNAMSIZ,
3c9b8860
TG
1251 link->ifname, netdev->ifname, NETDEVIF(netdev),
1252 NULL);
7951dea2 1253
6a0a2f86 1254 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2 1255 if (r < 0) {
6c861f0a 1256 log_link_struct(link, LOG_WARNING,
3f265037 1257 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1258 IFNAMSIZ,
3c9b8860
TG
1259 link->ifname, netdev->ifname,
1260 strerror(-r),
6a0a2f86 1261 NETDEVIF(netdev), NULL);
326cb406
SS
1262 link_enter_failed(link);
1263 return r;
1264 }
1265
326cb406
SS
1266 link->enslaving ++;
1267 }
1268
ef1ba606
TG
1269 return 0;
1270}
1271
a748b692 1272static int link_configure(Link *link) {
02b59d57
TG
1273 int r;
1274
ef1ba606 1275 assert(link);
b22d8a00 1276 assert(link->network);
8434fd5c 1277 assert(link->state == LINK_STATE_PENDING);
a748b692 1278
78c958f8 1279 if (link_ipv4ll_enabled(link)) {
b22d8a00 1280 r = ipv4ll_configure(link);
eb34d4af
TG
1281 if (r < 0)
1282 return r;
1283 }
1284
78c958f8 1285 if (link_dhcp4_enabled(link)) {
3c9b8860 1286 r = dhcp4_configure(link);
eb34d4af
TG
1287 if (r < 0)
1288 return r;
eb34d4af
TG
1289 }
1290
78c958f8 1291 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1292 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1293 if (r < 0)
1294 return r;
1295
1296 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1297 if (r < 0)
1298 return r;
dd43110f
TG
1299 }
1300
78c958f8 1301 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1302 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1303 if (r < 0)
1304 return r;
1305
1306 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1307 NULL, 0);
1308 if (r < 0)
1309 return r;
1310
1311 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1312 &link->mac);
1313 if (r < 0)
1314 return r;
1315
1316 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1317 link->ifindex);
1318 if (r < 0)
1319 return r;
1320
1321 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1322 icmp6_router_handler, link);
1323 if (r < 0)
1324 return r;
1325 }
1326
a61bb41c 1327 if (link_has_carrier(link)) {
1e9be60b
TG
1328 r = link_acquire_conf(link);
1329 if (r < 0)
1330 return r;
cc544d5f 1331 }
1e9be60b 1332
3f265037 1333 return link_enter_join_netdev(link);
505f8da7
TG
1334}
1335
3c9b8860
TG
1336static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1337 void *userdata) {
5da8149f 1338 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1339 Network *network;
505f8da7
TG
1340 int r;
1341
1342 assert(link);
1343 assert(link->ifname);
1344 assert(link->manager);
1345
8434fd5c 1346 if (link->state != LINK_STATE_PENDING)
5da8149f 1347 return 1;
505f8da7 1348
79008bdd 1349 log_link_debug(link, "link state is up-to-date");
505f8da7 1350
3c9b8860
TG
1351 r = network_get(link->manager, link->udev_device, link->ifname,
1352 &link->mac, &network);
57bd6899
TG
1353 if (r == -ENOENT) {
1354 link_enter_unmanaged(link);
5da8149f 1355 return 1;
57bd6899
TG
1356 } else if (r < 0)
1357 return r;
505f8da7 1358
bd2efe92 1359 if (link->flags & IFF_LOOPBACK) {
78c958f8 1360 if (network->ipv4ll)
79008bdd 1361 log_link_debug(link, "ignoring IPv4LL for loopback link");
78c958f8
TG
1362
1363 if (network->dhcp != DHCP_SUPPORT_NONE)
79008bdd 1364 log_link_debug(link, "ignoring DHCP clients for loopback link");
78c958f8
TG
1365
1366 if (network->dhcp_server)
79008bdd 1367 log_link_debug(link, "ignoring DHCP server for loopback link");
bd2efe92
TG
1368 }
1369
505f8da7
TG
1370 r = network_apply(link->manager, network, link);
1371 if (r < 0)
1372 return r;
1373
a748b692
TG
1374 r = link_configure(link);
1375 if (r < 0)
1376 return r;
1377
5da8149f 1378 return 1;
505f8da7
TG
1379}
1380
4f561e8e
TG
1381int link_initialized(Link *link, struct udev_device *device) {
1382 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1383 int r;
1384
1385 assert(link);
1386 assert(link->manager);
1387 assert(link->manager->rtnl);
1388 assert(device);
1389
8434fd5c 1390 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1391 return 0;
1392
679b3605
TG
1393 if (link->udev_device)
1394 return 0;
1395
79008bdd 1396 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1397
1398 link->udev_device = udev_device_ref(device);
1399
3c9b8860
TG
1400 /* udev has initialized the link, but we don't know if we have yet
1401 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1402 * when it returns we know that the pending NEWLINKs have already been
1403 * processed and that we are up-to-date */
4f561e8e 1404
3c9b8860
TG
1405 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1406 link->ifindex);
4f561e8e
TG
1407 if (r < 0)
1408 return r;
1409
3c9b8860
TG
1410 r = sd_rtnl_call_async(link->manager->rtnl, req,
1411 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1412 if (r < 0)
1413 return r;
1414
5da8149f
TG
1415 link_ref(link);
1416
4f561e8e
TG
1417 return 0;
1418}
1419
3c9b8860
TG
1420int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message,
1421 void *userdata) {
fbbeb65a
TG
1422 Manager *m = userdata;
1423 Link *link = NULL;
1424 uint16_t type;
1425 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1426 Address *ad;
fbbeb65a 1427 char buf[INET6_ADDRSTRLEN];
c6d3b303
TG
1428 char valid_buf[FORMAT_TIMESPAN_MAX];
1429 const char *valid_str = NULL;
428fd0a7 1430 bool address_dropped = false;
fbbeb65a
TG
1431 int r, ifindex;
1432
1433 assert(rtnl);
1434 assert(message);
1435 assert(m);
1436
1437 r = sd_rtnl_message_get_type(message, &type);
1438 if (r < 0) {
1439 log_warning("rtnl: could not get message type");
1440 return 0;
1441 }
1442
1443 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1444 if (r < 0 || ifindex <= 0) {
5ea846cc 1445 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1446 return 0;
1447 } else {
1448 r = link_get(m, ifindex, &link);
1449 if (r < 0 || !link) {
1e19f352 1450 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
1451 return 0;
1452 }
1453 }
1454
1455 r = address_new_dynamic(&address);
1456 if (r < 0)
393c0c5e 1457 return r;
fbbeb65a
TG
1458
1459 r = sd_rtnl_message_addr_get_family(message, &address->family);
1460 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
79008bdd 1461 log_link_warning(link,
3c9b8860 1462 "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1463 return 0;
1464 }
1465
1466 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1467 if (r < 0) {
79008bdd 1468 log_link_warning(link,
3c9b8860 1469 "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1470 return 0;
1471 }
1472
1473 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1474 if (r < 0) {
79008bdd 1475 log_link_warning(link,
3c9b8860 1476 "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1477 return 0;
1478 }
1479
81163121
TG
1480 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1481 if (r < 0) {
79008bdd 1482 log_link_warning(link,
81163121
TG
1483 "rtnl: received address with invalid flags, ignoring");
1484 return 0;
1485 }
1486
fbbeb65a
TG
1487 switch (address->family) {
1488 case AF_INET:
3c9b8860
TG
1489 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL,
1490 &address->in_addr.in);
fbbeb65a 1491 if (r < 0) {
79008bdd 1492 log_link_warning(link,
3c9b8860 1493 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1494 return 0;
1495 }
1496
1497 break;
1498
1499 case AF_INET6:
3c9b8860
TG
1500 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS,
1501 &address->in_addr.in6);
fbbeb65a 1502 if (r < 0) {
79008bdd 1503 log_link_warning(link,
3c9b8860 1504 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1505 return 0;
1506 }
1507
1508 break;
1509
1510 default:
1511 assert_not_reached("invalid address family");
1512 }
1513
3c9b8860
TG
1514 if (!inet_ntop(address->family, &address->in_addr, buf,
1515 INET6_ADDRSTRLEN)) {
79008bdd 1516 log_link_warning(link, "could not print address");
fbbeb65a
TG
1517 return 0;
1518 }
1519
c6d3b303
TG
1520 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO,
1521 &address->cinfo);
1522 if (r >= 0) {
1523 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1524 valid_str = "ever";
1525 else
1526 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1527 address->cinfo.ifa_valid * USEC_PER_SEC,
1528 USEC_PER_SEC);
1529 }
1530
428fd0a7
TG
1531 LIST_FOREACH(addresses, ad, link->addresses) {
1532 if (address_equal(ad, address)) {
1533 LIST_REMOVE(addresses, link->addresses, ad);
1534
1535 address_free(ad);
1536
1537 address_dropped = true;
1538
1539 break;
1540 }
1541 }
1542
fbbeb65a
TG
1543 switch (type) {
1544 case RTM_NEWADDR:
428fd0a7 1545 if (!address_dropped)
79008bdd 1546 log_link_debug(link, "added address: %s/%u (valid for %s)",
b1d6dcf5 1547 buf, address->prefixlen, valid_str);
393c0c5e 1548 else
79008bdd 1549 log_link_debug(link, "updated address: %s/%u (valid for %s)",
b1d6dcf5 1550 buf, address->prefixlen, valid_str);
fbbeb65a 1551
428fd0a7
TG
1552 LIST_PREPEND(addresses, link->addresses, address);
1553 address = NULL;
1554
f5602be9
TG
1555 link_save(link);
1556
428fd0a7 1557 break;
fbbeb65a 1558 case RTM_DELADDR:
f5602be9 1559 if (address_dropped) {
79008bdd 1560 log_link_debug(link, "removed address: %s/%u (valid for %s)",
b1d6dcf5 1561 buf, address->prefixlen, valid_str);
428fd0a7 1562
f5602be9 1563 link_save(link);
393c0c5e 1564 } else
79008bdd 1565 log_link_warning(link,
c6d3b303 1566 "removing non-existent address: %s/%u (valid for %s)",
b1d6dcf5 1567 buf, address->prefixlen, valid_str);
f5602be9 1568
fbbeb65a
TG
1569 break;
1570 default:
1571 assert_not_reached("Received invalid RTNL message type");
1572 }
1573
1574 return 1;
1575}
1576
505f8da7
TG
1577int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1578 Link *link;
fbbeb65a 1579 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1580 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1581 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1582 int r;
1583
1584 assert(m);
fbbeb65a 1585 assert(m->rtnl);
505f8da7
TG
1586 assert(message);
1587 assert(ret);
1588
1589 r = link_new(m, message, ret);
1590 if (r < 0)
1591 return r;
1592
1593 link = *ret;
1594
79008bdd 1595 log_link_debug(link, "link %d added", link->ifindex);
505f8da7 1596
3c9b8860
TG
1597 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex,
1598 0);
fbbeb65a
TG
1599 if (r < 0)
1600 return r;
1601
3c9b8860
TG
1602 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0,
1603 NULL);
fbbeb65a
TG
1604 if (r < 0)
1605 return r;
1606
5da8149f
TG
1607 link_ref(link);
1608
505f8da7
TG
1609 if (detect_container(NULL) <= 0) {
1610 /* not in a container, udev will be around */
ae06ab10 1611 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1612 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1613 if (!device) {
79008bdd 1614 log_link_warning(link,
3c9b8860 1615 "could not find udev device: %m");
9fecce80 1616 return -errno;
505f8da7
TG
1617 }
1618
3c4cb064 1619 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1620 /* not yet ready */
79008bdd 1621 log_link_debug(link, "link pending udev initialization...");
505f8da7 1622 return 0;
3c4cb064 1623 }
505f8da7 1624
4f561e8e
TG
1625 r = link_initialized(link, device);
1626 if (r < 0)
1627 return r;
1628 } else {
5da8149f
TG
1629 /* we are calling a callback directly, so must take a ref */
1630 link_ref(link);
1631
4f561e8e
TG
1632 r = link_initialized_and_synced(m->rtnl, NULL, link);
1633 if (r < 0)
1634 return r;
1635 }
505f8da7 1636
a748b692
TG
1637 return 0;
1638}
1639
22936833 1640int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1641 struct ether_addr mac;
ca4e095a 1642 const char *ifname;
afe7fd56 1643 uint32_t mtu;
a61bb41c 1644 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
1645 int r;
1646
dd3efc09 1647 assert(link);
b8941f74 1648 assert(link->ifname);
22936833
TG
1649 assert(m);
1650
7619683b
TG
1651 if (link->state == LINK_STATE_LINGER) {
1652 link_ref(link);
79008bdd 1653 log_link_info(link, "link readded");
7619683b
TG
1654 link->state = LINK_STATE_ENSLAVING;
1655 }
1656
b8941f74
TG
1657 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1658 if (r >= 0 && !streq(ifname, link->ifname)) {
79008bdd 1659 log_link_info(link, "renamed to %s", ifname);
b8941f74
TG
1660
1661 free(link->ifname);
1662 link->ifname = strdup(ifname);
1663 if (!link->ifname)
1664 return -ENOMEM;
1665 }
1666
afe7fd56
TG
1667 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1668 if (r >= 0 && mtu > 0) {
1669 link->mtu = mtu;
1670 if (!link->original_mtu) {
1671 link->original_mtu = mtu;
79008bdd 1672 log_link_debug(link, "saved original MTU: %"
afe7fd56
TG
1673 PRIu32, link->original_mtu);
1674 }
1675
1676 if (link->dhcp_client) {
3c9b8860
TG
1677 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1678 link->mtu);
afe7fd56 1679 if (r < 0) {
79008bdd 1680 log_link_warning(link,
3c9b8860 1681 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1682 strerror(-r));
1683 return r;
1684 }
1685 }
9842de0d 1686 }
69629de9 1687
e9189a1f
TG
1688 /* The kernel may broadcast NEWLINK messages without the MAC address
1689 set, simply ignore them. */
c49b33ac 1690 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1691 if (r >= 0) {
3c9b8860
TG
1692 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1693 ETH_ALEN)) {
c49b33ac 1694
3c9b8860
TG
1695 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1696 ETH_ALEN);
c49b33ac 1697
79008bdd 1698 log_link_debug(link, "MAC address: "
20861203
TG
1699 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1700 mac.ether_addr_octet[0],
1701 mac.ether_addr_octet[1],
1702 mac.ether_addr_octet[2],
1703 mac.ether_addr_octet[3],
1704 mac.ether_addr_octet[4],
1705 mac.ether_addr_octet[5]);
c49b33ac 1706
20861203
TG
1707 if (link->ipv4ll) {
1708 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1709 if (r < 0) {
79008bdd 1710 log_link_warning(link,
3c9b8860 1711 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1712 strerror(-r));
1713 return r;
1714 }
c49b33ac 1715 }
c49b33ac 1716
20861203 1717 if (link->dhcp_client) {
3c9b8860 1718 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
1719 (const uint8_t *) &link->mac,
1720 sizeof (link->mac),
1721 ARPHRD_ETHER);
20861203 1722 if (r < 0) {
79008bdd 1723 log_link_warning(link,
3c9b8860 1724 "Could not update MAC address in DHCP client: %s",
20861203
TG
1725 strerror(-r));
1726 return r;
1727 }
c49b33ac 1728 }
4138fb2c
PF
1729
1730 if (link->dhcp6_client) {
1731 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
1732 (const uint8_t *) &link->mac,
1733 sizeof (link->mac),
1734 ARPHRD_ETHER);
4138fb2c 1735 if (r < 0) {
79008bdd 1736 log_link_warning(link,
3c9b8860 1737 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1738 strerror(-r));
1739 return r;
1740 }
1741 }
c49b33ac 1742 }
4f882b2a
TG
1743 }
1744
a61bb41c
TG
1745 had_carrier = link_has_carrier(link);
1746
1747 r = link_update_flags(link, m);
1748 if (r < 0)
1749 return r;
1750
1751 carrier_gained = !had_carrier && link_has_carrier(link);
1752 carrier_lost = had_carrier && !link_has_carrier(link);
1753
1754 if (carrier_gained) {
79008bdd 1755 log_link_info(link, "gained carrier");
a61bb41c
TG
1756
1757 if (link->network) {
1758 r = link_acquire_conf(link);
1759 if (r < 0) {
1760 link_enter_failed(link);
1761 return r;
1762 }
1763 }
1764 } else if (carrier_lost) {
79008bdd 1765 log_link_info(link, "lost carrier");
a61bb41c
TG
1766
1767 r = link_stop_clients(link);
1768 if (r < 0) {
1769 link_enter_failed(link);
1770 return r;
1771 }
1772 }
1773
1774 return 0;
dd3efc09 1775}
fe8db0c5 1776
e375dcde
TG
1777static void link_update_operstate(Link *link) {
1778
1779 assert(link);
1780
1781 if (link->kernel_operstate == IF_OPER_DORMANT)
1782 link->operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 1783 else if (link_has_carrier(link)) {
e375dcde
TG
1784 Address *address;
1785 uint8_t scope = RT_SCOPE_NOWHERE;
1786
1787 /* if we have carrier, check what addresses we have */
1788 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
1789 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
1790 continue;
1791
e375dcde
TG
1792 if (address->scope < scope)
1793 scope = address->scope;
1794 }
1795
1796 if (scope < RT_SCOPE_SITE)
1797 /* universally accessible addresses found */
1798 link->operstate = LINK_OPERSTATE_ROUTABLE;
1799 else if (scope < RT_SCOPE_HOST)
1800 /* only link or site local addresses found */
1801 link->operstate = LINK_OPERSTATE_DEGRADED;
1802 else
1803 /* no useful addresses found */
1804 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1805 } else if (link->flags & IFF_UP)
d3df0e39 1806 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1807 else
d3df0e39 1808 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1809}
1810
fe8db0c5 1811int link_save(Link *link) {
68a8723c 1812 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1813 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1814 const char *admin_state, *oper_state;
fe8db0c5
TG
1815 int r;
1816
1817 assert(link);
1818 assert(link->state_file);
68a8723c 1819 assert(link->lease_file);
bbf7c048
TG
1820 assert(link->manager);
1821
e375dcde
TG
1822 link_update_operstate(link);
1823
bbf7c048
TG
1824 r = manager_save(link->manager);
1825 if (r < 0)
1826 return r;
fe8db0c5 1827
370e9930
TG
1828 if (link->state == LINK_STATE_LINGER) {
1829 unlink(link->state_file);
1830 return 0;
1831 }
1832
deb2e523
TG
1833 admin_state = link_state_to_string(link->state);
1834 assert(admin_state);
1835
e375dcde
TG
1836 oper_state = link_operstate_to_string(link->operstate);
1837 assert(oper_state);
deb2e523 1838
fe8db0c5
TG
1839 r = fopen_temporary(link->state_file, &f, &temp_path);
1840 if (r < 0)
c2d6bd61 1841 return r;
fe8db0c5
TG
1842
1843 fchmod(fileno(f), 0644);
1844
1845 fprintf(f,
1846 "# This is private data. Do not parse.\n"
deb2e523 1847 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1848 "OPER_STATE=%s\n",
1849 admin_state, oper_state);
fe8db0c5 1850
bcb7a07e 1851 if (link->network) {
ea352b40
LP
1852 char **address, **domain;
1853 bool space;
b0e39c82 1854
adc5b2e2
TG
1855 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
1856
b0e39c82 1857 fputs("DNS=", f);
ea352b40
LP
1858 space = false;
1859 STRV_FOREACH(address, link->network->dns) {
1860 if (space)
1861 fputc(' ', f);
1862 fputs(*address, f);
1863 space = true;
1864 }
d5314fff 1865
b0e39c82
TG
1866 if (link->network->dhcp_dns &&
1867 link->dhcp_lease) {
1868 const struct in_addr *addresses;
1869
1870 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1871 if (r > 0) {
ea352b40
LP
1872 if (space)
1873 fputc(' ', f);
b0e39c82 1874 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1875 }
1876 }
1877
b0e39c82
TG
1878 fputs("\n", f);
1879
1880 fprintf(f, "NTP=");
ea352b40
LP
1881 space = false;
1882 STRV_FOREACH(address, link->network->ntp) {
1883 if (space)
1884 fputc(' ', f);
1885 fputs(*address, f);
1886 space = true;
1887 }
d5314fff 1888
b0e39c82
TG
1889 if (link->network->dhcp_ntp &&
1890 link->dhcp_lease) {
1891 const struct in_addr *addresses;
1892
1893 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1894 if (r > 0) {
ea352b40
LP
1895 if (space)
1896 fputc(' ', f);
b0e39c82 1897 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1898 }
1899 }
1900
b0e39c82 1901 fputs("\n", f);
bd8f6538 1902
6192b846 1903 fprintf(f, "DOMAINS=");
ea352b40
LP
1904 space = false;
1905 STRV_FOREACH(domain, link->network->domains) {
1906 if (space)
1907 fputc(' ', f);
1908 fputs(*domain, f);
1909 space = true;
1910 }
d5314fff 1911
ad0734e8 1912 if (link->network->dhcp_domains &&
9b4d1882
TG
1913 link->dhcp_lease) {
1914 const char *domainname;
1915
1916 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 1917 if (r >= 0) {
ea352b40
LP
1918 if (space)
1919 fputc(' ', f);
6192b846 1920 fputs(domainname, f);
6192b846 1921 }
9b4d1882
TG
1922 }
1923
6192b846
TG
1924 fputs("\n", f);
1925
67272d15
TG
1926 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1927 yes_no(link->network->wildcard_domain));
1928
3c9b8860
TG
1929 fprintf(f, "LLMNR=%s\n",
1930 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1931 }
7374f9d8 1932
fe8db0c5 1933 if (link->dhcp_lease) {
d9876a52
TG
1934 assert(link->network);
1935
1dc24d5f 1936 r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1937 if (r < 0)
c2d6bd61 1938 goto fail;
fe8db0c5 1939
7374f9d8 1940 fprintf(f,
b0e39c82
TG
1941 "DHCP_LEASE=%s\n",
1942 link->lease_file);
deb2e523 1943 } else
68a8723c 1944 unlink(link->lease_file);
fe8db0c5 1945
c2d6bd61
LP
1946 r = fflush_and_check(f);
1947 if (r < 0)
1948 goto fail;
fe8db0c5 1949
c2d6bd61 1950 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1951 r = -errno;
c2d6bd61 1952 goto fail;
fe8db0c5
TG
1953 }
1954
c2d6bd61 1955 return 0;
c2d6bd61 1956fail:
79008bdd 1957 log_link_error(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
c2d6bd61
LP
1958 unlink(link->state_file);
1959 unlink(temp_path);
fe8db0c5
TG
1960 return r;
1961}
1962
1963static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1964 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1965 [LINK_STATE_ENSLAVING] = "configuring",
1966 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1967 [LINK_STATE_SETTING_ROUTES] = "configuring",
1968 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1969 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1970 [LINK_STATE_FAILED] = "failed",
370e9930 1971 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1972};
1973
1974DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1975
1976static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1977 [LINK_OPERSTATE_OFF] = "off",
1978 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1979 [LINK_OPERSTATE_DORMANT] = "dormant",
1980 [LINK_OPERSTATE_CARRIER] = "carrier",
1981 [LINK_OPERSTATE_DEGRADED] = "degraded",
1982 [LINK_OPERSTATE_ROUTABLE] = "routable",
1983};
1984
1985DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);