]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
sd-dhcp-server: add RELEASE support
[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) {
14b746f7 40 _cleanup_link_unref_ 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
14b746f7 70 link->n_ref = 1;
5a3eb5a7 71 link->manager = manager;
505f8da7
TG
72 link->state = LINK_STATE_INITIALIZING;
73 link->ifindex = ifindex;
74 link->ifname = strdup(ifname);
75 if (!link->ifname)
76 return -ENOMEM;
f579559b 77
512922f8
TG
78 r = sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
79 if (r < 0)
80 return r;
81
85b5673b 82 r = asprintf(&link->state_file, "/run/systemd/netif/links/%"PRIu64,
315db1a8 83 link->ifindex);
fe8db0c5 84 if (r < 0)
315db1a8 85 return -ENOMEM;
fe8db0c5 86
85b5673b 87 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%"PRIu64,
68a8723c
TG
88 link->ifindex);
89 if (r < 0)
90 return -ENOMEM;
91
0617ffab 92 r = hashmap_put(manager->links, &link->ifindex, link);
f579559b
TG
93 if (r < 0)
94 return r;
95
96 *ret = link;
97 link = NULL;
98
99 return 0;
100}
101
14b746f7 102static void link_free(Link *link) {
428fd0a7
TG
103 Address *address;
104
f579559b
TG
105 if (!link)
106 return;
107
0617ffab 108 assert(link->manager);
f579559b 109
428fd0a7
TG
110 while ((address = link->addresses)) {
111 LIST_REMOVE(addresses, link->addresses, address);
112 address_free(address);
113 }
114
e5b04c8d 115 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 116 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 117
68a8723c
TG
118 unlink(link->lease_file);
119 free(link->lease_file);
120
56cd007a 121 sd_ipv4ll_unref(link->ipv4ll);
5c1d3fc9 122
0617ffab 123 hashmap_remove(link->manager->links, &link->ifindex);
f579559b 124
c166a070 125 free(link->ifname);
68a8723c
TG
126
127 unlink(link->state_file);
fe8db0c5 128 free(link->state_file);
c166a070 129
b5db00e5
UTL
130 udev_device_unref(link->udev_device);
131
f579559b
TG
132 free(link);
133}
134
14b746f7
TG
135Link *link_unref(Link *link) {
136 if (link && (-- link->n_ref <= 0))
137 link_free(link);
138
139 return NULL;
140}
141
142Link *link_ref(Link *link) {
143 if (link)
144 assert_se(++ link->n_ref >= 2);
145
146 return link;
147}
148
11a7f229
TG
149int link_get(Manager *m, int ifindex, Link **ret) {
150 Link *link;
151 uint64_t ifindex_64;
152
153 assert(m);
154 assert(m->links);
155 assert(ifindex);
156 assert(ret);
157
158 ifindex_64 = ifindex;
159 link = hashmap_get(m->links, &ifindex_64);
160 if (!link)
161 return -ENODEV;
162
163 *ret = link;
164
165 return 0;
166}
167
370e9930
TG
168void link_drop(Link *link) {
169 if (!link || link->state == LINK_STATE_LINGER)
170 return;
171
172 link->state = LINK_STATE_LINGER;
173
7619683b 174 log_debug_link(link, "link removed");
370e9930
TG
175
176 link_unref(link);
177
178 return;
179}
180
f882c247 181static int link_enter_configured(Link *link) {
ef1ba606
TG
182 assert(link);
183 assert(link->state == LINK_STATE_SETTING_ROUTES);
184
39032b87 185 log_info_link(link, "link configured");
f882c247
TG
186
187 link->state = LINK_STATE_CONFIGURED;
188
fe8db0c5
TG
189 link_save(link);
190
f882c247
TG
191 return 0;
192}
193
57bd6899
TG
194static void link_enter_unmanaged(Link *link) {
195 assert(link);
196
df9aa406 197 log_debug_link(link, "unmanaged");
57bd6899
TG
198
199 link->state = LINK_STATE_UNMANAGED;
200
201 link_save(link);
202}
203
111bb8f9
TG
204static int link_stop_clients(Link *link) {
205 int r = 0, k;
206
207 assert(link);
208 assert(link->manager);
209 assert(link->manager->event);
210
211 if (!link->network)
212 return 0;
213
214 if (link->network->dhcp) {
215 assert(link->dhcp_client);
216
217 k = sd_dhcp_client_stop(link->dhcp_client);
218 if (k < 0) {
219 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
220 r = k;
221 }
222 }
223
224 if (link->network->ipv4ll) {
225 assert(link->ipv4ll);
226
227 k = sd_ipv4ll_stop(link->ipv4ll);
228 if (k < 0) {
229 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
230 r = k;
231 }
232 }
233
234 return r;
235}
236
ef1ba606
TG
237static void link_enter_failed(Link *link) {
238 assert(link);
f882c247 239
370e9930 240 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
241 return;
242
39032b87 243 log_warning_link(link, "failed");
449f7554 244
ef1ba606 245 link->state = LINK_STATE_FAILED;
fe8db0c5 246
111bb8f9
TG
247 link_stop_clients(link);
248
fe8db0c5 249 link_save(link);
f882c247
TG
250}
251
f882c247
TG
252static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
253 Link *link = userdata;
254 int r;
255
f5be5601 256 assert(link->route_messages > 0);
370e9930
TG
257 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
258 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
259 LINK_STATE_LINGER));
f882c247 260
f5be5601 261 link->route_messages --;
f882c247 262
370e9930 263 if (IN_SET(LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 264 link_unref(link);
f882c247 265 return 1;
b226d99b 266 }
f882c247
TG
267
268 r = sd_rtnl_message_get_errno(m);
c166a070 269 if (r < 0 && r != -EEXIST)
c9ccc19f 270 log_struct_link(LOG_WARNING, link,
987efa17
TG
271 "MESSAGE=%*s: could not set route: %s",
272 IFNAMSIZ,
c9ccc19f
TG
273 link->ifname, strerror(-r),
274 "ERRNO=%d", -r,
275 NULL);
f882c247 276
f5be5601
TG
277 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
278 * ignore it */
279 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
39032b87 280 log_debug_link(link, "routes set");
dd3efc09
TG
281 link_enter_configured(link);
282 }
f882c247 283
b226d99b
TG
284 link_unref(link);
285
f882c247
TG
286 return 1;
287}
288
289static int link_enter_set_routes(Link *link) {
a6cc569e 290 Route *rt;
f882c247
TG
291 int r;
292
293 assert(link);
294 assert(link->network);
ef1ba606 295 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 296
ef1ba606 297 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 298
5c1d3fc9 299 if (!link->network->static_routes && !link->dhcp_lease &&
370e9930 300 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
dd3efc09 301 return link_enter_configured(link);
f882c247 302
39032b87 303 log_debug_link(link, "setting routes");
449f7554 304
3d3d4255 305 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 306 r = route_configure(rt, link, &route_handler);
dd3efc09 307 if (r < 0) {
3333d748
ZJS
308 log_warning_link(link,
309 "could not set routes: %s", strerror(-r));
ef1ba606
TG
310 link_enter_failed(link);
311 return r;
dd3efc09 312 }
c166a070 313
b226d99b 314 link_ref(link);
f5be5601
TG
315 link->route_messages ++;
316 }
317
5c1d3fc9
UTL
318 if (link->ipv4ll && !link->dhcp_lease) {
319 _cleanup_route_free_ Route *route = NULL;
320 struct in_addr addr;
321
322 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
323 if (r < 0 && r != -ENOENT) {
324 log_warning_link(link, "IPV4LL error: no address: %s",
325 strerror(-r));
326 return r;
327 }
328
329 if (r != -ENOENT) {
330 r = route_new_dynamic(&route);
331 if (r < 0) {
332 log_error_link(link, "Could not allocate route: %s",
333 strerror(-r));
334 return r;
335 }
336
337 route->family = AF_INET;
338 route->scope = RT_SCOPE_LINK;
339 route->metrics = 99;
340
341 r = route_configure(route, link, &route_handler);
342 if (r < 0) {
343 log_warning_link(link,
344 "could not set routes: %s", strerror(-r));
345 link_enter_failed(link);
346 return r;
347 }
348
b226d99b 349 link_ref(link);
5c1d3fc9
UTL
350 link->route_messages ++;
351 }
352 }
353
a6cc569e
TG
354 if (link->dhcp_lease) {
355 _cleanup_route_free_ Route *route = NULL;
9765ce69 356 _cleanup_route_free_ Route *route_gw = NULL;
a6cc569e
TG
357 struct in_addr gateway;
358
359 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
8ddbeaa2
UTL
360 if (r < 0 && r != -ENOENT) {
361 log_warning_link(link, "DHCP error: %s", strerror(-r));
a6cc569e
TG
362 return r;
363 }
364
8ddbeaa2
UTL
365 if (r >= 0) {
366 r = route_new_dynamic(&route);
367 if (r < 0) {
368 log_error_link(link, "Could not allocate route: %s",
369 strerror(-r));
370 return r;
371 }
a6cc569e 372
8ddbeaa2
UTL
373 r = route_new_dynamic(&route_gw);
374 if (r < 0) {
375 log_error_link(link, "Could not allocate route: %s",
376 strerror(-r));
377 return r;
378 }
9765ce69 379
8ddbeaa2
UTL
380 /* The dhcp netmask may mask out the gateway. Add an explicit
381 * route for the gw host so that we can route no matter the
382 * netmask or existing kernel route tables. */
383 route_gw->family = AF_INET;
384 route_gw->dst_addr.in = gateway;
385 route_gw->dst_prefixlen = 32;
386 route_gw->scope = RT_SCOPE_LINK;
9765ce69 387
8ddbeaa2
UTL
388 r = route_configure(route_gw, link, &route_handler);
389 if (r < 0) {
390 log_warning_link(link,
391 "could not set host route: %s", strerror(-r));
392 return r;
393 }
9765ce69 394
b226d99b 395 link_ref(link);
8ddbeaa2 396 link->route_messages ++;
9765ce69 397
8ddbeaa2
UTL
398 route->family = AF_INET;
399 route->in_addr.in = gateway;
a6cc569e 400
8ddbeaa2
UTL
401 r = route_configure(route, link, &route_handler);
402 if (r < 0) {
403 log_warning_link(link,
404 "could not set routes: %s", strerror(-r));
405 link_enter_failed(link);
406 return r;
407 }
408
b226d99b 409 link_ref(link);
8ddbeaa2 410 link->route_messages ++;
f5be5601 411 }
8ddbeaa2 412 }
f5be5601 413
8ddbeaa2
UTL
414 if (link->route_messages == 0) {
415 link_enter_configured(link);
f882c247
TG
416 }
417
418 return 0;
419}
420
5c1d3fc9
UTL
421static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
422 Link *link = userdata;
423 int r;
424
425 assert(m);
426 assert(link);
427 assert(link->ifname);
428
370e9930 429 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 430 link_unref(link);
5c1d3fc9 431 return 1;
b226d99b 432 }
5c1d3fc9
UTL
433
434 r = sd_rtnl_message_get_errno(m);
b90b025a 435 if (r < 0 && r != -ESRCH)
5c1d3fc9 436 log_struct_link(LOG_WARNING, link,
987efa17
TG
437 "MESSAGE=%*s: could not drop route: %s",
438 IFNAMSIZ,
5c1d3fc9
UTL
439 link->ifname, strerror(-r),
440 "ERRNO=%d", -r,
441 NULL);
442
b226d99b
TG
443 link_unref(link);
444
5c1d3fc9
UTL
445 return 0;
446}
447
f882c247
TG
448static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
449 Link *link = userdata;
450 int r;
451
f5be5601
TG
452 assert(m);
453 assert(link);
454 assert(link->ifname);
455 assert(link->addr_messages > 0);
370e9930
TG
456 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
457 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 458
f5be5601 459 link->addr_messages --;
f882c247 460
370e9930 461 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 462 link_unref(link);
f882c247 463 return 1;
b226d99b 464 }
f882c247
TG
465
466 r = sd_rtnl_message_get_errno(m);
c166a070 467 if (r < 0 && r != -EEXIST)
c9ccc19f 468 log_struct_link(LOG_WARNING, link,
987efa17
TG
469 "MESSAGE=%*s: could not set address: %s",
470 IFNAMSIZ,
3333d748
ZJS
471 link->ifname, strerror(-r),
472 "ERRNO=%d", -r,
473 NULL);
f882c247 474
f5be5601 475 if (link->addr_messages == 0) {
39032b87 476 log_debug_link(link, "addresses set");
ef1ba606 477 link_enter_set_routes(link);
dd3efc09 478 }
f882c247 479
b226d99b
TG
480 link_unref(link);
481
f882c247
TG
482 return 1;
483}
484
485static int link_enter_set_addresses(Link *link) {
a6cc569e 486 Address *ad;
f882c247
TG
487 int r;
488
489 assert(link);
490 assert(link->network);
f5be5601 491 assert(link->state != _LINK_STATE_INVALID);
f882c247 492
ef1ba606 493 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 494
5c1d3fc9 495 if (!link->network->static_addresses && !link->dhcp_lease &&
aba496a5 496 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
ef1ba606 497 return link_enter_set_routes(link);
f882c247 498
39032b87 499 log_debug_link(link, "setting addresses");
449f7554 500
3d3d4255 501 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 502 r = address_configure(ad, link, &address_handler);
dd3efc09 503 if (r < 0) {
3333d748
ZJS
504 log_warning_link(link,
505 "could not set addresses: %s", strerror(-r));
ef1ba606
TG
506 link_enter_failed(link);
507 return r;
dd3efc09 508 }
c166a070 509
b226d99b 510 link_ref(link);
f5be5601
TG
511 link->addr_messages ++;
512 }
513
5c1d3fc9
UTL
514 if (link->ipv4ll && !link->dhcp_lease) {
515 _cleanup_address_free_ Address *ll_addr = NULL;
516 struct in_addr addr;
517
518 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
519 if (r < 0 && r != -ENOENT) {
520 log_warning_link(link, "IPV4LL error: no address: %s",
521 strerror(-r));
522 return r;
523 }
524
525 if (r != -ENOENT) {
526 r = address_new_dynamic(&ll_addr);
527 if (r < 0) {
528 log_error_link(link, "Could not allocate address: %s", strerror(-r));
529 return r;
530 }
531
532 ll_addr->family = AF_INET;
533 ll_addr->in_addr.in = addr;
534 ll_addr->prefixlen = 16;
535 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
536 ll_addr->scope = RT_SCOPE_LINK;
537
538 r = address_configure(ll_addr, link, &address_handler);
539 if (r < 0) {
540 log_warning_link(link,
541 "could not set addresses: %s", strerror(-r));
542 link_enter_failed(link);
543 return r;
544 }
545
b226d99b 546 link_ref(link);
5c1d3fc9
UTL
547 link->addr_messages ++;
548 }
549 }
550
a6cc569e
TG
551 if (link->dhcp_lease) {
552 _cleanup_address_free_ Address *address = NULL;
553 struct in_addr addr;
554 struct in_addr netmask;
555 unsigned prefixlen;
556
557 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
558 if (r < 0) {
559 log_warning_link(link, "DHCP error: no address: %s",
560 strerror(-r));
561 return r;
562 }
563
564 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
565 if (r < 0) {
566 log_warning_link(link, "DHCP error: no netmask: %s",
567 strerror(-r));
568 return r;
569 }
570
571 prefixlen = net_netmask_to_prefixlen(&netmask);
572
573 r = address_new_dynamic(&address);
574 if (r < 0) {
575 log_error_link(link, "Could not allocate address: %s",
576 strerror(-r));
577 return r;
578 }
579
580 address->family = AF_INET;
581 address->in_addr.in = addr;
582 address->prefixlen = prefixlen;
583 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
584
585 r = address_configure(address, link, &address_handler);
f5be5601 586 if (r < 0) {
3333d748
ZJS
587 log_warning_link(link,
588 "could not set addresses: %s", strerror(-r));
f5be5601
TG
589 link_enter_failed(link);
590 return r;
591 }
592
b226d99b 593 link_ref(link);
f5be5601 594 link->addr_messages ++;
f882c247
TG
595 }
596
597 return 0;
598}
599
aba496a5
UTL
600static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
601 Link *link = userdata;
602 int r;
603
604 assert(m);
605 assert(link);
606 assert(link->ifname);
607
370e9930 608 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 609 link_unref(link);
aba496a5 610 return 1;
b226d99b 611 }
aba496a5
UTL
612
613 r = sd_rtnl_message_get_errno(m);
614 if (r < 0 && r != -ENOENT)
615 log_struct_link(LOG_WARNING, link,
987efa17
TG
616 "MESSAGE=%*s: could not update address: %s",
617 IFNAMSIZ,
aba496a5
UTL
618 link->ifname, strerror(-r),
619 "ERRNO=%d", -r,
620 NULL);
621
b226d99b
TG
622 link_unref(link);
623
aba496a5
UTL
624 return 0;
625}
626
ff254138
TG
627static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
628 Link *link = userdata;
629 int r;
630
631 assert(m);
632 assert(link);
633 assert(link->ifname);
634
370e9930 635 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 636 link_unref(link);
ff254138 637 return 1;
b226d99b 638 }
ff254138
TG
639
640 r = sd_rtnl_message_get_errno(m);
b90b025a 641 if (r < 0 && r != -EADDRNOTAVAIL)
c9ccc19f 642 log_struct_link(LOG_WARNING, link,
987efa17
TG
643 "MESSAGE=%*s: could not drop address: %s",
644 IFNAMSIZ,
c9ccc19f
TG
645 link->ifname, strerror(-r),
646 "ERRNO=%d", -r,
647 NULL);
ff254138 648
b226d99b
TG
649 link_unref(link);
650
5c1d3fc9 651 return 0;
ff254138
TG
652}
653
1346b1f0 654static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
b226d99b 655 Link *link = userdata;
1346b1f0
TG
656 int r;
657
b226d99b
TG
658 assert(link);
659
370e9930
TG
660 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
661 link_unref(link);
662 return 1;
663 }
664
1346b1f0
TG
665 r = sd_bus_message_get_errno(m);
666 if (r < 0)
987efa17 667 log_warning_link(link, "Could not set hostname: %s", strerror(-r));
1346b1f0 668
b226d99b
TG
669 link_unref(link);
670
1346b1f0
TG
671 return 1;
672}
673
b226d99b 674static int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
675 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
676 int r = 0;
677
b226d99b
TG
678 assert(link);
679 assert(link->manager);
1346b1f0
TG
680 assert(hostname);
681
b226d99b 682 log_debug_link(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 683
b226d99b
TG
684 if (!link->manager->bus) { /* TODO: replace by assert when we can rely on kdbus */
685 log_info_link(link, "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
686 return 0;
687 }
688
1346b1f0 689 r = sd_bus_message_new_method_call(
b226d99b 690 link->manager->bus,
151b9b96 691 &m,
1346b1f0
TG
692 "org.freedesktop.hostname1",
693 "/org/freedesktop/hostname1",
694 "org.freedesktop.hostname1",
151b9b96 695 "SetHostname");
1346b1f0
TG
696 if (r < 0)
697 return r;
698
699 r = sd_bus_message_append(m, "sb", hostname, false);
700 if (r < 0)
701 return r;
702
19befb2d 703 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0);
1346b1f0 704 if (r < 0)
b226d99b
TG
705 log_error_link(link, "Could not set transient hostname: %s", strerror(-r));
706
707 link_ref(link);
1346b1f0
TG
708
709 return r;
710}
711
4f882b2a
TG
712static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
713 Link *link = userdata;
714 int r;
715
716 assert(m);
717 assert(link);
718 assert(link->ifname);
719
370e9930 720 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 721 link_unref(link);
4f882b2a 722 return 1;
b226d99b 723 }
4f882b2a
TG
724
725 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
726 if (r < 0)
727 log_struct_link(LOG_WARNING, link,
728 "MESSAGE=%s: could not set MTU: %s",
729 link->ifname, strerror(-r),
730 "ERRNO=%d", -r,
731 NULL);
4f882b2a 732
b226d99b
TG
733 link_unref(link);
734
4f882b2a
TG
735 return 1;
736}
737
738static int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 739 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
740 int r;
741
742 assert(link);
743 assert(link->manager);
744 assert(link->manager->rtnl);
745
746 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
747
151b9b96
LP
748 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
749 RTM_SETLINK, link->ifindex);
4f882b2a
TG
750 if (r < 0) {
751 log_error_link(link, "Could not allocate RTM_SETLINK message");
752 return r;
753 }
754
755 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
756 if (r < 0) {
757 log_error_link(link, "Could not append MTU: %s", strerror(-r));
758 return r;
759 }
760
761 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
762 if (r < 0) {
763 log_error_link(link,
764 "Could not send rtnetlink message: %s", strerror(-r));
765 return r;
766 }
767
b226d99b
TG
768 link_unref(link);
769
4f882b2a
TG
770 return 0;
771}
772
a6cc569e
TG
773static int dhcp_lease_lost(Link *link) {
774 _cleanup_address_free_ Address *address = NULL;
3e790eae
UTL
775 _cleanup_route_free_ Route *route_gw = NULL;
776 _cleanup_route_free_ Route *route = NULL;
a6cc569e
TG
777 struct in_addr addr;
778 struct in_addr netmask;
3e790eae 779 struct in_addr gateway;
a6cc569e 780 unsigned prefixlen;
ff254138
TG
781 int r;
782
783 assert(link);
a6cc569e 784 assert(link->dhcp_lease);
ff254138 785
14efd761
TG
786 log_warning_link(link, "DHCP lease lost");
787
a6cc569e
TG
788 r = address_new_dynamic(&address);
789 if (r >= 0) {
8ddbeaa2 790 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
3e790eae 791 if (r >= 0) {
8ddbeaa2
UTL
792 r = route_new_dynamic(&route_gw);
793 if (r >= 0) {
794 route_gw->family = AF_INET;
795 route_gw->dst_addr.in = gateway;
796 route_gw->dst_prefixlen = 32;
797 route_gw->scope = RT_SCOPE_LINK;
798
799 route_drop(route_gw, link, &route_drop_handler);
b226d99b 800 link_ref(link);
8ddbeaa2 801 }
3e790eae 802
8ddbeaa2
UTL
803 r = route_new_dynamic(&route);
804 if (r >= 0) {
805 route->family = AF_INET;
806 route->in_addr.in = gateway;
3e790eae 807
8ddbeaa2 808 route_drop(route, link, &route_drop_handler);
b226d99b 809 link_ref(link);
8ddbeaa2 810 }
3e790eae
UTL
811 }
812
8ddbeaa2
UTL
813 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
814 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
815 prefixlen = net_netmask_to_prefixlen(&netmask);
816
a6cc569e
TG
817 address->family = AF_INET;
818 address->in_addr.in = addr;
819 address->prefixlen = prefixlen;
ff254138 820
5c1d3fc9 821 address_drop(address, link, &address_drop_handler);
b226d99b 822 link_ref(link);
c07aeadf 823 }
eb27aeca 824
c07aeadf
TG
825 if (link->network->dhcp_mtu) {
826 uint16_t mtu;
ff254138 827
a6cc569e 828 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
c07aeadf
TG
829 if (r >= 0 && link->original_mtu != mtu) {
830 r = link_set_mtu(link, link->original_mtu);
831 if (r < 0) {
832 log_warning_link(link, "DHCP error: could not reset MTU");
833 link_enter_failed(link);
834 return r;
835 }
ff254138 836 }
c07aeadf 837 }
ff254138 838
c07aeadf 839 if (link->network->dhcp_hostname) {
216816c6
TG
840 const char *hostname = NULL;
841
842 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
843 if (r >= 0 && hostname) {
b226d99b 844 r = link_set_hostname(link, "");
216816c6 845 if (r < 0)
987efa17 846 log_error_link(link, "Failed to reset transient hostname");
216816c6 847 }
c07aeadf 848 }
4f882b2a 849
a6cc569e
TG
850 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
851
c07aeadf
TG
852 return 0;
853}
4f882b2a 854
c07aeadf 855static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
a6cc569e 856 sd_dhcp_lease *lease;
c07aeadf
TG
857 struct in_addr address;
858 struct in_addr netmask;
859 struct in_addr gateway;
860 unsigned prefixlen;
c07aeadf 861 int r;
1346b1f0 862
c07aeadf
TG
863 assert(client);
864 assert(link);
ff254138 865
a6cc569e
TG
866 r = sd_dhcp_client_get_lease(client, &lease);
867 if (r < 0) {
868 log_warning_link(link, "DHCP error: no lease: %s",
869 strerror(-r));
870 return r;
871 }
872
873 r = sd_dhcp_lease_get_address(lease, &address);
ff254138 874 if (r < 0) {
c07aeadf
TG
875 log_warning_link(link, "DHCP error: no address: %s",
876 strerror(-r));
877 return r;
ff254138
TG
878 }
879
a6cc569e 880 r = sd_dhcp_lease_get_netmask(lease, &netmask);
ff254138 881 if (r < 0) {
c07aeadf
TG
882 log_warning_link(link, "DHCP error: no netmask: %s",
883 strerror(-r));
884 return r;
ff254138
TG
885 }
886
377a218f 887 prefixlen = net_netmask_to_prefixlen(&netmask);
ff254138 888
a6cc569e 889 r = sd_dhcp_lease_get_router(lease, &gateway);
8ddbeaa2
UTL
890 if (r < 0 && r != -ENOENT) {
891 log_warning_link(link, "DHCP error: %s", strerror(-r));
c07aeadf 892 return r;
ff254138
TG
893 }
894
8ddbeaa2
UTL
895 if (r >= 0)
896 log_struct_link(LOG_INFO, link,
987efa17
TG
897 "MESSAGE=%*s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
898 IFNAMSIZ,
8ddbeaa2
UTL
899 link->ifname,
900 ADDRESS_FMT_VAL(address),
901 prefixlen,
902 ADDRESS_FMT_VAL(gateway),
903 "ADDRESS=%u.%u.%u.%u",
904 ADDRESS_FMT_VAL(address),
905 "PREFIXLEN=%u",
906 prefixlen,
907 "GATEWAY=%u.%u.%u.%u",
908 ADDRESS_FMT_VAL(gateway),
909 NULL);
910 else
911 log_struct_link(LOG_INFO, link,
987efa17
TG
912 "MESSAGE=%*s: DHCPv4 address %u.%u.%u.%u/%u",
913 IFNAMSIZ,
8ddbeaa2
UTL
914 link->ifname,
915 ADDRESS_FMT_VAL(address),
916 prefixlen,
917 "ADDRESS=%u.%u.%u.%u",
918 ADDRESS_FMT_VAL(address),
919 "PREFIXLEN=%u",
920 prefixlen,
921 NULL);
c07aeadf 922
d50cf59b
TG
923 link->dhcp_lease = lease;
924
c07aeadf
TG
925 if (link->network->dhcp_mtu) {
926 uint16_t mtu;
927
a6cc569e 928 r = sd_dhcp_lease_get_mtu(lease, &mtu);
c07aeadf
TG
929 if (r >= 0) {
930 r = link_set_mtu(link, mtu);
931 if (r < 0)
932 log_error_link(link, "Failed to set MTU "
933 "to %" PRIu16, mtu);
934 }
935 }
ff254138 936
c07aeadf
TG
937 if (link->network->dhcp_hostname) {
938 const char *hostname;
ff254138 939
a6cc569e 940 r = sd_dhcp_lease_get_hostname(lease, &hostname);
c07aeadf 941 if (r >= 0) {
b226d99b 942 r = link_set_hostname(link, hostname);
c07aeadf 943 if (r < 0)
987efa17 944 log_error_link(link, "Failed to set transient hostname "
c07aeadf 945 "to '%s'", hostname);
3bef724f 946 }
c07aeadf 947 }
3bef724f 948
c07aeadf
TG
949 link_enter_set_addresses(link);
950
951 return 0;
952}
953
954static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
955 Link *link = userdata;
aba496a5 956 int r = 0;
c07aeadf
TG
957
958 assert(link);
959 assert(link->network);
960 assert(link->manager);
961
370e9930 962 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
c07aeadf
TG
963 return;
964
965 switch (event) {
966 case DHCP_EVENT_NO_LEASE:
967 log_debug_link(link, "IP address in use.");
968 break;
969 case DHCP_EVENT_EXPIRED:
970 case DHCP_EVENT_STOP:
971 case DHCP_EVENT_IP_CHANGE:
972 if (link->network->dhcp_critical) {
973 log_error_link(link, "DHCPv4 connection considered system critical, "
974 "ignoring request to reconfigure it.");
975 return;
4f882b2a 976 }
4f882b2a 977
17256461
UTL
978 if (link->dhcp_lease) {
979 r = dhcp_lease_lost(link);
980 if (r < 0) {
981 link_enter_failed(link);
982 return;
983 }
c07aeadf 984 }
1346b1f0 985
c07aeadf
TG
986 if (event == DHCP_EVENT_IP_CHANGE) {
987 r = dhcp_lease_acquired(client, link);
988 if (r < 0) {
989 link_enter_failed(link);
990 return;
991 }
1346b1f0 992 }
1346b1f0 993
5c1d3fc9 994 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
aba496a5
UTL
995 if (!sd_ipv4ll_is_running(link->ipv4ll))
996 r = sd_ipv4ll_start(link->ipv4ll);
997 else if (ipv4ll_is_bound(link->ipv4ll))
998 r = ipv4ll_address_update(link, false);
5c1d3fc9
UTL
999 if (r < 0) {
1000 link_enter_failed(link);
1001 return;
1002 }
1003 }
1004
c07aeadf
TG
1005 break;
1006 case DHCP_EVENT_IP_ACQUIRE:
1007 r = dhcp_lease_acquired(client, link);
1008 if (r < 0) {
1009 link_enter_failed(link);
1010 return;
1011 }
5c1d3fc9 1012 if (link->ipv4ll) {
aba496a5
UTL
1013 if (ipv4ll_is_bound(link->ipv4ll))
1014 r = ipv4ll_address_update(link, true);
1015 else
1016 r = sd_ipv4ll_stop(link->ipv4ll);
5c1d3fc9
UTL
1017 if (r < 0) {
1018 link_enter_failed(link);
1019 return;
1020 }
1021 }
c07aeadf
TG
1022 break;
1023 default:
1024 if (event < 0)
1025 log_warning_link(link, "DHCP error: %s", strerror(-event));
1026 else
1027 log_warning_link(link, "DHCP unknown event: %d", event);
c07aeadf 1028 break;
ff254138
TG
1029 }
1030
1031 return;
1032}
1033
aba496a5
UTL
1034static int ipv4ll_address_update(Link *link, bool deprecate) {
1035 int r;
1036 struct in_addr addr;
1037
1038 assert(link);
1039
1040 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
1041 if (r >= 0) {
1042 _cleanup_address_free_ Address *address = NULL;
1043
1044 log_debug_link(link, "IPv4 link-local %s %u.%u.%u.%u",
1045 deprecate ? "deprecate" : "approve",
1046 ADDRESS_FMT_VAL(addr));
1047
1048 r = address_new_dynamic(&address);
1049 if (r < 0) {
1050 log_error_link(link, "Could not allocate address: %s", strerror(-r));
1051 return r;
1052 }
1053
1054 address->family = AF_INET;
1055 address->in_addr.in = addr;
1056 address->prefixlen = 16;
1057 address->scope = RT_SCOPE_LINK;
1058 address->cinfo.ifa_prefered = deprecate ? 0 : CACHE_INFO_INFINITY_LIFE_TIME;
1059 address->broadcast.s_addr = address->in_addr.in.s_addr | htonl(0xfffffffflu >> address->prefixlen);
1060
1061 address_update(address, link, &address_update_handler);
b226d99b 1062 link_ref(link);
aba496a5
UTL
1063 }
1064
1065 return 0;
1066
1067}
1068
1069static int ipv4ll_address_lost(Link *link) {
5c1d3fc9
UTL
1070 int r;
1071 struct in_addr addr;
1072
5c1d3fc9
UTL
1073 assert(link);
1074
1075 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
1076 if (r >= 0) {
1077 _cleanup_address_free_ Address *address = NULL;
1078 _cleanup_route_free_ Route *route = NULL;
1079
1080 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
1081 ADDRESS_FMT_VAL(addr));
1082
1083 r = address_new_dynamic(&address);
1084 if (r < 0) {
1085 log_error_link(link, "Could not allocate address: %s", strerror(-r));
1086 return r;
1087 }
1088
1089 address->family = AF_INET;
1090 address->in_addr.in = addr;
1091 address->prefixlen = 16;
1092 address->scope = RT_SCOPE_LINK;
1093
1094 address_drop(address, link, &address_drop_handler);
b226d99b 1095 link_ref(link);
5c1d3fc9
UTL
1096
1097 r = route_new_dynamic(&route);
1098 if (r < 0) {
1099 log_error_link(link, "Could not allocate route: %s",
1100 strerror(-r));
1101 return r;
1102 }
1103
1104 route->family = AF_INET;
1105 route->scope = RT_SCOPE_LINK;
1106 route->metrics = 99;
1107
1108 route_drop(route, link, &route_drop_handler);
b226d99b 1109 link_ref(link);
5c1d3fc9
UTL
1110 }
1111
1112 return 0;
1113}
1114
aba496a5
UTL
1115static bool ipv4ll_is_bound(sd_ipv4ll *ll) {
1116 int r;
1117 struct in_addr addr;
1118
1119 assert(ll);
1120
1121 r = sd_ipv4ll_get_address(ll, &addr);
1122 if (r < 0)
1123 return false;
1124 return true;
1125}
1126
5c1d3fc9
UTL
1127static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
1128 struct in_addr address;
1129 int r;
1130
1131 assert(ll);
1132 assert(link);
1133
1134 r = sd_ipv4ll_get_address(ll, &address);
1135 if (r < 0)
1136 return r;
1137
1138 log_struct_link(LOG_INFO, link,
987efa17
TG
1139 "MESSAGE=%*s: IPv4 link-local address %u.%u.%u.%u",
1140 IFNAMSIZ,
5c1d3fc9
UTL
1141 link->ifname,
1142 ADDRESS_FMT_VAL(address),
1143 NULL);
1144
1145 link_enter_set_addresses(link);
1146
1147 return 0;
1148}
1149
1150static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
1151 Link *link = userdata;
1152 int r;
1153
1154 assert(link);
1155 assert(link->network);
1156 assert(link->manager);
1157
370e9930
TG
1158 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1159 return;
1160
5c1d3fc9
UTL
1161 switch(event) {
1162 case IPV4LL_EVENT_STOP:
1163 case IPV4LL_EVENT_CONFLICT:
aba496a5 1164 r = ipv4ll_address_lost(link);
5c1d3fc9
UTL
1165 if (r < 0) {
1166 link_enter_failed(link);
1167 return;
1168 }
1169 break;
1170 case IPV4LL_EVENT_BIND:
1171 r = ipv4ll_address_claimed(ll, link);
1172 if (r < 0) {
1173 link_enter_failed(link);
1174 return;
1175 }
1176 break;
1177 default:
1178 if (event < 0)
1179 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
1180 else
1181 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
1182 break;
1183 }
1184}
1185
ff254138
TG
1186static int link_acquire_conf(Link *link) {
1187 int r;
1188
1189 assert(link);
1190 assert(link->network);
ff254138
TG
1191 assert(link->manager);
1192 assert(link->manager->event);
1193
5c1d3fc9 1194 if (link->network->ipv4ll) {
eb34d4af 1195 assert(link->ipv4ll);
ff254138 1196
5c1d3fc9
UTL
1197 log_debug_link(link, "acquiring IPv4 link-local address");
1198
1199 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6
TG
1200 if (r < 0) {
1201 log_warning_link(link, "could not acquire IPv4 "
1202 "link-local address");
ff254138 1203 return r;
124fa2c6 1204 }
5c1d3fc9
UTL
1205 }
1206
1207 if (link->network->dhcp) {
eb34d4af 1208 assert(link->dhcp_client);
ff254138 1209
5c1d3fc9 1210 log_debug_link(link, "acquiring DHCPv4 lease");
ab47d620 1211
5c1d3fc9 1212 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6
TG
1213 if (r < 0) {
1214 log_warning_link(link, "could not acquire DHCPv4 "
1215 "lease");
5c1d3fc9 1216 return r;
124fa2c6 1217 }
5c1d3fc9 1218 }
ff254138
TG
1219
1220 return 0;
1221}
1222
bbf7c048 1223bool link_has_carrier(unsigned flags, uint8_t operstate) {
deb2e523
TG
1224 /* see Documentation/networking/operstates.txt in the kernel sources */
1225
1226 if (operstate == IF_OPER_UP)
1227 return true;
1228
1229 if (operstate == IF_OPER_UNKNOWN)
1230 /* operstate may not be implemented, so fall back to flags */
1231 if ((flags & IFF_LOWER_UP) && !(flags & IFF_DORMANT))
1232 return true;
1233
1234 return false;
1235}
1236
389cc5f7
TG
1237#define FLAG_STRING(string, flag, old, new) \
1238 (((old ^ new) & flag) \
1239 ? ((old & flag) ? (" -" string) : (" +" string)) \
1240 : "")
1241
1e9be60b 1242static int link_update_flags(Link *link, sd_rtnl_message *m) {
389cc5f7 1243 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
1e9be60b
TG
1244 uint8_t operstate;
1245 bool carrier_gained = false, carrier_lost = false;
ff254138
TG
1246 int r;
1247
1248 assert(link);
ff254138 1249
1e9be60b
TG
1250 r = sd_rtnl_message_link_get_flags(m, &flags);
1251 if (r < 0) {
1252 log_warning_link(link, "Could not get link flags");
1253 return r;
1254 }
1255
1256 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
1257 if (r < 0)
1258 /* if we got a message without operstate, take it to mean
1259 the state was unchanged */
e375dcde 1260 operstate = link->kernel_operstate;
1e9be60b 1261
e375dcde 1262 if ((link->flags == flags) && (link->kernel_operstate == operstate))
efbc88b8 1263 return 0;
efbc88b8 1264
389cc5f7
TG
1265 if (link->flags != flags) {
1266 log_debug_link(link, "flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1267 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
1268 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
1269 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
1270 FLAG_STRING("UP", IFF_UP, link->flags, flags),
1271 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
1272 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
1273 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
1274 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
1275 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
1276 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
1277 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
1278 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
1279 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
1280 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
1281 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
1282 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
1283 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
1284 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
1285 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
1286
1287 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
1288 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
1289 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
1290 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
1291 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
1292 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
1293 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
1294 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
1295
1296 /* link flags are currently at most 18 bits, let's align to printing 20 */
1297 if (unknown_flags_added)
1298 log_debug_link(link, "unknown link flags gained: %#.5x (ignoring)",
1299 unknown_flags_added);
1300
1301 if (unknown_flags_removed)
1302 log_debug_link(link, "unknown link flags lost: %#.5x (ignoring)",
1303 unknown_flags_removed);
1304 }
505f8da7 1305
e375dcde 1306 carrier_gained = !link_has_carrier(link->flags, link->kernel_operstate) &&
1e9be60b 1307 link_has_carrier(flags, operstate);
e375dcde 1308 carrier_lost = link_has_carrier(link->flags, link->kernel_operstate) &&
1e9be60b
TG
1309 !link_has_carrier(flags, operstate);
1310
1311 link->flags = flags;
e375dcde 1312 link->kernel_operstate = operstate;
1e9be60b 1313
deb2e523
TG
1314 link_save(link);
1315
99b4cc3e
TG
1316 if (link->state == LINK_STATE_FAILED ||
1317 link->state == LINK_STATE_UNMANAGED)
1318 return 0;
1319
7cc832b9
TG
1320 if (carrier_gained) {
1321 log_info_link(link, "gained carrier");
ffba6166 1322
1e9be60b 1323 if (link->network) {
ffba6166
TG
1324 r = link_acquire_conf(link);
1325 if (r < 0) {
ffba6166
TG
1326 link_enter_failed(link);
1327 return r;
ff254138 1328 }
ffba6166 1329 }
7cc832b9
TG
1330 } else if (carrier_lost) {
1331 log_info_link(link, "lost carrier");
efbc88b8 1332
1e9be60b
TG
1333 r = link_stop_clients(link);
1334 if (r < 0) {
1335 link_enter_failed(link);
1336 return r;
ff254138
TG
1337 }
1338 }
1339
ff254138
TG
1340 return 0;
1341}
1342
dd3efc09
TG
1343static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1344 Link *link = userdata;
1345 int r;
1346
1746cf2a
TG
1347 assert(link);
1348
370e9930 1349 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 1350 link_unref(link);
1746cf2a 1351 return 1;
b226d99b 1352 }
1746cf2a 1353
dd3efc09 1354 r = sd_rtnl_message_get_errno(m);
45ad2c13 1355 if (r < 0) {
9b86b393
TG
1356 /* we warn but don't fail the link, as it may
1357 be brought up later */
76800848 1358 log_struct_link(LOG_WARNING, link,
987efa17
TG
1359 "MESSAGE=%*s: could not bring up interface: %s",
1360 IFNAMSIZ,
c9ccc19f
TG
1361 link->ifname, strerror(-r),
1362 "ERRNO=%d", -r,
1363 NULL);
45ad2c13
TG
1364 }
1365
b226d99b
TG
1366 link_unref(link);
1367
f882c247
TG
1368 return 1;
1369}
1370
1371static int link_up(Link *link) {
cf6a8911 1372 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1373 int r;
1374
f882c247
TG
1375 assert(link);
1376 assert(link->manager);
1377 assert(link->manager->rtnl);
1378
39032b87 1379 log_debug_link(link, "bringing link up");
449f7554 1380
151b9b96
LP
1381 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1382 RTM_SETLINK, link->ifindex);
f579559b 1383 if (r < 0) {
39032b87 1384 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1385 return r;
1386 }
1387
5d4795f3 1388 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1389 if (r < 0) {
3333d748 1390 log_error_link(link, "Could not set link flags: %s", strerror(-r));
fc25d7f8
TG
1391 return r;
1392 }
1393
dd3efc09 1394 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
f579559b 1395 if (r < 0) {
3333d748
ZJS
1396 log_error_link(link,
1397 "Could not send rtnetlink message: %s", strerror(-r));
f579559b
TG
1398 return r;
1399 }
1400
b226d99b
TG
1401 link_ref(link);
1402
f882c247
TG
1403 return 0;
1404}
1405
52433f6b 1406static int link_enslaved(Link *link) {
f882c247
TG
1407 int r;
1408
ef1ba606 1409 assert(link);
52433f6b 1410 assert(link->state == LINK_STATE_ENSLAVING);
f5be5601 1411 assert(link->network);
dd3efc09 1412
505f8da7
TG
1413 if (!(link->flags & IFF_UP)) {
1414 r = link_up(link);
1415 if (r < 0) {
1416 link_enter_failed(link);
1417 return r;
1418 }
ef1ba606 1419 }
f882c247 1420
5c1d3fc9 1421 if (!link->network->dhcp && !link->network->ipv4ll)
1746cf2a 1422 return link_enter_set_addresses(link);
ef1ba606
TG
1423
1424 return 0;
02b59d57
TG
1425}
1426
52433f6b 1427static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
02b59d57
TG
1428 Link *link = userdata;
1429 int r;
1430
1746cf2a 1431 assert(link);
370e9930
TG
1432 assert(IN_SET(link->state, LINK_STATE_ENSLAVING, LINK_STATE_FAILED,
1433 LINK_STATE_LINGER));
ef1ba606 1434 assert(link->network);
02b59d57 1435
52433f6b
TG
1436 link->enslaving --;
1437
370e9930 1438 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 1439 link_unref(link);
02b59d57 1440 return 1;
b226d99b 1441 }
02b59d57
TG
1442
1443 r = sd_rtnl_message_get_errno(m);
ef1ba606 1444 if (r < 0) {
c9ccc19f 1445 log_struct_link(LOG_ERR, link,
987efa17
TG
1446 "MESSAGE=%*s: could not enslave: %s",
1447 IFNAMSIZ,
c9ccc19f
TG
1448 link->ifname, strerror(-r),
1449 "ERRNO=%d", -r,
1450 NULL);
ef1ba606 1451 link_enter_failed(link);
b226d99b 1452 link_unref(link);
ef1ba606 1453 return 1;
3333d748 1454 }
02b59d57 1455
52433f6b 1456 log_debug_link(link, "enslaved");
ab47d620 1457
52433f6b
TG
1458 if (link->enslaving == 0)
1459 link_enslaved(link);
02b59d57 1460
b226d99b
TG
1461 link_unref(link);
1462
02b59d57
TG
1463 return 1;
1464}
1465
52433f6b 1466static int link_enter_enslave(Link *link) {
fe6b2d55 1467 NetDev *vlan, *macvlan;
672682a6 1468 Iterator i;
02b59d57
TG
1469 int r;
1470
1471 assert(link);
1472 assert(link->network);
505f8da7 1473 assert(link->state == LINK_STATE_INITIALIZING);
02b59d57 1474
52433f6b 1475 link->state = LINK_STATE_ENSLAVING;
02b59d57 1476
fe8db0c5
TG
1477 link_save(link);
1478
7951dea2
SS
1479 if (!link->network->bridge &&
1480 !link->network->bond &&
1481 !link->network->tunnel &&
fe6b2d55
TG
1482 hashmap_isempty(link->network->vlans) &&
1483 hashmap_isempty(link->network->macvlans))
52433f6b 1484 return link_enslaved(link);
02b59d57 1485
d9c67ea1 1486 if (link->network->bond) {
52433f6b 1487 log_struct_link(LOG_DEBUG, link,
987efa17
TG
1488 "MESSAGE=%*s: enslaving by '%s'",
1489 IFNAMSIZ,
af4e9e2c 1490 link->ifname, link->network->bond->ifname,
d9c67ea1 1491 NETDEV(link->network->bond),
52433f6b 1492 NULL);
449f7554 1493
d9c67ea1 1494 r = netdev_enslave(link->network->bond, link, &enslave_handler);
52433f6b
TG
1495 if (r < 0) {
1496 log_struct_link(LOG_WARNING, link,
987efa17
TG
1497 "MESSAGE=%*s: could not enslave by '%s': %s",
1498 IFNAMSIZ,
af4e9e2c 1499 link->ifname, link->network->bond->ifname, strerror(-r),
d9c67ea1 1500 NETDEV(link->network->bond),
52433f6b
TG
1501 NULL);
1502 link_enter_failed(link);
1503 return r;
1504 }
1505
b226d99b 1506 link_ref(link);
0ad6148e
MO
1507 link->enslaving ++;
1508 }
1509
d9c67ea1 1510 if (link->network->bridge) {
0ad6148e 1511 log_struct_link(LOG_DEBUG, link,
987efa17
TG
1512 "MESSAGE=%*s: enslaving by '%s'",
1513 IFNAMSIZ,
af4e9e2c 1514 link->ifname, link->network->bridge->ifname,
d9c67ea1 1515 NETDEV(link->network->bridge),
0ad6148e
MO
1516 NULL);
1517
d9c67ea1 1518 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
0ad6148e
MO
1519 if (r < 0) {
1520 log_struct_link(LOG_WARNING, link,
987efa17
TG
1521 "MESSAGE=%*s: could not enslave by '%s': %s",
1522 IFNAMSIZ,
af4e9e2c 1523 link->ifname, link->network->bridge->ifname, strerror(-r),
d9c67ea1 1524 NETDEV(link->network->bridge),
0ad6148e
MO
1525 NULL);
1526 link_enter_failed(link);
1527 return r;
1528 }
1529
b226d99b 1530 link_ref(link);
52433f6b
TG
1531 link->enslaving ++;
1532 }
1533
7951dea2
SS
1534 if (link->network->tunnel) {
1535 log_struct_link(LOG_DEBUG, link,
987efa17
TG
1536 "MESSAGE=%*s: enslaving by '%s'",
1537 IFNAMSIZ,
af4e9e2c 1538 link->ifname, link->network->tunnel->ifname,
7951dea2
SS
1539 NETDEV(link->network->tunnel),
1540 NULL);
1541
1542 r = netdev_enslave(link->network->tunnel, link, &enslave_handler);
1543 if (r < 0) {
1544 log_struct_link(LOG_WARNING, link,
987efa17
TG
1545 "MESSAGE=%*s: could not enslave by '%s': %s",
1546 IFNAMSIZ,
af4e9e2c 1547 link->ifname, link->network->tunnel->ifname, strerror(-r),
7951dea2
SS
1548 NETDEV(link->network->tunnel),
1549 NULL);
1550 link_enter_failed(link);
1551 return r;
1552 }
1553
1554 link_ref(link);
1555 link->enslaving ++;
1556 }
1557
672682a6 1558 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
52433f6b 1559 log_struct_link(LOG_DEBUG, link,
987efa17
TG
1560 "MESSAGE=%*s: enslaving by '%s'",
1561 IFNAMSIZ,
af4e9e2c 1562 link->ifname, vlan->ifname, NETDEV(vlan), NULL);
52433f6b 1563
672682a6 1564 r = netdev_enslave(vlan, link, &enslave_handler);
52433f6b
TG
1565 if (r < 0) {
1566 log_struct_link(LOG_WARNING, link,
987efa17
TG
1567 "MESSAGE=%*s: could not enslave by '%s': %s",
1568 IFNAMSIZ,
af4e9e2c 1569 link->ifname, vlan->ifname, strerror(-r),
672682a6 1570 NETDEV(vlan), NULL);
52433f6b
TG
1571 link_enter_failed(link);
1572 return r;
1573 }
1574
b226d99b 1575 link_ref(link);
52433f6b 1576 link->enslaving ++;
ef1ba606
TG
1577 }
1578
fe6b2d55
TG
1579 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1580 log_struct_link(LOG_DEBUG, link,
987efa17
TG
1581 "MESSAGE=%*s: enslaving by '%s'",
1582 IFNAMSIZ,
af4e9e2c 1583 link->ifname, macvlan->ifname, NETDEV(macvlan), NULL);
fe6b2d55
TG
1584
1585 r = netdev_enslave(macvlan, link, &enslave_handler);
1586 if (r < 0) {
1587 log_struct_link(LOG_WARNING, link,
987efa17
TG
1588 "MESSAGE=%*s: could not enslave by '%s': %s",
1589 IFNAMSIZ,
af4e9e2c 1590 link->ifname, macvlan->ifname, strerror(-r),
fe6b2d55
TG
1591 NETDEV(macvlan), NULL);
1592 link_enter_failed(link);
1593 return r;
1594 }
1595
b226d99b 1596 link_ref(link);
fe6b2d55
TG
1597 link->enslaving ++;
1598 }
1599
ef1ba606
TG
1600 return 0;
1601}
1602
a748b692 1603static int link_configure(Link *link) {
02b59d57
TG
1604 int r;
1605
ef1ba606 1606 assert(link);
505f8da7 1607 assert(link->state == LINK_STATE_INITIALIZING);
a748b692 1608
eb34d4af 1609 if (link->network->ipv4ll) {
b5db00e5 1610 uint8_t seed[8];
45ad2c13 1611
eb34d4af
TG
1612 r = sd_ipv4ll_new(&link->ipv4ll);
1613 if (r < 0)
1614 return r;
1615
505f8da7
TG
1616 if (link->udev_device) {
1617 r = net_get_unique_predictable_data(link->udev_device, seed);
1618 if (r >= 0) {
1619 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1620 if (r < 0)
1621 return r;
1622 }
b5db00e5
UTL
1623 }
1624
eb34d4af
TG
1625 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1626 if (r < 0)
1627 return r;
1628
4bb40e81
TG
1629 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1630 if (r < 0)
1631 return r;
1632
eb34d4af
TG
1633 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1634 if (r < 0)
1635 return r;
1636
1637 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1638 if (r < 0)
1639 return r;
1640 }
1641
1642 if (link->network->dhcp) {
1643 r = sd_dhcp_client_new(&link->dhcp_client);
1644 if (r < 0)
1645 return r;
1646
1647 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1648 if (r < 0)
1649 return r;
1650
4bb40e81
TG
1651 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1652 if (r < 0)
1653 return r;
1654
eb34d4af
TG
1655 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1656 if (r < 0)
1657 return r;
1658
1659 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1660 if (r < 0)
1661 return r;
1662
1663 if (link->network->dhcp_mtu) {
1664 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1665 if (r < 0)
1666 return r;
1667 }
1668 }
1669
e375dcde 1670 if (link_has_carrier(link->flags, link->kernel_operstate)) {
1e9be60b
TG
1671 r = link_acquire_conf(link);
1672 if (r < 0)
1673 return r;
cc544d5f 1674 }
1e9be60b 1675
505f8da7
TG
1676 return link_enter_enslave(link);
1677}
1678
1679int link_initialized(Link *link, struct udev_device *device) {
1680 Network *network;
505f8da7
TG
1681 int r;
1682
1683 assert(link);
1684 assert(link->ifname);
1685 assert(link->manager);
1686
1687 if (link->state != LINK_STATE_INITIALIZING)
1688 return 0;
1689
1690 if (device)
1691 link->udev_device = udev_device_ref(device);
1692
16cd414b 1693 log_debug_link(link, "udev initialized link");
505f8da7
TG
1694
1695 r = network_get(link->manager, device, link->ifname, &link->mac, &network);
57bd6899
TG
1696 if (r == -ENOENT) {
1697 link_enter_unmanaged(link);
1698 return 0;
1699 } else if (r < 0)
1700 return r;
505f8da7
TG
1701
1702 r = network_apply(link->manager, network, link);
1703 if (r < 0)
1704 return r;
1705
a748b692
TG
1706 r = link_configure(link);
1707 if (r < 0)
1708 return r;
1709
505f8da7
TG
1710 return 0;
1711}
1712
fbbeb65a
TG
1713int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
1714 Manager *m = userdata;
1715 Link *link = NULL;
1716 uint16_t type;
1717 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1718 Address *ad;
fbbeb65a 1719 char buf[INET6_ADDRSTRLEN];
428fd0a7 1720 bool address_dropped = false;
fbbeb65a
TG
1721 int r, ifindex;
1722
1723 assert(rtnl);
1724 assert(message);
1725 assert(m);
1726
1727 r = sd_rtnl_message_get_type(message, &type);
1728 if (r < 0) {
1729 log_warning("rtnl: could not get message type");
1730 return 0;
1731 }
1732
1733 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1734 if (r < 0 || ifindex <= 0) {
5ea846cc 1735 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1736 return 0;
1737 } else {
1738 r = link_get(m, ifindex, &link);
1739 if (r < 0 || !link) {
5ea846cc 1740 log_warning("rtnl: received address for a nonexistent link, ignoring");
fbbeb65a
TG
1741 return 0;
1742 }
1743 }
1744
1745 r = address_new_dynamic(&address);
1746 if (r < 0)
1747 return 0;
1748
1749 r = sd_rtnl_message_addr_get_family(message, &address->family);
1750 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
987efa17 1751 log_warning_link(link, "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1752 return 0;
1753 }
1754
1755 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1756 if (r < 0) {
e375dcde
TG
1757 log_warning_link(link, "rtnl: received address with invalid prefixlen, ignoring");
1758 return 0;
1759 }
1760
1761 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1762 if (r < 0) {
1763 log_warning_link(link, "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1764 return 0;
1765 }
1766
1767 switch (address->family) {
1768 case AF_INET:
1769 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
1770 if (r < 0) {
987efa17 1771 log_warning_link(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1772 return 0;
1773 }
1774
1775 break;
1776
1777 case AF_INET6:
1778 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
1779 if (r < 0) {
987efa17 1780 log_warning_link(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1781 return 0;
1782 }
1783
1784 break;
1785
1786 default:
1787 assert_not_reached("invalid address family");
1788 }
1789
1790 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
987efa17 1791 log_warning_link(link, "could not print address");
fbbeb65a
TG
1792 return 0;
1793 }
1794
428fd0a7
TG
1795 LIST_FOREACH(addresses, ad, link->addresses) {
1796 if (address_equal(ad, address)) {
1797 LIST_REMOVE(addresses, link->addresses, ad);
1798
1799 address_free(ad);
1800
1801 address_dropped = true;
1802
1803 break;
1804 }
1805 }
1806
fbbeb65a
TG
1807 switch (type) {
1808 case RTM_NEWADDR:
428fd0a7
TG
1809 if (!address_dropped)
1810 log_debug_link(link, "added address: %s/%u", buf,
1811 address->prefixlen);
fbbeb65a 1812
428fd0a7
TG
1813 LIST_PREPEND(addresses, link->addresses, address);
1814 address = NULL;
1815
f5602be9
TG
1816 link_save(link);
1817
428fd0a7 1818 break;
fbbeb65a 1819 case RTM_DELADDR:
f5602be9 1820 if (address_dropped) {
428fd0a7
TG
1821 log_debug_link(link, "removed address: %s/%u", buf,
1822 address->prefixlen);
1823
f5602be9
TG
1824 link_save(link);
1825 }
1826
fbbeb65a
TG
1827 break;
1828 default:
1829 assert_not_reached("Received invalid RTNL message type");
1830 }
1831
1832 return 1;
1833}
1834
1835static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1836 Link *link = userdata;
1837 int r;
1838
1839 assert(rtnl);
1840 assert(m);
1841 assert(link);
1842
1843 for (; m; m = sd_rtnl_message_next(m)) {
1844 r = sd_rtnl_message_get_errno(m);
1845 if (r < 0) {
1846 log_debug_link(link, "getting address failed: %s", strerror(-r));
1847 continue;
1848 }
1849
1850 r = link_rtnl_process_address(rtnl, m, link->manager);
1851 if (r < 0)
1852 log_warning_link(link, "could not process address: %s", strerror(-r));
1853 }
1854
1855 return 1;
1856}
1857
505f8da7
TG
1858int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1859 Link *link;
fbbeb65a 1860 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1861 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1862 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1863 int r;
1864
1865 assert(m);
fbbeb65a 1866 assert(m->rtnl);
505f8da7
TG
1867 assert(message);
1868 assert(ret);
1869
1870 r = link_new(m, message, ret);
1871 if (r < 0)
1872 return r;
1873
1874 link = *ret;
1875
5261692f 1876 log_debug_link(link, "link %"PRIu64" added", link->ifindex);
505f8da7 1877
fbbeb65a
TG
1878 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex, 0);
1879 if (r < 0)
1880 return r;
1881
1882 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0, NULL);
1883 if (r < 0)
1884 return r;
1885
505f8da7
TG
1886 if (detect_container(NULL) <= 0) {
1887 /* not in a container, udev will be around */
1888 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
1889 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1890 if (!device) {
1891 log_warning_link(link, "could not find udev device");
1892 return -errno;
1893 }
1894
3c4cb064 1895 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1896 /* not yet ready */
16cd414b 1897 log_debug_link(link, "udev initializing link...");
505f8da7 1898 return 0;
3c4cb064 1899 }
505f8da7
TG
1900 }
1901
1902 r = link_initialized(link, device);
1903 if (r < 0)
1904 return r;
1905
a748b692
TG
1906 return 0;
1907}
1908
22936833 1909int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1910 struct ether_addr mac;
b8941f74 1911 char *ifname;
22936833
TG
1912 int r;
1913
dd3efc09 1914 assert(link);
b8941f74 1915 assert(link->ifname);
22936833
TG
1916 assert(m);
1917
7619683b
TG
1918 if (link->state == LINK_STATE_LINGER) {
1919 link_ref(link);
1920 log_info_link(link, "link readded");
1921 link->state = LINK_STATE_ENSLAVING;
1922 }
1923
b8941f74
TG
1924 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1925 if (r >= 0 && !streq(ifname, link->ifname)) {
1926 log_info_link(link, "renamed to %s", ifname);
1927
1928 free(link->ifname);
1929 link->ifname = strdup(ifname);
1930 if (!link->ifname)
1931 return -ENOMEM;
1932 }
1933
505f8da7 1934 if (!link->original_mtu) {
9842de0d
TG
1935 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1936 if (r >= 0)
1937 log_debug_link(link, "saved original MTU: %"
1938 PRIu16, link->original_mtu);
1939 }
69629de9 1940
e9189a1f
TG
1941 /* The kernel may broadcast NEWLINK messages without the MAC address
1942 set, simply ignore them. */
c49b33ac 1943 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1944 if (r >= 0) {
20861203 1945 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 1946
20861203 1947 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 1948
20861203
TG
1949 log_debug_link(link, "MAC address: "
1950 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1951 mac.ether_addr_octet[0],
1952 mac.ether_addr_octet[1],
1953 mac.ether_addr_octet[2],
1954 mac.ether_addr_octet[3],
1955 mac.ether_addr_octet[4],
1956 mac.ether_addr_octet[5]);
c49b33ac 1957
20861203
TG
1958 if (link->ipv4ll) {
1959 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1960 if (r < 0) {
1961 log_warning_link(link, "Could not update MAC "
1962 "address in IPv4LL client: %s",
1963 strerror(-r));
1964 return r;
1965 }
c49b33ac 1966 }
c49b33ac 1967
20861203
TG
1968 if (link->dhcp_client) {
1969 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1970 if (r < 0) {
1971 log_warning_link(link, "Could not update MAC "
1972 "address in DHCP client: %s",
1973 strerror(-r));
1974 return r;
1975 }
c49b33ac
TG
1976 }
1977 }
4f882b2a
TG
1978 }
1979
1e9be60b 1980 return link_update_flags(link, m);
dd3efc09 1981}
fe8db0c5 1982
7374f9d8
TG
1983static void serialize_addresses(FILE *f, const char *key, Address *address) {
1984 Address *ad;
1985
1986 assert(f);
1987 assert(key);
1988
1989 if (!address)
1990 return;
1991
1992 fprintf(f, "%s=", key);
1993
1994 LIST_FOREACH(addresses, ad, address) {
1995 char buf[INET6_ADDRSTRLEN];
1996
d408b506 1997 if (inet_ntop(ad->family, &ad->in_addr, buf, INET6_ADDRSTRLEN))
7374f9d8
TG
1998 fprintf(f, "%s%s", buf, (ad->addresses_next) ? " ": "");
1999 }
2000
2001 fputs("\n", f);
2002}
2003
e375dcde
TG
2004static void link_update_operstate(Link *link) {
2005
2006 assert(link);
2007
2008 if (link->kernel_operstate == IF_OPER_DORMANT)
2009 link->operstate = LINK_OPERSTATE_DORMANT;
2010 else if (link_has_carrier(link->flags, link->kernel_operstate)) {
2011 Address *address;
2012 uint8_t scope = RT_SCOPE_NOWHERE;
2013
2014 /* if we have carrier, check what addresses we have */
2015 LIST_FOREACH(addresses, address, link->addresses) {
2016 if (address->scope < scope)
2017 scope = address->scope;
2018 }
2019
2020 if (scope < RT_SCOPE_SITE)
2021 /* universally accessible addresses found */
2022 link->operstate = LINK_OPERSTATE_ROUTABLE;
2023 else if (scope < RT_SCOPE_HOST)
2024 /* only link or site local addresses found */
2025 link->operstate = LINK_OPERSTATE_DEGRADED;
2026 else
2027 /* no useful addresses found */
2028 link->operstate = LINK_OPERSTATE_CARRIER;
2029 } else
2030 link->operstate = LINK_OPERSTATE_UNKNOWN;
2031}
2032
fe8db0c5 2033int link_save(Link *link) {
68a8723c 2034 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2035 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2036 const char *admin_state, *oper_state;
fe8db0c5
TG
2037 int r;
2038
2039 assert(link);
2040 assert(link->state_file);
68a8723c 2041 assert(link->lease_file);
bbf7c048
TG
2042 assert(link->manager);
2043
e375dcde
TG
2044 link_update_operstate(link);
2045
bbf7c048
TG
2046 r = manager_save(link->manager);
2047 if (r < 0)
2048 return r;
fe8db0c5 2049
370e9930
TG
2050 if (link->state == LINK_STATE_LINGER) {
2051 unlink(link->state_file);
2052 return 0;
2053 }
2054
deb2e523
TG
2055 admin_state = link_state_to_string(link->state);
2056 assert(admin_state);
2057
e375dcde
TG
2058 oper_state = link_operstate_to_string(link->operstate);
2059 assert(oper_state);
deb2e523 2060
fe8db0c5
TG
2061 r = fopen_temporary(link->state_file, &f, &temp_path);
2062 if (r < 0)
2063 goto finish;
2064
2065 fchmod(fileno(f), 0644);
2066
2067 fprintf(f,
2068 "# This is private data. Do not parse.\n"
deb2e523
TG
2069 "ADMIN_STATE=%s\n"
2070 "OPER_STATE=%s\n"
2071 "FLAGS=%u\n",
2072 admin_state, oper_state, link->flags);
fe8db0c5 2073
bcb7a07e 2074 if (link->network) {
7374f9d8 2075 serialize_addresses(f, "DNS", link->network->dns);
bcb7a07e
TG
2076 serialize_addresses(f, "NTP", link->network->ntp);
2077 }
7374f9d8 2078
fe8db0c5 2079 if (link->dhcp_lease) {
68a8723c 2080 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5
TG
2081 if (r < 0)
2082 goto finish;
2083
7374f9d8
TG
2084 fprintf(f,
2085 "DHCP_LEASE=%s\n"
bcb7a07e
TG
2086 "DHCP_USE_DNS=%s\n"
2087 "DHCP_USE_NTP=%s\n",
2088 link->lease_file,
2089 yes_no(link->network->dhcp_dns),
2090 yes_no(link->network->dhcp_ntp));
deb2e523 2091 } else
68a8723c 2092 unlink(link->lease_file);
fe8db0c5
TG
2093
2094 fflush(f);
2095
2096 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
2097 r = -errno;
2098 unlink(link->state_file);
2099 unlink(temp_path);
2100 }
2101
2102finish:
2103 if (r < 0)
987efa17 2104 log_error_link(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
fe8db0c5
TG
2105
2106 return r;
2107}
2108
2109static const char* const link_state_table[_LINK_STATE_MAX] = {
deb2e523 2110 [LINK_STATE_INITIALIZING] = "initializing",
fe8db0c5
TG
2111 [LINK_STATE_ENSLAVING] = "configuring",
2112 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
2113 [LINK_STATE_SETTING_ROUTES] = "configuring",
2114 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2115 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2116 [LINK_STATE_FAILED] = "failed",
370e9930 2117 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2118};
2119
2120DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2121
2122static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
2123 [LINK_OPERSTATE_UNKNOWN] = "unknown",
2124 [LINK_OPERSTATE_DORMANT] = "dormant",
2125 [LINK_OPERSTATE_CARRIER] = "carrier",
2126 [LINK_OPERSTATE_DEGRADED] = "degraded",
2127 [LINK_OPERSTATE_ROUTABLE] = "routable",
2128};
2129
2130DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);