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