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