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