1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <netinet/ether.h>
24 #include "alloc-util.h"
25 #include "dhcp-lease-internal.h"
26 #include "hostname-util.h"
27 #include "parse-util.h"
28 #include "netdev/vrf.h"
29 #include "network-internal.h"
30 #include "networkd-link.h"
31 #include "networkd-manager.h"
32 #include "networkd-network.h"
33 #include "string-util.h"
34 #include "sysctl-util.h"
36 static int dhcp4_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
,
38 _cleanup_link_unref_ Link
*link
= userdata
;
42 assert(link
->dhcp4_messages
> 0);
44 link
->dhcp4_messages
--;
46 r
= sd_netlink_message_get_errno(m
);
47 if (r
< 0 && r
!= -EEXIST
) {
48 log_link_error_errno(link
, r
, "Could not set DHCPv4 route: %m");
49 link_enter_failed(link
);
52 if (link
->dhcp4_messages
== 0) {
53 link
->dhcp4_configured
= true;
54 link_check_ready(link
);
60 static int route_scope_from_address(const Route
*route
, const struct in_addr
*self_addr
) {
64 if (in_addr_is_localhost(AF_INET
, &route
->dst
) ||
65 (self_addr
->s_addr
&& route
->dst
.in
.s_addr
== self_addr
->s_addr
))
67 else if (in4_addr_is_null(&route
->gw
.in
))
70 return RT_SCOPE_UNIVERSE
;
73 static int link_set_dhcp_routes(Link
*link
) {
74 struct in_addr gateway
, address
;
75 _cleanup_free_ sd_dhcp_route
**static_routes
= NULL
;
81 if (!link
->dhcp_lease
) /* link went down while we configured the IP addresses? */
84 if (!link
->network
) /* link went down while we configured the IP addresses? */
87 if (!link
->network
->dhcp_use_routes
)
90 /* When the interface is part of an VRF use the VRFs routing table, unless
91 * there is a another table specified. */
92 table
= link
->network
->dhcp_route_table
;
93 if (!link
->network
->dhcp_route_table_set
&& link
->network
->vrf
!= NULL
)
94 table
= VRF(link
->network
->vrf
)->table
;
96 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &address
);
98 return log_link_warning_errno(link
, r
, "DHCP error: could not get address: %m");
100 n
= sd_dhcp_lease_get_routes(link
->dhcp_lease
, &static_routes
);
102 log_link_debug_errno(link
, n
, "DHCP error: could not get routes: %m");
104 for (i
= 0; i
< n
; i
++) {
105 _cleanup_route_free_ Route
*route
= NULL
;
107 r
= route_new(&route
);
109 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
111 route
->family
= AF_INET
;
112 route
->protocol
= RTPROT_DHCP
;
113 assert_se(sd_dhcp_route_get_gateway(static_routes
[i
], &route
->gw
.in
) >= 0);
114 assert_se(sd_dhcp_route_get_destination(static_routes
[i
], &route
->dst
.in
) >= 0);
115 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes
[i
], &route
->dst_prefixlen
) >= 0);
116 route
->priority
= link
->network
->dhcp_route_metric
;
117 route
->table
= table
;
118 route
->scope
= route_scope_from_address(route
, &address
);
120 r
= route_configure(route
, link
, dhcp4_route_handler
);
122 return log_link_warning_errno(link
, r
, "Could not set host route: %m");
124 link
->dhcp4_messages
++;
127 r
= sd_dhcp_lease_get_router(link
->dhcp_lease
, &gateway
);
129 log_link_info_errno(link
, r
, "DHCP: No routes received from DHCP server: %m");
131 log_link_warning_errno(link
, r
, "DHCP error: could not get gateway: %m");
133 /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
134 a Router option, the DHCP client MUST ignore the Router option. */
135 if (r
>= 0 && link
->dhcp4_messages
<= 0) {
136 _cleanup_route_free_ Route
*route
= NULL
;
137 _cleanup_route_free_ Route
*route_gw
= NULL
;
139 r
= route_new(&route
);
141 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
143 route
->protocol
= RTPROT_DHCP
;
145 r
= route_new(&route_gw
);
147 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
149 /* The dhcp netmask may mask out the gateway. Add an explicit
150 * route for the gw host so that we can route no matter the
151 * netmask or existing kernel route tables. */
152 route_gw
->family
= AF_INET
;
153 route_gw
->dst
.in
= gateway
;
154 route_gw
->dst_prefixlen
= 32;
155 route_gw
->prefsrc
.in
= address
;
156 route_gw
->scope
= RT_SCOPE_LINK
;
157 route_gw
->protocol
= RTPROT_DHCP
;
158 route_gw
->priority
= link
->network
->dhcp_route_metric
;
159 route_gw
->table
= table
;
161 r
= route_configure(route_gw
, link
, dhcp4_route_handler
);
163 return log_link_warning_errno(link
, r
, "Could not set host route: %m");
165 link
->dhcp4_messages
++;
167 route
->family
= AF_INET
;
168 route
->gw
.in
= gateway
;
169 route
->prefsrc
.in
= address
;
170 route
->priority
= link
->network
->dhcp_route_metric
;
171 route
->table
= table
;
173 r
= route_configure(route
, link
, dhcp4_route_handler
);
175 log_link_warning_errno(link
, r
, "Could not set routes: %m");
176 link_enter_failed(link
);
180 link
->dhcp4_messages
++;
186 static int dhcp_lease_lost(Link
*link
) {
187 _cleanup_address_free_ Address
*address
= NULL
;
189 struct in_addr netmask
;
190 struct in_addr gateway
;
191 unsigned prefixlen
= 0;
195 assert(link
->dhcp_lease
);
197 log_link_warning(link
, "DHCP lease lost");
199 if (link
->network
->dhcp_use_routes
) {
200 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
203 n
= sd_dhcp_lease_get_routes(link
->dhcp_lease
, &routes
);
205 for (i
= 0; i
< n
; i
++) {
206 _cleanup_route_free_ Route
*route
= NULL
;
208 r
= route_new(&route
);
210 route
->family
= AF_INET
;
211 assert_se(sd_dhcp_route_get_gateway(routes
[i
], &route
->gw
.in
) >= 0);
212 assert_se(sd_dhcp_route_get_destination(routes
[i
], &route
->dst
.in
) >= 0);
213 assert_se(sd_dhcp_route_get_destination_prefix_length(routes
[i
], &route
->dst_prefixlen
) >= 0);
215 route_remove(route
, link
,
216 link_route_remove_handler
);
222 r
= address_new(&address
);
224 r
= sd_dhcp_lease_get_router(link
->dhcp_lease
, &gateway
);
226 _cleanup_route_free_ Route
*route_gw
= NULL
;
227 _cleanup_route_free_ Route
*route
= NULL
;
229 r
= route_new(&route_gw
);
231 route_gw
->family
= AF_INET
;
232 route_gw
->dst
.in
= gateway
;
233 route_gw
->dst_prefixlen
= 32;
234 route_gw
->scope
= RT_SCOPE_LINK
;
236 route_remove(route_gw
, link
,
237 link_route_remove_handler
);
240 r
= route_new(&route
);
242 route
->family
= AF_INET
;
243 route
->gw
.in
= gateway
;
245 route_remove(route
, link
,
246 link_route_remove_handler
);
250 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &addr
);
252 r
= sd_dhcp_lease_get_netmask(link
->dhcp_lease
, &netmask
);
254 prefixlen
= in4_addr_netmask_to_prefixlen(&netmask
);
256 address
->family
= AF_INET
;
257 address
->in_addr
.in
= addr
;
258 address
->prefixlen
= prefixlen
;
260 address_remove(address
, link
, link_address_remove_handler
);
264 if (link
->network
->dhcp_use_mtu
) {
267 r
= sd_dhcp_lease_get_mtu(link
->dhcp_lease
, &mtu
);
268 if (r
>= 0 && link
->original_mtu
!= mtu
) {
269 r
= link_set_mtu(link
, link
->original_mtu
);
271 log_link_warning(link
,
272 "DHCP error: could not reset MTU");
273 link_enter_failed(link
);
279 if (link
->network
->dhcp_use_hostname
) {
280 const char *hostname
= NULL
;
282 if (link
->network
->dhcp_hostname
)
283 hostname
= link
->network
->dhcp_hostname
;
285 (void) sd_dhcp_lease_get_hostname(link
->dhcp_lease
, &hostname
);
288 /* If a hostname was set due to the lease, then unset it now. */
289 r
= manager_set_hostname(link
->manager
, NULL
);
291 log_link_warning_errno(link
, r
, "Failed to reset transient hostname: %m");
295 link
->dhcp_lease
= sd_dhcp_lease_unref(link
->dhcp_lease
);
297 link
->dhcp4_configured
= false;
302 static int dhcp4_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
,
304 _cleanup_link_unref_ Link
*link
= userdata
;
309 r
= sd_netlink_message_get_errno(m
);
310 if (r
< 0 && r
!= -EEXIST
) {
311 log_link_error_errno(link
, r
, "Could not set DHCPv4 address: %m");
312 link_enter_failed(link
);
314 manager_rtnl_process_address(rtnl
, m
, link
->manager
);
316 link_set_dhcp_routes(link
);
321 static int dhcp4_update_address(Link
*link
,
322 struct in_addr
*address
,
323 struct in_addr
*netmask
,
325 _cleanup_address_free_ Address
*addr
= NULL
;
333 prefixlen
= in4_addr_netmask_to_prefixlen(netmask
);
335 r
= address_new(&addr
);
339 addr
->family
= AF_INET
;
340 addr
->in_addr
.in
.s_addr
= address
->s_addr
;
341 addr
->cinfo
.ifa_prefered
= lifetime
;
342 addr
->cinfo
.ifa_valid
= lifetime
;
343 addr
->prefixlen
= prefixlen
;
344 addr
->broadcast
.s_addr
= address
->s_addr
| ~netmask
->s_addr
;
346 /* allow reusing an existing address and simply update its lifetime
347 * in case it already exists */
348 r
= address_configure(addr
, link
, dhcp4_address_handler
, true);
355 static int dhcp_lease_renew(sd_dhcp_client
*client
, Link
*link
) {
356 sd_dhcp_lease
*lease
;
357 struct in_addr address
;
358 struct in_addr netmask
;
359 uint32_t lifetime
= CACHE_INFO_INFINITY_LIFE_TIME
;
364 assert(link
->network
);
366 r
= sd_dhcp_client_get_lease(client
, &lease
);
368 return log_link_warning_errno(link
, r
, "DHCP error: no lease: %m");
370 sd_dhcp_lease_unref(link
->dhcp_lease
);
371 link
->dhcp4_configured
= false;
372 link
->dhcp_lease
= sd_dhcp_lease_ref(lease
);
375 r
= sd_dhcp_lease_get_address(lease
, &address
);
377 return log_link_warning_errno(link
, r
, "DHCP error: no address: %m");
379 r
= sd_dhcp_lease_get_netmask(lease
, &netmask
);
381 return log_link_warning_errno(link
, r
, "DHCP error: no netmask: %m");
383 if (!link
->network
->dhcp_critical
) {
384 r
= sd_dhcp_lease_get_lifetime(link
->dhcp_lease
, &lifetime
);
386 return log_link_warning_errno(link
, r
, "DHCP error: no lifetime: %m");
389 r
= dhcp4_update_address(link
, &address
, &netmask
, lifetime
);
391 log_link_warning_errno(link
, r
, "Could not update IP address: %m");
392 link_enter_failed(link
);
399 static int dhcp_lease_acquired(sd_dhcp_client
*client
, Link
*link
) {
400 sd_dhcp_lease
*lease
;
401 struct in_addr address
;
402 struct in_addr netmask
;
403 struct in_addr gateway
;
405 uint32_t lifetime
= CACHE_INFO_INFINITY_LIFE_TIME
;
411 r
= sd_dhcp_client_get_lease(client
, &lease
);
413 return log_link_error_errno(link
, r
, "DHCP error: No lease: %m");
415 r
= sd_dhcp_lease_get_address(lease
, &address
);
417 return log_link_error_errno(link
, r
, "DHCP error: No address: %m");
419 r
= sd_dhcp_lease_get_netmask(lease
, &netmask
);
421 return log_link_error_errno(link
, r
, "DHCP error: No netmask: %m");
423 prefixlen
= in4_addr_netmask_to_prefixlen(&netmask
);
425 r
= sd_dhcp_lease_get_router(lease
, &gateway
);
426 if (r
< 0 && r
!= -ENODATA
)
427 return log_link_error_errno(link
, r
, "DHCP error: Could not get gateway: %m");
431 LOG_LINK_INTERFACE(link
),
432 LOG_LINK_MESSAGE(link
, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
433 ADDRESS_FMT_VAL(address
),
435 ADDRESS_FMT_VAL(gateway
)),
436 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address
),
437 "PREFIXLEN=%u", prefixlen
,
438 "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway
),
442 LOG_LINK_INTERFACE(link
),
443 LOG_LINK_MESSAGE(link
, "DHCPv4 address %u.%u.%u.%u/%u",
444 ADDRESS_FMT_VAL(address
),
446 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address
),
447 "PREFIXLEN=%u", prefixlen
,
450 link
->dhcp_lease
= sd_dhcp_lease_ref(lease
);
453 if (link
->network
->dhcp_use_mtu
) {
456 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
458 r
= link_set_mtu(link
, mtu
);
460 log_link_error_errno(link
, r
, "Failed to set MTU to %" PRIu16
": %m", mtu
);
464 if (link
->network
->dhcp_use_hostname
) {
465 const char *dhcpname
= NULL
;
466 _cleanup_free_
char *hostname
= NULL
;
468 if (link
->network
->dhcp_hostname
)
469 dhcpname
= link
->network
->dhcp_hostname
;
471 (void) sd_dhcp_lease_get_hostname(lease
, &dhcpname
);
474 r
= shorten_overlong(dhcpname
, &hostname
);
476 log_link_warning_errno(link
, r
, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname
);
478 log_link_notice(link
, "Overlong DCHP hostname received, shortened from '%s' to '%s'", dhcpname
, hostname
);
482 r
= manager_set_hostname(link
->manager
, hostname
);
484 log_link_error_errno(link
, r
, "Failed to set transient hostname to '%s': %m", hostname
);
488 if (link
->network
->dhcp_use_timezone
) {
489 const char *tz
= NULL
;
491 (void) sd_dhcp_lease_get_timezone(link
->dhcp_lease
, &tz
);
494 r
= manager_set_timezone(link
->manager
, tz
);
496 log_link_error_errno(link
, r
, "Failed to set timezone to '%s': %m", tz
);
500 if (!link
->network
->dhcp_critical
) {
501 r
= sd_dhcp_lease_get_lifetime(link
->dhcp_lease
, &lifetime
);
503 log_link_warning_errno(link
, r
, "DHCP error: no lifetime: %m");
508 r
= dhcp4_update_address(link
, &address
, &netmask
, lifetime
);
510 log_link_warning_errno(link
, r
, "Could not update IP address: %m");
511 link_enter_failed(link
);
517 static void dhcp4_handler(sd_dhcp_client
*client
, int event
, void *userdata
) {
518 Link
*link
= userdata
;
522 assert(link
->network
);
523 assert(link
->manager
);
525 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
529 case SD_DHCP_CLIENT_EVENT_EXPIRED
:
530 case SD_DHCP_CLIENT_EVENT_STOP
:
531 case SD_DHCP_CLIENT_EVENT_IP_CHANGE
:
532 if (link
->network
->dhcp_critical
) {
533 log_link_error(link
, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
537 if (link
->dhcp_lease
) {
538 r
= dhcp_lease_lost(link
);
540 link_enter_failed(link
);
545 if (event
== SD_DHCP_CLIENT_EVENT_IP_CHANGE
) {
546 r
= dhcp_lease_acquired(client
, link
);
548 link_enter_failed(link
);
554 case SD_DHCP_CLIENT_EVENT_RENEW
:
555 r
= dhcp_lease_renew(client
, link
);
557 link_enter_failed(link
);
561 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
:
562 r
= dhcp_lease_acquired(client
, link
);
564 link_enter_failed(link
);
570 log_link_warning_errno(link
, event
, "DHCP error: Client failed: %m");
572 log_link_warning(link
, "DHCP unknown event: %i", event
);
579 static int dhcp4_set_hostname(Link
*link
) {
580 _cleanup_free_
char *hostname
= NULL
;
586 if (!link
->network
->dhcp_send_hostname
)
588 else if (link
->network
->dhcp_hostname
)
589 hn
= link
->network
->dhcp_hostname
;
591 r
= gethostname_strict(&hostname
);
592 if (r
< 0 && r
!= -ENXIO
) /* ENXIO: no hostname set or hostname is "localhost" */
598 return sd_dhcp_client_set_hostname(link
->dhcp_client
, hn
);
601 static bool promote_secondaries_enabled(const char *ifname
) {
602 _cleanup_free_
char *promote_secondaries_sysctl
= NULL
;
603 char *promote_secondaries_path
;
606 promote_secondaries_path
= strjoina("net/ipv4/conf/", ifname
, "/promote_secondaries");
607 r
= sysctl_read(promote_secondaries_path
, &promote_secondaries_sysctl
);
609 log_debug_errno(r
, "Cannot read sysctl %s", promote_secondaries_path
);
613 truncate_nl(promote_secondaries_sysctl
);
614 r
= parse_boolean(promote_secondaries_sysctl
);
616 log_warning_errno(r
, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path
, promote_secondaries_sysctl
);
620 /* dhcp4_set_promote_secondaries will ensure this interface has
621 * the "promote_secondaries" option in the kernel set. If this sysctl
622 * is not set DHCP will work only as long as the IP address does not
623 * changes between leases. The kernel will remove all secondary IP
624 * addresses of an interface otherwise. The way systemd-network works
625 * is that the new IP of a lease is added as a secondary IP and when
626 * the primary one expires it relies on the kernel to promote the
627 * secondary IP. See also https://github.com/systemd/systemd/issues/7163
629 int dhcp4_set_promote_secondaries(Link
*link
) {
633 assert(link
->network
);
634 assert(link
->network
->dhcp
& ADDRESS_FAMILY_IPV4
);
636 /* check if the kernel has promote_secondaries enabled for our
637 * interface. If it is not globally enabled or enabled for the
638 * specific interface we must either enable it.
640 if (!(promote_secondaries_enabled("all") || promote_secondaries_enabled(link
->ifname
))) {
641 char *promote_secondaries_path
= NULL
;
643 log_link_debug(link
, "promote_secondaries is unset, setting it");
644 promote_secondaries_path
= strjoina("net/ipv4/conf/", link
->ifname
, "/promote_secondaries");
645 r
= sysctl_write(promote_secondaries_path
, "1");
647 log_link_warning_errno(link
, r
, "cannot set sysctl %s to 1", promote_secondaries_path
);
654 int dhcp4_configure(Link
*link
) {
658 assert(link
->network
);
659 assert(link
->network
->dhcp
& ADDRESS_FAMILY_IPV4
);
661 if (!link
->dhcp_client
) {
662 r
= sd_dhcp_client_new(&link
->dhcp_client
, link
->network
->dhcp_anonymize
);
667 r
= sd_dhcp_client_attach_event(link
->dhcp_client
, NULL
, 0);
671 r
= sd_dhcp_client_set_mac(link
->dhcp_client
,
672 (const uint8_t *) &link
->mac
,
673 sizeof (link
->mac
), ARPHRD_ETHER
);
677 r
= sd_dhcp_client_set_ifindex(link
->dhcp_client
, link
->ifindex
);
681 r
= sd_dhcp_client_set_callback(link
->dhcp_client
, dhcp4_handler
, link
);
685 r
= sd_dhcp_client_set_request_broadcast(link
->dhcp_client
,
686 link
->network
->dhcp_broadcast
);
691 r
= sd_dhcp_client_set_mtu(link
->dhcp_client
, link
->mtu
);
696 if (link
->network
->dhcp_use_mtu
) {
697 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
698 SD_DHCP_OPTION_INTERFACE_MTU
);
703 /* NOTE: even if this variable is called "use", it also "sends" PRL
704 * options, maybe there should be a different configuration variable
705 * to send or not route options?. */
706 /* NOTE: when using Anonymize=yes, routes PRL options are sent
707 * by default, so they don't need to be added here. */
708 if (link
->network
->dhcp_use_routes
&& !link
->network
->dhcp_anonymize
) {
709 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
710 SD_DHCP_OPTION_STATIC_ROUTE
);
713 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
714 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
);
719 if (link
->network
->dhcp_use_ntp
) {
720 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
, SD_DHCP_OPTION_NTP_SERVER
);
725 if (link
->network
->dhcp_use_timezone
) {
726 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
);
731 r
= dhcp4_set_hostname(link
);
735 if (link
->network
->dhcp_vendor_class_identifier
) {
736 r
= sd_dhcp_client_set_vendor_class_identifier(link
->dhcp_client
,
737 link
->network
->dhcp_vendor_class_identifier
);
742 if (link
->network
->dhcp_client_port
) {
743 r
= sd_dhcp_client_set_client_port(link
->dhcp_client
, link
->network
->dhcp_client_port
);
748 switch (link
->network
->dhcp_client_identifier
) {
749 case DHCP_CLIENT_ID_DUID
: {
750 /* If configured, apply user specified DUID and/or IAID */
751 const DUID
*duid
= link_duid(link
);
753 r
= sd_dhcp_client_set_iaid_duid(link
->dhcp_client
,
756 duid
->raw_data_len
> 0 ? duid
->raw_data
: NULL
,
762 case DHCP_CLIENT_ID_MAC
:
763 r
= sd_dhcp_client_set_client_id(link
->dhcp_client
,
765 (const uint8_t *) &link
->mac
,
771 assert_not_reached("Unknown client identifier type.");