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