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