]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: remove "*" from domains list
[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
bbf7c048 866bool link_has_carrier(unsigned flags, uint8_t operstate) {
deb2e523
TG
867 /* see Documentation/networking/operstates.txt in the kernel sources */
868
869 if (operstate == IF_OPER_UP)
870 return true;
871
872 if (operstate == IF_OPER_UNKNOWN)
873 /* operstate may not be implemented, so fall back to flags */
874 if ((flags & IFF_LOWER_UP) && !(flags & IFF_DORMANT))
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
TG
887 uint8_t operstate;
888 bool carrier_gained = false, carrier_lost = false;
ff254138
TG
889 int r;
890
891 assert(link);
ff254138 892
1e9be60b
TG
893 r = sd_rtnl_message_link_get_flags(m, &flags);
894 if (r < 0) {
895 log_warning_link(link, "Could not get link flags");
896 return r;
897 }
898
899 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
900 if (r < 0)
901 /* if we got a message without operstate, take it to mean
902 the state was unchanged */
e375dcde 903 operstate = link->kernel_operstate;
1e9be60b 904
e375dcde 905 if ((link->flags == flags) && (link->kernel_operstate == operstate))
efbc88b8 906 return 0;
efbc88b8 907
389cc5f7
TG
908 if (link->flags != flags) {
909 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",
910 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
911 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
912 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
913 FLAG_STRING("UP", IFF_UP, link->flags, flags),
914 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
915 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
916 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
917 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
918 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
919 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
920 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
921 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
922 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
923 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
924 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
925 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
926 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
927 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
928 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
929
930 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
931 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
932 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
933 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
934 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
935 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
936 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
937 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
938
3c9b8860
TG
939 /* link flags are currently at most 18 bits, let's align to
940 * printing 20 */
389cc5f7 941 if (unknown_flags_added)
3c9b8860
TG
942 log_debug_link(link,
943 "unknown link flags gained: %#.5x (ignoring)",
389cc5f7
TG
944 unknown_flags_added);
945
946 if (unknown_flags_removed)
3c9b8860
TG
947 log_debug_link(link,
948 "unknown link flags lost: %#.5x (ignoring)",
389cc5f7
TG
949 unknown_flags_removed);
950 }
505f8da7 951
e375dcde 952 carrier_gained = !link_has_carrier(link->flags, link->kernel_operstate) &&
1e9be60b 953 link_has_carrier(flags, operstate);
e375dcde 954 carrier_lost = link_has_carrier(link->flags, link->kernel_operstate) &&
1e9be60b
TG
955 !link_has_carrier(flags, operstate);
956
957 link->flags = flags;
e375dcde 958 link->kernel_operstate = operstate;
1e9be60b 959
deb2e523
TG
960 link_save(link);
961
99b4cc3e
TG
962 if (link->state == LINK_STATE_FAILED ||
963 link->state == LINK_STATE_UNMANAGED)
964 return 0;
965
7cc832b9
TG
966 if (carrier_gained) {
967 log_info_link(link, "gained carrier");
ffba6166 968
1e9be60b 969 if (link->network) {
ffba6166
TG
970 r = link_acquire_conf(link);
971 if (r < 0) {
ffba6166
TG
972 link_enter_failed(link);
973 return r;
ff254138 974 }
ffba6166 975 }
7cc832b9
TG
976 } else if (carrier_lost) {
977 log_info_link(link, "lost carrier");
efbc88b8 978
1e9be60b
TG
979 r = link_stop_clients(link);
980 if (r < 0) {
981 link_enter_failed(link);
982 return r;
ff254138
TG
983 }
984 }
985
ff254138
TG
986 return 0;
987}
988
dd3efc09 989static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 990 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
991 int r;
992
1746cf2a
TG
993 assert(link);
994
5da8149f 995 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
996 return 1;
997
dd3efc09 998 r = sd_rtnl_message_get_errno(m);
45ad2c13 999 if (r < 0) {
9b86b393
TG
1000 /* we warn but don't fail the link, as it may
1001 be brought up later */
76800848 1002 log_struct_link(LOG_WARNING, link,
97578344 1003 "MESSAGE=%-*s: could not bring up interface: %s",
987efa17 1004 IFNAMSIZ,
c9ccc19f
TG
1005 link->ifname, strerror(-r),
1006 "ERRNO=%d", -r,
1007 NULL);
45ad2c13
TG
1008 }
1009
f882c247
TG
1010 return 1;
1011}
1012
1013static int link_up(Link *link) {
cf6a8911 1014 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1015 int r;
1016
f882c247
TG
1017 assert(link);
1018 assert(link->manager);
1019 assert(link->manager->rtnl);
1020
39032b87 1021 log_debug_link(link, "bringing link up");
449f7554 1022
151b9b96
LP
1023 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1024 RTM_SETLINK, link->ifindex);
f579559b 1025 if (r < 0) {
39032b87 1026 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1027 return r;
1028 }
1029
5d4795f3 1030 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1031 if (r < 0) {
3c9b8860
TG
1032 log_error_link(link, "Could not set link flags: %s",
1033 strerror(-r));
fc25d7f8
TG
1034 return r;
1035 }
1036
3c9b8860
TG
1037 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1038 0, NULL);
f579559b 1039 if (r < 0) {
3333d748 1040 log_error_link(link,
3c9b8860
TG
1041 "Could not send rtnetlink message: %s",
1042 strerror(-r));
f579559b
TG
1043 return r;
1044 }
1045
b226d99b
TG
1046 link_ref(link);
1047
f882c247
TG
1048 return 0;
1049}
1050
3f265037 1051static int link_joined(Link *link) {
f882c247
TG
1052 int r;
1053
ef1ba606 1054 assert(link);
52433f6b 1055 assert(link->state == LINK_STATE_ENSLAVING);
f5be5601 1056 assert(link->network);
dd3efc09 1057
505f8da7
TG
1058 if (!(link->flags & IFF_UP)) {
1059 r = link_up(link);
1060 if (r < 0) {
1061 link_enter_failed(link);
1062 return r;
1063 }
ef1ba606 1064 }
f882c247 1065
fb6730c4 1066 return link_enter_set_addresses(link);
02b59d57
TG
1067}
1068
3c9b8860
TG
1069static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1070 void *userdata) {
5da8149f 1071 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1072 int r;
1073
1746cf2a 1074 assert(link);
370e9930
TG
1075 assert(IN_SET(link->state, LINK_STATE_ENSLAVING, LINK_STATE_FAILED,
1076 LINK_STATE_LINGER));
ef1ba606 1077 assert(link->network);
02b59d57 1078
52433f6b
TG
1079 link->enslaving --;
1080
5da8149f 1081 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1082 return 1;
1083
1084 r = sd_rtnl_message_get_errno(m);
856f962c 1085 if (r < 0 && r != -EEXIST) {
c9ccc19f 1086 log_struct_link(LOG_ERR, link,
3f265037 1087 "MESSAGE=%-*s: could not join netdev: %s",
987efa17 1088 IFNAMSIZ,
c9ccc19f
TG
1089 link->ifname, strerror(-r),
1090 "ERRNO=%d", -r,
1091 NULL);
ef1ba606
TG
1092 link_enter_failed(link);
1093 return 1;
ba179154
TG
1094 } else
1095 log_debug_link(link, "joined netdev");
02b59d57 1096
856f962c 1097 if (link->enslaving <= 0)
3f265037 1098 link_joined(link);
02b59d57
TG
1099
1100 return 1;
1101}
1102
3f265037 1103static int link_enter_join_netdev(Link *link) {
6a0a2f86 1104 NetDev *netdev;
672682a6 1105 Iterator i;
02b59d57
TG
1106 int r;
1107
1108 assert(link);
1109 assert(link->network);
8434fd5c 1110 assert(link->state == LINK_STATE_PENDING);
02b59d57 1111
52433f6b 1112 link->state = LINK_STATE_ENSLAVING;
02b59d57 1113
fe8db0c5
TG
1114 link_save(link);
1115
7951dea2
SS
1116 if (!link->network->bridge &&
1117 !link->network->bond &&
6a0a2f86 1118 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1119 return link_joined(link);
02b59d57 1120
d9c67ea1 1121 if (link->network->bond) {
52433f6b 1122 log_struct_link(LOG_DEBUG, link,
97578344 1123 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1124 IFNAMSIZ,
af4e9e2c 1125 link->ifname, link->network->bond->ifname,
aa9f1140 1126 NETDEVIF(link->network->bond),
52433f6b 1127 NULL);
449f7554 1128
3f265037 1129 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b
TG
1130 if (r < 0) {
1131 log_struct_link(LOG_WARNING, link,
3f265037 1132 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1133 IFNAMSIZ,
3c9b8860
TG
1134 link->ifname, link->network->bond->ifname,
1135 strerror(-r),
aa9f1140 1136 NETDEVIF(link->network->bond),
52433f6b
TG
1137 NULL);
1138 link_enter_failed(link);
1139 return r;
1140 }
1141
0ad6148e
MO
1142 link->enslaving ++;
1143 }
1144
d9c67ea1 1145 if (link->network->bridge) {
0ad6148e 1146 log_struct_link(LOG_DEBUG, link,
97578344 1147 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1148 IFNAMSIZ,
af4e9e2c 1149 link->ifname, link->network->bridge->ifname,
aa9f1140 1150 NETDEVIF(link->network->bridge),
0ad6148e
MO
1151 NULL);
1152
3c9b8860
TG
1153 r = netdev_join(link->network->bridge, link,
1154 &netdev_join_handler);
0ad6148e
MO
1155 if (r < 0) {
1156 log_struct_link(LOG_WARNING, link,
3f265037 1157 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1158 IFNAMSIZ,
3c9b8860
TG
1159 link->ifname, link->network->bridge->ifname,
1160 strerror(-r),
aa9f1140 1161 NETDEVIF(link->network->bridge),
0ad6148e
MO
1162 NULL);
1163 link_enter_failed(link);
1164 return r;
1165 }
1166
52433f6b
TG
1167 link->enslaving ++;
1168 }
1169
6a0a2f86 1170 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1171 log_struct_link(LOG_DEBUG, link,
97578344 1172 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1173 IFNAMSIZ,
3c9b8860
TG
1174 link->ifname, netdev->ifname, NETDEVIF(netdev),
1175 NULL);
7951dea2 1176
6a0a2f86 1177 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2
SS
1178 if (r < 0) {
1179 log_struct_link(LOG_WARNING, link,
3f265037 1180 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1181 IFNAMSIZ,
3c9b8860
TG
1182 link->ifname, netdev->ifname,
1183 strerror(-r),
6a0a2f86 1184 NETDEVIF(netdev), NULL);
326cb406
SS
1185 link_enter_failed(link);
1186 return r;
1187 }
1188
326cb406
SS
1189 link->enslaving ++;
1190 }
1191
ef1ba606
TG
1192 return 0;
1193}
1194
a748b692 1195static int link_configure(Link *link) {
02b59d57
TG
1196 int r;
1197
ef1ba606 1198 assert(link);
b22d8a00 1199 assert(link->network);
8434fd5c 1200 assert(link->state == LINK_STATE_PENDING);
a748b692 1201
eb34d4af 1202 if (link->network->ipv4ll) {
b22d8a00 1203 r = ipv4ll_configure(link);
eb34d4af
TG
1204 if (r < 0)
1205 return r;
1206 }
1207
ed942a9e 1208 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4)) {
3c9b8860 1209 r = dhcp4_configure(link);
eb34d4af
TG
1210 if (r < 0)
1211 return r;
eb34d4af
TG
1212 }
1213
dd43110f 1214 if (link->network->dhcp_server) {
dd43110f
TG
1215 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1216 if (r < 0)
1217 return r;
1218
1219 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1220 if (r < 0)
1221 return r;
dd43110f
TG
1222 }
1223
ed942a9e 1224 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
1225 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1226 if (r < 0)
1227 return r;
1228
1229 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1230 NULL, 0);
1231 if (r < 0)
1232 return r;
1233
1234 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1235 &link->mac);
1236 if (r < 0)
1237 return r;
1238
1239 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1240 link->ifindex);
1241 if (r < 0)
1242 return r;
1243
1244 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1245 icmp6_router_handler, link);
1246 if (r < 0)
1247 return r;
1248 }
1249
bf0308cb 1250 if (link_has_carrier(link->flags, link->kernel_operstate)) {
1e9be60b
TG
1251 r = link_acquire_conf(link);
1252 if (r < 0)
1253 return r;
cc544d5f 1254 }
1e9be60b 1255
3f265037 1256 return link_enter_join_netdev(link);
505f8da7
TG
1257}
1258
3c9b8860
TG
1259static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1260 void *userdata) {
5da8149f 1261 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1262 Network *network;
505f8da7
TG
1263 int r;
1264
1265 assert(link);
1266 assert(link->ifname);
1267 assert(link->manager);
1268
8434fd5c 1269 if (link->state != LINK_STATE_PENDING)
5da8149f 1270 return 1;
505f8da7 1271
4f561e8e 1272 log_debug_link(link, "link state is up-to-date");
505f8da7 1273
3c9b8860
TG
1274 r = network_get(link->manager, link->udev_device, link->ifname,
1275 &link->mac, &network);
57bd6899
TG
1276 if (r == -ENOENT) {
1277 link_enter_unmanaged(link);
5da8149f 1278 return 1;
57bd6899
TG
1279 } else if (r < 0)
1280 return r;
505f8da7
TG
1281
1282 r = network_apply(link->manager, network, link);
1283 if (r < 0)
1284 return r;
1285
a748b692
TG
1286 r = link_configure(link);
1287 if (r < 0)
1288 return r;
1289
5da8149f 1290 return 1;
505f8da7
TG
1291}
1292
4f561e8e
TG
1293int link_initialized(Link *link, struct udev_device *device) {
1294 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1295 int r;
1296
1297 assert(link);
1298 assert(link->manager);
1299 assert(link->manager->rtnl);
1300 assert(device);
1301
8434fd5c 1302 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1303 return 0;
1304
679b3605
TG
1305 if (link->udev_device)
1306 return 0;
1307
4f561e8e
TG
1308 log_debug_link(link, "udev initialized link");
1309
1310 link->udev_device = udev_device_ref(device);
1311
3c9b8860
TG
1312 /* udev has initialized the link, but we don't know if we have yet
1313 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1314 * when it returns we know that the pending NEWLINKs have already been
1315 * processed and that we are up-to-date */
4f561e8e 1316
3c9b8860
TG
1317 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1318 link->ifindex);
4f561e8e
TG
1319 if (r < 0)
1320 return r;
1321
3c9b8860
TG
1322 r = sd_rtnl_call_async(link->manager->rtnl, req,
1323 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1324 if (r < 0)
1325 return r;
1326
5da8149f
TG
1327 link_ref(link);
1328
4f561e8e
TG
1329 return 0;
1330}
1331
3c9b8860
TG
1332int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message,
1333 void *userdata) {
fbbeb65a
TG
1334 Manager *m = userdata;
1335 Link *link = NULL;
1336 uint16_t type;
1337 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1338 Address *ad;
fbbeb65a 1339 char buf[INET6_ADDRSTRLEN];
c6d3b303
TG
1340 char valid_buf[FORMAT_TIMESPAN_MAX];
1341 const char *valid_str = NULL;
428fd0a7 1342 bool address_dropped = false;
fbbeb65a
TG
1343 int r, ifindex;
1344
1345 assert(rtnl);
1346 assert(message);
1347 assert(m);
1348
1349 r = sd_rtnl_message_get_type(message, &type);
1350 if (r < 0) {
1351 log_warning("rtnl: could not get message type");
1352 return 0;
1353 }
1354
1355 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1356 if (r < 0 || ifindex <= 0) {
5ea846cc 1357 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1358 return 0;
1359 } else {
1360 r = link_get(m, ifindex, &link);
1361 if (r < 0 || !link) {
5ea846cc 1362 log_warning("rtnl: received address for a nonexistent link, ignoring");
fbbeb65a
TG
1363 return 0;
1364 }
1365 }
1366
1367 r = address_new_dynamic(&address);
1368 if (r < 0)
393c0c5e 1369 return r;
fbbeb65a
TG
1370
1371 r = sd_rtnl_message_addr_get_family(message, &address->family);
1372 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
3c9b8860
TG
1373 log_warning_link(link,
1374 "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1375 return 0;
1376 }
1377
1378 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1379 if (r < 0) {
3c9b8860
TG
1380 log_warning_link(link,
1381 "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1382 return 0;
1383 }
1384
1385 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1386 if (r < 0) {
3c9b8860
TG
1387 log_warning_link(link,
1388 "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1389 return 0;
1390 }
1391
1392 switch (address->family) {
1393 case AF_INET:
3c9b8860
TG
1394 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL,
1395 &address->in_addr.in);
fbbeb65a 1396 if (r < 0) {
3c9b8860
TG
1397 log_warning_link(link,
1398 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1399 return 0;
1400 }
1401
1402 break;
1403
1404 case AF_INET6:
3c9b8860
TG
1405 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS,
1406 &address->in_addr.in6);
fbbeb65a 1407 if (r < 0) {
3c9b8860
TG
1408 log_warning_link(link,
1409 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1410 return 0;
1411 }
1412
1413 break;
1414
1415 default:
1416 assert_not_reached("invalid address family");
1417 }
1418
3c9b8860
TG
1419 if (!inet_ntop(address->family, &address->in_addr, buf,
1420 INET6_ADDRSTRLEN)) {
987efa17 1421 log_warning_link(link, "could not print address");
fbbeb65a
TG
1422 return 0;
1423 }
1424
c6d3b303
TG
1425 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO,
1426 &address->cinfo);
1427 if (r >= 0) {
1428 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1429 valid_str = "ever";
1430 else
1431 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1432 address->cinfo.ifa_valid * USEC_PER_SEC,
1433 USEC_PER_SEC);
1434 }
1435
428fd0a7
TG
1436 LIST_FOREACH(addresses, ad, link->addresses) {
1437 if (address_equal(ad, address)) {
1438 LIST_REMOVE(addresses, link->addresses, ad);
1439
1440 address_free(ad);
1441
1442 address_dropped = true;
1443
1444 break;
1445 }
1446 }
1447
fbbeb65a
TG
1448 switch (type) {
1449 case RTM_NEWADDR:
428fd0a7 1450 if (!address_dropped)
c6d3b303
TG
1451 log_debug_link(link, "added address: %s/%u (valid for %s)",
1452 buf, address->prefixlen,
1453 strna(valid_str));
393c0c5e 1454 else
c6d3b303
TG
1455 log_debug_link(link, "updated address: %s/%u (valid for %s)",
1456 buf, address->prefixlen,
1457 strna(valid_str));
fbbeb65a 1458
428fd0a7
TG
1459 LIST_PREPEND(addresses, link->addresses, address);
1460 address = NULL;
1461
f5602be9
TG
1462 link_save(link);
1463
428fd0a7 1464 break;
fbbeb65a 1465 case RTM_DELADDR:
f5602be9 1466 if (address_dropped) {
c6d3b303
TG
1467 log_debug_link(link, "removed address: %s/%u (valid for %s)",
1468 buf, address->prefixlen,
1469 strna(valid_str));
428fd0a7 1470
f5602be9 1471 link_save(link);
393c0c5e 1472 } else
3c9b8860 1473 log_warning_link(link,
c6d3b303
TG
1474 "removing non-existent address: %s/%u (valid for %s)",
1475 buf, address->prefixlen,
1476 strna(valid_str));
f5602be9 1477
fbbeb65a
TG
1478 break;
1479 default:
1480 assert_not_reached("Received invalid RTNL message type");
1481 }
1482
1483 return 1;
1484}
1485
505f8da7
TG
1486int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1487 Link *link;
fbbeb65a 1488 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1489 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1490 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1491 int r;
1492
1493 assert(m);
fbbeb65a 1494 assert(m->rtnl);
505f8da7
TG
1495 assert(message);
1496 assert(ret);
1497
1498 r = link_new(m, message, ret);
1499 if (r < 0)
1500 return r;
1501
1502 link = *ret;
1503
ae06ab10 1504 log_debug_link(link, "link %d added", link->ifindex);
505f8da7 1505
3c9b8860
TG
1506 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex,
1507 0);
fbbeb65a
TG
1508 if (r < 0)
1509 return r;
1510
3c9b8860
TG
1511 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0,
1512 NULL);
fbbeb65a
TG
1513 if (r < 0)
1514 return r;
1515
5da8149f
TG
1516 link_ref(link);
1517
505f8da7
TG
1518 if (detect_container(NULL) <= 0) {
1519 /* not in a container, udev will be around */
ae06ab10 1520 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1521 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1522 if (!device) {
3c9b8860
TG
1523 log_warning_link(link,
1524 "could not find udev device: %m");
9fecce80 1525 return -errno;
505f8da7
TG
1526 }
1527
3c4cb064 1528 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1529 /* not yet ready */
8434fd5c 1530 log_debug_link(link, "link pending udev initialization...");
505f8da7 1531 return 0;
3c4cb064 1532 }
505f8da7 1533
4f561e8e
TG
1534 r = link_initialized(link, device);
1535 if (r < 0)
1536 return r;
1537 } else {
5da8149f
TG
1538 /* we are calling a callback directly, so must take a ref */
1539 link_ref(link);
1540
4f561e8e
TG
1541 r = link_initialized_and_synced(m->rtnl, NULL, link);
1542 if (r < 0)
1543 return r;
1544 }
505f8da7 1545
a748b692
TG
1546 return 0;
1547}
1548
22936833 1549int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1550 struct ether_addr mac;
ca4e095a 1551 const char *ifname;
afe7fd56 1552 uint32_t mtu;
22936833
TG
1553 int r;
1554
dd3efc09 1555 assert(link);
b8941f74 1556 assert(link->ifname);
22936833
TG
1557 assert(m);
1558
7619683b
TG
1559 if (link->state == LINK_STATE_LINGER) {
1560 link_ref(link);
1561 log_info_link(link, "link readded");
1562 link->state = LINK_STATE_ENSLAVING;
1563 }
1564
b8941f74
TG
1565 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1566 if (r >= 0 && !streq(ifname, link->ifname)) {
1567 log_info_link(link, "renamed to %s", ifname);
1568
1569 free(link->ifname);
1570 link->ifname = strdup(ifname);
1571 if (!link->ifname)
1572 return -ENOMEM;
1573 }
1574
afe7fd56
TG
1575 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1576 if (r >= 0 && mtu > 0) {
1577 link->mtu = mtu;
1578 if (!link->original_mtu) {
1579 link->original_mtu = mtu;
9842de0d 1580 log_debug_link(link, "saved original MTU: %"
afe7fd56
TG
1581 PRIu32, link->original_mtu);
1582 }
1583
1584 if (link->dhcp_client) {
3c9b8860
TG
1585 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1586 link->mtu);
afe7fd56 1587 if (r < 0) {
3c9b8860
TG
1588 log_warning_link(link,
1589 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1590 strerror(-r));
1591 return r;
1592 }
1593 }
9842de0d 1594 }
69629de9 1595
e9189a1f
TG
1596 /* The kernel may broadcast NEWLINK messages without the MAC address
1597 set, simply ignore them. */
c49b33ac 1598 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1599 if (r >= 0) {
3c9b8860
TG
1600 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1601 ETH_ALEN)) {
c49b33ac 1602
3c9b8860
TG
1603 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1604 ETH_ALEN);
c49b33ac 1605
20861203
TG
1606 log_debug_link(link, "MAC address: "
1607 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1608 mac.ether_addr_octet[0],
1609 mac.ether_addr_octet[1],
1610 mac.ether_addr_octet[2],
1611 mac.ether_addr_octet[3],
1612 mac.ether_addr_octet[4],
1613 mac.ether_addr_octet[5]);
c49b33ac 1614
20861203
TG
1615 if (link->ipv4ll) {
1616 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1617 if (r < 0) {
3c9b8860
TG
1618 log_warning_link(link,
1619 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1620 strerror(-r));
1621 return r;
1622 }
c49b33ac 1623 }
c49b33ac 1624
20861203 1625 if (link->dhcp_client) {
3c9b8860
TG
1626 r = sd_dhcp_client_set_mac(link->dhcp_client,
1627 &link->mac);
20861203 1628 if (r < 0) {
3c9b8860
TG
1629 log_warning_link(link,
1630 "Could not update MAC address in DHCP client: %s",
20861203
TG
1631 strerror(-r));
1632 return r;
1633 }
c49b33ac 1634 }
4138fb2c
PF
1635
1636 if (link->dhcp6_client) {
1637 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
1638 &link->mac);
1639 if (r < 0) {
3c9b8860
TG
1640 log_warning_link(link,
1641 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1642 strerror(-r));
1643 return r;
1644 }
1645 }
c49b33ac 1646 }
4f882b2a
TG
1647 }
1648
1e9be60b 1649 return link_update_flags(link, m);
dd3efc09 1650}
fe8db0c5 1651
e375dcde
TG
1652static void link_update_operstate(Link *link) {
1653
1654 assert(link);
1655
1656 if (link->kernel_operstate == IF_OPER_DORMANT)
1657 link->operstate = LINK_OPERSTATE_DORMANT;
1658 else if (link_has_carrier(link->flags, link->kernel_operstate)) {
1659 Address *address;
1660 uint8_t scope = RT_SCOPE_NOWHERE;
1661
1662 /* if we have carrier, check what addresses we have */
1663 LIST_FOREACH(addresses, address, link->addresses) {
1664 if (address->scope < scope)
1665 scope = address->scope;
1666 }
1667
1668 if (scope < RT_SCOPE_SITE)
1669 /* universally accessible addresses found */
1670 link->operstate = LINK_OPERSTATE_ROUTABLE;
1671 else if (scope < RT_SCOPE_HOST)
1672 /* only link or site local addresses found */
1673 link->operstate = LINK_OPERSTATE_DEGRADED;
1674 else
1675 /* no useful addresses found */
1676 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1677 } else if (link->flags & IFF_UP)
d3df0e39 1678 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1679 else
d3df0e39 1680 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1681}
1682
fe8db0c5 1683int link_save(Link *link) {
68a8723c 1684 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1685 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1686 const char *admin_state, *oper_state;
fe8db0c5
TG
1687 int r;
1688
1689 assert(link);
1690 assert(link->state_file);
68a8723c 1691 assert(link->lease_file);
bbf7c048
TG
1692 assert(link->manager);
1693
e375dcde
TG
1694 link_update_operstate(link);
1695
bbf7c048
TG
1696 r = manager_save(link->manager);
1697 if (r < 0)
1698 return r;
fe8db0c5 1699
370e9930
TG
1700 if (link->state == LINK_STATE_LINGER) {
1701 unlink(link->state_file);
1702 return 0;
1703 }
1704
deb2e523
TG
1705 admin_state = link_state_to_string(link->state);
1706 assert(admin_state);
1707
e375dcde
TG
1708 oper_state = link_operstate_to_string(link->operstate);
1709 assert(oper_state);
deb2e523 1710
fe8db0c5
TG
1711 r = fopen_temporary(link->state_file, &f, &temp_path);
1712 if (r < 0)
c2d6bd61 1713 return r;
fe8db0c5
TG
1714
1715 fchmod(fileno(f), 0644);
1716
1717 fprintf(f,
1718 "# This is private data. Do not parse.\n"
deb2e523 1719 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1720 "OPER_STATE=%s\n",
1721 admin_state, oper_state);
fe8db0c5 1722
bcb7a07e 1723 if (link->network) {
b0e39c82 1724 char **address;
6192b846 1725 char **domain;
b0e39c82
TG
1726
1727 fputs("DNS=", f);
1728
1729 if (link->network->dhcp_dns &&
1730 link->dhcp_lease) {
1731 const struct in_addr *addresses;
1732
1733 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1734 if (r > 0) {
1735 serialize_in_addrs(f, addresses, r);
1736 if (link->network->dns)
1737 fputs(" ", f);
1738 }
1739 }
1740
1741 STRV_FOREACH(address, link->network->dns)
1742 fprintf(f, "%s%s", *address,
1743 (address + 1 ? " " : ""));
1744
1745 fputs("\n", f);
1746
1747 fprintf(f, "NTP=");
1748
1749 if (link->network->dhcp_ntp &&
1750 link->dhcp_lease) {
1751 const struct in_addr *addresses;
1752
1753 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1754 if (r > 0) {
1755 serialize_in_addrs(f, addresses, r);
1756 if (link->network->ntp)
1757 fputs(" ", f);
1758 }
1759 }
1760
1761 STRV_FOREACH(address, link->network->ntp)
1762 fprintf(f, "%s%s", *address,
1763 (address + 1 ? " " : ""));
1764
1765 fputs("\n", f);
bd8f6538 1766
6192b846
TG
1767 fprintf(f, "DOMAINS=");
1768
ad0734e8 1769 if (link->network->dhcp_domains &&
9b4d1882
TG
1770 link->dhcp_lease) {
1771 const char *domainname;
1772
1773 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846
TG
1774 if (r >= 0) {
1775 fputs(domainname, f);
1776 if (link->network->domains)
1777 fputs(" ", f);
1778 }
9b4d1882
TG
1779 }
1780
6192b846
TG
1781 STRV_FOREACH(domain, link->network->domains)
1782 fprintf(f, "%s%s", *domain,
1783 (domain + 1 ? " " : ""));
1784
1785 fputs("\n", f);
1786
67272d15
TG
1787 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1788 yes_no(link->network->wildcard_domain));
1789
3c9b8860
TG
1790 fprintf(f, "LLMNR=%s\n",
1791 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1792 }
7374f9d8 1793
fe8db0c5 1794 if (link->dhcp_lease) {
d9876a52
TG
1795 assert(link->network);
1796
68a8723c 1797 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1798 if (r < 0)
c2d6bd61 1799 goto fail;
fe8db0c5 1800
7374f9d8 1801 fprintf(f,
b0e39c82
TG
1802 "DHCP_LEASE=%s\n",
1803 link->lease_file);
deb2e523 1804 } else
68a8723c 1805 unlink(link->lease_file);
fe8db0c5 1806
c2d6bd61
LP
1807 r = fflush_and_check(f);
1808 if (r < 0)
1809 goto fail;
fe8db0c5 1810
c2d6bd61 1811 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1812 r = -errno;
c2d6bd61 1813 goto fail;
fe8db0c5
TG
1814 }
1815
c2d6bd61 1816 return 0;
c2d6bd61
LP
1817fail:
1818 log_error_link(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
1819 unlink(link->state_file);
1820 unlink(temp_path);
fe8db0c5
TG
1821 return r;
1822}
1823
1824static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1825 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1826 [LINK_STATE_ENSLAVING] = "configuring",
1827 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1828 [LINK_STATE_SETTING_ROUTES] = "configuring",
1829 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1830 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1831 [LINK_STATE_FAILED] = "failed",
370e9930 1832 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1833};
1834
1835DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1836
1837static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1838 [LINK_OPERSTATE_OFF] = "off",
1839 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1840 [LINK_OPERSTATE_DORMANT] = "dormant",
1841 [LINK_OPERSTATE_CARRIER] = "carrier",
1842 [LINK_OPERSTATE_DEGRADED] = "degraded",
1843 [LINK_OPERSTATE_ROUTABLE] = "routable",
1844};
1845
1846DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);