]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
resolve-host: properly align long arguments in help text
[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
afe7fd56
TG
1838 if (link->mtu) {
1839 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
1840 if (r < 0)
1841 return r;
1842 }
1843
eb34d4af 1844 if (link->network->dhcp_mtu) {
ba179154 1845 r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_INTERFACE_MTU);
eb34d4af
TG
1846 if (r < 0)
1847 return r;
1848 }
4cc7a82c 1849
e1ea665e
EY
1850 if (link->network->dhcp_routes) {
1851 r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_STATIC_ROUTE);
1852 if (r < 0)
1853 return r;
1854 r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
1855 if (r < 0)
1856 return r;
1857 }
4cc7a82c
EY
1858
1859 if (link->network->dhcp_sendhost) {
1860 _cleanup_free_ char *hostname = gethostname_malloc();
1861 if (!hostname)
1862 return -ENOMEM;
1863
1864 if (!is_localhost(hostname)) {
1865 r = sd_dhcp_client_set_hostname(link->dhcp_client, hostname);
1866 if (r < 0)
1867 return r;
1868 }
1869 }
edb85f0d
SS
1870
1871 if (link->network->dhcp_vendor_class_identifier) {
1872 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
1873 link->network->dhcp_vendor_class_identifier);
1874 if (r < 0)
1875 return r;
1876 }
eb34d4af
TG
1877 }
1878
dd43110f 1879 if (link->network->dhcp_server) {
dd43110f
TG
1880 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1881 if (r < 0)
1882 return r;
1883
1884 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1885 if (r < 0)
1886 return r;
dd43110f
TG
1887 }
1888
ed942a9e 1889 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
1890 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1891 if (r < 0)
1892 return r;
1893
1894 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1895 NULL, 0);
1896 if (r < 0)
1897 return r;
1898
1899 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1900 &link->mac);
1901 if (r < 0)
1902 return r;
1903
1904 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1905 link->ifindex);
1906 if (r < 0)
1907 return r;
1908
1909 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1910 icmp6_router_handler, link);
1911 if (r < 0)
1912 return r;
1913 }
1914
bf0308cb 1915 if (link_has_carrier(link->flags, link->kernel_operstate)) {
1e9be60b
TG
1916 r = link_acquire_conf(link);
1917 if (r < 0)
1918 return r;
cc544d5f 1919 }
1e9be60b 1920
3f265037 1921 return link_enter_join_netdev(link);
505f8da7
TG
1922}
1923
4f561e8e 1924static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 1925 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1926 Network *network;
505f8da7
TG
1927 int r;
1928
1929 assert(link);
1930 assert(link->ifname);
1931 assert(link->manager);
1932
1933 if (link->state != LINK_STATE_INITIALIZING)
5da8149f 1934 return 1;
505f8da7 1935
4f561e8e 1936 log_debug_link(link, "link state is up-to-date");
505f8da7 1937
4f561e8e 1938 r = network_get(link->manager, link->udev_device, link->ifname, &link->mac, &network);
57bd6899
TG
1939 if (r == -ENOENT) {
1940 link_enter_unmanaged(link);
5da8149f 1941 return 1;
57bd6899
TG
1942 } else if (r < 0)
1943 return r;
505f8da7
TG
1944
1945 r = network_apply(link->manager, network, link);
1946 if (r < 0)
1947 return r;
1948
a748b692
TG
1949 r = link_configure(link);
1950 if (r < 0)
1951 return r;
1952
5da8149f 1953 return 1;
505f8da7
TG
1954}
1955
4f561e8e
TG
1956int link_initialized(Link *link, struct udev_device *device) {
1957 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1958 int r;
1959
1960 assert(link);
1961 assert(link->manager);
1962 assert(link->manager->rtnl);
1963 assert(device);
1964
1965 if (link->state != LINK_STATE_INITIALIZING)
1966 return 0;
1967
679b3605
TG
1968 if (link->udev_device)
1969 return 0;
1970
4f561e8e
TG
1971 log_debug_link(link, "udev initialized link");
1972
1973 link->udev_device = udev_device_ref(device);
1974
1975 /* udev has initialized the link, but we don't know if we have yet processed
1976 the NEWLINK messages with the latest state. Do a GETLINK, when it returns
1977 we know that the pending NEWLINKs have already been processed and that we
1978 are up-to-date */
1979
1980 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex);
1981 if (r < 0)
1982 return r;
1983
1984 r = sd_rtnl_call_async(link->manager->rtnl, req, link_initialized_and_synced, link, 0, NULL);
1985 if (r < 0)
1986 return r;
1987
5da8149f
TG
1988 link_ref(link);
1989
4f561e8e
TG
1990 return 0;
1991}
1992
fbbeb65a
TG
1993int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
1994 Manager *m = userdata;
1995 Link *link = NULL;
1996 uint16_t type;
1997 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1998 Address *ad;
fbbeb65a 1999 char buf[INET6_ADDRSTRLEN];
428fd0a7 2000 bool address_dropped = false;
fbbeb65a
TG
2001 int r, ifindex;
2002
2003 assert(rtnl);
2004 assert(message);
2005 assert(m);
2006
2007 r = sd_rtnl_message_get_type(message, &type);
2008 if (r < 0) {
2009 log_warning("rtnl: could not get message type");
2010 return 0;
2011 }
2012
2013 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
2014 if (r < 0 || ifindex <= 0) {
5ea846cc 2015 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
2016 return 0;
2017 } else {
2018 r = link_get(m, ifindex, &link);
2019 if (r < 0 || !link) {
5ea846cc 2020 log_warning("rtnl: received address for a nonexistent link, ignoring");
fbbeb65a
TG
2021 return 0;
2022 }
2023 }
2024
2025 r = address_new_dynamic(&address);
2026 if (r < 0)
393c0c5e 2027 return r;
fbbeb65a
TG
2028
2029 r = sd_rtnl_message_addr_get_family(message, &address->family);
2030 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
987efa17 2031 log_warning_link(link, "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
2032 return 0;
2033 }
2034
2035 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
2036 if (r < 0) {
e375dcde
TG
2037 log_warning_link(link, "rtnl: received address with invalid prefixlen, ignoring");
2038 return 0;
2039 }
2040
2041 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
2042 if (r < 0) {
2043 log_warning_link(link, "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
2044 return 0;
2045 }
2046
2047 switch (address->family) {
2048 case AF_INET:
2049 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
2050 if (r < 0) {
987efa17 2051 log_warning_link(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
2052 return 0;
2053 }
2054
2055 break;
2056
2057 case AF_INET6:
2058 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
2059 if (r < 0) {
987efa17 2060 log_warning_link(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
2061 return 0;
2062 }
2063
2064 break;
2065
2066 default:
2067 assert_not_reached("invalid address family");
2068 }
2069
2070 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
987efa17 2071 log_warning_link(link, "could not print address");
fbbeb65a
TG
2072 return 0;
2073 }
2074
428fd0a7
TG
2075 LIST_FOREACH(addresses, ad, link->addresses) {
2076 if (address_equal(ad, address)) {
2077 LIST_REMOVE(addresses, link->addresses, ad);
2078
2079 address_free(ad);
2080
2081 address_dropped = true;
2082
2083 break;
2084 }
2085 }
2086
fbbeb65a
TG
2087 switch (type) {
2088 case RTM_NEWADDR:
428fd0a7
TG
2089 if (!address_dropped)
2090 log_debug_link(link, "added address: %s/%u", buf,
393c0c5e
TG
2091 address->prefixlen);
2092 else
2093 log_debug_link(link, "updated address: %s/%u", buf,
2094 address->prefixlen);
fbbeb65a 2095
428fd0a7
TG
2096 LIST_PREPEND(addresses, link->addresses, address);
2097 address = NULL;
2098
f5602be9
TG
2099 link_save(link);
2100
428fd0a7 2101 break;
fbbeb65a 2102 case RTM_DELADDR:
f5602be9 2103 if (address_dropped) {
428fd0a7 2104 log_debug_link(link, "removed address: %s/%u", buf,
393c0c5e 2105 address->prefixlen);
428fd0a7 2106
f5602be9 2107 link_save(link);
393c0c5e
TG
2108 } else
2109 log_warning_link(link, "removing non-existent address: %s/%u",
2110 buf, address->prefixlen);
f5602be9 2111
fbbeb65a
TG
2112 break;
2113 default:
2114 assert_not_reached("Received invalid RTNL message type");
2115 }
2116
2117 return 1;
2118}
2119
505f8da7
TG
2120int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
2121 Link *link;
fbbeb65a 2122 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
2123 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2124 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2125 int r;
2126
2127 assert(m);
fbbeb65a 2128 assert(m->rtnl);
505f8da7
TG
2129 assert(message);
2130 assert(ret);
2131
2132 r = link_new(m, message, ret);
2133 if (r < 0)
2134 return r;
2135
2136 link = *ret;
2137
ae06ab10 2138 log_debug_link(link, "link %d added", link->ifindex);
505f8da7 2139
fbbeb65a
TG
2140 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex, 0);
2141 if (r < 0)
2142 return r;
2143
2144 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0, NULL);
2145 if (r < 0)
2146 return r;
2147
5da8149f
TG
2148 link_ref(link);
2149
505f8da7
TG
2150 if (detect_container(NULL) <= 0) {
2151 /* not in a container, udev will be around */
ae06ab10 2152 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
2153 device = udev_device_new_from_device_id(m->udev, ifindex_str);
2154 if (!device) {
9fecce80
TG
2155 log_warning_link(link, "could not find udev device: %m");
2156 return -errno;
505f8da7
TG
2157 }
2158
3c4cb064 2159 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 2160 /* not yet ready */
16cd414b 2161 log_debug_link(link, "udev initializing link...");
505f8da7 2162 return 0;
3c4cb064 2163 }
505f8da7 2164
4f561e8e
TG
2165 r = link_initialized(link, device);
2166 if (r < 0)
2167 return r;
2168 } else {
5da8149f
TG
2169 /* we are calling a callback directly, so must take a ref */
2170 link_ref(link);
2171
4f561e8e
TG
2172 r = link_initialized_and_synced(m->rtnl, NULL, link);
2173 if (r < 0)
2174 return r;
2175 }
505f8da7 2176
a748b692
TG
2177 return 0;
2178}
2179
22936833 2180int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 2181 struct ether_addr mac;
ca4e095a 2182 const char *ifname;
afe7fd56 2183 uint32_t mtu;
22936833
TG
2184 int r;
2185
dd3efc09 2186 assert(link);
b8941f74 2187 assert(link->ifname);
22936833
TG
2188 assert(m);
2189
7619683b
TG
2190 if (link->state == LINK_STATE_LINGER) {
2191 link_ref(link);
2192 log_info_link(link, "link readded");
2193 link->state = LINK_STATE_ENSLAVING;
2194 }
2195
b8941f74
TG
2196 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
2197 if (r >= 0 && !streq(ifname, link->ifname)) {
2198 log_info_link(link, "renamed to %s", ifname);
2199
2200 free(link->ifname);
2201 link->ifname = strdup(ifname);
2202 if (!link->ifname)
2203 return -ENOMEM;
2204 }
2205
afe7fd56
TG
2206 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
2207 if (r >= 0 && mtu > 0) {
2208 link->mtu = mtu;
2209 if (!link->original_mtu) {
2210 link->original_mtu = mtu;
9842de0d 2211 log_debug_link(link, "saved original MTU: %"
afe7fd56
TG
2212 PRIu32, link->original_mtu);
2213 }
2214
2215 if (link->dhcp_client) {
2216 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
2217 if (r < 0) {
2218 log_warning_link(link, "Could not update MTU in DHCP client: %s",
2219 strerror(-r));
2220 return r;
2221 }
2222 }
9842de0d 2223 }
69629de9 2224
e9189a1f
TG
2225 /* The kernel may broadcast NEWLINK messages without the MAC address
2226 set, simply ignore them. */
c49b33ac 2227 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 2228 if (r >= 0) {
20861203 2229 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 2230
20861203 2231 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 2232
20861203
TG
2233 log_debug_link(link, "MAC address: "
2234 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2235 mac.ether_addr_octet[0],
2236 mac.ether_addr_octet[1],
2237 mac.ether_addr_octet[2],
2238 mac.ether_addr_octet[3],
2239 mac.ether_addr_octet[4],
2240 mac.ether_addr_octet[5]);
c49b33ac 2241
20861203
TG
2242 if (link->ipv4ll) {
2243 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
2244 if (r < 0) {
2245 log_warning_link(link, "Could not update MAC "
2246 "address in IPv4LL client: %s",
2247 strerror(-r));
2248 return r;
2249 }
c49b33ac 2250 }
c49b33ac 2251
20861203
TG
2252 if (link->dhcp_client) {
2253 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
2254 if (r < 0) {
2255 log_warning_link(link, "Could not update MAC "
2256 "address in DHCP client: %s",
2257 strerror(-r));
2258 return r;
2259 }
c49b33ac 2260 }
4138fb2c
PF
2261
2262 if (link->dhcp6_client) {
2263 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
2264 &link->mac);
2265 if (r < 0) {
2266 log_warning_link(link, "Could not update MAC address in DHCPv6 client: %s",
2267 strerror(-r));
2268 return r;
2269 }
2270 }
c49b33ac 2271 }
4f882b2a
TG
2272 }
2273
1e9be60b 2274 return link_update_flags(link, m);
dd3efc09 2275}
fe8db0c5 2276
e375dcde
TG
2277static void link_update_operstate(Link *link) {
2278
2279 assert(link);
2280
2281 if (link->kernel_operstate == IF_OPER_DORMANT)
2282 link->operstate = LINK_OPERSTATE_DORMANT;
2283 else if (link_has_carrier(link->flags, link->kernel_operstate)) {
2284 Address *address;
2285 uint8_t scope = RT_SCOPE_NOWHERE;
2286
2287 /* if we have carrier, check what addresses we have */
2288 LIST_FOREACH(addresses, address, link->addresses) {
2289 if (address->scope < scope)
2290 scope = address->scope;
2291 }
2292
2293 if (scope < RT_SCOPE_SITE)
2294 /* universally accessible addresses found */
2295 link->operstate = LINK_OPERSTATE_ROUTABLE;
2296 else if (scope < RT_SCOPE_HOST)
2297 /* only link or site local addresses found */
2298 link->operstate = LINK_OPERSTATE_DEGRADED;
2299 else
2300 /* no useful addresses found */
2301 link->operstate = LINK_OPERSTATE_CARRIER;
2302 } else
2303 link->operstate = LINK_OPERSTATE_UNKNOWN;
2304}
2305
fe8db0c5 2306int link_save(Link *link) {
68a8723c 2307 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2308 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2309 const char *admin_state, *oper_state;
fe8db0c5
TG
2310 int r;
2311
2312 assert(link);
2313 assert(link->state_file);
68a8723c 2314 assert(link->lease_file);
bbf7c048
TG
2315 assert(link->manager);
2316
e375dcde
TG
2317 link_update_operstate(link);
2318
bbf7c048
TG
2319 r = manager_save(link->manager);
2320 if (r < 0)
2321 return r;
fe8db0c5 2322
370e9930
TG
2323 if (link->state == LINK_STATE_LINGER) {
2324 unlink(link->state_file);
2325 return 0;
2326 }
2327
deb2e523
TG
2328 admin_state = link_state_to_string(link->state);
2329 assert(admin_state);
2330
e375dcde
TG
2331 oper_state = link_operstate_to_string(link->operstate);
2332 assert(oper_state);
deb2e523 2333
fe8db0c5
TG
2334 r = fopen_temporary(link->state_file, &f, &temp_path);
2335 if (r < 0)
2336 goto finish;
2337
2338 fchmod(fileno(f), 0644);
2339
2340 fprintf(f,
2341 "# This is private data. Do not parse.\n"
deb2e523 2342 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
2343 "OPER_STATE=%s\n",
2344 admin_state, oper_state);
fe8db0c5 2345
bcb7a07e 2346 if (link->network) {
b0e39c82
TG
2347 char **address;
2348
2349 fputs("DNS=", f);
2350
2351 if (link->network->dhcp_dns &&
2352 link->dhcp_lease) {
2353 const struct in_addr *addresses;
2354
2355 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2356 if (r > 0) {
2357 serialize_in_addrs(f, addresses, r);
2358 if (link->network->dns)
2359 fputs(" ", f);
2360 }
2361 }
2362
2363 STRV_FOREACH(address, link->network->dns)
2364 fprintf(f, "%s%s", *address,
2365 (address + 1 ? " " : ""));
2366
2367 fputs("\n", f);
2368
2369 fprintf(f, "NTP=");
2370
2371 if (link->network->dhcp_ntp &&
2372 link->dhcp_lease) {
2373 const struct in_addr *addresses;
2374
2375 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2376 if (r > 0) {
2377 serialize_in_addrs(f, addresses, r);
2378 if (link->network->ntp)
2379 fputs(" ", f);
2380 }
2381 }
2382
2383 STRV_FOREACH(address, link->network->ntp)
2384 fprintf(f, "%s%s", *address,
2385 (address + 1 ? " " : ""));
2386
2387 fputs("\n", f);
bcb7a07e 2388 }
7374f9d8 2389
fe8db0c5 2390 if (link->dhcp_lease) {
d9876a52
TG
2391 assert(link->network);
2392
68a8723c 2393 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5
TG
2394 if (r < 0)
2395 goto finish;
2396
7374f9d8 2397 fprintf(f,
b0e39c82
TG
2398 "DHCP_LEASE=%s\n",
2399 link->lease_file);
deb2e523 2400 } else
68a8723c 2401 unlink(link->lease_file);
fe8db0c5
TG
2402
2403 fflush(f);
2404
2405 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
2406 r = -errno;
2407 unlink(link->state_file);
2408 unlink(temp_path);
2409 }
2410
2411finish:
2412 if (r < 0)
987efa17 2413 log_error_link(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
fe8db0c5
TG
2414
2415 return r;
2416}
2417
2418static const char* const link_state_table[_LINK_STATE_MAX] = {
deb2e523 2419 [LINK_STATE_INITIALIZING] = "initializing",
fe8db0c5
TG
2420 [LINK_STATE_ENSLAVING] = "configuring",
2421 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
2422 [LINK_STATE_SETTING_ROUTES] = "configuring",
2423 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2424 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2425 [LINK_STATE_FAILED] = "failed",
370e9930 2426 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2427};
2428
2429DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2430
2431static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
2432 [LINK_OPERSTATE_UNKNOWN] = "unknown",
2433 [LINK_OPERSTATE_DORMANT] = "dormant",
2434 [LINK_OPERSTATE_CARRIER] = "carrier",
2435 [LINK_OPERSTATE_DEGRADED] = "degraded",
2436 [LINK_OPERSTATE_ROUTABLE] = "routable",
2437};
2438
2439DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);
ed942a9e
TG
2440
2441static const char* const dhcp_support_table[_DHCP_SUPPORT_MAX] = {
2442 [DHCP_SUPPORT_NONE] = "none",
2443 [DHCP_SUPPORT_BOTH] = "both",
2444 [DHCP_SUPPORT_V4] = "v4",
2445 [DHCP_SUPPORT_V6] = "v6",
2446};
2447
2448DEFINE_STRING_TABLE_LOOKUP(dhcp_support, DHCPSupport);
2449
2450int config_parse_dhcp(
2451 const char* unit,
2452 const char *filename,
2453 unsigned line,
2454 const char *section,
2455 unsigned section_line,
2456 const char *lvalue,
2457 int ltype,
2458 const char *rvalue,
2459 void *data,
2460 void *userdata) {
2461
2462 DHCPSupport *dhcp = data;
2463 int k;
2464
2465 assert(filename);
2466 assert(lvalue);
2467 assert(rvalue);
2468 assert(data);
2469
2470 /* Our enum shall be a superset of booleans, hence first try
2471 * to parse as boolean, and then as enum */
2472
2473 k = parse_boolean(rvalue);
2474 if (k > 0)
2475 *dhcp = DHCP_SUPPORT_BOTH;
2476 else if (k == 0)
2477 *dhcp = DHCP_SUPPORT_NONE;
2478 else {
2479 DHCPSupport s;
2480
2481 s = dhcp_support_from_string(rvalue);
2482 if (s < 0){
2483 log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse DHCP option, ignoring: %s", rvalue);
2484 return 0;
2485 }
2486
2487 *dhcp = s;
2488 }
2489
2490 return 0;
2491}