]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: link - use IFF_DORMANT instead of IFF_RUNNING
[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;
75ee87c8 1062 generic_flags = ~(IFF_UP | IFF_LOWER_UP | IFF_DORMANT);
c49b33ac 1063
75ee87c8
TG
1064 /* consider link to have carrier when LOWER_UP and !DORMANT
1065
1066 TODO: use proper operstates once we start supporting 802.1X
1067
1068 see Documentation/networking/operstates.txt in the kernel sources
7cc832b9 1069 */
75ee87c8
TG
1070 carrier_gained = (((flags_added & IFF_LOWER_UP) && !(flags & IFF_DORMANT)) ||
1071 ((flags_removed & IFF_DORMANT) && (flags & IFF_LOWER_UP)));
1072 carrier_lost = ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT)) &&
1073 ((flags_removed & IFF_LOWER_UP) || (flags_added & IFF_DORMANT));
7cc832b9
TG
1074
1075 link->flags = flags;
1076
505f8da7
TG
1077 if (!link->network)
1078 /* not currently managing this link
1079 we track state changes, but don't log them
1080 they will be logged if and when a network is
1081 applied */
1082 return 0;
efbc88b8 1083
ffba6166
TG
1084 if (flags_added & IFF_UP)
1085 log_info_link(link, "link is up");
1086 else if (flags_removed & IFF_UP)
1087 log_info_link(link, "link is down");
1088
1089 if (flags_added & IFF_LOWER_UP)
3379e257 1090 log_debug_link(link, "link is lower up");
ffba6166 1091 else if (flags_removed & IFF_LOWER_UP)
3379e257 1092 log_debug_link(link, "link is lower down");
ffba6166 1093
75ee87c8
TG
1094 if (flags_added & IFF_DORMANT)
1095 log_debug_link(link, "link is dormant");
1096 else if (flags_removed & IFF_DORMANT)
1097 log_debug_link(link, "link is not dormant");
ffba6166 1098
069e10a0 1099 /* link flags are currently at most 18 bits, let's default to printing 20 */
505f8da7 1100 if (flags_added & generic_flags)
069e10a0 1101 log_debug_link(link, "unknown link flags gained: %#.5x (ignoring)",
505f8da7
TG
1102 flags_added & generic_flags);
1103
1104 if (flags_removed & generic_flags)
069e10a0 1105 log_debug_link(link, "unknown link flags lost: %#.5x (ignoring)",
75ee87c8 1106 flags_removed & generic_flags);
505f8da7 1107
7cc832b9
TG
1108 if (carrier_gained) {
1109 log_info_link(link, "gained carrier");
ffba6166
TG
1110
1111 if (link->network->dhcp || link->network->ipv4ll) {
1112 r = link_acquire_conf(link);
1113 if (r < 0) {
1114 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
1115 link_enter_failed(link);
1116 return r;
ff254138 1117 }
ffba6166 1118 }
7cc832b9
TG
1119 } else if (carrier_lost) {
1120 log_info_link(link, "lost carrier");
efbc88b8 1121
ffba6166
TG
1122 if (link->network->dhcp) {
1123 r = sd_dhcp_client_stop(link->dhcp_client);
1124 if (r < 0) {
1125 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
1126 link_enter_failed(link);
1127 return r;
ff254138 1128 }
ffba6166 1129 }
5c1d3fc9 1130
ffba6166
TG
1131 if (link->network->ipv4ll) {
1132 r = sd_ipv4ll_stop(link->ipv4ll);
1133 if (r < 0) {
1134 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
1135 link_enter_failed(link);
1136 return r;
5c1d3fc9 1137 }
ff254138
TG
1138 }
1139 }
1140
ff254138
TG
1141 return 0;
1142}
1143
dd3efc09
TG
1144static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1145 Link *link = userdata;
1146 int r;
1147
1746cf2a
TG
1148 assert(link);
1149
1150 if (link->state == LINK_STATE_FAILED)
1151 return 1;
1152
dd3efc09 1153 r = sd_rtnl_message_get_errno(m);
58b12917
ZJS
1154 if (r >= 0)
1155 link_update_flags(link, link->flags | IFF_UP);
1156 else
76800848 1157 log_struct_link(LOG_WARNING, link,
c9ccc19f
TG
1158 "MESSAGE=%s: could not bring up interface: %s",
1159 link->ifname, strerror(-r),
1160 "ERRNO=%d", -r,
1161 NULL);
f882c247
TG
1162 return 1;
1163}
1164
1165static int link_up(Link *link) {
cf6a8911 1166 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1167 int r;
1168
f882c247
TG
1169 assert(link);
1170 assert(link->manager);
1171 assert(link->manager->rtnl);
1172
39032b87 1173 log_debug_link(link, "bringing link up");
449f7554 1174
151b9b96
LP
1175 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1176 RTM_SETLINK, link->ifindex);
f579559b 1177 if (r < 0) {
39032b87 1178 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1179 return r;
1180 }
1181
5d4795f3 1182 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1183 if (r < 0) {
3333d748 1184 log_error_link(link, "Could not set link flags: %s", strerror(-r));
fc25d7f8
TG
1185 return r;
1186 }
1187
dd3efc09 1188 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
f579559b 1189 if (r < 0) {
3333d748
ZJS
1190 log_error_link(link,
1191 "Could not send rtnetlink message: %s", strerror(-r));
f579559b
TG
1192 return r;
1193 }
1194
f882c247
TG
1195 return 0;
1196}
1197
52433f6b 1198static int link_enslaved(Link *link) {
f882c247
TG
1199 int r;
1200
ef1ba606 1201 assert(link);
52433f6b 1202 assert(link->state == LINK_STATE_ENSLAVING);
f5be5601 1203 assert(link->network);
dd3efc09 1204
505f8da7
TG
1205 if (!(link->flags & IFF_UP)) {
1206 r = link_up(link);
1207 if (r < 0) {
1208 link_enter_failed(link);
1209 return r;
1210 }
ef1ba606 1211 }
f882c247 1212
5c1d3fc9 1213 if (!link->network->dhcp && !link->network->ipv4ll)
1746cf2a 1214 return link_enter_set_addresses(link);
ef1ba606
TG
1215
1216 return 0;
02b59d57
TG
1217}
1218
52433f6b 1219static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
02b59d57
TG
1220 Link *link = userdata;
1221 int r;
1222
1746cf2a 1223 assert(link);
52433f6b 1224 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
ef1ba606 1225 assert(link->network);
02b59d57 1226
52433f6b
TG
1227 link->enslaving --;
1228
02b59d57
TG
1229 if (link->state == LINK_STATE_FAILED)
1230 return 1;
1231
1232 r = sd_rtnl_message_get_errno(m);
ef1ba606 1233 if (r < 0) {
c9ccc19f
TG
1234 log_struct_link(LOG_ERR, link,
1235 "MESSAGE=%s: could not enslave: %s",
1236 link->ifname, strerror(-r),
1237 "ERRNO=%d", -r,
1238 NULL);
ef1ba606
TG
1239 link_enter_failed(link);
1240 return 1;
3333d748 1241 }
02b59d57 1242
52433f6b 1243 log_debug_link(link, "enslaved");
ab47d620 1244
52433f6b
TG
1245 if (link->enslaving == 0)
1246 link_enslaved(link);
02b59d57
TG
1247
1248 return 1;
1249}
1250
52433f6b 1251static int link_enter_enslave(Link *link) {
fe6b2d55 1252 NetDev *vlan, *macvlan;
672682a6 1253 Iterator i;
02b59d57
TG
1254 int r;
1255
1256 assert(link);
1257 assert(link->network);
505f8da7 1258 assert(link->state == LINK_STATE_INITIALIZING);
02b59d57 1259
52433f6b 1260 link->state = LINK_STATE_ENSLAVING;
02b59d57 1261
fe8db0c5
TG
1262 link_save(link);
1263
63ffa720 1264 if (!link->network->bridge && !link->network->bond &&
fe6b2d55
TG
1265 hashmap_isempty(link->network->vlans) &&
1266 hashmap_isempty(link->network->macvlans))
52433f6b 1267 return link_enslaved(link);
02b59d57 1268
52433f6b
TG
1269 if (link->network->bridge) {
1270 log_struct_link(LOG_DEBUG, link,
1271 "MESSAGE=%s: enslaving by '%s'",
c9ccc19f 1272 link->ifname, link->network->bridge->name,
52433f6b
TG
1273 NETDEV(link->network->bridge),
1274 NULL);
449f7554 1275
52433f6b
TG
1276 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1277 if (r < 0) {
1278 log_struct_link(LOG_WARNING, link,
1279 "MESSAGE=%s: could not enslave by '%s': %s",
c9ccc19f 1280 link->ifname, link->network->bridge->name, strerror(-r),
52433f6b
TG
1281 NETDEV(link->network->bridge),
1282 NULL);
1283 link_enter_failed(link);
1284 return r;
1285 }
1286
0ad6148e
MO
1287 link->enslaving ++;
1288 }
1289
1290 if (link->network->bond) {
1291 log_struct_link(LOG_DEBUG, link,
1292 "MESSAGE=%s: enslaving by '%s'",
1293 link->ifname, link->network->bond->name,
1294 NETDEV(link->network->bond),
1295 NULL);
1296
1297 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1298 if (r < 0) {
1299 log_struct_link(LOG_WARNING, link,
1300 "MESSAGE=%s: could not enslave by '%s': %s",
1301 link->ifname, link->network->bond->name, strerror(-r),
1302 NETDEV(link->network->bond),
1303 NULL);
1304 link_enter_failed(link);
1305 return r;
1306 }
1307
52433f6b
TG
1308 link->enslaving ++;
1309 }
1310
672682a6 1311 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
52433f6b
TG
1312 log_struct_link(LOG_DEBUG, link,
1313 "MESSAGE=%s: enslaving by '%s'",
672682a6 1314 link->ifname, vlan->name, NETDEV(vlan), NULL);
52433f6b 1315
672682a6 1316 r = netdev_enslave(vlan, link, &enslave_handler);
52433f6b
TG
1317 if (r < 0) {
1318 log_struct_link(LOG_WARNING, link,
1319 "MESSAGE=%s: could not enslave by '%s': %s",
672682a6
TG
1320 link->ifname, vlan->name, strerror(-r),
1321 NETDEV(vlan), NULL);
52433f6b
TG
1322 link_enter_failed(link);
1323 return r;
1324 }
1325
1326 link->enslaving ++;
ef1ba606
TG
1327 }
1328
fe6b2d55
TG
1329 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1330 log_struct_link(LOG_DEBUG, link,
1331 "MESSAGE=%s: enslaving by '%s'",
1332 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1333
1334 r = netdev_enslave(macvlan, link, &enslave_handler);
1335 if (r < 0) {
1336 log_struct_link(LOG_WARNING, link,
1337 "MESSAGE=%s: could not enslave by '%s': %s",
1338 link->ifname, macvlan->name, strerror(-r),
1339 NETDEV(macvlan), NULL);
1340 link_enter_failed(link);
1341 return r;
1342 }
1343
1344 link->enslaving ++;
1345 }
1346
ef1ba606
TG
1347 return 0;
1348}
1349
a748b692 1350static int link_configure(Link *link) {
02b59d57
TG
1351 int r;
1352
ef1ba606 1353 assert(link);
505f8da7 1354 assert(link->state == LINK_STATE_INITIALIZING);
a748b692 1355
eb34d4af 1356 if (link->network->ipv4ll) {
b5db00e5 1357 uint8_t seed[8];
eb34d4af
TG
1358 r = sd_ipv4ll_new(&link->ipv4ll);
1359 if (r < 0)
1360 return r;
1361
505f8da7
TG
1362 if (link->udev_device) {
1363 r = net_get_unique_predictable_data(link->udev_device, seed);
1364 if (r >= 0) {
1365 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1366 if (r < 0)
1367 return r;
1368 }
b5db00e5
UTL
1369 }
1370
eb34d4af
TG
1371 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1372 if (r < 0)
1373 return r;
1374
1375 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1376 if (r < 0)
1377 return r;
1378
1379 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1380 if (r < 0)
1381 return r;
1382 }
1383
1384 if (link->network->dhcp) {
1385 r = sd_dhcp_client_new(&link->dhcp_client);
1386 if (r < 0)
1387 return r;
1388
1389 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1390 if (r < 0)
1391 return r;
1392
1393 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1394 if (r < 0)
1395 return r;
1396
1397 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1398 if (r < 0)
1399 return r;
1400
1401 if (link->network->dhcp_mtu) {
1402 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1403 if (r < 0)
1404 return r;
1405 }
1406 }
1407
505f8da7
TG
1408 return link_enter_enslave(link);
1409}
1410
1411int link_initialized(Link *link, struct udev_device *device) {
1412 Network *network;
1413 unsigned flags;
1414 int r;
1415
1416 assert(link);
1417 assert(link->ifname);
1418 assert(link->manager);
1419
1420 if (link->state != LINK_STATE_INITIALIZING)
1421 return 0;
1422
1423 if (device)
1424 link->udev_device = udev_device_ref(device);
1425
1426 log_debug_link(link, "link initialized");
1427
1428 r = network_get(link->manager, device, link->ifname, &link->mac, &network);
1429 if (r < 0)
1430 return r == -ENOENT ? 0 : r;
1431
1432 r = network_apply(link->manager, network, link);
1433 if (r < 0)
1434 return r;
1435
a748b692
TG
1436 r = link_configure(link);
1437 if (r < 0)
1438 return r;
1439
505f8da7
TG
1440 /* re-trigger all state updates */
1441 flags = link->flags;
1442 link->flags = 0;
1443 r = link_update_flags(link, flags);
1444 if (r < 0)
1445 return r;
1446
1447 return 0;
1448}
1449
1450int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1451 Link *link;
1452 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1453 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1454 int r;
1455
1456 assert(m);
1457 assert(message);
1458 assert(ret);
1459
1460 r = link_new(m, message, ret);
1461 if (r < 0)
1462 return r;
1463
1464 link = *ret;
1465
1466 log_info_link(link, "link added");
1467
1468 if (detect_container(NULL) <= 0) {
1469 /* not in a container, udev will be around */
1470 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
1471 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1472 if (!device) {
1473 log_warning_link(link, "could not find udev device");
1474 return -errno;
1475 }
1476
1477 if (udev_device_get_is_initialized(device) <= 0)
1478 /* not yet ready */
1479 return 0;
1480 }
1481
1482 r = link_initialized(link, device);
1483 if (r < 0)
1484 return r;
1485
a748b692
TG
1486 return 0;
1487}
1488
22936833
TG
1489int link_update(Link *link, sd_rtnl_message *m) {
1490 unsigned flags;
c49b33ac 1491 struct ether_addr mac;
b8941f74 1492 char *ifname;
22936833
TG
1493 int r;
1494
dd3efc09 1495 assert(link);
b8941f74 1496 assert(link->ifname);
22936833
TG
1497 assert(m);
1498
1746cf2a
TG
1499 if (link->state == LINK_STATE_FAILED)
1500 return 0;
1501
b8941f74
TG
1502 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1503 if (r >= 0 && !streq(ifname, link->ifname)) {
1504 log_info_link(link, "renamed to %s", ifname);
1505
1506 free(link->ifname);
1507 link->ifname = strdup(ifname);
1508 if (!link->ifname)
1509 return -ENOMEM;
1510 }
1511
505f8da7 1512 if (!link->original_mtu) {
9842de0d
TG
1513 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1514 if (r >= 0)
1515 log_debug_link(link, "saved original MTU: %"
1516 PRIu16, link->original_mtu);
1517 }
69629de9 1518
e9189a1f
TG
1519 /* The kernel may broadcast NEWLINK messages without the MAC address
1520 set, simply ignore them. */
c49b33ac 1521 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1522 if (r >= 0) {
20861203 1523 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 1524
20861203 1525 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 1526
20861203
TG
1527 log_debug_link(link, "MAC address: "
1528 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1529 mac.ether_addr_octet[0],
1530 mac.ether_addr_octet[1],
1531 mac.ether_addr_octet[2],
1532 mac.ether_addr_octet[3],
1533 mac.ether_addr_octet[4],
1534 mac.ether_addr_octet[5]);
c49b33ac 1535
20861203
TG
1536 if (link->ipv4ll) {
1537 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1538 if (r < 0) {
1539 log_warning_link(link, "Could not update MAC "
1540 "address in IPv4LL client: %s",
1541 strerror(-r));
1542 return r;
1543 }
c49b33ac 1544 }
c49b33ac 1545
20861203
TG
1546 if (link->dhcp_client) {
1547 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1548 if (r < 0) {
1549 log_warning_link(link, "Could not update MAC "
1550 "address in DHCP client: %s",
1551 strerror(-r));
1552 return r;
1553 }
c49b33ac
TG
1554 }
1555 }
4f882b2a
TG
1556 }
1557
a748b692
TG
1558 r = sd_rtnl_message_link_get_flags(m, &flags);
1559 if (r < 0) {
1560 log_warning_link(link, "Could not get link flags");
1561 return r;
1562 }
1563
ff254138 1564 return link_update_flags(link, flags);
dd3efc09 1565}
fe8db0c5
TG
1566
1567int link_save(Link *link) {
1568 _cleanup_free_ char *temp_path = NULL;
1569 _cleanup_fclose_ FILE *f = NULL;
7ff8f4b5 1570 const char *state;
fe8db0c5
TG
1571 int r;
1572
1573 assert(link);
1574 assert(link->state_file);
1575
7ff8f4b5 1576 state = link_state_to_string(link->state);
70280736 1577 assert(state);
7ff8f4b5 1578
fe8db0c5
TG
1579 r = fopen_temporary(link->state_file, &f, &temp_path);
1580 if (r < 0)
1581 goto finish;
1582
1583 fchmod(fileno(f), 0644);
1584
1585 fprintf(f,
1586 "# This is private data. Do not parse.\n"
7ff8f4b5 1587 "STATE=%s\n", state);
fe8db0c5
TG
1588
1589 if (link->dhcp_lease) {
fd88eb8a 1590 _cleanup_free_ char *lease_file = NULL;
2a1763ed 1591
315db1a8
ZJS
1592 r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
1593 link->ifindex);
2a1763ed 1594 if (r < 0)
315db1a8 1595 return -ENOMEM;
fe8db0c5
TG
1596
1597 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1598 if (r < 0)
1599 goto finish;
1600
1601 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1602 }
1603
1604 fflush(f);
1605
1606 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1607 r = -errno;
1608 unlink(link->state_file);
1609 unlink(temp_path);
1610 }
1611
1612finish:
1613 if (r < 0)
1614 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1615
1616 return r;
1617}
1618
1619static const char* const link_state_table[_LINK_STATE_MAX] = {
505f8da7 1620 [LINK_STATE_INITIALIZING] = "configuring",
fe8db0c5
TG
1621 [LINK_STATE_ENSLAVING] = "configuring",
1622 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1623 [LINK_STATE_SETTING_ROUTES] = "configuring",
1624 [LINK_STATE_CONFIGURED] = "configured",
1625 [LINK_STATE_FAILED] = "failed",
1626};
1627
1628DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);