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