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