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