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