]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: move carrier gained/lost handling from link_update_flags() to link_update()
[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>
4cc7a82c 24#include <unistd.h>
f579559b 25
0b1831c2 26#include "networkd-link.h"
3be1d7e0 27#include "networkd-netdev.h"
f579559b 28#include "libudev-private.h"
505f8da7 29#include "udev-util.h"
f579559b 30#include "util.h"
505f8da7 31#include "virt.h"
1346b1f0 32#include "bus-util.h"
c6f7c917 33#include "network-internal.h"
ed942a9e 34#include "conf-parser.h"
f579559b 35
fe8db0c5
TG
36#include "dhcp-lease-internal.h"
37
505f8da7 38static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
14b746f7 39 _cleanup_link_unref_ Link *link = NULL;
505f8da7 40 uint16_t type;
ca4e095a 41 const char *ifname;
505f8da7 42 int r, ifindex;
f579559b 43
0c2f9b84 44 assert(manager);
505f8da7 45 assert(message);
f579559b
TG
46 assert(ret);
47
505f8da7
TG
48 r = sd_rtnl_message_get_type(message, &type);
49 if (r < 0)
50 return r;
51 else if (type != RTM_NEWLINK)
52 return -EINVAL;
53
54 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
55 if (r < 0)
56 return r;
57 else if (ifindex <= 0)
58 return -EINVAL;
59
60 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &ifname);
61 if (r < 0)
62 return r;
63
f579559b
TG
64 link = new0(Link, 1);
65 if (!link)
66 return -ENOMEM;
67
14b746f7 68 link->n_ref = 1;
5a3eb5a7 69 link->manager = manager;
8434fd5c 70 link->state = LINK_STATE_PENDING;
505f8da7
TG
71 link->ifindex = ifindex;
72 link->ifname = strdup(ifname);
73 if (!link->ifname)
74 return -ENOMEM;
f579559b 75
512922f8
TG
76 r = sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
77 if (r < 0)
1a941ac4 78 log_debug_link(link, "MAC address not found for new device, continuing without");
512922f8 79
3c9b8860
TG
80 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
81 link->ifindex);
fe8db0c5 82 if (r < 0)
315db1a8 83 return -ENOMEM;
fe8db0c5 84
3c9b8860
TG
85 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
86 link->ifindex);
68a8723c
TG
87 if (r < 0)
88 return -ENOMEM;
89
ae06ab10
TG
90 r = hashmap_ensure_allocated(&manager->links, NULL, NULL);
91 if (r < 0)
92 return r;
93
94 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
f579559b
TG
95 if (r < 0)
96 return r;
97
98 *ret = link;
99 link = NULL;
100
101 return 0;
102}
103
14b746f7 104static void link_free(Link *link) {
428fd0a7
TG
105 Address *address;
106
f579559b
TG
107 if (!link)
108 return;
109
428fd0a7
TG
110 while ((address = link->addresses)) {
111 LIST_REMOVE(addresses, link->addresses, address);
112 address_free(address);
113 }
114
11bf3cce
LP
115 while ((address = link->pool_addresses)) {
116 LIST_REMOVE(addresses, link->pool_addresses, address);
117 address_free(address);
118 }
119
e5b04c8d 120 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 121 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 122
68a8723c
TG
123 unlink(link->lease_file);
124 free(link->lease_file);
125
56cd007a 126 sd_ipv4ll_unref(link->ipv4ll);
4138fb2c 127 sd_dhcp6_client_unref(link->dhcp6_client);
6b66097b 128 sd_icmp6_nd_unref(link->icmp6_router_discovery);
4138fb2c 129
28aeb07f 130 if (link->manager)
ae06ab10 131 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
f579559b 132
c166a070 133 free(link->ifname);
68a8723c
TG
134
135 unlink(link->state_file);
fe8db0c5 136 free(link->state_file);
c166a070 137
b5db00e5
UTL
138 udev_device_unref(link->udev_device);
139
f579559b
TG
140 free(link);
141}
142
14b746f7
TG
143Link *link_unref(Link *link) {
144 if (link && (-- link->n_ref <= 0))
145 link_free(link);
146
147 return NULL;
148}
149
150Link *link_ref(Link *link) {
151 if (link)
152 assert_se(++ link->n_ref >= 2);
153
154 return link;
155}
156
11a7f229
TG
157int link_get(Manager *m, int ifindex, Link **ret) {
158 Link *link;
11a7f229
TG
159
160 assert(m);
11a7f229
TG
161 assert(ifindex);
162 assert(ret);
163
ae06ab10 164 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
11a7f229
TG
165 if (!link)
166 return -ENODEV;
167
168 *ret = link;
169
170 return 0;
171}
172
370e9930
TG
173void link_drop(Link *link) {
174 if (!link || link->state == LINK_STATE_LINGER)
175 return;
176
177 link->state = LINK_STATE_LINGER;
178
7619683b 179 log_debug_link(link, "link removed");
370e9930
TG
180
181 link_unref(link);
182
183 return;
184}
185
57bd6899
TG
186static void link_enter_unmanaged(Link *link) {
187 assert(link);
188
df9aa406 189 log_debug_link(link, "unmanaged");
57bd6899
TG
190
191 link->state = LINK_STATE_UNMANAGED;
192
193 link_save(link);
194}
195
111bb8f9
TG
196static int link_stop_clients(Link *link) {
197 int r = 0, k;
198
199 assert(link);
200 assert(link->manager);
201 assert(link->manager->event);
202
203 if (!link->network)
204 return 0;
205
ba179154 206 if (link->dhcp_client) {
111bb8f9
TG
207 k = sd_dhcp_client_stop(link->dhcp_client);
208 if (k < 0) {
3c9b8860
TG
209 log_warning_link(link, "Could not stop DHCPv4 client: %s",
210 strerror(-r));
111bb8f9
TG
211 r = k;
212 }
213 }
214
ba179154 215 if (link->ipv4ll) {
111bb8f9
TG
216 k = sd_ipv4ll_stop(link->ipv4ll);
217 if (k < 0) {
3c9b8860
TG
218 log_warning_link(link, "Could not stop IPv4 link-local: %s",
219 strerror(-r));
111bb8f9
TG
220 r = k;
221 }
222 }
223
ba179154 224 if (link->dhcp_server) {
dd43110f
TG
225 k = sd_dhcp_server_stop(link->dhcp_server);
226 if (k < 0) {
3c9b8860
TG
227 log_warning_link(link, "Could not stop DHCPv4 server: %s",
228 strerror(-r));
dd43110f
TG
229 r = k;
230 }
231 }
232
ba179154 233 if(link->icmp6_router_discovery) {
1873a3d3
PF
234
235 if (link->dhcp6_client) {
236 k = sd_dhcp6_client_stop(link->dhcp6_client);
237 if (k < 0) {
3c9b8860
TG
238 log_warning_link(link, "Could not stop DHCPv6 client: %s",
239 strerror(-r));
1873a3d3
PF
240 r = k;
241 }
242 }
4138fb2c 243
1873a3d3 244 k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
4138fb2c 245 if (k < 0) {
3c9b8860
TG
246 log_warning_link(link,
247 "Could not stop ICMPv6 router discovery: %s",
248 strerror(-r));
4138fb2c
PF
249 r = k;
250 }
251 }
252
111bb8f9
TG
253 return r;
254}
255
b22d8a00 256void link_enter_failed(Link *link) {
ef1ba606 257 assert(link);
f882c247 258
370e9930 259 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
260 return;
261
39032b87 262 log_warning_link(link, "failed");
449f7554 263
ef1ba606 264 link->state = LINK_STATE_FAILED;
fe8db0c5 265
111bb8f9
TG
266 link_stop_clients(link);
267
fe8db0c5 268 link_save(link);
f882c247
TG
269}
270
4f434938
LP
271static Address* link_find_dhcp_server_address(Link *link) {
272 Address *address;
273
274 assert(link);
275 assert(link->network);
276
277 /* The the first statically configured address if there is any */
278 LIST_FOREACH(addresses, address, link->network->static_addresses) {
279
280 if (address->family != AF_INET)
281 continue;
282
af93291c 283 if (in_addr_is_null(address->family, &address->in_addr))
4f434938
LP
284 continue;
285
286 return address;
287 }
288
289 /* If that didn't work, find a suitable address we got from the pool */
290 LIST_FOREACH(addresses, address, link->pool_addresses) {
291 if (address->family != AF_INET)
292 continue;
293
294 return address;
295 }
296
297 return NULL;
298}
299
dd43110f
TG
300static int link_enter_configured(Link *link) {
301 int r;
302
303 assert(link);
304 assert(link->network);
305 assert(link->state == LINK_STATE_SETTING_ROUTES);
306
7c16313f
TG
307 if (link->network->dhcp_server &&
308 !sd_dhcp_server_is_running(link->dhcp_server)) {
4f434938
LP
309 struct in_addr pool_start;
310 Address *address;
311
312 address = link_find_dhcp_server_address(link);
313 if (!address) {
3c9b8860
TG
314 log_warning_link(link,
315 "Failed to find suitable address for DHCPv4 server instance.");
4f434938
LP
316 link_enter_failed(link);
317 return 0;
318 }
319
dd43110f
TG
320 log_debug_link(link, "offering DHCPv4 leases");
321
3c9b8860
TG
322 r = sd_dhcp_server_set_address(link->dhcp_server,
323 &address->in_addr.in,
324 address->prefixlen);
4f434938
LP
325 if (r < 0)
326 return r;
327
328 /* offer 32 addresses starting from the address following the server address */
329 pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1);
330 r = sd_dhcp_server_set_lease_pool(link->dhcp_server,
331 &pool_start, 32);
332 if (r < 0)
333 return r;
334
335 /* TODO:
336 r = sd_dhcp_server_set_router(link->dhcp_server,
337 &main_address->in_addr.in);
338 if (r < 0)
339 return r;
340
341 r = sd_dhcp_server_set_prefixlen(link->dhcp_server,
342 main_address->prefixlen);
343 if (r < 0)
344 return r;
345 */
346
dd43110f
TG
347 r = sd_dhcp_server_start(link->dhcp_server);
348 if (r < 0) {
349 log_warning_link(link, "could not start DHCPv4 server "
350 "instance: %s", strerror(-r));
351
352 link_enter_failed(link);
353
354 return 0;
355 }
356 }
357
358 log_info_link(link, "link configured");
359
360 link->state = LINK_STATE_CONFIGURED;
361
362 link_save(link);
363
364 return 0;
365}
366
3c9b8860
TG
367void link_client_handler(Link *link) {
368 assert(link);
369 assert(link->network);
370
371 if (!link->static_configured)
372 return;
373
374 if (link->network->ipv4ll)
375 if (!link->ipv4ll_address ||
376 !link->ipv4ll_route)
377 return;
378
379 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4))
380 if (!link->dhcp4_configured)
381 return;
382
9fdaa992
TG
383 if (link->state != LINK_STATE_CONFIGURED)
384 link_enter_configured(link);
3c9b8860
TG
385
386 return;
387}
388
f882c247 389static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 390 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
391 int r;
392
3c9b8860 393 assert(link->link_messages > 0);
370e9930
TG
394 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
395 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
396 LINK_STATE_LINGER));
f882c247 397
3c9b8860 398 link->link_messages --;
f882c247 399
77a008c0 400 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
401 return 1;
402
403 r = sd_rtnl_message_get_errno(m);
c166a070 404 if (r < 0 && r != -EEXIST)
c9ccc19f 405 log_struct_link(LOG_WARNING, link,
97578344 406 "MESSAGE=%-*s: could not set route: %s",
987efa17 407 IFNAMSIZ,
c9ccc19f
TG
408 link->ifname, strerror(-r),
409 "ERRNO=%d", -r,
410 NULL);
f882c247 411
3c9b8860 412 if (link->link_messages == 0) {
39032b87 413 log_debug_link(link, "routes set");
3c9b8860
TG
414 link->static_configured = true;
415 link_client_handler(link);
dd3efc09 416 }
f882c247
TG
417
418 return 1;
419}
420
421static int link_enter_set_routes(Link *link) {
a6cc569e 422 Route *rt;
f882c247
TG
423 int r;
424
425 assert(link);
426 assert(link->network);
ef1ba606 427 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 428
ef1ba606 429 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 430
3d3d4255 431 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 432 r = route_configure(rt, link, &route_handler);
dd3efc09 433 if (r < 0) {
3333d748 434 log_warning_link(link,
3c9b8860 435 "could not set routes: %s",
b1666580 436 strerror(-r));
3c9b8860 437 link_enter_failed(link);
a6cc569e
TG
438 return r;
439 }
440
3c9b8860 441 link->link_messages ++;
8ddbeaa2 442 }
f5be5601 443
3c9b8860
TG
444 if (link->link_messages == 0) {
445 link->static_configured = true;
446 link_client_handler(link);
431ca2ce
TG
447 } else
448 log_debug_link(link, "setting routes");
f882c247
TG
449
450 return 0;
451}
452
b22d8a00 453int link_route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 454 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
455 int r;
456
457 assert(m);
458 assert(link);
459 assert(link->ifname);
460
5da8149f 461 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
462 return 1;
463
464 r = sd_rtnl_message_get_errno(m);
b90b025a 465 if (r < 0 && r != -ESRCH)
5c1d3fc9 466 log_struct_link(LOG_WARNING, link,
97578344 467 "MESSAGE=%-*s: could not drop route: %s",
987efa17 468 IFNAMSIZ,
5c1d3fc9
UTL
469 link->ifname, strerror(-r),
470 "ERRNO=%d", -r,
471 NULL);
472
5bdd314c 473 return 1;
5c1d3fc9
UTL
474}
475
b22d8a00 476int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
4958aee4
TG
477 _cleanup_link_unref_ Link *link = userdata;
478 int r;
479
480 assert(rtnl);
481 assert(m);
482 assert(link);
483 assert(link->manager);
484
485 for (; m; m = sd_rtnl_message_next(m)) {
486 r = sd_rtnl_message_get_errno(m);
487 if (r < 0) {
3c9b8860
TG
488 log_debug_link(link, "getting address failed: %s",
489 strerror(-r));
4958aee4
TG
490 continue;
491 }
492
493 r = link_rtnl_process_address(rtnl, m, link->manager);
494 if (r < 0)
3c9b8860
TG
495 log_warning_link(link, "could not process address: %s",
496 strerror(-r));
4958aee4
TG
497 }
498
499 return 1;
500}
501
f882c247 502static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 503 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
504 int r;
505
4958aee4 506 assert(rtnl);
f5be5601
TG
507 assert(m);
508 assert(link);
509 assert(link->ifname);
3c9b8860 510 assert(link->link_messages > 0);
370e9930
TG
511 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
512 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 513
3c9b8860 514 link->link_messages --;
f882c247 515
5da8149f 516 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
517 return 1;
518
519 r = sd_rtnl_message_get_errno(m);
c166a070 520 if (r < 0 && r != -EEXIST)
c9ccc19f 521 log_struct_link(LOG_WARNING, link,
97578344 522 "MESSAGE=%-*s: could not set address: %s",
987efa17 523 IFNAMSIZ,
3333d748
ZJS
524 link->ifname, strerror(-r),
525 "ERRNO=%d", -r,
526 NULL);
5bdd314c 527 else if (r >= 0) {
4958aee4
TG
528 /* calling handler directly so take a ref */
529 link_ref(link);
530 link_get_address_handler(rtnl, m, link);
531 }
f882c247 532
3c9b8860 533 if (link->link_messages == 0) {
39032b87 534 log_debug_link(link, "addresses set");
ef1ba606 535 link_enter_set_routes(link);
dd3efc09 536 }
f882c247
TG
537
538 return 1;
539}
540
541static int link_enter_set_addresses(Link *link) {
a6cc569e 542 Address *ad;
f882c247
TG
543 int r;
544
545 assert(link);
546 assert(link->network);
f5be5601 547 assert(link->state != _LINK_STATE_INVALID);
f882c247 548
ef1ba606 549 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 550
3d3d4255 551 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 552 r = address_configure(ad, link, &address_handler);
dd3efc09 553 if (r < 0) {
3333d748 554 log_warning_link(link,
3c9b8860 555 "could not set addresses: %s",
a6cc569e 556 strerror(-r));
f5be5601
TG
557 link_enter_failed(link);
558 return r;
559 }
560
3c9b8860 561 link->link_messages ++;
f882c247
TG
562 }
563
3c9b8860 564 if (link->link_messages == 0) {
431ca2ce
TG
565 link_enter_set_routes(link);
566 } else
567 log_debug_link(link, "setting addresses");
568
f882c247
TG
569 return 0;
570}
571
b22d8a00 572int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 573 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
574 int r;
575
576 assert(m);
577 assert(link);
578 assert(link->ifname);
579
5da8149f 580 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
581 return 1;
582
583 r = sd_rtnl_message_get_errno(m);
b90b025a 584 if (r < 0 && r != -EADDRNOTAVAIL)
c9ccc19f 585 log_struct_link(LOG_WARNING, link,
97578344 586 "MESSAGE=%-*s: could not drop address: %s",
987efa17 587 IFNAMSIZ,
c9ccc19f
TG
588 link->ifname, strerror(-r),
589 "ERRNO=%d", -r,
590 NULL);
ff254138 591
5bdd314c 592 return 1;
ff254138
TG
593}
594
3c9b8860
TG
595static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata,
596 sd_bus_error *ret_error) {
5da8149f 597 _cleanup_link_unref_ Link *link = userdata;
1346b1f0
TG
598 int r;
599
b226d99b
TG
600 assert(link);
601
5da8149f 602 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 603 return 1;
370e9930 604
1346b1f0
TG
605 r = sd_bus_message_get_errno(m);
606 if (r < 0)
70b34f5d
MM
607 r = -r;
608 if (r > 0)
3c9b8860
TG
609 log_warning_link(link, "Could not set hostname: %s",
610 strerror(r));
1346b1f0
TG
611
612 return 1;
613}
614
3c9b8860 615int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
616 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
617 int r = 0;
618
b226d99b
TG
619 assert(link);
620 assert(link->manager);
1346b1f0
TG
621 assert(hostname);
622
b226d99b 623 log_debug_link(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 624
3c9b8860
TG
625 if (!link->manager->bus) {
626 /* TODO: replace by assert when we can rely on kdbus */
627 log_info_link(link,
628 "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
629 return 0;
630 }
631
1346b1f0 632 r = sd_bus_message_new_method_call(
b226d99b 633 link->manager->bus,
151b9b96 634 &m,
1346b1f0
TG
635 "org.freedesktop.hostname1",
636 "/org/freedesktop/hostname1",
637 "org.freedesktop.hostname1",
151b9b96 638 "SetHostname");
1346b1f0
TG
639 if (r < 0)
640 return r;
641
642 r = sd_bus_message_append(m, "sb", hostname, false);
643 if (r < 0)
644 return r;
645
3c9b8860
TG
646 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler,
647 link, 0);
5da8149f 648 if (r < 0) {
3c9b8860
TG
649 log_error_link(link, "Could not set transient hostname: %s",
650 strerror(-r));
5da8149f
TG
651 return r;
652 }
b226d99b
TG
653
654 link_ref(link);
1346b1f0 655
5da8149f 656 return 0;
1346b1f0
TG
657}
658
4f882b2a 659static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 660 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
661 int r;
662
663 assert(m);
664 assert(link);
665 assert(link->ifname);
666
5da8149f 667 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
668 return 1;
669
670 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
671 if (r < 0)
672 log_struct_link(LOG_WARNING, link,
97578344
TG
673 "MESSAGE=%-*s: could not set MTU: %s",
674 IFNAMSIZ, link->ifname, strerror(-r),
c9ccc19f
TG
675 "ERRNO=%d", -r,
676 NULL);
4f882b2a
TG
677
678 return 1;
679}
680
3c9b8860 681int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 682 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
683 int r;
684
685 assert(link);
686 assert(link->manager);
687 assert(link->manager->rtnl);
688
689 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
690
151b9b96
LP
691 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
692 RTM_SETLINK, link->ifindex);
4f882b2a
TG
693 if (r < 0) {
694 log_error_link(link, "Could not allocate RTM_SETLINK message");
695 return r;
696 }
697
698 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
699 if (r < 0) {
700 log_error_link(link, "Could not append MTU: %s", strerror(-r));
701 return r;
702 }
703
3c9b8860
TG
704 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link,
705 0, NULL);
4f882b2a
TG
706 if (r < 0) {
707 log_error_link(link,
3c9b8860
TG
708 "Could not send rtnetlink message: %s",
709 strerror(-r));
4f882b2a
TG
710 return r;
711 }
712
ae941762 713 link_ref(link);
b226d99b 714
4f882b2a
TG
715 return 0;
716}
717
4138fb2c
PF
718static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
719 Link *link = userdata;
720
721 assert(link);
722 assert(link->network);
723 assert(link->manager);
724
725 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
726 return;
727
728 switch(event) {
729 case DHCP6_EVENT_STOP:
730 case DHCP6_EVENT_RESEND_EXPIRE:
731 case DHCP6_EVENT_RETRANS_MAX:
732 case DHCP6_EVENT_IP_ACQUIRE:
733 log_debug_link(link, "DHCPv6 event %d", event);
734
735 break;
736
737 default:
738 if (event < 0)
739 log_warning_link(link, "DHCPv6 error: %s",
740 strerror(-event));
741 else
742 log_warning_link(link, "DHCPv6 unknown event: %d",
743 event);
744 return;
745 }
746}
747
748static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
749 Link *link = userdata;
750 int r;
751
752 assert(link);
753 assert(link->network);
754 assert(link->manager);
755
756 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
757 return;
758
759 switch(event) {
760 case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
761 case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
762 return;
763
764 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
765 case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
766 break;
767
768 default:
769 if (event < 0)
770 log_warning_link(link, "ICMPv6 error: %s",
771 strerror(-event));
772 else
773 log_warning_link(link, "ICMPv6 unknown event: %d",
774 event);
775
776 return;
777 }
778
779 if (link->dhcp6_client)
780 return;
781
782 r = sd_dhcp6_client_new(&link->dhcp6_client);
783 if (r < 0)
784 return;
785
786 r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
787 if (r < 0) {
788 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
789 return;
790 }
791
792 r = sd_dhcp6_client_set_mac(link->dhcp6_client, &link->mac);
793 if (r < 0) {
794 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
795 return;
796 }
797
798 r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
799 if (r < 0) {
800 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
801 return;
802 }
803
804 r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
805 link);
806 if (r < 0) {
807 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
808 return;
809 }
810
811 r = sd_dhcp6_client_start(link->dhcp6_client);
812 if (r < 0)
813 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
814}
815
ff254138
TG
816static int link_acquire_conf(Link *link) {
817 int r;
818
819 assert(link);
820 assert(link->network);
ff254138
TG
821 assert(link->manager);
822 assert(link->manager->event);
823
5c1d3fc9 824 if (link->network->ipv4ll) {
eb34d4af 825 assert(link->ipv4ll);
ff254138 826
5c1d3fc9
UTL
827 log_debug_link(link, "acquiring IPv4 link-local address");
828
829 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6
TG
830 if (r < 0) {
831 log_warning_link(link, "could not acquire IPv4 "
832 "link-local address");
ff254138 833 return r;
124fa2c6 834 }
5c1d3fc9
UTL
835 }
836
ed942a9e 837 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4)) {
eb34d4af 838 assert(link->dhcp_client);
ff254138 839
5c1d3fc9 840 log_debug_link(link, "acquiring DHCPv4 lease");
ab47d620 841
5c1d3fc9 842 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6
TG
843 if (r < 0) {
844 log_warning_link(link, "could not acquire DHCPv4 "
845 "lease");
5c1d3fc9 846 return r;
124fa2c6 847 }
5c1d3fc9 848 }
ff254138 849
ed942a9e 850 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
851 assert(link->icmp6_router_discovery);
852
853 log_debug_link(link, "discovering IPv6 routers");
854
855 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
856 if (r < 0) {
3c9b8860
TG
857 log_warning_link(link,
858 "could not start IPv6 router discovery");
4138fb2c
PF
859 return r;
860 }
861 }
862
ff254138
TG
863 return 0;
864}
865
a61bb41c 866bool link_has_carrier(Link *link) {
deb2e523
TG
867 /* see Documentation/networking/operstates.txt in the kernel sources */
868
a61bb41c 869 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
870 return true;
871
a61bb41c 872 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 873 /* operstate may not be implemented, so fall back to flags */
a61bb41c 874 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
875 return true;
876
877 return false;
878}
879
389cc5f7
TG
880#define FLAG_STRING(string, flag, old, new) \
881 (((old ^ new) & flag) \
882 ? ((old & flag) ? (" -" string) : (" +" string)) \
883 : "")
884
1e9be60b 885static int link_update_flags(Link *link, sd_rtnl_message *m) {
389cc5f7 886 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
1e9be60b 887 uint8_t operstate;
ff254138
TG
888 int r;
889
890 assert(link);
ff254138 891
1e9be60b
TG
892 r = sd_rtnl_message_link_get_flags(m, &flags);
893 if (r < 0) {
894 log_warning_link(link, "Could not get link flags");
895 return r;
896 }
897
898 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
899 if (r < 0)
900 /* if we got a message without operstate, take it to mean
901 the state was unchanged */
e375dcde 902 operstate = link->kernel_operstate;
1e9be60b 903
e375dcde 904 if ((link->flags == flags) && (link->kernel_operstate == operstate))
efbc88b8 905 return 0;
efbc88b8 906
389cc5f7
TG
907 if (link->flags != flags) {
908 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",
909 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
910 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
911 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
912 FLAG_STRING("UP", IFF_UP, link->flags, flags),
913 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
914 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
915 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
916 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
917 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
918 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
919 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
920 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
921 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
922 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
923 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
924 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
925 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
926 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
927 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
928
929 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
930 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
931 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
932 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
933 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
934 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
935 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
936 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
937
3c9b8860
TG
938 /* link flags are currently at most 18 bits, let's align to
939 * printing 20 */
389cc5f7 940 if (unknown_flags_added)
3c9b8860
TG
941 log_debug_link(link,
942 "unknown link flags gained: %#.5x (ignoring)",
389cc5f7
TG
943 unknown_flags_added);
944
945 if (unknown_flags_removed)
3c9b8860
TG
946 log_debug_link(link,
947 "unknown link flags lost: %#.5x (ignoring)",
389cc5f7
TG
948 unknown_flags_removed);
949 }
505f8da7 950
1e9be60b 951 link->flags = flags;
e375dcde 952 link->kernel_operstate = operstate;
1e9be60b 953
deb2e523
TG
954 link_save(link);
955
ff254138
TG
956 return 0;
957}
958
dd3efc09 959static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 960 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
961 int r;
962
1746cf2a
TG
963 assert(link);
964
5da8149f 965 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
966 return 1;
967
dd3efc09 968 r = sd_rtnl_message_get_errno(m);
45ad2c13 969 if (r < 0) {
9b86b393
TG
970 /* we warn but don't fail the link, as it may
971 be brought up later */
76800848 972 log_struct_link(LOG_WARNING, link,
97578344 973 "MESSAGE=%-*s: could not bring up interface: %s",
987efa17 974 IFNAMSIZ,
c9ccc19f
TG
975 link->ifname, strerror(-r),
976 "ERRNO=%d", -r,
977 NULL);
45ad2c13
TG
978 }
979
f882c247
TG
980 return 1;
981}
982
983static int link_up(Link *link) {
cf6a8911 984 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
985 int r;
986
f882c247
TG
987 assert(link);
988 assert(link->manager);
989 assert(link->manager->rtnl);
990
39032b87 991 log_debug_link(link, "bringing link up");
449f7554 992
151b9b96
LP
993 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
994 RTM_SETLINK, link->ifindex);
f579559b 995 if (r < 0) {
39032b87 996 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
997 return r;
998 }
999
5d4795f3 1000 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1001 if (r < 0) {
3c9b8860
TG
1002 log_error_link(link, "Could not set link flags: %s",
1003 strerror(-r));
fc25d7f8
TG
1004 return r;
1005 }
1006
3c9b8860
TG
1007 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1008 0, NULL);
f579559b 1009 if (r < 0) {
3333d748 1010 log_error_link(link,
3c9b8860
TG
1011 "Could not send rtnetlink message: %s",
1012 strerror(-r));
f579559b
TG
1013 return r;
1014 }
1015
b226d99b
TG
1016 link_ref(link);
1017
f882c247
TG
1018 return 0;
1019}
1020
3f265037 1021static int link_joined(Link *link) {
f882c247
TG
1022 int r;
1023
ef1ba606 1024 assert(link);
f5be5601 1025 assert(link->network);
dd3efc09 1026
505f8da7
TG
1027 if (!(link->flags & IFF_UP)) {
1028 r = link_up(link);
1029 if (r < 0) {
1030 link_enter_failed(link);
1031 return r;
1032 }
ef1ba606 1033 }
f882c247 1034
fb6730c4 1035 return link_enter_set_addresses(link);
02b59d57
TG
1036}
1037
3c9b8860
TG
1038static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1039 void *userdata) {
5da8149f 1040 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1041 int r;
1042
1746cf2a 1043 assert(link);
ef1ba606 1044 assert(link->network);
02b59d57 1045
52433f6b
TG
1046 link->enslaving --;
1047
5da8149f 1048 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1049 return 1;
1050
1051 r = sd_rtnl_message_get_errno(m);
856f962c 1052 if (r < 0 && r != -EEXIST) {
c9ccc19f 1053 log_struct_link(LOG_ERR, link,
3f265037 1054 "MESSAGE=%-*s: could not join netdev: %s",
987efa17 1055 IFNAMSIZ,
c9ccc19f
TG
1056 link->ifname, strerror(-r),
1057 "ERRNO=%d", -r,
1058 NULL);
ef1ba606
TG
1059 link_enter_failed(link);
1060 return 1;
ba179154
TG
1061 } else
1062 log_debug_link(link, "joined netdev");
02b59d57 1063
856f962c 1064 if (link->enslaving <= 0)
3f265037 1065 link_joined(link);
02b59d57
TG
1066
1067 return 1;
1068}
1069
3f265037 1070static int link_enter_join_netdev(Link *link) {
6a0a2f86 1071 NetDev *netdev;
672682a6 1072 Iterator i;
02b59d57
TG
1073 int r;
1074
1075 assert(link);
1076 assert(link->network);
8434fd5c 1077 assert(link->state == LINK_STATE_PENDING);
02b59d57 1078
52433f6b 1079 link->state = LINK_STATE_ENSLAVING;
02b59d57 1080
fe8db0c5
TG
1081 link_save(link);
1082
7951dea2
SS
1083 if (!link->network->bridge &&
1084 !link->network->bond &&
6a0a2f86 1085 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1086 return link_joined(link);
02b59d57 1087
d9c67ea1 1088 if (link->network->bond) {
52433f6b 1089 log_struct_link(LOG_DEBUG, link,
97578344 1090 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1091 IFNAMSIZ,
af4e9e2c 1092 link->ifname, link->network->bond->ifname,
aa9f1140 1093 NETDEVIF(link->network->bond),
52433f6b 1094 NULL);
449f7554 1095
3f265037 1096 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b
TG
1097 if (r < 0) {
1098 log_struct_link(LOG_WARNING, link,
3f265037 1099 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1100 IFNAMSIZ,
3c9b8860
TG
1101 link->ifname, link->network->bond->ifname,
1102 strerror(-r),
aa9f1140 1103 NETDEVIF(link->network->bond),
52433f6b
TG
1104 NULL);
1105 link_enter_failed(link);
1106 return r;
1107 }
1108
0ad6148e
MO
1109 link->enslaving ++;
1110 }
1111
d9c67ea1 1112 if (link->network->bridge) {
0ad6148e 1113 log_struct_link(LOG_DEBUG, link,
97578344 1114 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1115 IFNAMSIZ,
af4e9e2c 1116 link->ifname, link->network->bridge->ifname,
aa9f1140 1117 NETDEVIF(link->network->bridge),
0ad6148e
MO
1118 NULL);
1119
3c9b8860
TG
1120 r = netdev_join(link->network->bridge, link,
1121 &netdev_join_handler);
0ad6148e
MO
1122 if (r < 0) {
1123 log_struct_link(LOG_WARNING, link,
3f265037 1124 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1125 IFNAMSIZ,
3c9b8860
TG
1126 link->ifname, link->network->bridge->ifname,
1127 strerror(-r),
aa9f1140 1128 NETDEVIF(link->network->bridge),
0ad6148e
MO
1129 NULL);
1130 link_enter_failed(link);
1131 return r;
1132 }
1133
52433f6b
TG
1134 link->enslaving ++;
1135 }
1136
6a0a2f86 1137 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1138 log_struct_link(LOG_DEBUG, link,
97578344 1139 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1140 IFNAMSIZ,
3c9b8860
TG
1141 link->ifname, netdev->ifname, NETDEVIF(netdev),
1142 NULL);
7951dea2 1143
6a0a2f86 1144 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2
SS
1145 if (r < 0) {
1146 log_struct_link(LOG_WARNING, link,
3f265037 1147 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1148 IFNAMSIZ,
3c9b8860
TG
1149 link->ifname, netdev->ifname,
1150 strerror(-r),
6a0a2f86 1151 NETDEVIF(netdev), NULL);
326cb406
SS
1152 link_enter_failed(link);
1153 return r;
1154 }
1155
326cb406
SS
1156 link->enslaving ++;
1157 }
1158
ef1ba606
TG
1159 return 0;
1160}
1161
a748b692 1162static int link_configure(Link *link) {
02b59d57
TG
1163 int r;
1164
ef1ba606 1165 assert(link);
b22d8a00 1166 assert(link->network);
8434fd5c 1167 assert(link->state == LINK_STATE_PENDING);
a748b692 1168
eb34d4af 1169 if (link->network->ipv4ll) {
b22d8a00 1170 r = ipv4ll_configure(link);
eb34d4af
TG
1171 if (r < 0)
1172 return r;
1173 }
1174
ed942a9e 1175 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4)) {
3c9b8860 1176 r = dhcp4_configure(link);
eb34d4af
TG
1177 if (r < 0)
1178 return r;
eb34d4af
TG
1179 }
1180
dd43110f 1181 if (link->network->dhcp_server) {
dd43110f
TG
1182 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1183 if (r < 0)
1184 return r;
1185
1186 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1187 if (r < 0)
1188 return r;
dd43110f
TG
1189 }
1190
ed942a9e 1191 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
1192 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1193 if (r < 0)
1194 return r;
1195
1196 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1197 NULL, 0);
1198 if (r < 0)
1199 return r;
1200
1201 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1202 &link->mac);
1203 if (r < 0)
1204 return r;
1205
1206 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1207 link->ifindex);
1208 if (r < 0)
1209 return r;
1210
1211 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1212 icmp6_router_handler, link);
1213 if (r < 0)
1214 return r;
1215 }
1216
a61bb41c 1217 if (link_has_carrier(link)) {
1e9be60b
TG
1218 r = link_acquire_conf(link);
1219 if (r < 0)
1220 return r;
cc544d5f 1221 }
1e9be60b 1222
3f265037 1223 return link_enter_join_netdev(link);
505f8da7
TG
1224}
1225
3c9b8860
TG
1226static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1227 void *userdata) {
5da8149f 1228 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1229 Network *network;
505f8da7
TG
1230 int r;
1231
1232 assert(link);
1233 assert(link->ifname);
1234 assert(link->manager);
1235
8434fd5c 1236 if (link->state != LINK_STATE_PENDING)
5da8149f 1237 return 1;
505f8da7 1238
4f561e8e 1239 log_debug_link(link, "link state is up-to-date");
505f8da7 1240
3c9b8860
TG
1241 r = network_get(link->manager, link->udev_device, link->ifname,
1242 &link->mac, &network);
57bd6899
TG
1243 if (r == -ENOENT) {
1244 link_enter_unmanaged(link);
5da8149f 1245 return 1;
57bd6899
TG
1246 } else if (r < 0)
1247 return r;
505f8da7
TG
1248
1249 r = network_apply(link->manager, network, link);
1250 if (r < 0)
1251 return r;
1252
a748b692
TG
1253 r = link_configure(link);
1254 if (r < 0)
1255 return r;
1256
5da8149f 1257 return 1;
505f8da7
TG
1258}
1259
4f561e8e
TG
1260int link_initialized(Link *link, struct udev_device *device) {
1261 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1262 int r;
1263
1264 assert(link);
1265 assert(link->manager);
1266 assert(link->manager->rtnl);
1267 assert(device);
1268
8434fd5c 1269 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1270 return 0;
1271
679b3605
TG
1272 if (link->udev_device)
1273 return 0;
1274
4f561e8e
TG
1275 log_debug_link(link, "udev initialized link");
1276
1277 link->udev_device = udev_device_ref(device);
1278
3c9b8860
TG
1279 /* udev has initialized the link, but we don't know if we have yet
1280 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1281 * when it returns we know that the pending NEWLINKs have already been
1282 * processed and that we are up-to-date */
4f561e8e 1283
3c9b8860
TG
1284 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1285 link->ifindex);
4f561e8e
TG
1286 if (r < 0)
1287 return r;
1288
3c9b8860
TG
1289 r = sd_rtnl_call_async(link->manager->rtnl, req,
1290 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1291 if (r < 0)
1292 return r;
1293
5da8149f
TG
1294 link_ref(link);
1295
4f561e8e
TG
1296 return 0;
1297}
1298
3c9b8860
TG
1299int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message,
1300 void *userdata) {
fbbeb65a
TG
1301 Manager *m = userdata;
1302 Link *link = NULL;
1303 uint16_t type;
1304 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1305 Address *ad;
fbbeb65a 1306 char buf[INET6_ADDRSTRLEN];
c6d3b303
TG
1307 char valid_buf[FORMAT_TIMESPAN_MAX];
1308 const char *valid_str = NULL;
428fd0a7 1309 bool address_dropped = false;
fbbeb65a
TG
1310 int r, ifindex;
1311
1312 assert(rtnl);
1313 assert(message);
1314 assert(m);
1315
1316 r = sd_rtnl_message_get_type(message, &type);
1317 if (r < 0) {
1318 log_warning("rtnl: could not get message type");
1319 return 0;
1320 }
1321
1322 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1323 if (r < 0 || ifindex <= 0) {
5ea846cc 1324 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1325 return 0;
1326 } else {
1327 r = link_get(m, ifindex, &link);
1328 if (r < 0 || !link) {
5ea846cc 1329 log_warning("rtnl: received address for a nonexistent link, ignoring");
fbbeb65a
TG
1330 return 0;
1331 }
1332 }
1333
1334 r = address_new_dynamic(&address);
1335 if (r < 0)
393c0c5e 1336 return r;
fbbeb65a
TG
1337
1338 r = sd_rtnl_message_addr_get_family(message, &address->family);
1339 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
3c9b8860
TG
1340 log_warning_link(link,
1341 "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1342 return 0;
1343 }
1344
1345 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1346 if (r < 0) {
3c9b8860
TG
1347 log_warning_link(link,
1348 "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1349 return 0;
1350 }
1351
1352 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1353 if (r < 0) {
3c9b8860
TG
1354 log_warning_link(link,
1355 "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1356 return 0;
1357 }
1358
81163121
TG
1359 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1360 if (r < 0) {
1361 log_warning_link(link,
1362 "rtnl: received address with invalid flags, ignoring");
1363 return 0;
1364 }
1365
fbbeb65a
TG
1366 switch (address->family) {
1367 case AF_INET:
3c9b8860
TG
1368 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL,
1369 &address->in_addr.in);
fbbeb65a 1370 if (r < 0) {
3c9b8860
TG
1371 log_warning_link(link,
1372 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1373 return 0;
1374 }
1375
1376 break;
1377
1378 case AF_INET6:
3c9b8860
TG
1379 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS,
1380 &address->in_addr.in6);
fbbeb65a 1381 if (r < 0) {
3c9b8860
TG
1382 log_warning_link(link,
1383 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1384 return 0;
1385 }
1386
1387 break;
1388
1389 default:
1390 assert_not_reached("invalid address family");
1391 }
1392
3c9b8860
TG
1393 if (!inet_ntop(address->family, &address->in_addr, buf,
1394 INET6_ADDRSTRLEN)) {
987efa17 1395 log_warning_link(link, "could not print address");
fbbeb65a
TG
1396 return 0;
1397 }
1398
c6d3b303
TG
1399 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO,
1400 &address->cinfo);
1401 if (r >= 0) {
1402 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1403 valid_str = "ever";
1404 else
1405 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1406 address->cinfo.ifa_valid * USEC_PER_SEC,
1407 USEC_PER_SEC);
1408 }
1409
428fd0a7
TG
1410 LIST_FOREACH(addresses, ad, link->addresses) {
1411 if (address_equal(ad, address)) {
1412 LIST_REMOVE(addresses, link->addresses, ad);
1413
1414 address_free(ad);
1415
1416 address_dropped = true;
1417
1418 break;
1419 }
1420 }
1421
fbbeb65a
TG
1422 switch (type) {
1423 case RTM_NEWADDR:
428fd0a7 1424 if (!address_dropped)
c6d3b303
TG
1425 log_debug_link(link, "added address: %s/%u (valid for %s)",
1426 buf, address->prefixlen,
1427 strna(valid_str));
393c0c5e 1428 else
c6d3b303
TG
1429 log_debug_link(link, "updated address: %s/%u (valid for %s)",
1430 buf, address->prefixlen,
1431 strna(valid_str));
fbbeb65a 1432
428fd0a7
TG
1433 LIST_PREPEND(addresses, link->addresses, address);
1434 address = NULL;
1435
f5602be9
TG
1436 link_save(link);
1437
428fd0a7 1438 break;
fbbeb65a 1439 case RTM_DELADDR:
f5602be9 1440 if (address_dropped) {
c6d3b303
TG
1441 log_debug_link(link, "removed address: %s/%u (valid for %s)",
1442 buf, address->prefixlen,
1443 strna(valid_str));
428fd0a7 1444
f5602be9 1445 link_save(link);
393c0c5e 1446 } else
3c9b8860 1447 log_warning_link(link,
c6d3b303
TG
1448 "removing non-existent address: %s/%u (valid for %s)",
1449 buf, address->prefixlen,
1450 strna(valid_str));
f5602be9 1451
fbbeb65a
TG
1452 break;
1453 default:
1454 assert_not_reached("Received invalid RTNL message type");
1455 }
1456
1457 return 1;
1458}
1459
505f8da7
TG
1460int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1461 Link *link;
fbbeb65a 1462 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1463 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1464 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1465 int r;
1466
1467 assert(m);
fbbeb65a 1468 assert(m->rtnl);
505f8da7
TG
1469 assert(message);
1470 assert(ret);
1471
1472 r = link_new(m, message, ret);
1473 if (r < 0)
1474 return r;
1475
1476 link = *ret;
1477
ae06ab10 1478 log_debug_link(link, "link %d added", link->ifindex);
505f8da7 1479
3c9b8860
TG
1480 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex,
1481 0);
fbbeb65a
TG
1482 if (r < 0)
1483 return r;
1484
3c9b8860
TG
1485 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0,
1486 NULL);
fbbeb65a
TG
1487 if (r < 0)
1488 return r;
1489
5da8149f
TG
1490 link_ref(link);
1491
505f8da7
TG
1492 if (detect_container(NULL) <= 0) {
1493 /* not in a container, udev will be around */
ae06ab10 1494 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1495 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1496 if (!device) {
3c9b8860
TG
1497 log_warning_link(link,
1498 "could not find udev device: %m");
9fecce80 1499 return -errno;
505f8da7
TG
1500 }
1501
3c4cb064 1502 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1503 /* not yet ready */
8434fd5c 1504 log_debug_link(link, "link pending udev initialization...");
505f8da7 1505 return 0;
3c4cb064 1506 }
505f8da7 1507
4f561e8e
TG
1508 r = link_initialized(link, device);
1509 if (r < 0)
1510 return r;
1511 } else {
5da8149f
TG
1512 /* we are calling a callback directly, so must take a ref */
1513 link_ref(link);
1514
4f561e8e
TG
1515 r = link_initialized_and_synced(m->rtnl, NULL, link);
1516 if (r < 0)
1517 return r;
1518 }
505f8da7 1519
a748b692
TG
1520 return 0;
1521}
1522
22936833 1523int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1524 struct ether_addr mac;
ca4e095a 1525 const char *ifname;
afe7fd56 1526 uint32_t mtu;
a61bb41c 1527 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
1528 int r;
1529
dd3efc09 1530 assert(link);
b8941f74 1531 assert(link->ifname);
22936833
TG
1532 assert(m);
1533
7619683b
TG
1534 if (link->state == LINK_STATE_LINGER) {
1535 link_ref(link);
1536 log_info_link(link, "link readded");
1537 link->state = LINK_STATE_ENSLAVING;
1538 }
1539
b8941f74
TG
1540 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1541 if (r >= 0 && !streq(ifname, link->ifname)) {
1542 log_info_link(link, "renamed to %s", ifname);
1543
1544 free(link->ifname);
1545 link->ifname = strdup(ifname);
1546 if (!link->ifname)
1547 return -ENOMEM;
1548 }
1549
afe7fd56
TG
1550 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1551 if (r >= 0 && mtu > 0) {
1552 link->mtu = mtu;
1553 if (!link->original_mtu) {
1554 link->original_mtu = mtu;
9842de0d 1555 log_debug_link(link, "saved original MTU: %"
afe7fd56
TG
1556 PRIu32, link->original_mtu);
1557 }
1558
1559 if (link->dhcp_client) {
3c9b8860
TG
1560 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1561 link->mtu);
afe7fd56 1562 if (r < 0) {
3c9b8860
TG
1563 log_warning_link(link,
1564 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1565 strerror(-r));
1566 return r;
1567 }
1568 }
9842de0d 1569 }
69629de9 1570
e9189a1f
TG
1571 /* The kernel may broadcast NEWLINK messages without the MAC address
1572 set, simply ignore them. */
c49b33ac 1573 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1574 if (r >= 0) {
3c9b8860
TG
1575 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1576 ETH_ALEN)) {
c49b33ac 1577
3c9b8860
TG
1578 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1579 ETH_ALEN);
c49b33ac 1580
20861203
TG
1581 log_debug_link(link, "MAC address: "
1582 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1583 mac.ether_addr_octet[0],
1584 mac.ether_addr_octet[1],
1585 mac.ether_addr_octet[2],
1586 mac.ether_addr_octet[3],
1587 mac.ether_addr_octet[4],
1588 mac.ether_addr_octet[5]);
c49b33ac 1589
20861203
TG
1590 if (link->ipv4ll) {
1591 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1592 if (r < 0) {
3c9b8860
TG
1593 log_warning_link(link,
1594 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1595 strerror(-r));
1596 return r;
1597 }
c49b33ac 1598 }
c49b33ac 1599
20861203 1600 if (link->dhcp_client) {
3c9b8860
TG
1601 r = sd_dhcp_client_set_mac(link->dhcp_client,
1602 &link->mac);
20861203 1603 if (r < 0) {
3c9b8860
TG
1604 log_warning_link(link,
1605 "Could not update MAC address in DHCP client: %s",
20861203
TG
1606 strerror(-r));
1607 return r;
1608 }
c49b33ac 1609 }
4138fb2c
PF
1610
1611 if (link->dhcp6_client) {
1612 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
1613 &link->mac);
1614 if (r < 0) {
3c9b8860
TG
1615 log_warning_link(link,
1616 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1617 strerror(-r));
1618 return r;
1619 }
1620 }
c49b33ac 1621 }
4f882b2a
TG
1622 }
1623
a61bb41c
TG
1624 had_carrier = link_has_carrier(link);
1625
1626 r = link_update_flags(link, m);
1627 if (r < 0)
1628 return r;
1629
1630 carrier_gained = !had_carrier && link_has_carrier(link);
1631 carrier_lost = had_carrier && !link_has_carrier(link);
1632
1633 if (carrier_gained) {
1634 log_info_link(link, "gained carrier");
1635
1636 if (link->network) {
1637 r = link_acquire_conf(link);
1638 if (r < 0) {
1639 link_enter_failed(link);
1640 return r;
1641 }
1642 }
1643 } else if (carrier_lost) {
1644 log_info_link(link, "lost carrier");
1645
1646 r = link_stop_clients(link);
1647 if (r < 0) {
1648 link_enter_failed(link);
1649 return r;
1650 }
1651 }
1652
1653 return 0;
dd3efc09 1654}
fe8db0c5 1655
e375dcde
TG
1656static void link_update_operstate(Link *link) {
1657
1658 assert(link);
1659
1660 if (link->kernel_operstate == IF_OPER_DORMANT)
1661 link->operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 1662 else if (link_has_carrier(link)) {
e375dcde
TG
1663 Address *address;
1664 uint8_t scope = RT_SCOPE_NOWHERE;
1665
1666 /* if we have carrier, check what addresses we have */
1667 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
1668 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
1669 continue;
1670
e375dcde
TG
1671 if (address->scope < scope)
1672 scope = address->scope;
1673 }
1674
1675 if (scope < RT_SCOPE_SITE)
1676 /* universally accessible addresses found */
1677 link->operstate = LINK_OPERSTATE_ROUTABLE;
1678 else if (scope < RT_SCOPE_HOST)
1679 /* only link or site local addresses found */
1680 link->operstate = LINK_OPERSTATE_DEGRADED;
1681 else
1682 /* no useful addresses found */
1683 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1684 } else if (link->flags & IFF_UP)
d3df0e39 1685 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1686 else
d3df0e39 1687 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1688}
1689
fe8db0c5 1690int link_save(Link *link) {
68a8723c 1691 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1692 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1693 const char *admin_state, *oper_state;
fe8db0c5
TG
1694 int r;
1695
1696 assert(link);
1697 assert(link->state_file);
68a8723c 1698 assert(link->lease_file);
bbf7c048
TG
1699 assert(link->manager);
1700
e375dcde
TG
1701 link_update_operstate(link);
1702
bbf7c048
TG
1703 r = manager_save(link->manager);
1704 if (r < 0)
1705 return r;
fe8db0c5 1706
370e9930
TG
1707 if (link->state == LINK_STATE_LINGER) {
1708 unlink(link->state_file);
1709 return 0;
1710 }
1711
deb2e523
TG
1712 admin_state = link_state_to_string(link->state);
1713 assert(admin_state);
1714
e375dcde
TG
1715 oper_state = link_operstate_to_string(link->operstate);
1716 assert(oper_state);
deb2e523 1717
fe8db0c5
TG
1718 r = fopen_temporary(link->state_file, &f, &temp_path);
1719 if (r < 0)
c2d6bd61 1720 return r;
fe8db0c5
TG
1721
1722 fchmod(fileno(f), 0644);
1723
1724 fprintf(f,
1725 "# This is private data. Do not parse.\n"
deb2e523 1726 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1727 "OPER_STATE=%s\n",
1728 admin_state, oper_state);
fe8db0c5 1729
bcb7a07e 1730 if (link->network) {
ea352b40
LP
1731 char **address, **domain;
1732 bool space;
b0e39c82
TG
1733
1734 fputs("DNS=", f);
ea352b40
LP
1735 space = false;
1736 STRV_FOREACH(address, link->network->dns) {
1737 if (space)
1738 fputc(' ', f);
1739 fputs(*address, f);
1740 space = true;
1741 }
d5314fff 1742
b0e39c82
TG
1743 if (link->network->dhcp_dns &&
1744 link->dhcp_lease) {
1745 const struct in_addr *addresses;
1746
1747 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1748 if (r > 0) {
ea352b40
LP
1749 if (space)
1750 fputc(' ', f);
b0e39c82 1751 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1752 }
1753 }
1754
b0e39c82
TG
1755 fputs("\n", f);
1756
1757 fprintf(f, "NTP=");
ea352b40
LP
1758 space = false;
1759 STRV_FOREACH(address, link->network->ntp) {
1760 if (space)
1761 fputc(' ', f);
1762 fputs(*address, f);
1763 space = true;
1764 }
d5314fff 1765
b0e39c82
TG
1766 if (link->network->dhcp_ntp &&
1767 link->dhcp_lease) {
1768 const struct in_addr *addresses;
1769
1770 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1771 if (r > 0) {
ea352b40
LP
1772 if (space)
1773 fputc(' ', f);
b0e39c82 1774 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1775 }
1776 }
1777
b0e39c82 1778 fputs("\n", f);
bd8f6538 1779
6192b846 1780 fprintf(f, "DOMAINS=");
ea352b40
LP
1781 space = false;
1782 STRV_FOREACH(domain, link->network->domains) {
1783 if (space)
1784 fputc(' ', f);
1785 fputs(*domain, f);
1786 space = true;
1787 }
d5314fff 1788
ad0734e8 1789 if (link->network->dhcp_domains &&
9b4d1882
TG
1790 link->dhcp_lease) {
1791 const char *domainname;
1792
1793 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 1794 if (r >= 0) {
ea352b40
LP
1795 if (space)
1796 fputc(' ', f);
6192b846 1797 fputs(domainname, f);
6192b846 1798 }
9b4d1882
TG
1799 }
1800
6192b846
TG
1801 fputs("\n", f);
1802
67272d15
TG
1803 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1804 yes_no(link->network->wildcard_domain));
1805
3c9b8860
TG
1806 fprintf(f, "LLMNR=%s\n",
1807 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1808 }
7374f9d8 1809
fe8db0c5 1810 if (link->dhcp_lease) {
d9876a52
TG
1811 assert(link->network);
1812
68a8723c 1813 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1814 if (r < 0)
c2d6bd61 1815 goto fail;
fe8db0c5 1816
7374f9d8 1817 fprintf(f,
b0e39c82
TG
1818 "DHCP_LEASE=%s\n",
1819 link->lease_file);
deb2e523 1820 } else
68a8723c 1821 unlink(link->lease_file);
fe8db0c5 1822
c2d6bd61
LP
1823 r = fflush_and_check(f);
1824 if (r < 0)
1825 goto fail;
fe8db0c5 1826
c2d6bd61 1827 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1828 r = -errno;
c2d6bd61 1829 goto fail;
fe8db0c5
TG
1830 }
1831
c2d6bd61 1832 return 0;
c2d6bd61
LP
1833fail:
1834 log_error_link(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
1835 unlink(link->state_file);
1836 unlink(temp_path);
fe8db0c5
TG
1837 return r;
1838}
1839
1840static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1841 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1842 [LINK_STATE_ENSLAVING] = "configuring",
1843 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1844 [LINK_STATE_SETTING_ROUTES] = "configuring",
1845 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1846 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1847 [LINK_STATE_FAILED] = "failed",
370e9930 1848 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1849};
1850
1851DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1852
1853static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1854 [LINK_OPERSTATE_OFF] = "off",
1855 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1856 [LINK_OPERSTATE_DORMANT] = "dormant",
1857 [LINK_OPERSTATE_CARRIER] = "carrier",
1858 [LINK_OPERSTATE_DEGRADED] = "degraded",
1859 [LINK_OPERSTATE_ROUTABLE] = "routable",
1860};
1861
1862DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);