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