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