]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
Merge pull request #1072 from piotrdrag/master
[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
f579559b 26#include "util.h"
505f8da7 27#include "virt.h"
5a8bcb67 28#include "fileio.h"
fe027299 29#include "socket-util.h"
1346b1f0 30#include "bus-util.h"
5a8bcb67 31#include "udev-util.h"
fc2f9534 32#include "netlink-util.h"
bd91b83e 33#include "dhcp-lease-internal.h"
c6f7c917 34#include "network-internal.h"
fc2f9534 35
5a8bcb67
LP
36#include "networkd-link.h"
37#include "networkd-netdev.h"
fe8db0c5 38
a97dcc12 39bool link_dhcp6_enabled(Link *link) {
78c958f8
TG
40 if (link->flags & IFF_LOOPBACK)
41 return false;
42
43 if (!link->network)
44 return false;
45
e0ee46f2 46 return link->network->dhcp & ADDRESS_FAMILY_IPV6;
78c958f8
TG
47}
48
a97dcc12 49bool link_dhcp4_enabled(Link *link) {
78c958f8
TG
50 if (link->flags & IFF_LOOPBACK)
51 return false;
52
53 if (!link->network)
54 return false;
55
e0ee46f2 56 return link->network->dhcp & ADDRESS_FAMILY_IPV4;
78c958f8
TG
57}
58
a97dcc12 59bool link_dhcp4_server_enabled(Link *link) {
78c958f8
TG
60 if (link->flags & IFF_LOOPBACK)
61 return false;
62
63 if (!link->network)
64 return false;
65
66 return link->network->dhcp_server;
67}
68
a97dcc12 69bool link_ipv4ll_enabled(Link *link) {
78c958f8
TG
70 if (link->flags & IFF_LOOPBACK)
71 return false;
72
73 if (!link->network)
74 return false;
75
e0ee46f2 76 return link->network->link_local & ADDRESS_FAMILY_IPV4;
d0d6a4cd
TG
77}
78
79bool link_ipv6ll_enabled(Link *link) {
80 if (link->flags & IFF_LOOPBACK)
81 return false;
82
83 if (!link->network)
84 return false;
85
e0ee46f2 86 return link->network->link_local & ADDRESS_FAMILY_IPV6;
78c958f8
TG
87}
88
a97dcc12 89bool link_lldp_enabled(Link *link) {
ce43e484
SS
90 if (link->flags & IFF_LOOPBACK)
91 return false;
92
93 if (!link->network)
94 return false;
95
5a8bcb67 96 if (link->network->bridge)
ce43e484
SS
97 return false;
98
99 return link->network->lldp;
100}
101
769d324c 102static bool link_ipv4_forward_enabled(Link *link) {
5a8bcb67
LP
103 if (link->flags & IFF_LOOPBACK)
104 return false;
105
106 if (!link->network)
107 return false;
108
e0ee46f2 109 return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
769d324c
LP
110}
111
112static bool link_ipv6_forward_enabled(Link *link) {
113 if (link->flags & IFF_LOOPBACK)
114 return false;
115
116 if (!link->network)
117 return false;
118
e0ee46f2 119 return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
5a8bcb67
LP
120}
121
1f0d9695 122static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
49092e22 123 if (link->flags & IFF_LOOPBACK)
1f0d9695 124 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
49092e22
SS
125
126 if (!link->network)
1f0d9695 127 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
49092e22
SS
128
129 return link->network->ipv6_privacy_extensions;
130}
131
51d18171
TG
132#define FLAG_STRING(string, flag, old, new) \
133 (((old ^ new) & flag) \
134 ? ((old & flag) ? (" -" string) : (" +" string)) \
135 : "")
136
1c4baffc 137static int link_update_flags(Link *link, sd_netlink_message *m) {
51d18171
TG
138 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
139 uint8_t operstate;
140 int r;
141
142 assert(link);
143
144 r = sd_rtnl_message_link_get_flags(m, &flags);
6a7a4e4d
LP
145 if (r < 0)
146 return log_link_warning_errno(link, r, "Could not get link flags: %m");
51d18171 147
1c4baffc 148 r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate);
51d18171
TG
149 if (r < 0)
150 /* if we got a message without operstate, take it to mean
151 the state was unchanged */
152 operstate = link->kernel_operstate;
153
154 if ((link->flags == flags) && (link->kernel_operstate == operstate))
155 return 0;
156
157 if (link->flags != flags) {
6a7a4e4d 158 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
159 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
160 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
161 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
162 FLAG_STRING("UP", IFF_UP, link->flags, flags),
163 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
164 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
165 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
166 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
167 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
168 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
169 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
170 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
171 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
172 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
173 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
174 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
175 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
176 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
177 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
178
179 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
180 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
181 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
182 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
183 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
184 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
185 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
186 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
187
188 /* link flags are currently at most 18 bits, let's align to
189 * printing 20 */
190 if (unknown_flags_added)
79008bdd 191 log_link_debug(link,
6a7a4e4d 192 "Unknown link flags gained: %#.5x (ignoring)",
51d18171
TG
193 unknown_flags_added);
194
195 if (unknown_flags_removed)
79008bdd 196 log_link_debug(link,
6a7a4e4d 197 "Unknown link flags lost: %#.5x (ignoring)",
51d18171
TG
198 unknown_flags_removed);
199 }
200
201 link->flags = flags;
202 link->kernel_operstate = operstate;
203
204 link_save(link);
205
206 return 0;
207}
208
1c4baffc 209static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
14b746f7 210 _cleanup_link_unref_ Link *link = NULL;
505f8da7 211 uint16_t type;
ca4e095a 212 const char *ifname;
505f8da7 213 int r, ifindex;
f579559b 214
0c2f9b84 215 assert(manager);
505f8da7 216 assert(message);
f579559b
TG
217 assert(ret);
218
1c4baffc 219 r = sd_netlink_message_get_type(message, &type);
505f8da7
TG
220 if (r < 0)
221 return r;
222 else if (type != RTM_NEWLINK)
223 return -EINVAL;
224
225 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
226 if (r < 0)
227 return r;
228 else if (ifindex <= 0)
229 return -EINVAL;
230
1c4baffc 231 r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
505f8da7
TG
232 if (r < 0)
233 return r;
234
f579559b
TG
235 link = new0(Link, 1);
236 if (!link)
237 return -ENOMEM;
238
14b746f7 239 link->n_ref = 1;
5a3eb5a7 240 link->manager = manager;
8434fd5c 241 link->state = LINK_STATE_PENDING;
be3a09b7 242 link->rtnl_extended_attrs = true;
505f8da7
TG
243 link->ifindex = ifindex;
244 link->ifname = strdup(ifname);
245 if (!link->ifname)
246 return -ENOMEM;
f579559b 247
1c4baffc 248 r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
512922f8 249 if (r < 0)
79008bdd 250 log_link_debug(link, "MAC address not found for new device, continuing without");
512922f8 251
3c9b8860
TG
252 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
253 link->ifindex);
fe8db0c5 254 if (r < 0)
315db1a8 255 return -ENOMEM;
fe8db0c5 256
3c9b8860
TG
257 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
258 link->ifindex);
68a8723c
TG
259 if (r < 0)
260 return -ENOMEM;
261
49699bac
SS
262 r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
263 link->ifindex);
264 if (r < 0)
265 return -ENOMEM;
266
267
d5099efc 268 r = hashmap_ensure_allocated(&manager->links, NULL);
ae06ab10
TG
269 if (r < 0)
270 return r;
271
272 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
f579559b
TG
273 if (r < 0)
274 return r;
275
51d18171
TG
276 r = link_update_flags(link, message);
277 if (r < 0)
278 return r;
279
f579559b
TG
280 *ret = link;
281 link = NULL;
282
283 return 0;
284}
285
14b746f7 286static void link_free(Link *link) {
428fd0a7 287 Address *address;
0d4ad91d
AR
288 Iterator i;
289 Link *carrier;
428fd0a7 290
f579559b
TG
291 if (!link)
292 return;
293
428fd0a7
TG
294 while ((address = link->addresses)) {
295 LIST_REMOVE(addresses, link->addresses, address);
296 address_free(address);
297 }
298
11bf3cce
LP
299 while ((address = link->pool_addresses)) {
300 LIST_REMOVE(addresses, link->pool_addresses, address);
301 address_free(address);
302 }
303
bfcdba8d 304 sd_dhcp_server_unref(link->dhcp_server);
e5b04c8d 305 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 306 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 307
68a8723c
TG
308 free(link->lease_file);
309
07e10d1a
TG
310 sd_lldp_free(link->lldp);
311
49699bac
SS
312 free(link->lldp_file);
313
56cd007a 314 sd_ipv4ll_unref(link->ipv4ll);
4138fb2c 315 sd_dhcp6_client_unref(link->dhcp6_client);
6b66097b 316 sd_icmp6_nd_unref(link->icmp6_router_discovery);
4138fb2c 317
28aeb07f 318 if (link->manager)
ae06ab10 319 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
f579559b 320
c166a070 321 free(link->ifname);
68a8723c 322
fe8db0c5 323 free(link->state_file);
c166a070 324
b5db00e5
UTL
325 udev_device_unref(link->udev_device);
326
0d4ad91d
AR
327 HASHMAP_FOREACH (carrier, link->bound_to_links, i)
328 hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
329 hashmap_free(link->bound_to_links);
330
331 HASHMAP_FOREACH (carrier, link->bound_by_links, i)
332 hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
333 hashmap_free(link->bound_by_links);
334
f579559b
TG
335 free(link);
336}
337
14b746f7
TG
338Link *link_unref(Link *link) {
339 if (link && (-- link->n_ref <= 0))
340 link_free(link);
341
342 return NULL;
343}
344
345Link *link_ref(Link *link) {
346 if (link)
347 assert_se(++ link->n_ref >= 2);
348
349 return link;
350}
351
11a7f229
TG
352int link_get(Manager *m, int ifindex, Link **ret) {
353 Link *link;
11a7f229
TG
354
355 assert(m);
11a7f229
TG
356 assert(ifindex);
357 assert(ret);
358
ae06ab10 359 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
11a7f229
TG
360 if (!link)
361 return -ENODEV;
362
363 *ret = link;
364
365 return 0;
366}
367
e331e246
TG
368static void link_set_state(Link *link, LinkState state) {
369 assert(link);
370
371 if (link->state == state)
372 return;
373
374 link->state = state;
375
376 link_send_changed(link, "AdministrativeState", NULL);
377
378 return;
379}
380
57bd6899
TG
381static void link_enter_unmanaged(Link *link) {
382 assert(link);
383
6a7a4e4d 384 log_link_debug(link, "Unmanaged");
57bd6899 385
e331e246 386 link_set_state(link, LINK_STATE_UNMANAGED);
57bd6899
TG
387
388 link_save(link);
389}
390
111bb8f9
TG
391static int link_stop_clients(Link *link) {
392 int r = 0, k;
393
394 assert(link);
395 assert(link->manager);
396 assert(link->manager->event);
397
398 if (!link->network)
399 return 0;
400
ba179154 401 if (link->dhcp_client) {
111bb8f9 402 k = sd_dhcp_client_stop(link->dhcp_client);
6a7a4e4d
LP
403 if (k < 0)
404 r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
111bb8f9
TG
405 }
406
ba179154 407 if (link->ipv4ll) {
111bb8f9 408 k = sd_ipv4ll_stop(link->ipv4ll);
6a7a4e4d
LP
409 if (k < 0)
410 r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
dd43110f
TG
411 }
412
ba179154 413 if(link->icmp6_router_discovery) {
1873a3d3
PF
414 if (link->dhcp6_client) {
415 k = sd_dhcp6_client_stop(link->dhcp6_client);
6a7a4e4d
LP
416 if (k < 0)
417 r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
1873a3d3 418 }
4138fb2c 419
1873a3d3 420 k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
6a7a4e4d
LP
421 if (k < 0)
422 r = log_link_warning_errno(link, r, "Could not stop ICMPv6 router discovery: %m");
4138fb2c
PF
423 }
424
ce43e484 425 if (link->lldp) {
ce43e484 426 k = sd_lldp_stop(link->lldp);
6a7a4e4d
LP
427 if (k < 0)
428 r = log_link_warning_errno(link, r, "Could not stop LLDP: %m");
ce43e484
SS
429 }
430
111bb8f9
TG
431 return r;
432}
433
b22d8a00 434void link_enter_failed(Link *link) {
ef1ba606 435 assert(link);
f882c247 436
370e9930 437 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
438 return;
439
6a7a4e4d 440 log_link_warning(link, "Failed");
449f7554 441
e331e246 442 link_set_state(link, LINK_STATE_FAILED);
fe8db0c5 443
111bb8f9
TG
444 link_stop_clients(link);
445
fe8db0c5 446 link_save(link);
f882c247
TG
447}
448
4f434938
LP
449static Address* link_find_dhcp_server_address(Link *link) {
450 Address *address;
451
452 assert(link);
453 assert(link->network);
454
d4cdbea5 455 /* The first statically configured address if there is any */
4f434938
LP
456 LIST_FOREACH(addresses, address, link->network->static_addresses) {
457
458 if (address->family != AF_INET)
459 continue;
460
af93291c 461 if (in_addr_is_null(address->family, &address->in_addr))
4f434938
LP
462 continue;
463
464 return address;
465 }
466
467 /* If that didn't work, find a suitable address we got from the pool */
468 LIST_FOREACH(addresses, address, link->pool_addresses) {
469 if (address->family != AF_INET)
470 continue;
471
472 return address;
473 }
474
475 return NULL;
476}
477
dd43110f 478static int link_enter_configured(Link *link) {
dd43110f
TG
479 assert(link);
480 assert(link->network);
481 assert(link->state == LINK_STATE_SETTING_ROUTES);
482
6a7a4e4d 483 log_link_info(link, "Configured");
dd43110f 484
e331e246 485 link_set_state(link, LINK_STATE_CONFIGURED);
dd43110f
TG
486
487 link_save(link);
488
489 return 0;
490}
491
3c9b8860
TG
492void link_client_handler(Link *link) {
493 assert(link);
494 assert(link->network);
495
496 if (!link->static_configured)
497 return;
498
78c958f8 499 if (link_ipv4ll_enabled(link))
3c9b8860
TG
500 if (!link->ipv4ll_address ||
501 !link->ipv4ll_route)
502 return;
503
78c958f8 504 if (link_dhcp4_enabled(link) && !link->dhcp4_configured)
3c9b8860
TG
505 return;
506
9fdaa992
TG
507 if (link->state != LINK_STATE_CONFIGURED)
508 link_enter_configured(link);
3c9b8860
TG
509
510 return;
511}
512
1c4baffc 513static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 514 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
515 int r;
516
3c9b8860 517 assert(link->link_messages > 0);
370e9930
TG
518 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
519 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
520 LINK_STATE_LINGER));
f882c247 521
3c9b8860 522 link->link_messages --;
f882c247 523
77a008c0 524 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
525 return 1;
526
1c4baffc 527 r = sd_netlink_message_get_errno(m);
c166a070 528 if (r < 0 && r != -EEXIST)
6a7a4e4d 529 log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
f882c247 530
3c9b8860 531 if (link->link_messages == 0) {
6a7a4e4d 532 log_link_debug(link, "Routes set");
3c9b8860
TG
533 link->static_configured = true;
534 link_client_handler(link);
dd3efc09 535 }
f882c247
TG
536
537 return 1;
538}
539
540static int link_enter_set_routes(Link *link) {
a6cc569e 541 Route *rt;
f882c247
TG
542 int r;
543
544 assert(link);
545 assert(link->network);
ef1ba606 546 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 547
e331e246 548 link_set_state(link, LINK_STATE_SETTING_ROUTES);
f882c247 549
3d3d4255 550 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 551 r = route_configure(rt, link, &route_handler);
dd3efc09 552 if (r < 0) {
6a7a4e4d 553 log_link_warning_errno(link, r, "Could not set routes: %m");
3c9b8860 554 link_enter_failed(link);
a6cc569e
TG
555 return r;
556 }
557
3c9b8860 558 link->link_messages ++;
8ddbeaa2 559 }
f5be5601 560
3c9b8860
TG
561 if (link->link_messages == 0) {
562 link->static_configured = true;
563 link_client_handler(link);
431ca2ce 564 } else
6a7a4e4d 565 log_link_debug(link, "Setting routes");
f882c247
TG
566
567 return 0;
568}
569
1c4baffc 570int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 571 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
572 int r;
573
574 assert(m);
575 assert(link);
576 assert(link->ifname);
577
5da8149f 578 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
579 return 1;
580
1c4baffc 581 r = sd_netlink_message_get_errno(m);
b90b025a 582 if (r < 0 && r != -ESRCH)
6a7a4e4d 583 log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
5c1d3fc9 584
5bdd314c 585 return 1;
5c1d3fc9
UTL
586}
587
1c4baffc 588static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 589 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
590 int r;
591
4958aee4 592 assert(rtnl);
f5be5601
TG
593 assert(m);
594 assert(link);
595 assert(link->ifname);
3c9b8860 596 assert(link->link_messages > 0);
370e9930
TG
597 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
598 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 599
3c9b8860 600 link->link_messages --;
f882c247 601
5da8149f 602 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
603 return 1;
604
1c4baffc 605 r = sd_netlink_message_get_errno(m);
c166a070 606 if (r < 0 && r != -EEXIST)
6a7a4e4d 607 log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
45af44d4
TG
608 else if (r >= 0)
609 link_rtnl_process_address(rtnl, m, link->manager);
f882c247 610
3c9b8860 611 if (link->link_messages == 0) {
6a7a4e4d 612 log_link_debug(link, "Addresses set");
ef1ba606 613 link_enter_set_routes(link);
dd3efc09 614 }
f882c247
TG
615
616 return 1;
617}
618
4f5f911e
LP
619static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
620 _cleanup_free_ struct in_addr *addresses = NULL;
621 size_t n_addresses = 0, n_allocated = 0;
622 char **a;
623
624 log_debug("Copying DNS server information from %s", link->ifname);
625
626 if (!link->network)
627 return 0;
628
629 STRV_FOREACH(a, link->network->dns) {
630 struct in_addr ia;
631
632 /* Only look for IPv4 addresses */
633 if (inet_pton(AF_INET, *a, &ia) <= 0)
634 continue;
635
636 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
637 return log_oom();
638
639 addresses[n_addresses++] = ia;
640 }
641
642 if (link->network->dhcp_dns &&
643 link->dhcp_lease) {
644 const struct in_addr *da = NULL;
645 int n;
646
647 n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
648 if (n > 0) {
649
650 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
651 return log_oom();
652
653 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
654 n_addresses += n;
655 }
656 }
657
658 if (n_addresses <= 0)
659 return 0;
660
661 return sd_dhcp_server_set_dns(s, addresses, n_addresses);
662}
663
664static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
665 _cleanup_free_ struct in_addr *addresses = NULL;
666 size_t n_addresses = 0, n_allocated = 0;
667 char **a;
668
669 if (!link->network)
670 return 0;
671
672 log_debug("Copying NTP server information from %s", link->ifname);
673
674 STRV_FOREACH(a, link->network->ntp) {
675 struct in_addr ia;
676
677 /* Only look for IPv4 addresses */
678 if (inet_pton(AF_INET, *a, &ia) <= 0)
679 continue;
680
681 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
682 return log_oom();
683
684 addresses[n_addresses++] = ia;
685 }
686
687 if (link->network->dhcp_ntp &&
688 link->dhcp_lease) {
689 const struct in_addr *da = NULL;
690 int n;
691
692 n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
693 if (n > 0) {
694
695 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
696 return log_oom();
697
698 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
699 n_addresses += n;
700 }
701 }
702
703 if (n_addresses <= 0)
704 return 0;
705
706 return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
707}
708
f882c247 709static int link_enter_set_addresses(Link *link) {
a6cc569e 710 Address *ad;
f882c247
TG
711 int r;
712
713 assert(link);
714 assert(link->network);
f5be5601 715 assert(link->state != _LINK_STATE_INVALID);
f882c247 716
e331e246 717 link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
f882c247 718
3d3d4255 719 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 720 r = address_configure(ad, link, &address_handler);
dd3efc09 721 if (r < 0) {
5a8bcb67 722 log_link_warning_errno(link, r, "Could not set addresses: %m");
f5be5601
TG
723 link_enter_failed(link);
724 return r;
725 }
726
3c9b8860 727 link->link_messages ++;
f882c247
TG
728 }
729
d4cdbea5
TG
730 /* now that we can figure out a default address for the dhcp server,
731 start it */
732 if (link_dhcp4_server_enabled(link)) {
733 struct in_addr pool_start;
734 Address *address;
4f5f911e
LP
735 Link *uplink = NULL;
736 bool acquired_uplink = false;
d4cdbea5
TG
737
738 address = link_find_dhcp_server_address(link);
739 if (!address) {
6a7a4e4d 740 log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
d4cdbea5
TG
741 link_enter_failed(link);
742 return 0;
743 }
744
745 r = sd_dhcp_server_set_address(link->dhcp_server,
746 &address->in_addr.in,
747 address->prefixlen);
748 if (r < 0)
749 return r;
750
751 /* offer 32 addresses starting from the address following the server address */
752 pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1);
753 r = sd_dhcp_server_set_lease_pool(link->dhcp_server,
754 &pool_start, 32);
755 if (r < 0)
756 return r;
757
758 /* TODO:
759 r = sd_dhcp_server_set_router(link->dhcp_server,
760 &main_address->in_addr.in);
761 if (r < 0)
762 return r;
763
764 r = sd_dhcp_server_set_prefixlen(link->dhcp_server,
765 main_address->prefixlen);
766 if (r < 0)
767 return r;
768 */
769
586ac6f7
LP
770 if (link->network->dhcp_server_max_lease_time_usec > 0) {
771 r = sd_dhcp_server_set_max_lease_time(
772 link->dhcp_server,
773 DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
774 if (r < 0)
775 return r;
776 }
777
778 if (link->network->dhcp_server_default_lease_time_usec > 0) {
779 r = sd_dhcp_server_set_default_lease_time(
780 link->dhcp_server,
781 DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
782 if (r < 0)
783 return r;
784 }
785
1a04db0f
LP
786 if (link->network->dhcp_server_emit_dns) {
787
4f5f911e 788 if (link->network->n_dhcp_server_dns > 0)
1a04db0f 789 r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
4f5f911e
LP
790 else {
791 uplink = manager_find_uplink(link->manager, link);
792 acquired_uplink = true;
793
794 if (!uplink) {
795 log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
796 r = 0;
797 } else
798 r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
799 }
800 if (r < 0)
801 log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
1a04db0f
LP
802 }
803
804
805 if (link->network->dhcp_server_emit_ntp) {
806
4f5f911e 807 if (link->network->n_dhcp_server_ntp > 0)
1a04db0f 808 r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
4f5f911e
LP
809 else {
810 if (!acquired_uplink)
811 uplink = manager_find_uplink(link->manager, link);
812
813 if (!uplink) {
814 log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
815 r = 0;
816 } else
817 r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
818
819 }
820 if (r < 0)
821 log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
1a04db0f
LP
822 }
823
8eb9058d
LP
824 if (link->network->dhcp_server_emit_timezone) {
825 _cleanup_free_ char *buffer = NULL;
0ab8a1b6 826 const char *tz = NULL;
8eb9058d
LP
827
828 if (link->network->dhcp_server_timezone)
829 tz = link->network->dhcp_server_timezone;
830 else {
831 r = get_timezone(&buffer);
832 if (r < 0)
833 log_warning_errno(r, "Failed to determine timezone: %m");
834 else
835 tz = buffer;
836 }
837
838 if (tz) {
839 r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
840 if (r < 0)
841 return r;
842 }
843 }
844
d4cdbea5
TG
845 r = sd_dhcp_server_start(link->dhcp_server);
846 if (r < 0) {
6a7a4e4d 847 log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
d4cdbea5
TG
848
849 link_enter_failed(link);
850
851 return 0;
852 }
853
6a7a4e4d 854 log_link_debug(link, "Offering DHCPv4 leases");
d4cdbea5
TG
855 }
856
6a7a4e4d 857 if (link->link_messages == 0)
431ca2ce 858 link_enter_set_routes(link);
6a7a4e4d
LP
859 else
860 log_link_debug(link, "Setting addresses");
431ca2ce 861
f882c247
TG
862 return 0;
863}
864
1c4baffc 865int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 866 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
867 int r;
868
869 assert(m);
870 assert(link);
871 assert(link->ifname);
872
5da8149f 873 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
874 return 1;
875
1c4baffc 876 r = sd_netlink_message_get_errno(m);
b90b025a 877 if (r < 0 && r != -EADDRNOTAVAIL)
6a7a4e4d 878 log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
ff254138 879
5bdd314c 880 return 1;
ff254138
TG
881}
882
a245ced0 883static int link_set_bridge_fdb(Link *const link) {
b98b483b
AR
884 FdbEntry *fdb_entry;
885 int r = 0;
886
887 LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
ea6ec096 888 r = fdb_entry_configure(link, fdb_entry);
b98b483b 889 if(r < 0) {
6a7a4e4d 890 log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
b98b483b
AR
891 break;
892 }
893 }
894
895 return r;
896}
897
1c4baffc 898static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
e1853b00
SS
899 _cleanup_link_unref_ Link *link = userdata;
900 int r;
901
6a7a4e4d 902 log_link_debug(link, "Set link");
e1853b00 903
1c4baffc 904 r = sd_netlink_message_get_errno(m);
e1853b00 905 if (r < 0 && r != -EEXIST) {
f2341e0a 906 log_link_error_errno(link, r, "Could not join netdev: %m");
e1853b00
SS
907 link_enter_failed(link);
908 return 1;
909 }
910
911 return 0;
912}
913
19070062 914static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
5da8149f 915 _cleanup_link_unref_ Link *link = userdata;
21b80ad1 916 const sd_bus_error *e;
1346b1f0 917
19070062 918 assert(m);
b226d99b
TG
919 assert(link);
920
5da8149f 921 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 922 return 1;
370e9930 923
21b80ad1
LP
924 e = sd_bus_message_get_error(m);
925 if (e)
926 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
1346b1f0
TG
927
928 return 1;
929}
930
3c9b8860 931int link_set_hostname(Link *link, const char *hostname) {
21b80ad1 932 int r;
1346b1f0 933
b226d99b
TG
934 assert(link);
935 assert(link->manager);
1346b1f0 936
dce391e7 937 log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
1346b1f0 938
3c9b8860
TG
939 if (!link->manager->bus) {
940 /* TODO: replace by assert when we can rely on kdbus */
6a7a4e4d 941 log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
942 return 0;
943 }
944
9c34154a 945 r = sd_bus_call_method_async(
b226d99b 946 link->manager->bus,
9c34154a 947 NULL,
1346b1f0
TG
948 "org.freedesktop.hostname1",
949 "/org/freedesktop/hostname1",
950 "org.freedesktop.hostname1",
9c34154a
UTL
951 "SetHostname",
952 set_hostname_handler,
953 link,
954 "sb",
955 hostname,
956 false);
1346b1f0 957
6a7a4e4d
LP
958 if (r < 0)
959 return log_link_error_errno(link, r, "Could not set transient hostname: %m");
b226d99b
TG
960
961 link_ref(link);
1346b1f0 962
5da8149f 963 return 0;
1346b1f0
TG
964}
965
21b80ad1
LP
966static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
967 _cleanup_link_unref_ Link *link = userdata;
968 const sd_bus_error *e;
969
970 assert(m);
971 assert(link);
972
973 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
974 return 1;
975
976 e = sd_bus_message_get_error(m);
977 if (e)
978 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
979
980 return 1;
981}
982
983int link_set_timezone(Link *link, const char *timezone) {
984 int r;
985
986 assert(link);
987 assert(link->manager);
988 assert(timezone);
989
990 log_link_debug(link, "Setting system timezone: '%s'", timezone);
991
992 if (!link->manager->bus) {
993 log_link_info(link, "Not connected to system bus, ignoring timezone.");
994 return 0;
995 }
996
997 r = sd_bus_call_method_async(
998 link->manager->bus,
999 NULL,
1000 "org.freedesktop.timedate1",
1001 "/org/freedesktop/timedate1",
1002 "org.freedesktop.timedate1",
1003 "SetTimezone",
1004 set_timezone_handler,
1005 link,
1006 "sb",
1007 timezone,
1008 false);
1009 if (r < 0)
1010 return log_link_error_errno(link, r, "Could not set timezone: %m");
1011
1012 link_ref(link);
1013
1014 return 0;
1015}
1016
1c4baffc 1017static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1018 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
1019 int r;
1020
1021 assert(m);
1022 assert(link);
1023 assert(link->ifname);
1024
5da8149f 1025 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
1026 return 1;
1027
1c4baffc 1028 r = sd_netlink_message_get_errno(m);
c9ccc19f 1029 if (r < 0)
6a7a4e4d 1030 log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
4f882b2a
TG
1031
1032 return 1;
1033}
1034
3c9b8860 1035int link_set_mtu(Link *link, uint32_t mtu) {
1c4baffc 1036 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f882b2a
TG
1037 int r;
1038
1039 assert(link);
1040 assert(link->manager);
1041 assert(link->manager->rtnl);
1042
6a7a4e4d 1043 log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
4f882b2a 1044
6a7a4e4d
LP
1045 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1046 if (r < 0)
1047 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
4f882b2a 1048
1c4baffc 1049 r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
6a7a4e4d
LP
1050 if (r < 0)
1051 return log_link_error_errno(link, r, "Could not append MTU: %m");
4f882b2a 1052
1c4baffc 1053 r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
6a7a4e4d
LP
1054 if (r < 0)
1055 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
4f882b2a 1056
ae941762 1057 link_ref(link);
b226d99b 1058
4f882b2a
TG
1059 return 0;
1060}
1061
e1853b00 1062static int link_set_bridge(Link *link) {
1c4baffc 1063 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
e1853b00
SS
1064 int r;
1065
1066 assert(link);
1067 assert(link->network);
1068
6a7a4e4d
LP
1069 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1070 if (r < 0)
1071 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
e1853b00
SS
1072
1073 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
6a7a4e4d
LP
1074 if (r < 0)
1075 return log_link_error_errno(link, r, "Could not set message family: %m");
e1853b00 1076
1c4baffc 1077 r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
6a7a4e4d
LP
1078 if (r < 0)
1079 return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
e1853b00 1080
84c34096 1081 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
eb7ff4dd
SS
1082 if (r < 0)
1083 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
1084
1085 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
1086 if (r < 0)
1087 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
1088
1089 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
1090 if (r < 0)
1091 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
1092
23da66bb 1093 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
eb7ff4dd
SS
1094 if (r < 0)
1095 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
1096
1097 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
1098 if (r < 0)
1099 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
1100
e1853b00 1101 if(link->network->cost != 0) {
1c4baffc 1102 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
6a7a4e4d
LP
1103 if (r < 0)
1104 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
e1853b00
SS
1105 }
1106
1c4baffc 1107 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1108 if (r < 0)
1109 return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
e1853b00 1110
1c4baffc 1111 r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
6a7a4e4d
LP
1112 if (r < 0)
1113 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
e1853b00
SS
1114
1115 link_ref(link);
1116
1117 return r;
1118}
1119
49699bac
SS
1120static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
1121 Link *link = userdata;
1122 int r;
1123
1124 assert(link);
1125 assert(link->network);
1126 assert(link->manager);
1127
1128 if (event != UPDATE_INFO)
1129 return;
1130
1131 r = sd_lldp_save(link->lldp, link->lldp_file);
1132 if (r < 0)
6a7a4e4d 1133 log_link_warning_errno(link, r, "Could not save LLDP: %m");
49699bac
SS
1134
1135}
1136
ff254138
TG
1137static int link_acquire_conf(Link *link) {
1138 int r;
1139
1140 assert(link);
1141 assert(link->network);
ff254138
TG
1142 assert(link->manager);
1143 assert(link->manager->event);
1144
78c958f8 1145 if (link_ipv4ll_enabled(link)) {
eb34d4af 1146 assert(link->ipv4ll);
ff254138 1147
6a7a4e4d 1148 log_link_debug(link, "Acquiring IPv4 link-local address");
5c1d3fc9
UTL
1149
1150 r = sd_ipv4ll_start(link->ipv4ll);
6a7a4e4d
LP
1151 if (r < 0)
1152 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
5c1d3fc9
UTL
1153 }
1154
78c958f8 1155 if (link_dhcp4_enabled(link)) {
eb34d4af 1156 assert(link->dhcp_client);
ff254138 1157
6a7a4e4d 1158 log_link_debug(link, "Acquiring DHCPv4 lease");
ab47d620 1159
5c1d3fc9 1160 r = sd_dhcp_client_start(link->dhcp_client);
6a7a4e4d
LP
1161 if (r < 0)
1162 return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
5c1d3fc9 1163 }
ff254138 1164
78c958f8 1165 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1166 assert(link->icmp6_router_discovery);
1167
6a7a4e4d 1168 log_link_debug(link, "Discovering IPv6 routers");
4138fb2c
PF
1169
1170 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
6a7a4e4d
LP
1171 if (r < 0)
1172 return log_link_warning_errno(link, r, "Could not start IPv6 router discovery: %m");
4138fb2c
PF
1173 }
1174
ce43e484
SS
1175 if (link_lldp_enabled(link)) {
1176 assert(link->lldp);
1177
1178 log_link_debug(link, "Starting LLDP");
1179
1180 r = sd_lldp_start(link->lldp);
6a7a4e4d
LP
1181 if (r < 0)
1182 return log_link_warning_errno(link, r, "Could not start LLDP: %m");
ce43e484
SS
1183 }
1184
ff254138
TG
1185 return 0;
1186}
1187
a61bb41c 1188bool link_has_carrier(Link *link) {
deb2e523
TG
1189 /* see Documentation/networking/operstates.txt in the kernel sources */
1190
a61bb41c 1191 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1192 return true;
1193
a61bb41c 1194 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1195 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1196 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1197 return true;
1198
1199 return false;
1200}
1201
1c4baffc 1202static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1203 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1204 int r;
1205
1746cf2a
TG
1206 assert(link);
1207
5da8149f 1208 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1209 return 1;
1210
1c4baffc 1211 r = sd_netlink_message_get_errno(m);
6a7a4e4d
LP
1212 if (r < 0)
1213 /* we warn but don't fail the link, as it may be
1214 brought up later */
1215 log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
45ad2c13 1216
f882c247
TG
1217 return 1;
1218}
1219
1220static int link_up(Link *link) {
1c4baffc 1221 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
5c3072ea 1222 uint8_t ipv6ll_mode;
f579559b
TG
1223 int r;
1224
f882c247 1225 assert(link);
c106cc36 1226 assert(link->network);
f882c247
TG
1227 assert(link->manager);
1228 assert(link->manager->rtnl);
1229
6a7a4e4d 1230 log_link_debug(link, "Bringing link up");
449f7554 1231
6a7a4e4d
LP
1232 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1233 if (r < 0)
1234 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
f579559b 1235
5d4795f3 1236 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
6a7a4e4d
LP
1237 if (r < 0)
1238 return log_link_error_errno(link, r, "Could not set link flags: %m");
fc25d7f8 1239
c106cc36 1240 if (link->network->mac) {
1c4baffc 1241 r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
6a7a4e4d
LP
1242 if (r < 0)
1243 return log_link_error_errno(link, r, "Could not set MAC address: %m");
c106cc36
TG
1244 }
1245
1246 if (link->network->mtu) {
1c4baffc 1247 r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
6a7a4e4d
LP
1248 if (r < 0)
1249 return log_link_error_errno(link, r, "Could not set MTU: %m");
c106cc36
TG
1250 }
1251
1c4baffc 1252 r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
6a7a4e4d
LP
1253 if (r < 0)
1254 return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
d0d6a4cd 1255
01d28f81
TG
1256 if (socket_ipv6_is_supported()) {
1257 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
1c4baffc 1258 r = sd_netlink_message_open_container(req, AF_INET6);
01d28f81
TG
1259 if (r < 0)
1260 return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
d0d6a4cd 1261
01d28f81 1262 ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
1c4baffc 1263 r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
01d28f81
TG
1264 if (r < 0)
1265 return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
d0d6a4cd 1266
01d28f81 1267 if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
1c4baffc 1268 r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
01d28f81
TG
1269 if (r < 0)
1270 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
1271 }
1272
1c4baffc 1273 r = sd_netlink_message_close_container(req);
6a7a4e4d 1274 if (r < 0)
01d28f81 1275 return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
7f77697a 1276 }
d0d6a4cd 1277
1c4baffc 1278 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1279 if (r < 0)
1280 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
d0d6a4cd 1281
1c4baffc 1282 r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
6a7a4e4d
LP
1283 if (r < 0)
1284 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
f579559b 1285
b226d99b
TG
1286 link_ref(link);
1287
f882c247
TG
1288 return 0;
1289}
1290
1c4baffc 1291static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
0d4ad91d
AR
1292 _cleanup_link_unref_ Link *link = userdata;
1293 int r;
1294
1295 assert(link);
1296
1297 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1298 return 1;
1299
1c4baffc 1300 r = sd_netlink_message_get_errno(m);
0d4ad91d 1301 if (r < 0)
6a7a4e4d 1302 log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
0d4ad91d
AR
1303
1304 return 1;
1305}
1306
1307static int link_down(Link *link) {
1c4baffc 1308 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
0d4ad91d
AR
1309 int r;
1310
1311 assert(link);
1312 assert(link->manager);
1313 assert(link->manager->rtnl);
1314
6a7a4e4d 1315 log_link_debug(link, "Bringing link down");
0d4ad91d
AR
1316
1317 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1318 RTM_SETLINK, link->ifindex);
6a7a4e4d
LP
1319 if (r < 0)
1320 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
0d4ad91d
AR
1321
1322 r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
6a7a4e4d
LP
1323 if (r < 0)
1324 return log_link_error_errno(link, r, "Could not set link flags: %m");
0d4ad91d 1325
1c4baffc 1326 r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
6a7a4e4d
LP
1327 if (r < 0)
1328 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
0d4ad91d
AR
1329
1330 link_ref(link);
1331
1332 return 0;
1333}
1334
1335static int link_handle_bound_to_list(Link *link) {
1336 Link *l;
1337 Iterator i;
1338 int r;
1339 bool required_up = false;
1340 bool link_is_up = false;
1341
1342 assert(link);
1343
1344 if (hashmap_isempty(link->bound_to_links))
1345 return 0;
1346
1347 if (link->flags & IFF_UP)
1348 link_is_up = true;
1349
1350 HASHMAP_FOREACH (l, link->bound_to_links, i)
1351 if (link_has_carrier(l)) {
1352 required_up = true;
1353 break;
1354 }
1355
1356 if (!required_up && link_is_up) {
1357 r = link_down(link);
1358 if (r < 0)
1359 return r;
1360 } else if (required_up && !link_is_up) {
1361 r = link_up(link);
1362 if (r < 0)
1363 return r;
1364 }
1365
1366 return 0;
1367}
1368
1369static int link_handle_bound_by_list(Link *link) {
1370 Iterator i;
1371 Link *l;
1372 int r;
1373
1374 assert(link);
1375
1376 if (hashmap_isempty(link->bound_by_links))
1377 return 0;
1378
1379 HASHMAP_FOREACH (l, link->bound_by_links, i) {
1380 r = link_handle_bound_to_list(l);
1381 if (r < 0)
1382 return r;
1383 }
1384
1385 return 0;
1386}
1387
1388static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
1389 int r;
1390
1391 assert(link);
1392 assert(carrier);
1393
1394 if (link == carrier)
1395 return 0;
1396
1397 if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
1398 return 0;
1399
1400 r = hashmap_ensure_allocated(h, NULL);
1401 if (r < 0)
1402 return r;
1403
1404 r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
1405 if (r < 0)
1406 return r;
1407
1408 return 0;
1409}
1410
1411static int link_new_bound_by_list(Link *link) {
1412 Manager *m;
1413 Link *carrier;
1414 Iterator i;
1415 int r;
1416 bool list_updated = false;
1417
1418 assert(link);
1419 assert(link->manager);
1420
1421 m = link->manager;
1422
1423 HASHMAP_FOREACH (carrier, m->links, i) {
1424 if (!carrier->network)
1425 continue;
1426
1427 if (strv_isempty(carrier->network->bind_carrier))
1428 continue;
1429
1430 if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
1431 r = link_put_carrier(link, carrier, &link->bound_by_links);
1432 if (r < 0)
1433 return r;
1434
1435 list_updated = true;
1436 }
1437 }
1438
1439 if (list_updated)
1440 link_save(link);
1441
1442 HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
1443 r = link_put_carrier(carrier, link, &carrier->bound_to_links);
1444 if (r < 0)
1445 return r;
1446
1447 link_save(carrier);
1448 }
1449
1450 return 0;
1451}
1452
1453static int link_new_bound_to_list(Link *link) {
1454 Manager *m;
1455 Link *carrier;
1456 Iterator i;
1457 int r;
1458 bool list_updated = false;
1459
1460 assert(link);
1461 assert(link->manager);
1462
1463 if (!link->network)
1464 return 0;
1465
1466 if (strv_isempty(link->network->bind_carrier))
1467 return 0;
1468
1469 m = link->manager;
1470
1471 HASHMAP_FOREACH (carrier, m->links, i) {
1472 if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
1473 r = link_put_carrier(link, carrier, &link->bound_to_links);
1474 if (r < 0)
1475 return r;
1476
1477 list_updated = true;
1478 }
1479 }
1480
1481 if (list_updated)
1482 link_save(link);
1483
1484 HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
1485 r = link_put_carrier(carrier, link, &carrier->bound_by_links);
1486 if (r < 0)
1487 return r;
1488
1489 link_save(carrier);
1490 }
1491
1492 return 0;
1493}
1494
1495static int link_new_carrier_maps(Link *link) {
1496 int r;
1497
1498 r = link_new_bound_by_list(link);
1499 if (r < 0)
1500 return r;
1501
1502 r = link_handle_bound_by_list(link);
1503 if (r < 0)
1504 return r;
1505
1506 r = link_new_bound_to_list(link);
1507 if (r < 0)
1508 return r;
1509
1510 r = link_handle_bound_to_list(link);
1511 if (r < 0)
1512 return r;
1513
1514 return 0;
1515}
1516
1517static void link_free_bound_to_list(Link *link) {
1518 Link *bound_to;
1519 Iterator i;
1520
1521 HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
1522 hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
1523
1524 if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
1525 link_save(bound_to);
1526 }
1527
1528 return;
1529}
1530
1531static void link_free_bound_by_list(Link *link) {
1532 Link *bound_by;
1533 Iterator i;
1534
1535 HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
1536 hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
1537
1538 if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
1539 link_save(bound_by);
1540 link_handle_bound_to_list(bound_by);
1541 }
1542 }
1543
1544 return;
1545}
1546
1547static void link_free_carrier_maps(Link *link) {
1548 bool list_updated = false;
1549
1550 assert(link);
1551
1552 if (!hashmap_isempty(link->bound_to_links)) {
1553 link_free_bound_to_list(link);
1554 list_updated = true;
1555 }
1556
1557 if (!hashmap_isempty(link->bound_by_links)) {
1558 link_free_bound_by_list(link);
1559 list_updated = true;
1560 }
1561
1562 if (list_updated)
1563 link_save(link);
1564
1565 return;
1566}
1567
1568void link_drop(Link *link) {
1569 if (!link || link->state == LINK_STATE_LINGER)
1570 return;
1571
1572 link_set_state(link, LINK_STATE_LINGER);
1573
1574 link_free_carrier_maps(link);
1575
6a7a4e4d 1576 log_link_debug(link, "Link removed");
0d4ad91d
AR
1577
1578 link_unref(link);
1579
1580 return;
1581}
1582
3f265037 1583static int link_joined(Link *link) {
f882c247
TG
1584 int r;
1585
ef1ba606 1586 assert(link);
f5be5601 1587 assert(link->network);
dd3efc09 1588
0d4ad91d
AR
1589 if (!hashmap_isempty(link->bound_to_links)) {
1590 r = link_handle_bound_to_list(link);
1591 if (r < 0)
1592 return r;
1593 } else if (!(link->flags & IFF_UP)) {
505f8da7
TG
1594 r = link_up(link);
1595 if (r < 0) {
1596 link_enter_failed(link);
1597 return r;
1598 }
ef1ba606 1599 }
f882c247 1600
e1853b00
SS
1601 if(link->network->bridge) {
1602 r = link_set_bridge(link);
6a7a4e4d
LP
1603 if (r < 0)
1604 log_link_error_errno(link, r, "Could not set bridge message: %m");
e1853b00
SS
1605 }
1606
fb6730c4 1607 return link_enter_set_addresses(link);
02b59d57
TG
1608}
1609
62e2d5bb 1610static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1611 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1612 int r;
1613
1746cf2a 1614 assert(link);
ef1ba606 1615 assert(link->network);
02b59d57 1616
52433f6b
TG
1617 link->enslaving --;
1618
5da8149f 1619 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1620 return 1;
1621
1c4baffc 1622 r = sd_netlink_message_get_errno(m);
856f962c 1623 if (r < 0 && r != -EEXIST) {
6a7a4e4d 1624 log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1625 link_enter_failed(link);
1626 return 1;
ba179154 1627 } else
6a7a4e4d 1628 log_link_debug(link, "Joined netdev");
02b59d57 1629
856f962c 1630 if (link->enslaving <= 0)
3f265037 1631 link_joined(link);
02b59d57
TG
1632
1633 return 1;
1634}
1635
3f265037 1636static int link_enter_join_netdev(Link *link) {
6a0a2f86 1637 NetDev *netdev;
672682a6 1638 Iterator i;
02b59d57
TG
1639 int r;
1640
1641 assert(link);
1642 assert(link->network);
8434fd5c 1643 assert(link->state == LINK_STATE_PENDING);
02b59d57 1644
e331e246 1645 link_set_state(link, LINK_STATE_ENSLAVING);
02b59d57 1646
fe8db0c5
TG
1647 link_save(link);
1648
7951dea2
SS
1649 if (!link->network->bridge &&
1650 !link->network->bond &&
6a0a2f86 1651 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1652 return link_joined(link);
02b59d57 1653
d9c67ea1 1654 if (link->network->bond) {
f2341e0a
LP
1655 log_struct(LOG_DEBUG,
1656 LOG_LINK_INTERFACE(link),
1657 LOG_NETDEV_INTERFACE(link->network->bond),
1658 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
1659 NULL);
1660
1661 r = netdev_join(link->network->bond, link, netdev_join_handler);
52433f6b 1662 if (r < 0) {
f2341e0a
LP
1663 log_struct_errno(LOG_WARNING, r,
1664 LOG_LINK_INTERFACE(link),
1665 LOG_NETDEV_INTERFACE(link->network->bond),
1666 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
1667 NULL);
1668
52433f6b
TG
1669 link_enter_failed(link);
1670 return r;
1671 }
1672
0ad6148e
MO
1673 link->enslaving ++;
1674 }
1675
d9c67ea1 1676 if (link->network->bridge) {
f2341e0a
LP
1677 log_struct(LOG_DEBUG,
1678 LOG_LINK_INTERFACE(link),
1679 LOG_NETDEV_INTERFACE(link->network->bridge),
1680 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
1681 NULL);
1682
1683 r = netdev_join(link->network->bridge, link, netdev_join_handler);
0ad6148e 1684 if (r < 0) {
f2341e0a
LP
1685 log_struct_errno(LOG_WARNING, r,
1686 LOG_LINK_INTERFACE(link),
1687 LOG_NETDEV_INTERFACE(link->network->bridge),
1688 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
1689 NULL),
0ad6148e
MO
1690 link_enter_failed(link);
1691 return r;
1692 }
1693
52433f6b
TG
1694 link->enslaving ++;
1695 }
1696
6a0a2f86 1697 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1698
f2341e0a
LP
1699 log_struct(LOG_DEBUG,
1700 LOG_LINK_INTERFACE(link),
1701 LOG_NETDEV_INTERFACE(netdev),
1702 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
1703 NULL);
1704
1705 r = netdev_join(netdev, link, netdev_join_handler);
7951dea2 1706 if (r < 0) {
f2341e0a
LP
1707 log_struct_errno(LOG_WARNING, r,
1708 LOG_LINK_INTERFACE(link),
1709 LOG_NETDEV_INTERFACE(netdev),
1710 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
1711 NULL);
326cb406
SS
1712 link_enter_failed(link);
1713 return r;
1714 }
1715
326cb406
SS
1716 link->enslaving ++;
1717 }
1718
ef1ba606
TG
1719 return 0;
1720}
1721
769d324c 1722static int link_set_ipv4_forward(Link *link) {
15dee3f0 1723 const char *p = NULL, *v;
5a8bcb67
LP
1724 int r;
1725
15dee3f0
LP
1726 if (link->flags & IFF_LOOPBACK)
1727 return 0;
1728
8add5f79
NO
1729 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1730 return 0;
1731
63c372cb 1732 p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1733 v = one_zero(link_ipv4_forward_enabled(link));
1734
4c1fc3e4 1735 r = write_string_file(p, v, 0);
15dee3f0
LP
1736 if (r < 0) {
1737 /* If the right value is set anyway, don't complain */
1738 if (verify_one_line_file(p, v) > 0)
1739 return 0;
1740
43c6d5ab 1741 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
15dee3f0 1742 }
43c6d5ab 1743
769d324c
LP
1744 return 0;
1745}
1746
1747static int link_set_ipv6_forward(Link *link) {
15dee3f0 1748 const char *p = NULL, *v = NULL;
769d324c
LP
1749 int r;
1750
fe027299
LP
1751 /* Make this a NOP if IPv6 is not available */
1752 if (!socket_ipv6_is_supported())
1753 return 0;
1754
15dee3f0
LP
1755 if (link->flags & IFF_LOOPBACK)
1756 return 0;
1757
8add5f79
NO
1758 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1759 return 0;
1760
63c372cb 1761 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1762 v = one_zero(link_ipv6_forward_enabled(link));
1763
4c1fc3e4 1764 r = write_string_file(p, v, 0);
15dee3f0
LP
1765 if (r < 0) {
1766 /* If the right value is set anyway, don't complain */
1767 if (verify_one_line_file(p, v) > 0)
1768 return 0;
1769
769d324c 1770 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
15dee3f0 1771 }
5a8bcb67
LP
1772
1773 return 0;
1774}
1775
49092e22 1776static int link_set_ipv6_privacy_extensions(Link *link) {
1f0d9695
LP
1777 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1778 IPv6PrivacyExtensions s;
49092e22
SS
1779 const char *p = NULL;
1780 int r;
1781
1782 /* Make this a NOP if IPv6 is not available */
1783 if (!socket_ipv6_is_supported())
1784 return 0;
1785
1f0d9695
LP
1786 s = link_ipv6_privacy_extensions(link);
1787 if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
49092e22
SS
1788 return 0;
1789
1790 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
1791 xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
1792
4c1fc3e4 1793 r = write_string_file(p, buf, 0);
1f0d9695
LP
1794 if (r < 0) {
1795 /* If the right value is set anyway, don't complain */
1796 if (verify_one_line_file(p, buf) > 0)
1797 return 0;
1798
49092e22 1799 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
1f0d9695 1800 }
49092e22
SS
1801
1802 return 0;
1803}
1804
a748b692 1805static int link_configure(Link *link) {
02b59d57
TG
1806 int r;
1807
ef1ba606 1808 assert(link);
b22d8a00 1809 assert(link->network);
8434fd5c 1810 assert(link->state == LINK_STATE_PENDING);
a748b692 1811
b98b483b
AR
1812 r = link_set_bridge_fdb(link);
1813 if (r < 0)
1814 return r;
1815
769d324c
LP
1816 r = link_set_ipv4_forward(link);
1817 if (r < 0)
1818 return r;
1819
1820 r = link_set_ipv6_forward(link);
5a8bcb67
LP
1821 if (r < 0)
1822 return r;
1823
49092e22
SS
1824 r = link_set_ipv6_privacy_extensions(link);
1825 if (r < 0)
1826 return r;
1827
78c958f8 1828 if (link_ipv4ll_enabled(link)) {
b22d8a00 1829 r = ipv4ll_configure(link);
eb34d4af
TG
1830 if (r < 0)
1831 return r;
1832 }
1833
78c958f8 1834 if (link_dhcp4_enabled(link)) {
3c9b8860 1835 r = dhcp4_configure(link);
eb34d4af
TG
1836 if (r < 0)
1837 return r;
eb34d4af
TG
1838 }
1839
78c958f8 1840 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1841 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1842 if (r < 0)
1843 return r;
1844
1845 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1846 if (r < 0)
1847 return r;
dd43110f
TG
1848 }
1849
78c958f8 1850 if (link_dhcp6_enabled(link)) {
5c79bd79 1851 r = icmp6_configure(link);
4138fb2c
PF
1852 if (r < 0)
1853 return r;
1854 }
1855
ce43e484
SS
1856 if (link_lldp_enabled(link)) {
1857 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
1858 if (r < 0)
1859 return r;
1860
1861 r = sd_lldp_attach_event(link->lldp, NULL, 0);
1862 if (r < 0)
1863 return r;
49699bac
SS
1864
1865 r = sd_lldp_set_callback(link->lldp,
1866 lldp_handler, link);
1867 if (r < 0)
1868 return r;
ce43e484
SS
1869 }
1870
a61bb41c 1871 if (link_has_carrier(link)) {
1e9be60b
TG
1872 r = link_acquire_conf(link);
1873 if (r < 0)
1874 return r;
cc544d5f 1875 }
1e9be60b 1876
3f265037 1877 return link_enter_join_netdev(link);
505f8da7
TG
1878}
1879
1c4baffc 1880static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860 1881 void *userdata) {
5da8149f 1882 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1883 Network *network;
505f8da7
TG
1884 int r;
1885
1886 assert(link);
1887 assert(link->ifname);
1888 assert(link->manager);
1889
8434fd5c 1890 if (link->state != LINK_STATE_PENDING)
5da8149f 1891 return 1;
505f8da7 1892
6a7a4e4d 1893 log_link_debug(link, "Link state is up-to-date");
505f8da7 1894
0d4ad91d
AR
1895 r = link_new_bound_by_list(link);
1896 if (r < 0)
1897 return r;
1898
1899 r = link_handle_bound_by_list(link);
1900 if (r < 0)
1901 return r;
1902
3c9b8860
TG
1903 r = network_get(link->manager, link->udev_device, link->ifname,
1904 &link->mac, &network);
57bd6899
TG
1905 if (r == -ENOENT) {
1906 link_enter_unmanaged(link);
5da8149f 1907 return 1;
57bd6899
TG
1908 } else if (r < 0)
1909 return r;
505f8da7 1910
bd2efe92 1911 if (link->flags & IFF_LOOPBACK) {
d0d6a4cd 1912 if (network->link_local != ADDRESS_FAMILY_NO)
6a7a4e4d 1913 log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
78c958f8 1914
cb9fc36a 1915 if (network->dhcp != ADDRESS_FAMILY_NO)
6a7a4e4d 1916 log_link_debug(link, "Ignoring DHCP clients for loopback link");
78c958f8
TG
1917
1918 if (network->dhcp_server)
6a7a4e4d 1919 log_link_debug(link, "Ignoring DHCP server for loopback link");
bd2efe92
TG
1920 }
1921
505f8da7
TG
1922 r = network_apply(link->manager, network, link);
1923 if (r < 0)
1924 return r;
1925
0d4ad91d
AR
1926 r = link_new_bound_to_list(link);
1927 if (r < 0)
1928 return r;
1929
a748b692
TG
1930 r = link_configure(link);
1931 if (r < 0)
1932 return r;
1933
5da8149f 1934 return 1;
505f8da7
TG
1935}
1936
4f561e8e 1937int link_initialized(Link *link, struct udev_device *device) {
1c4baffc 1938 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f561e8e
TG
1939 int r;
1940
1941 assert(link);
1942 assert(link->manager);
1943 assert(link->manager->rtnl);
1944 assert(device);
1945
8434fd5c 1946 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1947 return 0;
1948
679b3605
TG
1949 if (link->udev_device)
1950 return 0;
1951
79008bdd 1952 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1953
1954 link->udev_device = udev_device_ref(device);
1955
3c9b8860
TG
1956 /* udev has initialized the link, but we don't know if we have yet
1957 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1958 * when it returns we know that the pending NEWLINKs have already been
1959 * processed and that we are up-to-date */
4f561e8e 1960
3c9b8860
TG
1961 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1962 link->ifindex);
4f561e8e
TG
1963 if (r < 0)
1964 return r;
1965
1c4baffc 1966 r = sd_netlink_call_async(link->manager->rtnl, req,
3c9b8860 1967 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1968 if (r < 0)
1969 return r;
1970
5da8149f
TG
1971 link_ref(link);
1972
4f561e8e
TG
1973 return 0;
1974}
1975
5a8bcb67
LP
1976static Address* link_get_equal_address(Link *link, Address *needle) {
1977 Address *i;
1978
1979 assert(link);
1980 assert(needle);
1981
1982 LIST_FOREACH(addresses, i, link->addresses)
1983 if (address_equal(i, needle))
1984 return i;
1985
1986 return NULL;
1987}
1988
1c4baffc 1989int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
fbbeb65a
TG
1990 Manager *m = userdata;
1991 Link *link = NULL;
1992 uint16_t type;
1993 _cleanup_address_free_ Address *address = NULL;
851c9f82 1994 unsigned char flags;
5a8bcb67
LP
1995 Address *existing;
1996 char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
c6d3b303 1997 const char *valid_str = NULL;
fbbeb65a
TG
1998 int r, ifindex;
1999
2000 assert(rtnl);
2001 assert(message);
2002 assert(m);
2003
1c4baffc
TG
2004 if (sd_netlink_message_is_error(message)) {
2005 r = sd_netlink_message_get_errno(message);
45af44d4
TG
2006 if (r < 0)
2007 log_warning_errno(r, "rtnl: failed to receive address: %m");
2008
2009 return 0;
2010 }
2011
1c4baffc 2012 r = sd_netlink_message_get_type(message, &type);
fbbeb65a 2013 if (r < 0) {
6a7a4e4d 2014 log_warning_errno(r, "rtnl: could not get message type: %m");
fbbeb65a 2015 return 0;
cdfee943
TG
2016 } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
2017 log_warning("rtnl: received unexpected message type when processing address");
2018 return 0;
fbbeb65a
TG
2019 }
2020
2021 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
45af44d4 2022 if (r < 0) {
cdfee943 2023 log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
45af44d4
TG
2024 return 0;
2025 } else if (ifindex <= 0) {
2026 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
fbbeb65a
TG
2027 return 0;
2028 } else {
2029 r = link_get(m, ifindex, &link);
2030 if (r < 0 || !link) {
6a24f148
TG
2031 /* when enumerating we might be out of sync, but we will
2032 * get the address again, so just ignore it */
2033 if (!m->enumerating)
2034 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
2035 return 0;
2036 }
2037 }
2038
2039 r = address_new_dynamic(&address);
2040 if (r < 0)
393c0c5e 2041 return r;
fbbeb65a
TG
2042
2043 r = sd_rtnl_message_addr_get_family(message, &address->family);
2044 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
6a7a4e4d 2045 log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
fbbeb65a
TG
2046 return 0;
2047 }
2048
2049 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
2050 if (r < 0) {
6a7a4e4d 2051 log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
e375dcde
TG
2052 return 0;
2053 }
2054
2055 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
2056 if (r < 0) {
6a7a4e4d 2057 log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
fbbeb65a
TG
2058 return 0;
2059 }
2060
851c9f82 2061 r = sd_rtnl_message_addr_get_flags(message, &flags);
81163121 2062 if (r < 0) {
6a7a4e4d 2063 log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
81163121
TG
2064 return 0;
2065 }
851c9f82 2066 address->flags = flags;
81163121 2067
fbbeb65a
TG
2068 switch (address->family) {
2069 case AF_INET:
1c4baffc 2070 r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
fbbeb65a 2071 if (r < 0) {
6a7a4e4d 2072 log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
fbbeb65a
TG
2073 return 0;
2074 }
2075
2076 break;
2077
2078 case AF_INET6:
1c4baffc 2079 r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
fbbeb65a 2080 if (r < 0) {
6a7a4e4d 2081 log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
fbbeb65a
TG
2082 return 0;
2083 }
2084
2085 break;
2086
2087 default:
2088 assert_not_reached("invalid address family");
2089 }
2090
5a8bcb67 2091 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
6a7a4e4d 2092 log_link_warning(link, "Could not print address");
fbbeb65a
TG
2093 return 0;
2094 }
2095
1c4baffc 2096 r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
c6d3b303
TG
2097 if (r >= 0) {
2098 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
2099 valid_str = "ever";
2100 else
2101 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
2102 address->cinfo.ifa_valid * USEC_PER_SEC,
2103 USEC_PER_SEC);
2104 }
2105
5a8bcb67
LP
2106 existing = link_get_equal_address(link, address);
2107
2108 switch (type) {
2109 case RTM_NEWADDR:
2110 if (existing) {
2111 log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 2112
428fd0a7 2113
5a8bcb67
LP
2114 existing->scope = address->scope;
2115 existing->flags = address->flags;
2116 existing->cinfo = address->cinfo;
428fd0a7 2117
5a8bcb67
LP
2118 } else {
2119 log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 2120
5a8bcb67
LP
2121 LIST_PREPEND(addresses, link->addresses, address);
2122 address_establish(address, link);
fbbeb65a 2123
5a8bcb67 2124 address = NULL;
428fd0a7 2125
5a8bcb67
LP
2126 link_save(link);
2127 }
f5602be9 2128
428fd0a7 2129 break;
5a8bcb67 2130
fbbeb65a 2131 case RTM_DELADDR:
428fd0a7 2132
5a8bcb67
LP
2133 if (existing) {
2134 log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
2135 address_release(existing, link);
2136 LIST_REMOVE(addresses, link->addresses, existing);
2137 address_free(existing);
393c0c5e 2138 } else
5a8bcb67 2139 log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
f5602be9 2140
fbbeb65a
TG
2141 break;
2142 default:
2143 assert_not_reached("Received invalid RTNL message type");
2144 }
2145
2146 return 1;
2147}
2148
1c4baffc 2149int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
505f8da7
TG
2150 Link *link;
2151 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2152 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2153 int r;
2154
2155 assert(m);
fbbeb65a 2156 assert(m->rtnl);
505f8da7
TG
2157 assert(message);
2158 assert(ret);
2159
2160 r = link_new(m, message, ret);
2161 if (r < 0)
2162 return r;
2163
2164 link = *ret;
2165
6a7a4e4d 2166 log_link_debug(link, "Link %d added", link->ifindex);
505f8da7
TG
2167
2168 if (detect_container(NULL) <= 0) {
2169 /* not in a container, udev will be around */
ae06ab10 2170 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7 2171 device = udev_device_new_from_device_id(m->udev, ifindex_str);
6a7a4e4d
LP
2172 if (!device)
2173 return log_link_warning_errno(link, errno, "Could not find udev device: %m");
505f8da7 2174
3c4cb064 2175 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 2176 /* not yet ready */
79008bdd 2177 log_link_debug(link, "link pending udev initialization...");
505f8da7 2178 return 0;
3c4cb064 2179 }
505f8da7 2180
4f561e8e
TG
2181 r = link_initialized(link, device);
2182 if (r < 0)
2183 return r;
2184 } else {
5da8149f
TG
2185 /* we are calling a callback directly, so must take a ref */
2186 link_ref(link);
2187
4f561e8e
TG
2188 r = link_initialized_and_synced(m->rtnl, NULL, link);
2189 if (r < 0)
2190 return r;
2191 }
505f8da7 2192
a748b692
TG
2193 return 0;
2194}
2195
9c0a72f9
TG
2196static int link_carrier_gained(Link *link) {
2197 int r;
2198
2199 assert(link);
2200
2201 if (link->network) {
2202 r = link_acquire_conf(link);
2203 if (r < 0) {
2204 link_enter_failed(link);
2205 return r;
2206 }
2207 }
2208
0d4ad91d
AR
2209 r = link_handle_bound_by_list(link);
2210 if (r < 0)
2211 return r;
2212
9c0a72f9
TG
2213 return 0;
2214}
2215
2216static int link_carrier_lost(Link *link) {
2217 int r;
2218
2219 assert(link);
2220
2221 r = link_stop_clients(link);
2222 if (r < 0) {
2223 link_enter_failed(link);
2224 return r;
2225 }
2226
0d4ad91d
AR
2227 r = link_handle_bound_by_list(link);
2228 if (r < 0)
2229 return r;
2230
9c0a72f9
TG
2231 return 0;
2232}
2233
2234int link_carrier_reset(Link *link) {
2235 int r;
2236
2237 assert(link);
2238
2239 if (link_has_carrier(link)) {
2240 r = link_carrier_lost(link);
2241 if (r < 0)
2242 return r;
2243
2244 r = link_carrier_gained(link);
2245 if (r < 0)
2246 return r;
2247
6a7a4e4d 2248 log_link_info(link, "Reset carrier");
9c0a72f9
TG
2249 }
2250
2251 return 0;
2252}
2253
2254
1c4baffc 2255int link_update(Link *link, sd_netlink_message *m) {
c49b33ac 2256 struct ether_addr mac;
ca4e095a 2257 const char *ifname;
afe7fd56 2258 uint32_t mtu;
a61bb41c 2259 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
2260 int r;
2261
dd3efc09 2262 assert(link);
b8941f74 2263 assert(link->ifname);
22936833
TG
2264 assert(m);
2265
7619683b
TG
2266 if (link->state == LINK_STATE_LINGER) {
2267 link_ref(link);
6a7a4e4d 2268 log_link_info(link, "Link readded");
e331e246 2269 link_set_state(link, LINK_STATE_ENSLAVING);
0d4ad91d
AR
2270
2271 r = link_new_carrier_maps(link);
2272 if (r < 0)
2273 return r;
7619683b
TG
2274 }
2275
1c4baffc 2276 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
b8941f74 2277 if (r >= 0 && !streq(ifname, link->ifname)) {
6a7a4e4d 2278 log_link_info(link, "Renamed to %s", ifname);
b8941f74 2279
0d4ad91d
AR
2280 link_free_carrier_maps(link);
2281
2fc09a9c
DM
2282 r = free_and_strdup(&link->ifname, ifname);
2283 if (r < 0)
2284 return r;
0d4ad91d
AR
2285
2286 r = link_new_carrier_maps(link);
2287 if (r < 0)
2288 return r;
b8941f74
TG
2289 }
2290
1c4baffc 2291 r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
afe7fd56
TG
2292 if (r >= 0 && mtu > 0) {
2293 link->mtu = mtu;
2294 if (!link->original_mtu) {
2295 link->original_mtu = mtu;
6a7a4e4d 2296 log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
afe7fd56
TG
2297 }
2298
2299 if (link->dhcp_client) {
3c9b8860
TG
2300 r = sd_dhcp_client_set_mtu(link->dhcp_client,
2301 link->mtu);
afe7fd56 2302 if (r < 0) {
6a7a4e4d 2303 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
afe7fd56
TG
2304 return r;
2305 }
2306 }
9842de0d 2307 }
69629de9 2308
e9189a1f
TG
2309 /* The kernel may broadcast NEWLINK messages without the MAC address
2310 set, simply ignore them. */
1c4baffc 2311 r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 2312 if (r >= 0) {
3c9b8860
TG
2313 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
2314 ETH_ALEN)) {
c49b33ac 2315
3c9b8860
TG
2316 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
2317 ETH_ALEN);
c49b33ac 2318
79008bdd 2319 log_link_debug(link, "MAC address: "
20861203
TG
2320 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2321 mac.ether_addr_octet[0],
2322 mac.ether_addr_octet[1],
2323 mac.ether_addr_octet[2],
2324 mac.ether_addr_octet[3],
2325 mac.ether_addr_octet[4],
2326 mac.ether_addr_octet[5]);
c49b33ac 2327
20861203
TG
2328 if (link->ipv4ll) {
2329 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
6a7a4e4d
LP
2330 if (r < 0)
2331 return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
c49b33ac 2332 }
c49b33ac 2333
20861203 2334 if (link->dhcp_client) {
3c9b8860 2335 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
2336 (const uint8_t *) &link->mac,
2337 sizeof (link->mac),
2338 ARPHRD_ETHER);
6a7a4e4d
LP
2339 if (r < 0)
2340 return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
c49b33ac 2341 }
4138fb2c
PF
2342
2343 if (link->dhcp6_client) {
2344 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
2345 (const uint8_t *) &link->mac,
2346 sizeof (link->mac),
2347 ARPHRD_ETHER);
6a7a4e4d
LP
2348 if (r < 0)
2349 return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
4138fb2c 2350 }
c49b33ac 2351 }
4f882b2a
TG
2352 }
2353
a61bb41c
TG
2354 had_carrier = link_has_carrier(link);
2355
2356 r = link_update_flags(link, m);
2357 if (r < 0)
2358 return r;
2359
2360 carrier_gained = !had_carrier && link_has_carrier(link);
2361 carrier_lost = had_carrier && !link_has_carrier(link);
2362
2363 if (carrier_gained) {
6a7a4e4d 2364 log_link_info(link, "Gained carrier");
a61bb41c 2365
9c0a72f9
TG
2366 r = link_carrier_gained(link);
2367 if (r < 0)
2368 return r;
a61bb41c 2369 } else if (carrier_lost) {
6a7a4e4d 2370 log_link_info(link, "Lost carrier");
a61bb41c 2371
9c0a72f9
TG
2372 r = link_carrier_lost(link);
2373 if (r < 0)
a61bb41c 2374 return r;
9c0a72f9 2375
a61bb41c
TG
2376 }
2377
2378 return 0;
dd3efc09 2379}
fe8db0c5 2380
e375dcde 2381static void link_update_operstate(Link *link) {
e331e246 2382 LinkOperationalState operstate;
e375dcde
TG
2383 assert(link);
2384
2385 if (link->kernel_operstate == IF_OPER_DORMANT)
e331e246 2386 operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 2387 else if (link_has_carrier(link)) {
e375dcde
TG
2388 Address *address;
2389 uint8_t scope = RT_SCOPE_NOWHERE;
2390
2391 /* if we have carrier, check what addresses we have */
2392 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
2393 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
2394 continue;
2395
e375dcde
TG
2396 if (address->scope < scope)
2397 scope = address->scope;
2398 }
2399
2400 if (scope < RT_SCOPE_SITE)
2401 /* universally accessible addresses found */
e331e246 2402 operstate = LINK_OPERSTATE_ROUTABLE;
e375dcde
TG
2403 else if (scope < RT_SCOPE_HOST)
2404 /* only link or site local addresses found */
e331e246 2405 operstate = LINK_OPERSTATE_DEGRADED;
e375dcde
TG
2406 else
2407 /* no useful addresses found */
e331e246 2408 operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 2409 } else if (link->flags & IFF_UP)
e331e246 2410 operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 2411 else
e331e246
TG
2412 operstate = LINK_OPERSTATE_OFF;
2413
2414 if (link->operstate != operstate) {
2415 link->operstate = operstate;
2416 link_send_changed(link, "OperationalState", NULL);
2417 }
e375dcde
TG
2418}
2419
fe8db0c5 2420int link_save(Link *link) {
68a8723c 2421 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2422 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2423 const char *admin_state, *oper_state;
fe8db0c5
TG
2424 int r;
2425
2426 assert(link);
2427 assert(link->state_file);
68a8723c 2428 assert(link->lease_file);
bbf7c048
TG
2429 assert(link->manager);
2430
e375dcde
TG
2431 link_update_operstate(link);
2432
bbf7c048
TG
2433 r = manager_save(link->manager);
2434 if (r < 0)
2435 return r;
fe8db0c5 2436
370e9930
TG
2437 if (link->state == LINK_STATE_LINGER) {
2438 unlink(link->state_file);
2439 return 0;
2440 }
2441
deb2e523
TG
2442 admin_state = link_state_to_string(link->state);
2443 assert(admin_state);
2444
e375dcde
TG
2445 oper_state = link_operstate_to_string(link->operstate);
2446 assert(oper_state);
deb2e523 2447
fe8db0c5
TG
2448 r = fopen_temporary(link->state_file, &f, &temp_path);
2449 if (r < 0)
6a7a4e4d 2450 goto fail;
fe8db0c5
TG
2451
2452 fchmod(fileno(f), 0644);
2453
2454 fprintf(f,
2455 "# This is private data. Do not parse.\n"
deb2e523 2456 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
2457 "OPER_STATE=%s\n",
2458 admin_state, oper_state);
fe8db0c5 2459
bcb7a07e 2460 if (link->network) {
ea352b40
LP
2461 char **address, **domain;
2462 bool space;
07bdc70d
PF
2463 sd_dhcp6_lease *dhcp6_lease = NULL;
2464
2465 if (link->dhcp6_client) {
2466 r = sd_dhcp6_client_get_lease(link->dhcp6_client,
2467 &dhcp6_lease);
2468 if (r < 0)
2469 log_link_debug(link, "No DHCPv6 lease");
2470 }
b0e39c82 2471
adc5b2e2
TG
2472 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
2473
b0e39c82 2474 fputs("DNS=", f);
ea352b40
LP
2475 space = false;
2476 STRV_FOREACH(address, link->network->dns) {
2477 if (space)
2478 fputc(' ', f);
2479 fputs(*address, f);
2480 space = true;
2481 }
d5314fff 2482
b0e39c82
TG
2483 if (link->network->dhcp_dns &&
2484 link->dhcp_lease) {
2485 const struct in_addr *addresses;
2486
2487 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2488 if (r > 0) {
ea352b40
LP
2489 if (space)
2490 fputc(' ', f);
b0e39c82 2491 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2492 space = true;
2493 }
2494 }
2495
2496 if (link->network->dhcp_dns && dhcp6_lease) {
2497 struct in6_addr *in6_addrs;
2498
2499 r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
2500 if (r > 0) {
2501 if (space)
2502 fputc(' ', f);
2503 serialize_in6_addrs(f, in6_addrs, r);
2504 space = true;
b0e39c82
TG
2505 }
2506 }
2507
b0e39c82
TG
2508 fputs("\n", f);
2509
2510 fprintf(f, "NTP=");
ea352b40
LP
2511 space = false;
2512 STRV_FOREACH(address, link->network->ntp) {
2513 if (space)
2514 fputc(' ', f);
2515 fputs(*address, f);
2516 space = true;
2517 }
d5314fff 2518
b0e39c82
TG
2519 if (link->network->dhcp_ntp &&
2520 link->dhcp_lease) {
2521 const struct in_addr *addresses;
2522
2523 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2524 if (r > 0) {
ea352b40
LP
2525 if (space)
2526 fputc(' ', f);
b0e39c82 2527 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2528 space = true;
2529 }
2530 }
2531
2532 if (link->network->dhcp_ntp && dhcp6_lease) {
2533 struct in6_addr *in6_addrs;
2534 char **hosts;
2535 char **hostname;
2536
2537 r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
2538 &in6_addrs);
2539 if (r > 0) {
2540 if (space)
2541 fputc(' ', f);
2542 serialize_in6_addrs(f, in6_addrs, r);
2543 space = true;
2544 }
2545
2546 r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
2547 if (r > 0) {
2548 STRV_FOREACH(hostname, hosts) {
2549 if (space)
2550 fputc(' ', f);
2551 fputs(*hostname, f);
2552 space = true;
2553 }
b0e39c82
TG
2554 }
2555 }
2556
b0e39c82 2557 fputs("\n", f);
bd8f6538 2558
6192b846 2559 fprintf(f, "DOMAINS=");
ea352b40
LP
2560 space = false;
2561 STRV_FOREACH(domain, link->network->domains) {
2562 if (space)
2563 fputc(' ', f);
2564 fputs(*domain, f);
2565 space = true;
2566 }
d5314fff 2567
ad0734e8 2568 if (link->network->dhcp_domains &&
9b4d1882
TG
2569 link->dhcp_lease) {
2570 const char *domainname;
2571
2572 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 2573 if (r >= 0) {
ea352b40
LP
2574 if (space)
2575 fputc(' ', f);
6192b846 2576 fputs(domainname, f);
07bdc70d
PF
2577 space = true;
2578 }
2579 }
2580
2581 if (link->network->dhcp_domains && dhcp6_lease) {
2582 char **domains;
2583
2584 r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
2585 if (r >= 0) {
2586 STRV_FOREACH(domain, domains) {
2587 if (space)
2588 fputc(' ', f);
2589 fputs(*domain, f);
2590 space = true;
2591 }
6192b846 2592 }
9b4d1882
TG
2593 }
2594
6192b846
TG
2595 fputs("\n", f);
2596
67272d15
TG
2597 fprintf(f, "WILDCARD_DOMAIN=%s\n",
2598 yes_no(link->network->wildcard_domain));
2599
3c9b8860 2600 fprintf(f, "LLMNR=%s\n",
a7e5da6e 2601 resolve_support_to_string(link->network->llmnr));
bcb7a07e 2602 }
7374f9d8 2603
0d4ad91d
AR
2604 if (!hashmap_isempty(link->bound_to_links)) {
2605 Link *carrier;
2606 Iterator i;
2607 bool space = false;
2608
2609 fputs("CARRIER_BOUND_TO=", f);
2610 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
2611 if (space)
2612 fputc(' ', f);
2613 fputs(carrier->ifname, f);
2614 space = true;
2615 }
2616
2617 fputs("\n", f);
2618 }
2619
2620 if (!hashmap_isempty(link->bound_by_links)) {
2621 Link *carrier;
2622 Iterator i;
2623 bool space = false;
2624
2625 fputs("CARRIER_BOUND_BY=", f);
0d4ad91d
AR
2626 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
2627 if (space)
2628 fputc(' ', f);
2629 fputs(carrier->ifname, f);
2630 space = true;
2631 }
2632
2633 fputs("\n", f);
2634 }
2635
8eb9058d
LP
2636 if (link->dhcp_lease) {
2637 const char *tz = NULL;
2638
2639 r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
2640 if (r >= 0)
2641 fprintf(f, "TIMEZONE=%s\n", tz);
2642 }
2643
fe8db0c5 2644 if (link->dhcp_lease) {
d9876a52
TG
2645 assert(link->network);
2646
bd91b83e 2647 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 2648 if (r < 0)
c2d6bd61 2649 goto fail;
fe8db0c5 2650
7374f9d8 2651 fprintf(f,
b0e39c82
TG
2652 "DHCP_LEASE=%s\n",
2653 link->lease_file);
deb2e523 2654 } else
68a8723c 2655 unlink(link->lease_file);
fe8db0c5 2656
49699bac
SS
2657 if (link->lldp) {
2658 assert(link->network);
2659
2660 r = sd_lldp_save(link->lldp, link->lldp_file);
2661 if (r < 0)
2662 goto fail;
2663
2664 fprintf(f,
2665 "LLDP_FILE=%s\n",
2666 link->lldp_file);
2667 } else
2668 unlink(link->lldp_file);
2669
c2d6bd61
LP
2670 r = fflush_and_check(f);
2671 if (r < 0)
2672 goto fail;
fe8db0c5 2673
c2d6bd61 2674 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 2675 r = -errno;
c2d6bd61 2676 goto fail;
fe8db0c5
TG
2677 }
2678
c2d6bd61 2679 return 0;
dacd6cee 2680
c2d6bd61 2681fail:
6a7a4e4d 2682 (void) unlink(link->state_file);
6a7a4e4d
LP
2683 if (temp_path)
2684 (void) unlink(temp_path);
2685
dacd6cee 2686 return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
fe8db0c5
TG
2687}
2688
2689static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 2690 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
2691 [LINK_STATE_ENSLAVING] = "configuring",
2692 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
2693 [LINK_STATE_SETTING_ROUTES] = "configuring",
2694 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2695 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2696 [LINK_STATE_FAILED] = "failed",
370e9930 2697 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2698};
2699
2700DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2701
2702static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
2703 [LINK_OPERSTATE_OFF] = "off",
2704 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
2705 [LINK_OPERSTATE_DORMANT] = "dormant",
2706 [LINK_OPERSTATE_CARRIER] = "carrier",
2707 [LINK_OPERSTATE_DEGRADED] = "degraded",
2708 [LINK_OPERSTATE_ROUTABLE] = "routable",
2709};
2710
2711DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);