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