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