]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
Update TODO
[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);
f5be5601 1055 assert(link->network);
dd3efc09 1056
505f8da7
TG
1057 if (!(link->flags & IFF_UP)) {
1058 r = link_up(link);
1059 if (r < 0) {
1060 link_enter_failed(link);
1061 return r;
1062 }
ef1ba606 1063 }
f882c247 1064
fb6730c4 1065 return link_enter_set_addresses(link);
02b59d57
TG
1066}
1067
3c9b8860
TG
1068static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1069 void *userdata) {
5da8149f 1070 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1071 int r;
1072
1746cf2a 1073 assert(link);
ef1ba606 1074 assert(link->network);
02b59d57 1075
52433f6b
TG
1076 link->enslaving --;
1077
5da8149f 1078 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1079 return 1;
1080
1081 r = sd_rtnl_message_get_errno(m);
856f962c 1082 if (r < 0 && r != -EEXIST) {
c9ccc19f 1083 log_struct_link(LOG_ERR, link,
3f265037 1084 "MESSAGE=%-*s: could not join netdev: %s",
987efa17 1085 IFNAMSIZ,
c9ccc19f
TG
1086 link->ifname, strerror(-r),
1087 "ERRNO=%d", -r,
1088 NULL);
ef1ba606
TG
1089 link_enter_failed(link);
1090 return 1;
ba179154
TG
1091 } else
1092 log_debug_link(link, "joined netdev");
02b59d57 1093
856f962c 1094 if (link->enslaving <= 0)
3f265037 1095 link_joined(link);
02b59d57
TG
1096
1097 return 1;
1098}
1099
3f265037 1100static int link_enter_join_netdev(Link *link) {
6a0a2f86 1101 NetDev *netdev;
672682a6 1102 Iterator i;
02b59d57
TG
1103 int r;
1104
1105 assert(link);
1106 assert(link->network);
8434fd5c 1107 assert(link->state == LINK_STATE_PENDING);
02b59d57 1108
52433f6b 1109 link->state = LINK_STATE_ENSLAVING;
02b59d57 1110
fe8db0c5
TG
1111 link_save(link);
1112
7951dea2
SS
1113 if (!link->network->bridge &&
1114 !link->network->bond &&
6a0a2f86 1115 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1116 return link_joined(link);
02b59d57 1117
d9c67ea1 1118 if (link->network->bond) {
52433f6b 1119 log_struct_link(LOG_DEBUG, link,
97578344 1120 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1121 IFNAMSIZ,
af4e9e2c 1122 link->ifname, link->network->bond->ifname,
aa9f1140 1123 NETDEVIF(link->network->bond),
52433f6b 1124 NULL);
449f7554 1125
3f265037 1126 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b
TG
1127 if (r < 0) {
1128 log_struct_link(LOG_WARNING, link,
3f265037 1129 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1130 IFNAMSIZ,
3c9b8860
TG
1131 link->ifname, link->network->bond->ifname,
1132 strerror(-r),
aa9f1140 1133 NETDEVIF(link->network->bond),
52433f6b
TG
1134 NULL);
1135 link_enter_failed(link);
1136 return r;
1137 }
1138
0ad6148e
MO
1139 link->enslaving ++;
1140 }
1141
d9c67ea1 1142 if (link->network->bridge) {
0ad6148e 1143 log_struct_link(LOG_DEBUG, link,
97578344 1144 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1145 IFNAMSIZ,
af4e9e2c 1146 link->ifname, link->network->bridge->ifname,
aa9f1140 1147 NETDEVIF(link->network->bridge),
0ad6148e
MO
1148 NULL);
1149
3c9b8860
TG
1150 r = netdev_join(link->network->bridge, link,
1151 &netdev_join_handler);
0ad6148e
MO
1152 if (r < 0) {
1153 log_struct_link(LOG_WARNING, link,
3f265037 1154 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1155 IFNAMSIZ,
3c9b8860
TG
1156 link->ifname, link->network->bridge->ifname,
1157 strerror(-r),
aa9f1140 1158 NETDEVIF(link->network->bridge),
0ad6148e
MO
1159 NULL);
1160 link_enter_failed(link);
1161 return r;
1162 }
1163
52433f6b
TG
1164 link->enslaving ++;
1165 }
1166
6a0a2f86 1167 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1168 log_struct_link(LOG_DEBUG, link,
97578344 1169 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1170 IFNAMSIZ,
3c9b8860
TG
1171 link->ifname, netdev->ifname, NETDEVIF(netdev),
1172 NULL);
7951dea2 1173
6a0a2f86 1174 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2
SS
1175 if (r < 0) {
1176 log_struct_link(LOG_WARNING, link,
3f265037 1177 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1178 IFNAMSIZ,
3c9b8860
TG
1179 link->ifname, netdev->ifname,
1180 strerror(-r),
6a0a2f86 1181 NETDEVIF(netdev), NULL);
326cb406
SS
1182 link_enter_failed(link);
1183 return r;
1184 }
1185
326cb406
SS
1186 link->enslaving ++;
1187 }
1188
ef1ba606
TG
1189 return 0;
1190}
1191
a748b692 1192static int link_configure(Link *link) {
02b59d57
TG
1193 int r;
1194
ef1ba606 1195 assert(link);
b22d8a00 1196 assert(link->network);
8434fd5c 1197 assert(link->state == LINK_STATE_PENDING);
a748b692 1198
eb34d4af 1199 if (link->network->ipv4ll) {
b22d8a00 1200 r = ipv4ll_configure(link);
eb34d4af
TG
1201 if (r < 0)
1202 return r;
1203 }
1204
ed942a9e 1205 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4)) {
3c9b8860 1206 r = dhcp4_configure(link);
eb34d4af
TG
1207 if (r < 0)
1208 return r;
eb34d4af
TG
1209 }
1210
dd43110f 1211 if (link->network->dhcp_server) {
dd43110f
TG
1212 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1213 if (r < 0)
1214 return r;
1215
1216 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1217 if (r < 0)
1218 return r;
dd43110f
TG
1219 }
1220
ed942a9e 1221 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
1222 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1223 if (r < 0)
1224 return r;
1225
1226 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1227 NULL, 0);
1228 if (r < 0)
1229 return r;
1230
1231 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1232 &link->mac);
1233 if (r < 0)
1234 return r;
1235
1236 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1237 link->ifindex);
1238 if (r < 0)
1239 return r;
1240
1241 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1242 icmp6_router_handler, link);
1243 if (r < 0)
1244 return r;
1245 }
1246
bf0308cb 1247 if (link_has_carrier(link->flags, link->kernel_operstate)) {
1e9be60b
TG
1248 r = link_acquire_conf(link);
1249 if (r < 0)
1250 return r;
cc544d5f 1251 }
1e9be60b 1252
3f265037 1253 return link_enter_join_netdev(link);
505f8da7
TG
1254}
1255
3c9b8860
TG
1256static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1257 void *userdata) {
5da8149f 1258 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1259 Network *network;
505f8da7
TG
1260 int r;
1261
1262 assert(link);
1263 assert(link->ifname);
1264 assert(link->manager);
1265
8434fd5c 1266 if (link->state != LINK_STATE_PENDING)
5da8149f 1267 return 1;
505f8da7 1268
4f561e8e 1269 log_debug_link(link, "link state is up-to-date");
505f8da7 1270
3c9b8860
TG
1271 r = network_get(link->manager, link->udev_device, link->ifname,
1272 &link->mac, &network);
57bd6899
TG
1273 if (r == -ENOENT) {
1274 link_enter_unmanaged(link);
5da8149f 1275 return 1;
57bd6899
TG
1276 } else if (r < 0)
1277 return r;
505f8da7
TG
1278
1279 r = network_apply(link->manager, network, link);
1280 if (r < 0)
1281 return r;
1282
a748b692
TG
1283 r = link_configure(link);
1284 if (r < 0)
1285 return r;
1286
5da8149f 1287 return 1;
505f8da7
TG
1288}
1289
4f561e8e
TG
1290int link_initialized(Link *link, struct udev_device *device) {
1291 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1292 int r;
1293
1294 assert(link);
1295 assert(link->manager);
1296 assert(link->manager->rtnl);
1297 assert(device);
1298
8434fd5c 1299 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1300 return 0;
1301
679b3605
TG
1302 if (link->udev_device)
1303 return 0;
1304
4f561e8e
TG
1305 log_debug_link(link, "udev initialized link");
1306
1307 link->udev_device = udev_device_ref(device);
1308
3c9b8860
TG
1309 /* udev has initialized the link, but we don't know if we have yet
1310 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1311 * when it returns we know that the pending NEWLINKs have already been
1312 * processed and that we are up-to-date */
4f561e8e 1313
3c9b8860
TG
1314 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1315 link->ifindex);
4f561e8e
TG
1316 if (r < 0)
1317 return r;
1318
3c9b8860
TG
1319 r = sd_rtnl_call_async(link->manager->rtnl, req,
1320 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1321 if (r < 0)
1322 return r;
1323
5da8149f
TG
1324 link_ref(link);
1325
4f561e8e
TG
1326 return 0;
1327}
1328
3c9b8860
TG
1329int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message,
1330 void *userdata) {
fbbeb65a
TG
1331 Manager *m = userdata;
1332 Link *link = NULL;
1333 uint16_t type;
1334 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1335 Address *ad;
fbbeb65a 1336 char buf[INET6_ADDRSTRLEN];
c6d3b303
TG
1337 char valid_buf[FORMAT_TIMESPAN_MAX];
1338 const char *valid_str = NULL;
428fd0a7 1339 bool address_dropped = false;
fbbeb65a
TG
1340 int r, ifindex;
1341
1342 assert(rtnl);
1343 assert(message);
1344 assert(m);
1345
1346 r = sd_rtnl_message_get_type(message, &type);
1347 if (r < 0) {
1348 log_warning("rtnl: could not get message type");
1349 return 0;
1350 }
1351
1352 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1353 if (r < 0 || ifindex <= 0) {
5ea846cc 1354 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1355 return 0;
1356 } else {
1357 r = link_get(m, ifindex, &link);
1358 if (r < 0 || !link) {
5ea846cc 1359 log_warning("rtnl: received address for a nonexistent link, ignoring");
fbbeb65a
TG
1360 return 0;
1361 }
1362 }
1363
1364 r = address_new_dynamic(&address);
1365 if (r < 0)
393c0c5e 1366 return r;
fbbeb65a
TG
1367
1368 r = sd_rtnl_message_addr_get_family(message, &address->family);
1369 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
3c9b8860
TG
1370 log_warning_link(link,
1371 "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1372 return 0;
1373 }
1374
1375 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1376 if (r < 0) {
3c9b8860
TG
1377 log_warning_link(link,
1378 "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1379 return 0;
1380 }
1381
1382 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1383 if (r < 0) {
3c9b8860
TG
1384 log_warning_link(link,
1385 "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1386 return 0;
1387 }
1388
81163121
TG
1389 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1390 if (r < 0) {
1391 log_warning_link(link,
1392 "rtnl: received address with invalid flags, ignoring");
1393 return 0;
1394 }
1395
fbbeb65a
TG
1396 switch (address->family) {
1397 case AF_INET:
3c9b8860
TG
1398 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL,
1399 &address->in_addr.in);
fbbeb65a 1400 if (r < 0) {
3c9b8860
TG
1401 log_warning_link(link,
1402 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1403 return 0;
1404 }
1405
1406 break;
1407
1408 case AF_INET6:
3c9b8860
TG
1409 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS,
1410 &address->in_addr.in6);
fbbeb65a 1411 if (r < 0) {
3c9b8860
TG
1412 log_warning_link(link,
1413 "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1414 return 0;
1415 }
1416
1417 break;
1418
1419 default:
1420 assert_not_reached("invalid address family");
1421 }
1422
3c9b8860
TG
1423 if (!inet_ntop(address->family, &address->in_addr, buf,
1424 INET6_ADDRSTRLEN)) {
987efa17 1425 log_warning_link(link, "could not print address");
fbbeb65a
TG
1426 return 0;
1427 }
1428
c6d3b303
TG
1429 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO,
1430 &address->cinfo);
1431 if (r >= 0) {
1432 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1433 valid_str = "ever";
1434 else
1435 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1436 address->cinfo.ifa_valid * USEC_PER_SEC,
1437 USEC_PER_SEC);
1438 }
1439
428fd0a7
TG
1440 LIST_FOREACH(addresses, ad, link->addresses) {
1441 if (address_equal(ad, address)) {
1442 LIST_REMOVE(addresses, link->addresses, ad);
1443
1444 address_free(ad);
1445
1446 address_dropped = true;
1447
1448 break;
1449 }
1450 }
1451
fbbeb65a
TG
1452 switch (type) {
1453 case RTM_NEWADDR:
428fd0a7 1454 if (!address_dropped)
c6d3b303
TG
1455 log_debug_link(link, "added address: %s/%u (valid for %s)",
1456 buf, address->prefixlen,
1457 strna(valid_str));
393c0c5e 1458 else
c6d3b303
TG
1459 log_debug_link(link, "updated address: %s/%u (valid for %s)",
1460 buf, address->prefixlen,
1461 strna(valid_str));
fbbeb65a 1462
428fd0a7
TG
1463 LIST_PREPEND(addresses, link->addresses, address);
1464 address = NULL;
1465
f5602be9
TG
1466 link_save(link);
1467
428fd0a7 1468 break;
fbbeb65a 1469 case RTM_DELADDR:
f5602be9 1470 if (address_dropped) {
c6d3b303
TG
1471 log_debug_link(link, "removed address: %s/%u (valid for %s)",
1472 buf, address->prefixlen,
1473 strna(valid_str));
428fd0a7 1474
f5602be9 1475 link_save(link);
393c0c5e 1476 } else
3c9b8860 1477 log_warning_link(link,
c6d3b303
TG
1478 "removing non-existent address: %s/%u (valid for %s)",
1479 buf, address->prefixlen,
1480 strna(valid_str));
f5602be9 1481
fbbeb65a
TG
1482 break;
1483 default:
1484 assert_not_reached("Received invalid RTNL message type");
1485 }
1486
1487 return 1;
1488}
1489
505f8da7
TG
1490int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1491 Link *link;
fbbeb65a 1492 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1493 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1494 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1495 int r;
1496
1497 assert(m);
fbbeb65a 1498 assert(m->rtnl);
505f8da7
TG
1499 assert(message);
1500 assert(ret);
1501
1502 r = link_new(m, message, ret);
1503 if (r < 0)
1504 return r;
1505
1506 link = *ret;
1507
ae06ab10 1508 log_debug_link(link, "link %d added", link->ifindex);
505f8da7 1509
3c9b8860
TG
1510 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex,
1511 0);
fbbeb65a
TG
1512 if (r < 0)
1513 return r;
1514
3c9b8860
TG
1515 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0,
1516 NULL);
fbbeb65a
TG
1517 if (r < 0)
1518 return r;
1519
5da8149f
TG
1520 link_ref(link);
1521
505f8da7
TG
1522 if (detect_container(NULL) <= 0) {
1523 /* not in a container, udev will be around */
ae06ab10 1524 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1525 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1526 if (!device) {
3c9b8860
TG
1527 log_warning_link(link,
1528 "could not find udev device: %m");
9fecce80 1529 return -errno;
505f8da7
TG
1530 }
1531
3c4cb064 1532 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1533 /* not yet ready */
8434fd5c 1534 log_debug_link(link, "link pending udev initialization...");
505f8da7 1535 return 0;
3c4cb064 1536 }
505f8da7 1537
4f561e8e
TG
1538 r = link_initialized(link, device);
1539 if (r < 0)
1540 return r;
1541 } else {
5da8149f
TG
1542 /* we are calling a callback directly, so must take a ref */
1543 link_ref(link);
1544
4f561e8e
TG
1545 r = link_initialized_and_synced(m->rtnl, NULL, link);
1546 if (r < 0)
1547 return r;
1548 }
505f8da7 1549
a748b692
TG
1550 return 0;
1551}
1552
22936833 1553int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1554 struct ether_addr mac;
ca4e095a 1555 const char *ifname;
afe7fd56 1556 uint32_t mtu;
22936833
TG
1557 int r;
1558
dd3efc09 1559 assert(link);
b8941f74 1560 assert(link->ifname);
22936833
TG
1561 assert(m);
1562
7619683b
TG
1563 if (link->state == LINK_STATE_LINGER) {
1564 link_ref(link);
1565 log_info_link(link, "link readded");
1566 link->state = LINK_STATE_ENSLAVING;
1567 }
1568
b8941f74
TG
1569 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1570 if (r >= 0 && !streq(ifname, link->ifname)) {
1571 log_info_link(link, "renamed to %s", ifname);
1572
1573 free(link->ifname);
1574 link->ifname = strdup(ifname);
1575 if (!link->ifname)
1576 return -ENOMEM;
1577 }
1578
afe7fd56
TG
1579 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1580 if (r >= 0 && mtu > 0) {
1581 link->mtu = mtu;
1582 if (!link->original_mtu) {
1583 link->original_mtu = mtu;
9842de0d 1584 log_debug_link(link, "saved original MTU: %"
afe7fd56
TG
1585 PRIu32, link->original_mtu);
1586 }
1587
1588 if (link->dhcp_client) {
3c9b8860
TG
1589 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1590 link->mtu);
afe7fd56 1591 if (r < 0) {
3c9b8860
TG
1592 log_warning_link(link,
1593 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1594 strerror(-r));
1595 return r;
1596 }
1597 }
9842de0d 1598 }
69629de9 1599
e9189a1f
TG
1600 /* The kernel may broadcast NEWLINK messages without the MAC address
1601 set, simply ignore them. */
c49b33ac 1602 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1603 if (r >= 0) {
3c9b8860
TG
1604 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1605 ETH_ALEN)) {
c49b33ac 1606
3c9b8860
TG
1607 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1608 ETH_ALEN);
c49b33ac 1609
20861203
TG
1610 log_debug_link(link, "MAC address: "
1611 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1612 mac.ether_addr_octet[0],
1613 mac.ether_addr_octet[1],
1614 mac.ether_addr_octet[2],
1615 mac.ether_addr_octet[3],
1616 mac.ether_addr_octet[4],
1617 mac.ether_addr_octet[5]);
c49b33ac 1618
20861203
TG
1619 if (link->ipv4ll) {
1620 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1621 if (r < 0) {
3c9b8860
TG
1622 log_warning_link(link,
1623 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1624 strerror(-r));
1625 return r;
1626 }
c49b33ac 1627 }
c49b33ac 1628
20861203 1629 if (link->dhcp_client) {
3c9b8860
TG
1630 r = sd_dhcp_client_set_mac(link->dhcp_client,
1631 &link->mac);
20861203 1632 if (r < 0) {
3c9b8860
TG
1633 log_warning_link(link,
1634 "Could not update MAC address in DHCP client: %s",
20861203
TG
1635 strerror(-r));
1636 return r;
1637 }
c49b33ac 1638 }
4138fb2c
PF
1639
1640 if (link->dhcp6_client) {
1641 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
1642 &link->mac);
1643 if (r < 0) {
3c9b8860
TG
1644 log_warning_link(link,
1645 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1646 strerror(-r));
1647 return r;
1648 }
1649 }
c49b33ac 1650 }
4f882b2a
TG
1651 }
1652
1e9be60b 1653 return link_update_flags(link, m);
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;
1662 else if (link_has_carrier(link->flags, link->kernel_operstate)) {
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);