]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
sd-rtnl: socet_read_message - make sure we only shrink the partial rqueue when proces...
[thirdparty/systemd.git] / src / network / networkd-link.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <netinet/ether.h>
23#include <linux/if.h>
24
25#include "networkd.h"
26#include "libudev-private.h"
505f8da7 27#include "udev-util.h"
f579559b 28#include "util.h"
505f8da7 29#include "virt.h"
1346b1f0 30#include "bus-util.h"
c6f7c917 31#include "network-internal.h"
f579559b 32
fe8db0c5
TG
33#include "dhcp-lease-internal.h"
34
aba496a5
UTL
35static int ipv4ll_address_update(Link *link, bool deprecate);
36static bool ipv4ll_is_bound(sd_ipv4ll *ll);
37
505f8da7 38static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
f579559b 39 _cleanup_link_free_ Link *link = NULL;
505f8da7
TG
40 uint16_t type;
41 char *ifname;
42 int r, ifindex;
f579559b 43
0c2f9b84
TG
44 assert(manager);
45 assert(manager->links);
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
5a3eb5a7 69 link->manager = manager;
505f8da7
TG
70 link->state = LINK_STATE_INITIALIZING;
71 link->ifindex = ifindex;
72 link->ifname = strdup(ifname);
73 if (!link->ifname)
74 return -ENOMEM;
f579559b 75
315db1a8
ZJS
76 r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
77 link->ifindex);
fe8db0c5 78 if (r < 0)
315db1a8 79 return -ENOMEM;
fe8db0c5 80
0617ffab 81 r = hashmap_put(manager->links, &link->ifindex, link);
f579559b
TG
82 if (r < 0)
83 return r;
84
85 *ret = link;
86 link = NULL;
87
88 return 0;
89}
90
91void link_free(Link *link) {
92 if (!link)
93 return;
94
0617ffab 95 assert(link->manager);
f579559b 96
e5b04c8d 97 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 98 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 99
56cd007a 100 sd_ipv4ll_unref(link->ipv4ll);
5c1d3fc9 101
0617ffab 102 hashmap_remove(link->manager->links, &link->ifindex);
f579559b 103
c166a070 104 free(link->ifname);
fe8db0c5 105 free(link->state_file);
c166a070 106
b5db00e5
UTL
107 udev_device_unref(link->udev_device);
108
f579559b
TG
109 free(link);
110}
111
11a7f229
TG
112int link_get(Manager *m, int ifindex, Link **ret) {
113 Link *link;
114 uint64_t ifindex_64;
115
116 assert(m);
117 assert(m->links);
118 assert(ifindex);
119 assert(ret);
120
121 ifindex_64 = ifindex;
122 link = hashmap_get(m->links, &ifindex_64);
123 if (!link)
124 return -ENODEV;
125
126 *ret = link;
127
128 return 0;
129}
130
f882c247 131static int link_enter_configured(Link *link) {
ef1ba606
TG
132 assert(link);
133 assert(link->state == LINK_STATE_SETTING_ROUTES);
134
39032b87 135 log_info_link(link, "link configured");
f882c247
TG
136
137 link->state = LINK_STATE_CONFIGURED;
138
fe8db0c5
TG
139 link_save(link);
140
f882c247
TG
141 return 0;
142}
143
ef1ba606
TG
144static void link_enter_failed(Link *link) {
145 assert(link);
f882c247 146
39032b87 147 log_warning_link(link, "failed");
449f7554 148
ef1ba606 149 link->state = LINK_STATE_FAILED;
fe8db0c5
TG
150
151 link_save(link);
f882c247
TG
152}
153
f882c247
TG
154static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
155 Link *link = userdata;
156 int r;
157
f5be5601
TG
158 assert(link->route_messages > 0);
159 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
160 link->state == LINK_STATE_SETTING_ROUTES ||
161 link->state == LINK_STATE_FAILED);
f882c247 162
f5be5601 163 link->route_messages --;
f882c247
TG
164
165 if (link->state == LINK_STATE_FAILED)
166 return 1;
167
168 r = sd_rtnl_message_get_errno(m);
c166a070 169 if (r < 0 && r != -EEXIST)
c9ccc19f
TG
170 log_struct_link(LOG_WARNING, link,
171 "MESSAGE=%s: could not set route: %s",
172 link->ifname, strerror(-r),
173 "ERRNO=%d", -r,
174 NULL);
f882c247 175
f5be5601
TG
176 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
177 * ignore it */
178 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
39032b87 179 log_debug_link(link, "routes set");
dd3efc09
TG
180 link_enter_configured(link);
181 }
f882c247
TG
182
183 return 1;
184}
185
186static int link_enter_set_routes(Link *link) {
a6cc569e 187 Route *rt;
f882c247
TG
188 int r;
189
190 assert(link);
191 assert(link->network);
ef1ba606 192 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 193
ef1ba606 194 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 195
5c1d3fc9 196 if (!link->network->static_routes && !link->dhcp_lease &&
aba496a5 197 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
dd3efc09 198 return link_enter_configured(link);
f882c247 199
39032b87 200 log_debug_link(link, "setting routes");
449f7554 201
a6cc569e
TG
202 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
203 r = route_configure(rt, link, &route_handler);
dd3efc09 204 if (r < 0) {
3333d748
ZJS
205 log_warning_link(link,
206 "could not set routes: %s", strerror(-r));
ef1ba606
TG
207 link_enter_failed(link);
208 return r;
dd3efc09 209 }
c166a070 210
f5be5601
TG
211 link->route_messages ++;
212 }
213
5c1d3fc9
UTL
214 if (link->ipv4ll && !link->dhcp_lease) {
215 _cleanup_route_free_ Route *route = NULL;
216 struct in_addr addr;
217
218 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
219 if (r < 0 && r != -ENOENT) {
220 log_warning_link(link, "IPV4LL error: no address: %s",
221 strerror(-r));
222 return r;
223 }
224
225 if (r != -ENOENT) {
226 r = route_new_dynamic(&route);
227 if (r < 0) {
228 log_error_link(link, "Could not allocate route: %s",
229 strerror(-r));
230 return r;
231 }
232
233 route->family = AF_INET;
234 route->scope = RT_SCOPE_LINK;
235 route->metrics = 99;
236
237 r = route_configure(route, link, &route_handler);
238 if (r < 0) {
239 log_warning_link(link,
240 "could not set routes: %s", strerror(-r));
241 link_enter_failed(link);
242 return r;
243 }
244
245 link->route_messages ++;
246 }
247 }
248
a6cc569e
TG
249 if (link->dhcp_lease) {
250 _cleanup_route_free_ Route *route = NULL;
9765ce69 251 _cleanup_route_free_ Route *route_gw = NULL;
a6cc569e
TG
252 struct in_addr gateway;
253
254 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
255 if (r < 0) {
256 log_warning_link(link, "DHCP error: no router: %s",
257 strerror(-r));
258 return r;
259 }
260
261 r = route_new_dynamic(&route);
262 if (r < 0) {
263 log_error_link(link, "Could not allocate route: %s",
264 strerror(-r));
265 return r;
266 }
267
9765ce69
BP
268 r = route_new_dynamic(&route_gw);
269 if (r < 0) {
270 log_error_link(link, "Could not allocate route: %s",
271 strerror(-r));
272 return r;
273 }
274
275 /* The dhcp netmask may mask out the gateway. Add an explicit
276 * route for the gw host so that we can route no matter the
277 * netmask or existing kernel route tables. */
278 route_gw->family = AF_INET;
279 route_gw->dst_addr.in = gateway;
280 route_gw->dst_prefixlen = 32;
281 route_gw->scope = RT_SCOPE_LINK;
282
283 r = route_configure(route_gw, link, &route_handler);
284 if (r < 0) {
285 log_warning_link(link,
286 "could not set host route: %s", strerror(-r));
287 return r;
288 }
289
290 link->route_messages ++;
291
a6cc569e
TG
292 route->family = AF_INET;
293 route->in_addr.in = gateway;
294
295 r = route_configure(route, link, &route_handler);
f5be5601 296 if (r < 0) {
3333d748
ZJS
297 log_warning_link(link,
298 "could not set routes: %s", strerror(-r));
f5be5601
TG
299 link_enter_failed(link);
300 return r;
301 }
302
303 link->route_messages ++;
f882c247
TG
304 }
305
306 return 0;
307}
308
5c1d3fc9
UTL
309static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
310 Link *link = userdata;
311 int r;
312
313 assert(m);
314 assert(link);
315 assert(link->ifname);
316
317 if (link->state == LINK_STATE_FAILED)
318 return 1;
319
320 r = sd_rtnl_message_get_errno(m);
321 if (r < 0 && r != -ENOENT)
322 log_struct_link(LOG_WARNING, link,
323 "MESSAGE=%s: could not drop route: %s",
324 link->ifname, strerror(-r),
325 "ERRNO=%d", -r,
326 NULL);
327
328 return 0;
329}
330
f882c247
TG
331static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
332 Link *link = userdata;
333 int r;
334
f5be5601
TG
335 assert(m);
336 assert(link);
337 assert(link->ifname);
338 assert(link->addr_messages > 0);
ef1ba606 339 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
f882c247 340
f5be5601 341 link->addr_messages --;
f882c247
TG
342
343 if (link->state == LINK_STATE_FAILED)
344 return 1;
345
346 r = sd_rtnl_message_get_errno(m);
c166a070 347 if (r < 0 && r != -EEXIST)
c9ccc19f 348 log_struct_link(LOG_WARNING, link,
3333d748
ZJS
349 "MESSAGE=%s: could not set address: %s",
350 link->ifname, strerror(-r),
351 "ERRNO=%d", -r,
352 NULL);
f882c247 353
f5be5601 354 if (link->addr_messages == 0) {
39032b87 355 log_debug_link(link, "addresses set");
ef1ba606 356 link_enter_set_routes(link);
dd3efc09 357 }
f882c247
TG
358
359 return 1;
360}
361
362static int link_enter_set_addresses(Link *link) {
a6cc569e 363 Address *ad;
f882c247
TG
364 int r;
365
366 assert(link);
367 assert(link->network);
f5be5601 368 assert(link->state != _LINK_STATE_INVALID);
f882c247 369
ef1ba606 370 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 371
5c1d3fc9 372 if (!link->network->static_addresses && !link->dhcp_lease &&
aba496a5 373 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
ef1ba606 374 return link_enter_set_routes(link);
f882c247 375
39032b87 376 log_debug_link(link, "setting addresses");
449f7554 377
a6cc569e
TG
378 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
379 r = address_configure(ad, link, &address_handler);
dd3efc09 380 if (r < 0) {
3333d748
ZJS
381 log_warning_link(link,
382 "could not set addresses: %s", strerror(-r));
ef1ba606
TG
383 link_enter_failed(link);
384 return r;
dd3efc09 385 }
c166a070 386
f5be5601
TG
387 link->addr_messages ++;
388 }
389
5c1d3fc9
UTL
390 if (link->ipv4ll && !link->dhcp_lease) {
391 _cleanup_address_free_ Address *ll_addr = NULL;
392 struct in_addr addr;
393
394 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
395 if (r < 0 && r != -ENOENT) {
396 log_warning_link(link, "IPV4LL error: no address: %s",
397 strerror(-r));
398 return r;
399 }
400
401 if (r != -ENOENT) {
402 r = address_new_dynamic(&ll_addr);
403 if (r < 0) {
404 log_error_link(link, "Could not allocate address: %s", strerror(-r));
405 return r;
406 }
407
408 ll_addr->family = AF_INET;
409 ll_addr->in_addr.in = addr;
410 ll_addr->prefixlen = 16;
411 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
412 ll_addr->scope = RT_SCOPE_LINK;
413
414 r = address_configure(ll_addr, link, &address_handler);
415 if (r < 0) {
416 log_warning_link(link,
417 "could not set addresses: %s", strerror(-r));
418 link_enter_failed(link);
419 return r;
420 }
421
422 link->addr_messages ++;
423 }
424 }
425
a6cc569e
TG
426 if (link->dhcp_lease) {
427 _cleanup_address_free_ Address *address = NULL;
428 struct in_addr addr;
429 struct in_addr netmask;
430 unsigned prefixlen;
431
432 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
433 if (r < 0) {
434 log_warning_link(link, "DHCP error: no address: %s",
435 strerror(-r));
436 return r;
437 }
438
439 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
440 if (r < 0) {
441 log_warning_link(link, "DHCP error: no netmask: %s",
442 strerror(-r));
443 return r;
444 }
445
446 prefixlen = net_netmask_to_prefixlen(&netmask);
447
448 r = address_new_dynamic(&address);
449 if (r < 0) {
450 log_error_link(link, "Could not allocate address: %s",
451 strerror(-r));
452 return r;
453 }
454
455 address->family = AF_INET;
456 address->in_addr.in = addr;
457 address->prefixlen = prefixlen;
458 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
459
460 r = address_configure(address, link, &address_handler);
f5be5601 461 if (r < 0) {
3333d748
ZJS
462 log_warning_link(link,
463 "could not set addresses: %s", strerror(-r));
f5be5601
TG
464 link_enter_failed(link);
465 return r;
466 }
467
468 link->addr_messages ++;
f882c247
TG
469 }
470
471 return 0;
472}
473
aba496a5
UTL
474static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
475 Link *link = userdata;
476 int r;
477
478 assert(m);
479 assert(link);
480 assert(link->ifname);
481
482 if (link->state == LINK_STATE_FAILED)
483 return 1;
484
485 r = sd_rtnl_message_get_errno(m);
486 if (r < 0 && r != -ENOENT)
487 log_struct_link(LOG_WARNING, link,
488 "MESSAGE=%s: could not update address: %s",
489 link->ifname, strerror(-r),
490 "ERRNO=%d", -r,
491 NULL);
492
493 return 0;
494}
495
ff254138
TG
496static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
497 Link *link = userdata;
498 int r;
499
500 assert(m);
501 assert(link);
502 assert(link->ifname);
503
504 if (link->state == LINK_STATE_FAILED)
505 return 1;
506
507 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
508 if (r < 0 && r != -ENOENT)
509 log_struct_link(LOG_WARNING, link,
510 "MESSAGE=%s: could not drop address: %s",
511 link->ifname, strerror(-r),
512 "ERRNO=%d", -r,
513 NULL);
ff254138 514
5c1d3fc9 515 return 0;
ff254138
TG
516}
517
1346b1f0
TG
518static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
519 int r;
520
521 r = sd_bus_message_get_errno(m);
522 if (r < 0)
523 log_warning("Could not set hostname: %s", strerror(-r));
524
525 return 1;
526}
527
528static int set_hostname(sd_bus *bus, const char *hostname) {
529 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
530 int r = 0;
531
1346b1f0
TG
532 assert(hostname);
533
534 log_debug("Setting transient hostname: '%s'", hostname);
535
bcbca829
TG
536 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
537 log_info("Not connected to system bus, ignoring transient hostname.");
538 return 0;
539 }
540
1346b1f0
TG
541 r = sd_bus_message_new_method_call(
542 bus,
151b9b96 543 &m,
1346b1f0
TG
544 "org.freedesktop.hostname1",
545 "/org/freedesktop/hostname1",
546 "org.freedesktop.hostname1",
151b9b96 547 "SetHostname");
1346b1f0
TG
548 if (r < 0)
549 return r;
550
551 r = sd_bus_message_append(m, "sb", hostname, false);
552 if (r < 0)
553 return r;
554
555 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
556 if (r < 0)
557 log_error("Could not set transient hostname: %s", strerror(-r));
558
559 return r;
560}
561
4f882b2a
TG
562static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
563 Link *link = userdata;
564 int r;
565
566 assert(m);
567 assert(link);
568 assert(link->ifname);
569
570 if (link->state == LINK_STATE_FAILED)
571 return 1;
572
573 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
574 if (r < 0)
575 log_struct_link(LOG_WARNING, link,
576 "MESSAGE=%s: could not set MTU: %s",
577 link->ifname, strerror(-r),
578 "ERRNO=%d", -r,
579 NULL);
4f882b2a
TG
580
581 return 1;
582}
583
584static int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 585 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
586 int r;
587
588 assert(link);
589 assert(link->manager);
590 assert(link->manager->rtnl);
591
592 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
593
151b9b96
LP
594 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
595 RTM_SETLINK, link->ifindex);
4f882b2a
TG
596 if (r < 0) {
597 log_error_link(link, "Could not allocate RTM_SETLINK message");
598 return r;
599 }
600
601 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
602 if (r < 0) {
603 log_error_link(link, "Could not append MTU: %s", strerror(-r));
604 return r;
605 }
606
607 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
608 if (r < 0) {
609 log_error_link(link,
610 "Could not send rtnetlink message: %s", strerror(-r));
611 return r;
612 }
613
614 return 0;
615}
616
a6cc569e
TG
617static int dhcp_lease_lost(Link *link) {
618 _cleanup_address_free_ Address *address = NULL;
3e790eae
UTL
619 _cleanup_route_free_ Route *route_gw = NULL;
620 _cleanup_route_free_ Route *route = NULL;
a6cc569e
TG
621 struct in_addr addr;
622 struct in_addr netmask;
3e790eae 623 struct in_addr gateway;
a6cc569e 624 unsigned prefixlen;
ff254138
TG
625 int r;
626
627 assert(link);
a6cc569e 628 assert(link->dhcp_lease);
ff254138 629
14efd761
TG
630 log_warning_link(link, "DHCP lease lost");
631
a6cc569e
TG
632 r = address_new_dynamic(&address);
633 if (r >= 0) {
634 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
635 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
3e790eae 636 sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
a6cc569e 637 prefixlen = net_netmask_to_prefixlen(&netmask);
ff254138 638
3e790eae
UTL
639 r = route_new_dynamic(&route_gw);
640 if (r >= 0) {
641 route_gw->family = AF_INET;
642 route_gw->dst_addr.in = gateway;
643 route_gw->dst_prefixlen = 32;
644 route_gw->scope = RT_SCOPE_LINK;
645
646 route_drop(route_gw, link, &route_drop_handler);
647 }
648
649 r = route_new_dynamic(&route);
650 if (r >= 0) {
651 route->family = AF_INET;
652 route->in_addr.in = gateway;
653
654 route_drop(route, link, &route_drop_handler);
655 }
656
a6cc569e
TG
657 address->family = AF_INET;
658 address->in_addr.in = addr;
659 address->prefixlen = prefixlen;
ff254138 660
5c1d3fc9 661 address_drop(address, link, &address_drop_handler);
c07aeadf 662 }
eb27aeca 663
c07aeadf
TG
664 if (link->network->dhcp_mtu) {
665 uint16_t mtu;
ff254138 666
a6cc569e 667 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
c07aeadf
TG
668 if (r >= 0 && link->original_mtu != mtu) {
669 r = link_set_mtu(link, link->original_mtu);
670 if (r < 0) {
671 log_warning_link(link, "DHCP error: could not reset MTU");
672 link_enter_failed(link);
673 return r;
674 }
ff254138 675 }
c07aeadf 676 }
ff254138 677
c07aeadf 678 if (link->network->dhcp_hostname) {
216816c6
TG
679 const char *hostname = NULL;
680
681 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
682 if (r >= 0 && hostname) {
683 r = set_hostname(link->manager->bus, "");
684 if (r < 0)
685 log_error("Failed to reset transient hostname");
686 }
c07aeadf 687 }
4f882b2a 688
a6cc569e
TG
689 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
690
c07aeadf
TG
691 return 0;
692}
4f882b2a 693
c07aeadf 694static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
a6cc569e 695 sd_dhcp_lease *lease;
c07aeadf
TG
696 struct in_addr address;
697 struct in_addr netmask;
698 struct in_addr gateway;
699 unsigned prefixlen;
c07aeadf
TG
700 struct in_addr *nameservers;
701 size_t nameservers_size;
702 int r;
1346b1f0 703
c07aeadf
TG
704 assert(client);
705 assert(link);
ff254138 706
a6cc569e
TG
707 r = sd_dhcp_client_get_lease(client, &lease);
708 if (r < 0) {
709 log_warning_link(link, "DHCP error: no lease: %s",
710 strerror(-r));
711 return r;
712 }
713
714 r = sd_dhcp_lease_get_address(lease, &address);
ff254138 715 if (r < 0) {
c07aeadf
TG
716 log_warning_link(link, "DHCP error: no address: %s",
717 strerror(-r));
718 return r;
ff254138
TG
719 }
720
a6cc569e 721 r = sd_dhcp_lease_get_netmask(lease, &netmask);
ff254138 722 if (r < 0) {
c07aeadf
TG
723 log_warning_link(link, "DHCP error: no netmask: %s",
724 strerror(-r));
725 return r;
ff254138
TG
726 }
727
377a218f 728 prefixlen = net_netmask_to_prefixlen(&netmask);
ff254138 729
a6cc569e 730 r = sd_dhcp_lease_get_router(lease, &gateway);
ff254138 731 if (r < 0) {
c07aeadf
TG
732 log_warning_link(link, "DHCP error: no router: %s",
733 strerror(-r));
734 return r;
ff254138
TG
735 }
736
c07aeadf
TG
737 log_struct_link(LOG_INFO, link,
738 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
739 link->ifname,
740 ADDRESS_FMT_VAL(address),
741 prefixlen,
742 ADDRESS_FMT_VAL(gateway),
743 "ADDRESS=%u.%u.%u.%u",
744 ADDRESS_FMT_VAL(address),
745 "PREFIXLEN=%u",
746 prefixlen,
747 "GATEWAY=%u.%u.%u.%u",
748 ADDRESS_FMT_VAL(gateway),
749 NULL);
750
d50cf59b
TG
751 link->dhcp_lease = lease;
752
c07aeadf 753 if (link->network->dhcp_dns) {
a6cc569e 754 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
c07aeadf
TG
755 if (r >= 0) {
756 r = manager_update_resolv_conf(link->manager);
757 if (r < 0)
758 log_error("Failed to update resolv.conf");
ff254138 759 }
c07aeadf 760 }
ff254138 761
c07aeadf
TG
762 if (link->network->dhcp_mtu) {
763 uint16_t mtu;
764
a6cc569e 765 r = sd_dhcp_lease_get_mtu(lease, &mtu);
c07aeadf
TG
766 if (r >= 0) {
767 r = link_set_mtu(link, mtu);
768 if (r < 0)
769 log_error_link(link, "Failed to set MTU "
770 "to %" PRIu16, mtu);
771 }
772 }
ff254138 773
c07aeadf
TG
774 if (link->network->dhcp_hostname) {
775 const char *hostname;
ff254138 776
a6cc569e 777 r = sd_dhcp_lease_get_hostname(lease, &hostname);
c07aeadf
TG
778 if (r >= 0) {
779 r = set_hostname(link->manager->bus, hostname);
780 if (r < 0)
781 log_error("Failed to set transient hostname "
782 "to '%s'", hostname);
3bef724f 783 }
c07aeadf 784 }
3bef724f 785
c07aeadf
TG
786 link_enter_set_addresses(link);
787
788 return 0;
789}
790
791static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
792 Link *link = userdata;
aba496a5 793 int r = 0;
c07aeadf
TG
794
795 assert(link);
796 assert(link->network);
797 assert(link->manager);
798
799 if (link->state == LINK_STATE_FAILED)
800 return;
801
802 switch (event) {
803 case DHCP_EVENT_NO_LEASE:
804 log_debug_link(link, "IP address in use.");
805 break;
806 case DHCP_EVENT_EXPIRED:
807 case DHCP_EVENT_STOP:
808 case DHCP_EVENT_IP_CHANGE:
809 if (link->network->dhcp_critical) {
810 log_error_link(link, "DHCPv4 connection considered system critical, "
811 "ignoring request to reconfigure it.");
812 return;
4f882b2a 813 }
4f882b2a 814
17256461
UTL
815 if (link->dhcp_lease) {
816 r = dhcp_lease_lost(link);
817 if (r < 0) {
818 link_enter_failed(link);
819 return;
820 }
c07aeadf 821 }
1346b1f0 822
c07aeadf
TG
823 if (event == DHCP_EVENT_IP_CHANGE) {
824 r = dhcp_lease_acquired(client, link);
825 if (r < 0) {
826 link_enter_failed(link);
827 return;
828 }
1346b1f0 829 }
1346b1f0 830
5c1d3fc9 831 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
aba496a5
UTL
832 if (!sd_ipv4ll_is_running(link->ipv4ll))
833 r = sd_ipv4ll_start(link->ipv4ll);
834 else if (ipv4ll_is_bound(link->ipv4ll))
835 r = ipv4ll_address_update(link, false);
5c1d3fc9
UTL
836 if (r < 0) {
837 link_enter_failed(link);
838 return;
839 }
840 }
841
c07aeadf
TG
842 break;
843 case DHCP_EVENT_IP_ACQUIRE:
844 r = dhcp_lease_acquired(client, link);
845 if (r < 0) {
846 link_enter_failed(link);
847 return;
848 }
5c1d3fc9 849 if (link->ipv4ll) {
aba496a5
UTL
850 if (ipv4ll_is_bound(link->ipv4ll))
851 r = ipv4ll_address_update(link, true);
852 else
853 r = sd_ipv4ll_stop(link->ipv4ll);
5c1d3fc9
UTL
854 if (r < 0) {
855 link_enter_failed(link);
856 return;
857 }
858 }
c07aeadf
TG
859 break;
860 default:
861 if (event < 0)
862 log_warning_link(link, "DHCP error: %s", strerror(-event));
863 else
864 log_warning_link(link, "DHCP unknown event: %d", event);
c07aeadf 865 break;
ff254138
TG
866 }
867
868 return;
869}
870
aba496a5
UTL
871static int ipv4ll_address_update(Link *link, bool deprecate) {
872 int r;
873 struct in_addr addr;
874
875 assert(link);
876
877 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
878 if (r >= 0) {
879 _cleanup_address_free_ Address *address = NULL;
880
881 log_debug_link(link, "IPv4 link-local %s %u.%u.%u.%u",
882 deprecate ? "deprecate" : "approve",
883 ADDRESS_FMT_VAL(addr));
884
885 r = address_new_dynamic(&address);
886 if (r < 0) {
887 log_error_link(link, "Could not allocate address: %s", strerror(-r));
888 return r;
889 }
890
891 address->family = AF_INET;
892 address->in_addr.in = addr;
893 address->prefixlen = 16;
894 address->scope = RT_SCOPE_LINK;
895 address->cinfo.ifa_prefered = deprecate ? 0 : CACHE_INFO_INFINITY_LIFE_TIME;
896 address->broadcast.s_addr = address->in_addr.in.s_addr | htonl(0xfffffffflu >> address->prefixlen);
897
898 address_update(address, link, &address_update_handler);
899 }
900
901 return 0;
902
903}
904
905static int ipv4ll_address_lost(Link *link) {
5c1d3fc9
UTL
906 int r;
907 struct in_addr addr;
908
5c1d3fc9
UTL
909 assert(link);
910
911 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
912 if (r >= 0) {
913 _cleanup_address_free_ Address *address = NULL;
914 _cleanup_route_free_ Route *route = NULL;
915
916 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
917 ADDRESS_FMT_VAL(addr));
918
919 r = address_new_dynamic(&address);
920 if (r < 0) {
921 log_error_link(link, "Could not allocate address: %s", strerror(-r));
922 return r;
923 }
924
925 address->family = AF_INET;
926 address->in_addr.in = addr;
927 address->prefixlen = 16;
928 address->scope = RT_SCOPE_LINK;
929
930 address_drop(address, link, &address_drop_handler);
931
932 r = route_new_dynamic(&route);
933 if (r < 0) {
934 log_error_link(link, "Could not allocate route: %s",
935 strerror(-r));
936 return r;
937 }
938
939 route->family = AF_INET;
940 route->scope = RT_SCOPE_LINK;
941 route->metrics = 99;
942
943 route_drop(route, link, &route_drop_handler);
944 }
945
946 return 0;
947}
948
aba496a5
UTL
949static bool ipv4ll_is_bound(sd_ipv4ll *ll) {
950 int r;
951 struct in_addr addr;
952
953 assert(ll);
954
955 r = sd_ipv4ll_get_address(ll, &addr);
956 if (r < 0)
957 return false;
958 return true;
959}
960
5c1d3fc9
UTL
961static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
962 struct in_addr address;
963 int r;
964
965 assert(ll);
966 assert(link);
967
968 r = sd_ipv4ll_get_address(ll, &address);
969 if (r < 0)
970 return r;
971
972 log_struct_link(LOG_INFO, link,
973 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
974 link->ifname,
975 ADDRESS_FMT_VAL(address),
976 NULL);
977
978 link_enter_set_addresses(link);
979
980 return 0;
981}
982
983static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
984 Link *link = userdata;
985 int r;
986
987 assert(link);
988 assert(link->network);
989 assert(link->manager);
990
991 switch(event) {
992 case IPV4LL_EVENT_STOP:
993 case IPV4LL_EVENT_CONFLICT:
aba496a5 994 r = ipv4ll_address_lost(link);
5c1d3fc9
UTL
995 if (r < 0) {
996 link_enter_failed(link);
997 return;
998 }
999 break;
1000 case IPV4LL_EVENT_BIND:
1001 r = ipv4ll_address_claimed(ll, link);
1002 if (r < 0) {
1003 link_enter_failed(link);
1004 return;
1005 }
1006 break;
1007 default:
1008 if (event < 0)
1009 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
1010 else
1011 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
1012 break;
1013 }
1014}
1015
ff254138
TG
1016static int link_acquire_conf(Link *link) {
1017 int r;
1018
1019 assert(link);
1020 assert(link->network);
ff254138
TG
1021 assert(link->manager);
1022 assert(link->manager->event);
1023
5c1d3fc9 1024 if (link->network->ipv4ll) {
eb34d4af 1025 assert(link->ipv4ll);
ff254138 1026
5c1d3fc9
UTL
1027 log_debug_link(link, "acquiring IPv4 link-local address");
1028
1029 r = sd_ipv4ll_start(link->ipv4ll);
ff254138
TG
1030 if (r < 0)
1031 return r;
5c1d3fc9
UTL
1032 }
1033
1034 if (link->network->dhcp) {
eb34d4af 1035 assert(link->dhcp_client);
ff254138 1036
5c1d3fc9 1037 log_debug_link(link, "acquiring DHCPv4 lease");
ab47d620 1038
5c1d3fc9
UTL
1039 r = sd_dhcp_client_start(link->dhcp_client);
1040 if (r < 0)
1041 return r;
1042 }
ff254138
TG
1043
1044 return 0;
1045}
1046
1047static int link_update_flags(Link *link, unsigned flags) {
ffba6166 1048 unsigned flags_added, flags_removed, generic_flags;
7cc832b9 1049 bool carrier_gained, carrier_lost;
ff254138
TG
1050 int r;
1051
1052 assert(link);
ff254138
TG
1053
1054 if (link->state == LINK_STATE_FAILED)
1055 return 0;
1056
a748b692 1057 if (link->flags == flags)
efbc88b8 1058 return 0;
efbc88b8 1059
ffba6166
TG
1060 flags_added = (link->flags ^ flags) & flags;
1061 flags_removed = (link->flags ^ flags) & link->flags;
1062 generic_flags = ~(IFF_UP | IFF_LOWER_UP | IFF_RUNNING);
c49b33ac 1063
7cc832b9
TG
1064 /* consider link to have carrier when both RUNNING and LOWER_UP, as RUNNING
1065 may mean that the oper state is unknown, in which case we should fall back to
1066 simply trust LOWER_UP, even thought that is less reliable
1067 */
1068 carrier_gained = ((flags_added & IFF_LOWER_UP) && (flags & IFF_RUNNING)) ||
1069 ((flags_added & IFF_RUNNING) && (flags & IFF_LOWER_UP));
1070 carrier_lost = ((link->flags & (IFF_RUNNING | IFF_LOWER_UP)) ==
1071 (IFF_RUNNING | IFF_LOWER_UP)) &&
1072 (flags_removed & (IFF_LOWER_UP | IFF_RUNNING));
1073
1074 link->flags = flags;
1075
505f8da7
TG
1076 if (!link->network)
1077 /* not currently managing this link
1078 we track state changes, but don't log them
1079 they will be logged if and when a network is
1080 applied */
1081 return 0;
efbc88b8 1082
ffba6166
TG
1083 if (flags_added & IFF_UP)
1084 log_info_link(link, "link is up");
1085 else if (flags_removed & IFF_UP)
1086 log_info_link(link, "link is down");
1087
1088 if (flags_added & IFF_LOWER_UP)
3379e257 1089 log_debug_link(link, "link is lower up");
ffba6166 1090 else if (flags_removed & IFF_LOWER_UP)
3379e257 1091 log_debug_link(link, "link is lower down");
ffba6166 1092
7cc832b9 1093 if (flags_added & IFF_RUNNING)
3379e257 1094 log_debug_link(link, "link is running");
7cc832b9 1095 else if (flags_removed & IFF_RUNNING)
3379e257 1096 log_debug_link(link, "link is not running");
ffba6166 1097
505f8da7
TG
1098 if (flags_added & generic_flags)
1099 log_debug_link(link, "ignored link flags gained: %#.8x",
1100 flags_added & generic_flags);
1101
1102 if (flags_removed & generic_flags)
1103 log_debug_link(link, "ignored link flags lost: %#.8x",
1104 flags_removed & generic_flags);
1105
7cc832b9
TG
1106 if (carrier_gained) {
1107 log_info_link(link, "gained carrier");
ffba6166
TG
1108
1109 if (link->network->dhcp || link->network->ipv4ll) {
1110 r = link_acquire_conf(link);
1111 if (r < 0) {
1112 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
1113 link_enter_failed(link);
1114 return r;
ff254138 1115 }
ffba6166 1116 }
7cc832b9
TG
1117 } else if (carrier_lost) {
1118 log_info_link(link, "lost carrier");
efbc88b8 1119
ffba6166
TG
1120 if (link->network->dhcp) {
1121 r = sd_dhcp_client_stop(link->dhcp_client);
1122 if (r < 0) {
1123 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
1124 link_enter_failed(link);
1125 return r;
ff254138 1126 }
ffba6166 1127 }
5c1d3fc9 1128
ffba6166
TG
1129 if (link->network->ipv4ll) {
1130 r = sd_ipv4ll_stop(link->ipv4ll);
1131 if (r < 0) {
1132 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
1133 link_enter_failed(link);
1134 return r;
5c1d3fc9 1135 }
ff254138
TG
1136 }
1137 }
1138
ff254138
TG
1139 return 0;
1140}
1141
dd3efc09
TG
1142static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1143 Link *link = userdata;
1144 int r;
1145
1746cf2a
TG
1146 assert(link);
1147
1148 if (link->state == LINK_STATE_FAILED)
1149 return 1;
1150
dd3efc09 1151 r = sd_rtnl_message_get_errno(m);
58b12917
ZJS
1152 if (r >= 0)
1153 link_update_flags(link, link->flags | IFF_UP);
1154 else
76800848 1155 log_struct_link(LOG_WARNING, link,
c9ccc19f
TG
1156 "MESSAGE=%s: could not bring up interface: %s",
1157 link->ifname, strerror(-r),
1158 "ERRNO=%d", -r,
1159 NULL);
f882c247
TG
1160 return 1;
1161}
1162
1163static int link_up(Link *link) {
cf6a8911 1164 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1165 int r;
1166
f882c247
TG
1167 assert(link);
1168 assert(link->manager);
1169 assert(link->manager->rtnl);
1170
39032b87 1171 log_debug_link(link, "bringing link up");
449f7554 1172
151b9b96
LP
1173 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1174 RTM_SETLINK, link->ifindex);
f579559b 1175 if (r < 0) {
39032b87 1176 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1177 return r;
1178 }
1179
5d4795f3 1180 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1181 if (r < 0) {
3333d748 1182 log_error_link(link, "Could not set link flags: %s", strerror(-r));
fc25d7f8
TG
1183 return r;
1184 }
1185
dd3efc09 1186 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
f579559b 1187 if (r < 0) {
3333d748
ZJS
1188 log_error_link(link,
1189 "Could not send rtnetlink message: %s", strerror(-r));
f579559b
TG
1190 return r;
1191 }
1192
f882c247
TG
1193 return 0;
1194}
1195
52433f6b 1196static int link_enslaved(Link *link) {
f882c247
TG
1197 int r;
1198
ef1ba606 1199 assert(link);
52433f6b 1200 assert(link->state == LINK_STATE_ENSLAVING);
f5be5601 1201 assert(link->network);
dd3efc09 1202
505f8da7
TG
1203 if (!(link->flags & IFF_UP)) {
1204 r = link_up(link);
1205 if (r < 0) {
1206 link_enter_failed(link);
1207 return r;
1208 }
ef1ba606 1209 }
f882c247 1210
5c1d3fc9 1211 if (!link->network->dhcp && !link->network->ipv4ll)
1746cf2a 1212 return link_enter_set_addresses(link);
ef1ba606
TG
1213
1214 return 0;
02b59d57
TG
1215}
1216
52433f6b 1217static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
02b59d57
TG
1218 Link *link = userdata;
1219 int r;
1220
1746cf2a 1221 assert(link);
52433f6b 1222 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
ef1ba606 1223 assert(link->network);
02b59d57 1224
52433f6b
TG
1225 link->enslaving --;
1226
02b59d57
TG
1227 if (link->state == LINK_STATE_FAILED)
1228 return 1;
1229
1230 r = sd_rtnl_message_get_errno(m);
ef1ba606 1231 if (r < 0) {
c9ccc19f
TG
1232 log_struct_link(LOG_ERR, link,
1233 "MESSAGE=%s: could not enslave: %s",
1234 link->ifname, strerror(-r),
1235 "ERRNO=%d", -r,
1236 NULL);
ef1ba606
TG
1237 link_enter_failed(link);
1238 return 1;
3333d748 1239 }
02b59d57 1240
52433f6b 1241 log_debug_link(link, "enslaved");
ab47d620 1242
52433f6b
TG
1243 if (link->enslaving == 0)
1244 link_enslaved(link);
02b59d57
TG
1245
1246 return 1;
1247}
1248
52433f6b 1249static int link_enter_enslave(Link *link) {
fe6b2d55 1250 NetDev *vlan, *macvlan;
672682a6 1251 Iterator i;
02b59d57
TG
1252 int r;
1253
1254 assert(link);
1255 assert(link->network);
505f8da7 1256 assert(link->state == LINK_STATE_INITIALIZING);
02b59d57 1257
52433f6b 1258 link->state = LINK_STATE_ENSLAVING;
02b59d57 1259
fe8db0c5
TG
1260 link_save(link);
1261
63ffa720 1262 if (!link->network->bridge && !link->network->bond &&
fe6b2d55
TG
1263 hashmap_isempty(link->network->vlans) &&
1264 hashmap_isempty(link->network->macvlans))
52433f6b 1265 return link_enslaved(link);
02b59d57 1266
52433f6b
TG
1267 if (link->network->bridge) {
1268 log_struct_link(LOG_DEBUG, link,
1269 "MESSAGE=%s: enslaving by '%s'",
c9ccc19f 1270 link->ifname, link->network->bridge->name,
52433f6b
TG
1271 NETDEV(link->network->bridge),
1272 NULL);
449f7554 1273
52433f6b
TG
1274 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1275 if (r < 0) {
1276 log_struct_link(LOG_WARNING, link,
1277 "MESSAGE=%s: could not enslave by '%s': %s",
c9ccc19f 1278 link->ifname, link->network->bridge->name, strerror(-r),
52433f6b
TG
1279 NETDEV(link->network->bridge),
1280 NULL);
1281 link_enter_failed(link);
1282 return r;
1283 }
1284
0ad6148e
MO
1285 link->enslaving ++;
1286 }
1287
1288 if (link->network->bond) {
1289 log_struct_link(LOG_DEBUG, link,
1290 "MESSAGE=%s: enslaving by '%s'",
1291 link->ifname, link->network->bond->name,
1292 NETDEV(link->network->bond),
1293 NULL);
1294
1295 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1296 if (r < 0) {
1297 log_struct_link(LOG_WARNING, link,
1298 "MESSAGE=%s: could not enslave by '%s': %s",
1299 link->ifname, link->network->bond->name, strerror(-r),
1300 NETDEV(link->network->bond),
1301 NULL);
1302 link_enter_failed(link);
1303 return r;
1304 }
1305
52433f6b
TG
1306 link->enslaving ++;
1307 }
1308
672682a6 1309 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
52433f6b
TG
1310 log_struct_link(LOG_DEBUG, link,
1311 "MESSAGE=%s: enslaving by '%s'",
672682a6 1312 link->ifname, vlan->name, NETDEV(vlan), NULL);
52433f6b 1313
672682a6 1314 r = netdev_enslave(vlan, link, &enslave_handler);
52433f6b
TG
1315 if (r < 0) {
1316 log_struct_link(LOG_WARNING, link,
1317 "MESSAGE=%s: could not enslave by '%s': %s",
672682a6
TG
1318 link->ifname, vlan->name, strerror(-r),
1319 NETDEV(vlan), NULL);
52433f6b
TG
1320 link_enter_failed(link);
1321 return r;
1322 }
1323
1324 link->enslaving ++;
ef1ba606
TG
1325 }
1326
fe6b2d55
TG
1327 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1328 log_struct_link(LOG_DEBUG, link,
1329 "MESSAGE=%s: enslaving by '%s'",
1330 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1331
1332 r = netdev_enslave(macvlan, link, &enslave_handler);
1333 if (r < 0) {
1334 log_struct_link(LOG_WARNING, link,
1335 "MESSAGE=%s: could not enslave by '%s': %s",
1336 link->ifname, macvlan->name, strerror(-r),
1337 NETDEV(macvlan), NULL);
1338 link_enter_failed(link);
1339 return r;
1340 }
1341
1342 link->enslaving ++;
1343 }
1344
ef1ba606
TG
1345 return 0;
1346}
1347
a748b692 1348static int link_configure(Link *link) {
02b59d57
TG
1349 int r;
1350
ef1ba606 1351 assert(link);
505f8da7 1352 assert(link->state == LINK_STATE_INITIALIZING);
a748b692 1353
eb34d4af 1354 if (link->network->ipv4ll) {
b5db00e5 1355 uint8_t seed[8];
eb34d4af
TG
1356 r = sd_ipv4ll_new(&link->ipv4ll);
1357 if (r < 0)
1358 return r;
1359
505f8da7
TG
1360 if (link->udev_device) {
1361 r = net_get_unique_predictable_data(link->udev_device, seed);
1362 if (r >= 0) {
1363 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1364 if (r < 0)
1365 return r;
1366 }
b5db00e5
UTL
1367 }
1368
eb34d4af
TG
1369 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1370 if (r < 0)
1371 return r;
1372
1373 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1374 if (r < 0)
1375 return r;
1376
1377 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1378 if (r < 0)
1379 return r;
1380 }
1381
1382 if (link->network->dhcp) {
1383 r = sd_dhcp_client_new(&link->dhcp_client);
1384 if (r < 0)
1385 return r;
1386
1387 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1388 if (r < 0)
1389 return r;
1390
1391 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1392 if (r < 0)
1393 return r;
1394
1395 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1396 if (r < 0)
1397 return r;
1398
1399 if (link->network->dhcp_mtu) {
1400 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1401 if (r < 0)
1402 return r;
1403 }
1404 }
1405
505f8da7
TG
1406 return link_enter_enslave(link);
1407}
1408
1409int link_initialized(Link *link, struct udev_device *device) {
1410 Network *network;
1411 unsigned flags;
1412 int r;
1413
1414 assert(link);
1415 assert(link->ifname);
1416 assert(link->manager);
1417
1418 if (link->state != LINK_STATE_INITIALIZING)
1419 return 0;
1420
1421 if (device)
1422 link->udev_device = udev_device_ref(device);
1423
1424 log_debug_link(link, "link initialized");
1425
1426 r = network_get(link->manager, device, link->ifname, &link->mac, &network);
1427 if (r < 0)
1428 return r == -ENOENT ? 0 : r;
1429
1430 r = network_apply(link->manager, network, link);
1431 if (r < 0)
1432 return r;
1433
a748b692
TG
1434 r = link_configure(link);
1435 if (r < 0)
1436 return r;
1437
505f8da7
TG
1438 /* re-trigger all state updates */
1439 flags = link->flags;
1440 link->flags = 0;
1441 r = link_update_flags(link, flags);
1442 if (r < 0)
1443 return r;
1444
1445 return 0;
1446}
1447
1448int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1449 Link *link;
1450 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1451 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1452 int r;
1453
1454 assert(m);
1455 assert(message);
1456 assert(ret);
1457
1458 r = link_new(m, message, ret);
1459 if (r < 0)
1460 return r;
1461
1462 link = *ret;
1463
1464 log_info_link(link, "link added");
1465
1466 if (detect_container(NULL) <= 0) {
1467 /* not in a container, udev will be around */
1468 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
1469 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1470 if (!device) {
1471 log_warning_link(link, "could not find udev device");
1472 return -errno;
1473 }
1474
1475 if (udev_device_get_is_initialized(device) <= 0)
1476 /* not yet ready */
1477 return 0;
1478 }
1479
1480 r = link_initialized(link, device);
1481 if (r < 0)
1482 return r;
1483
a748b692
TG
1484 return 0;
1485}
1486
22936833
TG
1487int link_update(Link *link, sd_rtnl_message *m) {
1488 unsigned flags;
c49b33ac 1489 struct ether_addr mac;
22936833
TG
1490 int r;
1491
dd3efc09 1492 assert(link);
22936833
TG
1493 assert(m);
1494
1746cf2a
TG
1495 if (link->state == LINK_STATE_FAILED)
1496 return 0;
1497
505f8da7 1498 if (!link->original_mtu) {
9842de0d
TG
1499 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1500 if (r >= 0)
1501 log_debug_link(link, "saved original MTU: %"
1502 PRIu16, link->original_mtu);
1503 }
69629de9 1504
e9189a1f
TG
1505 /* The kernel may broadcast NEWLINK messages without the MAC address
1506 set, simply ignore them. */
c49b33ac 1507 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1508 if (r >= 0) {
20861203 1509 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 1510
20861203 1511 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 1512
20861203
TG
1513 log_debug_link(link, "MAC address: "
1514 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1515 mac.ether_addr_octet[0],
1516 mac.ether_addr_octet[1],
1517 mac.ether_addr_octet[2],
1518 mac.ether_addr_octet[3],
1519 mac.ether_addr_octet[4],
1520 mac.ether_addr_octet[5]);
c49b33ac 1521
20861203
TG
1522 if (link->ipv4ll) {
1523 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1524 if (r < 0) {
1525 log_warning_link(link, "Could not update MAC "
1526 "address in IPv4LL client: %s",
1527 strerror(-r));
1528 return r;
1529 }
c49b33ac 1530 }
c49b33ac 1531
20861203
TG
1532 if (link->dhcp_client) {
1533 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1534 if (r < 0) {
1535 log_warning_link(link, "Could not update MAC "
1536 "address in DHCP client: %s",
1537 strerror(-r));
1538 return r;
1539 }
c49b33ac
TG
1540 }
1541 }
4f882b2a
TG
1542 }
1543
a748b692
TG
1544 r = sd_rtnl_message_link_get_flags(m, &flags);
1545 if (r < 0) {
1546 log_warning_link(link, "Could not get link flags");
1547 return r;
1548 }
1549
ff254138 1550 return link_update_flags(link, flags);
dd3efc09 1551}
fe8db0c5
TG
1552
1553int link_save(Link *link) {
1554 _cleanup_free_ char *temp_path = NULL;
1555 _cleanup_fclose_ FILE *f = NULL;
7ff8f4b5 1556 const char *state;
fe8db0c5
TG
1557 int r;
1558
1559 assert(link);
1560 assert(link->state_file);
1561
7ff8f4b5 1562 state = link_state_to_string(link->state);
70280736 1563 assert(state);
7ff8f4b5 1564
fe8db0c5
TG
1565 r = fopen_temporary(link->state_file, &f, &temp_path);
1566 if (r < 0)
1567 goto finish;
1568
1569 fchmod(fileno(f), 0644);
1570
1571 fprintf(f,
1572 "# This is private data. Do not parse.\n"
7ff8f4b5 1573 "STATE=%s\n", state);
fe8db0c5
TG
1574
1575 if (link->dhcp_lease) {
fd88eb8a 1576 _cleanup_free_ char *lease_file = NULL;
2a1763ed 1577
315db1a8
ZJS
1578 r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
1579 link->ifindex);
2a1763ed 1580 if (r < 0)
315db1a8 1581 return -ENOMEM;
fe8db0c5
TG
1582
1583 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1584 if (r < 0)
1585 goto finish;
1586
1587 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1588 }
1589
1590 fflush(f);
1591
1592 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1593 r = -errno;
1594 unlink(link->state_file);
1595 unlink(temp_path);
1596 }
1597
1598finish:
1599 if (r < 0)
1600 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1601
1602 return r;
1603}
1604
1605static const char* const link_state_table[_LINK_STATE_MAX] = {
505f8da7 1606 [LINK_STATE_INITIALIZING] = "configuring",
fe8db0c5
TG
1607 [LINK_STATE_ENSLAVING] = "configuring",
1608 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1609 [LINK_STATE_SETTING_ROUTES] = "configuring",
1610 [LINK_STATE_CONFIGURED] = "configured",
1611 [LINK_STATE_FAILED] = "failed",
1612};
1613
1614DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);