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 "netdev/vrf.h"
28 #include "network-internal.h"
29 #include "networkd-link.h"
30 #include "networkd-manager.h"
31 #include "networkd-network.h"
33 static int dhcp4_route_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
,
35 _cleanup_link_unref_ Link
*link
= userdata
;
39 assert(link
->dhcp4_messages
> 0);
41 link
->dhcp4_messages
--;
43 r
= sd_netlink_message_get_errno(m
);
44 if (r
< 0 && r
!= -EEXIST
) {
45 log_link_error_errno(link
, r
, "Could not set DHCPv4 route: %m");
46 link_enter_failed(link
);
49 if (link
->dhcp4_messages
== 0) {
50 link
->dhcp4_configured
= true;
51 link_check_ready(link
);
57 static int route_scope_from_address(const Route
*route
, const struct in_addr
*self_addr
) {
61 if (in_addr_is_localhost(AF_INET
, &route
->dst
) ||
62 (self_addr
->s_addr
&& route
->dst
.in
.s_addr
== self_addr
->s_addr
))
64 else if (in4_addr_is_null(&route
->gw
.in
))
67 return RT_SCOPE_UNIVERSE
;
70 static int link_set_dhcp_routes(Link
*link
) {
71 struct in_addr gateway
, address
;
72 _cleanup_free_ sd_dhcp_route
**static_routes
= NULL
;
78 if (!link
->dhcp_lease
) /* link went down while we configured the IP addresses? */
81 if (!link
->network
) /* link went down while we configured the IP addresses? */
84 if (!link
->network
->dhcp_use_routes
)
87 /* When the interface is part of an VRF use the VRFs routing table, unless
88 * there is a another table specified. */
89 table
= link
->network
->dhcp_route_table
;
90 if (!link
->network
->dhcp_route_table_set
&& link
->network
->vrf
!= NULL
)
91 table
= VRF(link
->network
->vrf
)->table
;
93 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &address
);
95 return log_link_warning_errno(link
, r
, "DHCP error: could not get address: %m");
97 r
= sd_dhcp_lease_get_router(link
->dhcp_lease
, &gateway
);
99 log_link_info_errno(link
, r
, "DHCP: No routes received from DHCP server: %m");
101 log_link_warning_errno(link
, r
, "DHCP error: could not get gateway: %m");
104 _cleanup_route_free_ Route
*route
= NULL
;
105 _cleanup_route_free_ Route
*route_gw
= NULL
;
107 r
= route_new(&route
);
109 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
111 route
->protocol
= RTPROT_DHCP
;
113 r
= route_new(&route_gw
);
115 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
117 /* The dhcp netmask may mask out the gateway. Add an explicit
118 * route for the gw host so that we can route no matter the
119 * netmask or existing kernel route tables. */
120 route_gw
->family
= AF_INET
;
121 route_gw
->dst
.in
= gateway
;
122 route_gw
->dst_prefixlen
= 32;
123 route_gw
->prefsrc
.in
= address
;
124 route_gw
->scope
= RT_SCOPE_LINK
;
125 route_gw
->protocol
= RTPROT_DHCP
;
126 route_gw
->priority
= link
->network
->dhcp_route_metric
;
127 route_gw
->table
= table
;
129 r
= route_configure(route_gw
, link
, dhcp4_route_handler
);
131 return log_link_warning_errno(link
, r
, "Could not set host route: %m");
133 link
->dhcp4_messages
++;
135 route
->family
= AF_INET
;
136 route
->gw
.in
= gateway
;
137 route
->prefsrc
.in
= address
;
138 route
->priority
= link
->network
->dhcp_route_metric
;
139 route
->table
= table
;
141 r
= route_configure(route
, link
, dhcp4_route_handler
);
143 log_link_warning_errno(link
, r
, "Could not set routes: %m");
144 link_enter_failed(link
);
148 link
->dhcp4_messages
++;
151 n
= sd_dhcp_lease_get_routes(link
->dhcp_lease
, &static_routes
);
153 log_link_info_errno(link
, n
, "DHCP: No routes received from DHCP server: %m");
155 log_link_warning_errno(link
, n
, "DHCP error: could not get routes: %m");
157 for (i
= 0; i
< n
; i
++) {
158 _cleanup_route_free_ Route
*route
= NULL
;
160 r
= route_new(&route
);
162 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
164 route
->family
= AF_INET
;
165 route
->protocol
= RTPROT_DHCP
;
166 assert_se(sd_dhcp_route_get_gateway(static_routes
[i
], &route
->gw
.in
) >= 0);
167 assert_se(sd_dhcp_route_get_destination(static_routes
[i
], &route
->dst
.in
) >= 0);
168 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes
[i
], &route
->dst_prefixlen
) >= 0);
169 route
->priority
= link
->network
->dhcp_route_metric
;
170 route
->table
= table
;
171 route
->scope
= route_scope_from_address(route
, &address
);
173 r
= route_configure(route
, link
, dhcp4_route_handler
);
175 return log_link_warning_errno(link
, r
, "Could not set host route: %m");
177 link
->dhcp4_messages
++;
180 if (link
->dhcp4_messages
== 0) {
181 link
->dhcp4_configured
= true;
182 link_check_ready(link
);
188 static int dhcp_lease_lost(Link
*link
) {
189 _cleanup_address_free_ Address
*address
= NULL
;
191 struct in_addr netmask
;
192 struct in_addr gateway
;
193 unsigned prefixlen
= 0;
197 assert(link
->dhcp_lease
);
199 log_link_warning(link
, "DHCP lease lost");
201 if (link
->network
->dhcp_use_routes
) {
202 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
205 n
= sd_dhcp_lease_get_routes(link
->dhcp_lease
, &routes
);
207 for (i
= 0; i
< n
; i
++) {
208 _cleanup_route_free_ Route
*route
= NULL
;
210 r
= route_new(&route
);
212 route
->family
= AF_INET
;
213 assert_se(sd_dhcp_route_get_gateway(routes
[i
], &route
->gw
.in
) >= 0);
214 assert_se(sd_dhcp_route_get_destination(routes
[i
], &route
->dst
.in
) >= 0);
215 assert_se(sd_dhcp_route_get_destination_prefix_length(routes
[i
], &route
->dst_prefixlen
) >= 0);
217 route_remove(route
, link
,
218 link_route_remove_handler
);
224 r
= address_new(&address
);
226 r
= sd_dhcp_lease_get_router(link
->dhcp_lease
, &gateway
);
228 _cleanup_route_free_ Route
*route_gw
= NULL
;
229 _cleanup_route_free_ Route
*route
= NULL
;
231 r
= route_new(&route_gw
);
233 route_gw
->family
= AF_INET
;
234 route_gw
->dst
.in
= gateway
;
235 route_gw
->dst_prefixlen
= 32;
236 route_gw
->scope
= RT_SCOPE_LINK
;
238 route_remove(route_gw
, link
,
239 link_route_remove_handler
);
242 r
= route_new(&route
);
244 route
->family
= AF_INET
;
245 route
->gw
.in
= gateway
;
247 route_remove(route
, link
,
248 link_route_remove_handler
);
252 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &addr
);
254 r
= sd_dhcp_lease_get_netmask(link
->dhcp_lease
, &netmask
);
256 prefixlen
= in4_addr_netmask_to_prefixlen(&netmask
);
258 address
->family
= AF_INET
;
259 address
->in_addr
.in
= addr
;
260 address
->prefixlen
= prefixlen
;
262 address_remove(address
, link
, link_address_remove_handler
);
266 if (link
->network
->dhcp_use_mtu
) {
269 r
= sd_dhcp_lease_get_mtu(link
->dhcp_lease
, &mtu
);
270 if (r
>= 0 && link
->original_mtu
!= mtu
) {
271 r
= link_set_mtu(link
, link
->original_mtu
);
273 log_link_warning(link
,
274 "DHCP error: could not reset MTU");
275 link_enter_failed(link
);
281 if (link
->network
->dhcp_use_hostname
) {
282 const char *hostname
= NULL
;
284 if (link
->network
->dhcp_hostname
)
285 hostname
= link
->network
->dhcp_hostname
;
287 (void) sd_dhcp_lease_get_hostname(link
->dhcp_lease
, &hostname
);
290 /* If a hostname was set due to the lease, then unset it now. */
291 r
= manager_set_hostname(link
->manager
, NULL
);
293 log_link_warning_errno(link
, r
, "Failed to reset transient hostname: %m");
297 link
->dhcp_lease
= sd_dhcp_lease_unref(link
->dhcp_lease
);
299 link
->dhcp4_configured
= false;
304 static int dhcp4_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
,
306 _cleanup_link_unref_ Link
*link
= userdata
;
311 r
= sd_netlink_message_get_errno(m
);
312 if (r
< 0 && r
!= -EEXIST
) {
313 log_link_error_errno(link
, r
, "Could not set DHCPv4 address: %m");
314 link_enter_failed(link
);
316 manager_rtnl_process_address(rtnl
, m
, link
->manager
);
318 link_set_dhcp_routes(link
);
323 static int dhcp4_update_address(Link
*link
,
324 struct in_addr
*address
,
325 struct in_addr
*netmask
,
327 _cleanup_address_free_ Address
*addr
= NULL
;
335 prefixlen
= in4_addr_netmask_to_prefixlen(netmask
);
337 r
= address_new(&addr
);
341 addr
->family
= AF_INET
;
342 addr
->in_addr
.in
.s_addr
= address
->s_addr
;
343 addr
->cinfo
.ifa_prefered
= lifetime
;
344 addr
->cinfo
.ifa_valid
= lifetime
;
345 addr
->prefixlen
= prefixlen
;
346 addr
->broadcast
.s_addr
= address
->s_addr
| ~netmask
->s_addr
;
348 /* allow reusing an existing address and simply update its lifetime
349 * in case it already exists */
350 r
= address_configure(addr
, link
, dhcp4_address_handler
, true);
357 static int dhcp_lease_renew(sd_dhcp_client
*client
, Link
*link
) {
358 sd_dhcp_lease
*lease
;
359 struct in_addr address
;
360 struct in_addr netmask
;
361 uint32_t lifetime
= CACHE_INFO_INFINITY_LIFE_TIME
;
366 assert(link
->network
);
368 r
= sd_dhcp_client_get_lease(client
, &lease
);
370 return log_link_warning_errno(link
, r
, "DHCP error: no lease: %m");
372 sd_dhcp_lease_unref(link
->dhcp_lease
);
373 link
->dhcp4_configured
= false;
374 link
->dhcp_lease
= sd_dhcp_lease_ref(lease
);
377 r
= sd_dhcp_lease_get_address(lease
, &address
);
379 return log_link_warning_errno(link
, r
, "DHCP error: no address: %m");
381 r
= sd_dhcp_lease_get_netmask(lease
, &netmask
);
383 return log_link_warning_errno(link
, r
, "DHCP error: no netmask: %m");
385 if (!link
->network
->dhcp_critical
) {
386 r
= sd_dhcp_lease_get_lifetime(link
->dhcp_lease
, &lifetime
);
388 return log_link_warning_errno(link
, r
, "DHCP error: no lifetime: %m");
391 r
= dhcp4_update_address(link
, &address
, &netmask
, lifetime
);
393 log_link_warning_errno(link
, r
, "Could not update IP address: %m");
394 link_enter_failed(link
);
401 static int dhcp_lease_acquired(sd_dhcp_client
*client
, Link
*link
) {
402 sd_dhcp_lease
*lease
;
403 struct in_addr address
;
404 struct in_addr netmask
;
405 struct in_addr gateway
;
407 uint32_t lifetime
= CACHE_INFO_INFINITY_LIFE_TIME
;
413 r
= sd_dhcp_client_get_lease(client
, &lease
);
415 return log_link_error_errno(link
, r
, "DHCP error: No lease: %m");
417 r
= sd_dhcp_lease_get_address(lease
, &address
);
419 return log_link_error_errno(link
, r
, "DHCP error: No address: %m");
421 r
= sd_dhcp_lease_get_netmask(lease
, &netmask
);
423 return log_link_error_errno(link
, r
, "DHCP error: No netmask: %m");
425 prefixlen
= in4_addr_netmask_to_prefixlen(&netmask
);
427 r
= sd_dhcp_lease_get_router(lease
, &gateway
);
428 if (r
< 0 && r
!= -ENODATA
)
429 return log_link_error_errno(link
, r
, "DHCP error: Could not get gateway: %m");
433 LOG_LINK_INTERFACE(link
),
434 LOG_LINK_MESSAGE(link
, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
435 ADDRESS_FMT_VAL(address
),
437 ADDRESS_FMT_VAL(gateway
)),
438 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address
),
439 "PREFIXLEN=%u", prefixlen
,
440 "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway
),
444 LOG_LINK_INTERFACE(link
),
445 LOG_LINK_MESSAGE(link
, "DHCPv4 address %u.%u.%u.%u/%u",
446 ADDRESS_FMT_VAL(address
),
448 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address
),
449 "PREFIXLEN=%u", prefixlen
,
452 link
->dhcp_lease
= sd_dhcp_lease_ref(lease
);
455 if (link
->network
->dhcp_use_mtu
) {
458 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
460 r
= link_set_mtu(link
, mtu
);
462 log_link_error_errno(link
, r
, "Failed to set MTU to %" PRIu16
": %m", mtu
);
466 if (link
->network
->dhcp_use_hostname
) {
467 const char *hostname
= NULL
;
469 if (link
->network
->dhcp_hostname
)
470 hostname
= link
->network
->dhcp_hostname
;
472 (void) sd_dhcp_lease_get_hostname(lease
, &hostname
);
475 r
= manager_set_hostname(link
->manager
, hostname
);
477 log_link_error_errno(link
, r
, "Failed to set transient hostname to '%s': %m", hostname
);
481 if (link
->network
->dhcp_use_timezone
) {
482 const char *tz
= NULL
;
484 (void) sd_dhcp_lease_get_timezone(link
->dhcp_lease
, &tz
);
487 r
= manager_set_timezone(link
->manager
, tz
);
489 log_link_error_errno(link
, r
, "Failed to set timezone to '%s': %m", tz
);
493 if (!link
->network
->dhcp_critical
) {
494 r
= sd_dhcp_lease_get_lifetime(link
->dhcp_lease
, &lifetime
);
496 log_link_warning_errno(link
, r
, "DHCP error: no lifetime: %m");
501 r
= dhcp4_update_address(link
, &address
, &netmask
, lifetime
);
503 log_link_warning_errno(link
, r
, "Could not update IP address: %m");
504 link_enter_failed(link
);
510 static void dhcp4_handler(sd_dhcp_client
*client
, int event
, void *userdata
) {
511 Link
*link
= userdata
;
515 assert(link
->network
);
516 assert(link
->manager
);
518 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
522 case SD_DHCP_CLIENT_EVENT_EXPIRED
:
523 case SD_DHCP_CLIENT_EVENT_STOP
:
524 case SD_DHCP_CLIENT_EVENT_IP_CHANGE
:
525 if (link
->network
->dhcp_critical
) {
526 log_link_error(link
, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
530 if (link
->dhcp_lease
) {
531 r
= dhcp_lease_lost(link
);
533 link_enter_failed(link
);
538 if (event
== SD_DHCP_CLIENT_EVENT_IP_CHANGE
) {
539 r
= dhcp_lease_acquired(client
, link
);
541 link_enter_failed(link
);
547 case SD_DHCP_CLIENT_EVENT_RENEW
:
548 r
= dhcp_lease_renew(client
, link
);
550 link_enter_failed(link
);
554 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
:
555 r
= dhcp_lease_acquired(client
, link
);
557 link_enter_failed(link
);
563 log_link_warning_errno(link
, event
, "DHCP error: Client failed: %m");
565 log_link_warning(link
, "DHCP unknown event: %i", event
);
572 static int dhcp4_set_hostname(Link
*link
) {
573 _cleanup_free_
char *hostname
= NULL
;
579 if (!link
->network
->dhcp_send_hostname
)
581 else if (link
->network
->dhcp_hostname
)
582 hn
= link
->network
->dhcp_hostname
;
584 r
= gethostname_strict(&hostname
);
585 if (r
< 0 && r
!= -ENXIO
) /* ENXIO: no hostname set or hostname is "localhost" */
591 return sd_dhcp_client_set_hostname(link
->dhcp_client
, hn
);
594 int dhcp4_configure(Link
*link
) {
598 assert(link
->network
);
599 assert(link
->network
->dhcp
& ADDRESS_FAMILY_IPV4
);
601 if (!link
->dhcp_client
) {
602 r
= sd_dhcp_client_new(&link
->dhcp_client
, link
->network
->dhcp_anonymize
);
607 r
= sd_dhcp_client_attach_event(link
->dhcp_client
, NULL
, 0);
611 r
= sd_dhcp_client_set_mac(link
->dhcp_client
,
612 (const uint8_t *) &link
->mac
,
613 sizeof (link
->mac
), ARPHRD_ETHER
);
617 r
= sd_dhcp_client_set_ifindex(link
->dhcp_client
, link
->ifindex
);
621 r
= sd_dhcp_client_set_callback(link
->dhcp_client
, dhcp4_handler
, link
);
625 r
= sd_dhcp_client_set_request_broadcast(link
->dhcp_client
,
626 link
->network
->dhcp_broadcast
);
631 r
= sd_dhcp_client_set_mtu(link
->dhcp_client
, link
->mtu
);
636 if (link
->network
->dhcp_use_mtu
) {
637 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
638 SD_DHCP_OPTION_INTERFACE_MTU
);
643 /* NOTE: even if this variable is called "use", it also "sends" PRL
644 * options, maybe there should be a different configuration variable
645 * to send or not route options?. */
646 /* NOTE: when using Anonymize=yes, routes PRL options are sent
647 * by default, so they don't need to be added here. */
648 if (link
->network
->dhcp_use_routes
&& !link
->network
->dhcp_anonymize
) {
649 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
650 SD_DHCP_OPTION_STATIC_ROUTE
);
653 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
654 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
);
659 if (link
->network
->dhcp_use_ntp
) {
660 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
, SD_DHCP_OPTION_NTP_SERVER
);
665 if (link
->network
->dhcp_use_timezone
) {
666 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
);
671 r
= dhcp4_set_hostname(link
);
675 if (link
->network
->dhcp_vendor_class_identifier
) {
676 r
= sd_dhcp_client_set_vendor_class_identifier(link
->dhcp_client
,
677 link
->network
->dhcp_vendor_class_identifier
);
682 if (link
->network
->dhcp_client_port
) {
683 r
= sd_dhcp_client_set_client_port(link
->dhcp_client
, link
->network
->dhcp_client_port
);
688 switch (link
->network
->dhcp_client_identifier
) {
689 case DHCP_CLIENT_ID_DUID
: {
690 /* If configured, apply user specified DUID and/or IAID */
691 const DUID
*duid
= link_duid(link
);
693 r
= sd_dhcp_client_set_iaid_duid(link
->dhcp_client
,
696 duid
->raw_data_len
> 0 ? duid
->raw_data
: NULL
,
702 case DHCP_CLIENT_ID_MAC
:
703 r
= sd_dhcp_client_set_client_id(link
->dhcp_client
,
705 (const uint8_t *) &link
->mac
,
711 assert_not_reached("Unknown client identifier type.");