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 n
= sd_dhcp_lease_get_routes(link
->dhcp_lease
, &static_routes
);
99 log_link_debug_errno(link
, n
, "DHCP error: could not get routes: %m");
101 for (i
= 0; i
< n
; i
++) {
102 _cleanup_route_free_ Route
*route
= NULL
;
104 r
= route_new(&route
);
106 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
108 route
->family
= AF_INET
;
109 route
->protocol
= RTPROT_DHCP
;
110 assert_se(sd_dhcp_route_get_gateway(static_routes
[i
], &route
->gw
.in
) >= 0);
111 assert_se(sd_dhcp_route_get_destination(static_routes
[i
], &route
->dst
.in
) >= 0);
112 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes
[i
], &route
->dst_prefixlen
) >= 0);
113 route
->priority
= link
->network
->dhcp_route_metric
;
114 route
->table
= table
;
115 route
->scope
= route_scope_from_address(route
, &address
);
117 r
= route_configure(route
, link
, dhcp4_route_handler
);
119 return log_link_warning_errno(link
, r
, "Could not set host route: %m");
121 link
->dhcp4_messages
++;
124 r
= sd_dhcp_lease_get_router(link
->dhcp_lease
, &gateway
);
126 log_link_info_errno(link
, r
, "DHCP: No routes received from DHCP server: %m");
128 log_link_warning_errno(link
, r
, "DHCP error: could not get gateway: %m");
130 /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
131 a Router option, the DHCP client MUST ignore the Router option. */
132 if (r
>= 0 && link
->dhcp4_messages
<= 0) {
133 _cleanup_route_free_ Route
*route
= NULL
;
134 _cleanup_route_free_ Route
*route_gw
= NULL
;
136 r
= route_new(&route
);
138 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
140 route
->protocol
= RTPROT_DHCP
;
142 r
= route_new(&route_gw
);
144 return log_link_error_errno(link
, r
, "Could not allocate route: %m");
146 /* The dhcp netmask may mask out the gateway. Add an explicit
147 * route for the gw host so that we can route no matter the
148 * netmask or existing kernel route tables. */
149 route_gw
->family
= AF_INET
;
150 route_gw
->dst
.in
= gateway
;
151 route_gw
->dst_prefixlen
= 32;
152 route_gw
->prefsrc
.in
= address
;
153 route_gw
->scope
= RT_SCOPE_LINK
;
154 route_gw
->protocol
= RTPROT_DHCP
;
155 route_gw
->priority
= link
->network
->dhcp_route_metric
;
156 route_gw
->table
= table
;
158 r
= route_configure(route_gw
, link
, dhcp4_route_handler
);
160 return log_link_warning_errno(link
, r
, "Could not set host route: %m");
162 link
->dhcp4_messages
++;
164 route
->family
= AF_INET
;
165 route
->gw
.in
= gateway
;
166 route
->prefsrc
.in
= address
;
167 route
->priority
= link
->network
->dhcp_route_metric
;
168 route
->table
= table
;
170 r
= route_configure(route
, link
, dhcp4_route_handler
);
172 log_link_warning_errno(link
, r
, "Could not set routes: %m");
173 link_enter_failed(link
);
177 link
->dhcp4_messages
++;
183 static int dhcp_lease_lost(Link
*link
) {
184 _cleanup_address_free_ Address
*address
= NULL
;
186 struct in_addr netmask
;
187 struct in_addr gateway
;
188 unsigned prefixlen
= 0;
192 assert(link
->dhcp_lease
);
194 log_link_warning(link
, "DHCP lease lost");
196 if (link
->network
->dhcp_use_routes
) {
197 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
200 n
= sd_dhcp_lease_get_routes(link
->dhcp_lease
, &routes
);
202 for (i
= 0; i
< n
; i
++) {
203 _cleanup_route_free_ Route
*route
= NULL
;
205 r
= route_new(&route
);
207 route
->family
= AF_INET
;
208 assert_se(sd_dhcp_route_get_gateway(routes
[i
], &route
->gw
.in
) >= 0);
209 assert_se(sd_dhcp_route_get_destination(routes
[i
], &route
->dst
.in
) >= 0);
210 assert_se(sd_dhcp_route_get_destination_prefix_length(routes
[i
], &route
->dst_prefixlen
) >= 0);
212 route_remove(route
, link
,
213 link_route_remove_handler
);
219 r
= address_new(&address
);
221 r
= sd_dhcp_lease_get_router(link
->dhcp_lease
, &gateway
);
223 _cleanup_route_free_ Route
*route_gw
= NULL
;
224 _cleanup_route_free_ Route
*route
= NULL
;
226 r
= route_new(&route_gw
);
228 route_gw
->family
= AF_INET
;
229 route_gw
->dst
.in
= gateway
;
230 route_gw
->dst_prefixlen
= 32;
231 route_gw
->scope
= RT_SCOPE_LINK
;
233 route_remove(route_gw
, link
,
234 link_route_remove_handler
);
237 r
= route_new(&route
);
239 route
->family
= AF_INET
;
240 route
->gw
.in
= gateway
;
242 route_remove(route
, link
,
243 link_route_remove_handler
);
247 r
= sd_dhcp_lease_get_address(link
->dhcp_lease
, &addr
);
249 r
= sd_dhcp_lease_get_netmask(link
->dhcp_lease
, &netmask
);
251 prefixlen
= in4_addr_netmask_to_prefixlen(&netmask
);
253 address
->family
= AF_INET
;
254 address
->in_addr
.in
= addr
;
255 address
->prefixlen
= prefixlen
;
257 address_remove(address
, link
, link_address_remove_handler
);
261 if (link
->network
->dhcp_use_mtu
) {
264 r
= sd_dhcp_lease_get_mtu(link
->dhcp_lease
, &mtu
);
265 if (r
>= 0 && link
->original_mtu
!= mtu
) {
266 r
= link_set_mtu(link
, link
->original_mtu
);
268 log_link_warning(link
,
269 "DHCP error: could not reset MTU");
270 link_enter_failed(link
);
276 if (link
->network
->dhcp_use_hostname
) {
277 const char *hostname
= NULL
;
279 if (link
->network
->dhcp_hostname
)
280 hostname
= link
->network
->dhcp_hostname
;
282 (void) sd_dhcp_lease_get_hostname(link
->dhcp_lease
, &hostname
);
285 /* If a hostname was set due to the lease, then unset it now. */
286 r
= manager_set_hostname(link
->manager
, NULL
);
288 log_link_warning_errno(link
, r
, "Failed to reset transient hostname: %m");
292 link
->dhcp_lease
= sd_dhcp_lease_unref(link
->dhcp_lease
);
294 link
->dhcp4_configured
= false;
299 static int dhcp4_address_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
,
301 _cleanup_link_unref_ Link
*link
= userdata
;
306 r
= sd_netlink_message_get_errno(m
);
307 if (r
< 0 && r
!= -EEXIST
) {
308 log_link_error_errno(link
, r
, "Could not set DHCPv4 address: %m");
309 link_enter_failed(link
);
311 manager_rtnl_process_address(rtnl
, m
, link
->manager
);
313 link_set_dhcp_routes(link
);
318 static int dhcp4_update_address(Link
*link
,
319 struct in_addr
*address
,
320 struct in_addr
*netmask
,
322 _cleanup_address_free_ Address
*addr
= NULL
;
330 prefixlen
= in4_addr_netmask_to_prefixlen(netmask
);
332 r
= address_new(&addr
);
336 addr
->family
= AF_INET
;
337 addr
->in_addr
.in
.s_addr
= address
->s_addr
;
338 addr
->cinfo
.ifa_prefered
= lifetime
;
339 addr
->cinfo
.ifa_valid
= lifetime
;
340 addr
->prefixlen
= prefixlen
;
341 addr
->broadcast
.s_addr
= address
->s_addr
| ~netmask
->s_addr
;
343 /* allow reusing an existing address and simply update its lifetime
344 * in case it already exists */
345 r
= address_configure(addr
, link
, dhcp4_address_handler
, true);
352 static int dhcp_lease_renew(sd_dhcp_client
*client
, Link
*link
) {
353 sd_dhcp_lease
*lease
;
354 struct in_addr address
;
355 struct in_addr netmask
;
356 uint32_t lifetime
= CACHE_INFO_INFINITY_LIFE_TIME
;
361 assert(link
->network
);
363 r
= sd_dhcp_client_get_lease(client
, &lease
);
365 return log_link_warning_errno(link
, r
, "DHCP error: no lease: %m");
367 sd_dhcp_lease_unref(link
->dhcp_lease
);
368 link
->dhcp4_configured
= false;
369 link
->dhcp_lease
= sd_dhcp_lease_ref(lease
);
372 r
= sd_dhcp_lease_get_address(lease
, &address
);
374 return log_link_warning_errno(link
, r
, "DHCP error: no address: %m");
376 r
= sd_dhcp_lease_get_netmask(lease
, &netmask
);
378 return log_link_warning_errno(link
, r
, "DHCP error: no netmask: %m");
380 if (!link
->network
->dhcp_critical
) {
381 r
= sd_dhcp_lease_get_lifetime(link
->dhcp_lease
, &lifetime
);
383 return log_link_warning_errno(link
, r
, "DHCP error: no lifetime: %m");
386 r
= dhcp4_update_address(link
, &address
, &netmask
, lifetime
);
388 log_link_warning_errno(link
, r
, "Could not update IP address: %m");
389 link_enter_failed(link
);
396 static int dhcp_lease_acquired(sd_dhcp_client
*client
, Link
*link
) {
397 sd_dhcp_lease
*lease
;
398 struct in_addr address
;
399 struct in_addr netmask
;
400 struct in_addr gateway
;
402 uint32_t lifetime
= CACHE_INFO_INFINITY_LIFE_TIME
;
408 r
= sd_dhcp_client_get_lease(client
, &lease
);
410 return log_link_error_errno(link
, r
, "DHCP error: No lease: %m");
412 r
= sd_dhcp_lease_get_address(lease
, &address
);
414 return log_link_error_errno(link
, r
, "DHCP error: No address: %m");
416 r
= sd_dhcp_lease_get_netmask(lease
, &netmask
);
418 return log_link_error_errno(link
, r
, "DHCP error: No netmask: %m");
420 prefixlen
= in4_addr_netmask_to_prefixlen(&netmask
);
422 r
= sd_dhcp_lease_get_router(lease
, &gateway
);
423 if (r
< 0 && r
!= -ENODATA
)
424 return log_link_error_errno(link
, r
, "DHCP error: Could not get gateway: %m");
428 LOG_LINK_INTERFACE(link
),
429 LOG_LINK_MESSAGE(link
, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
430 ADDRESS_FMT_VAL(address
),
432 ADDRESS_FMT_VAL(gateway
)),
433 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address
),
434 "PREFIXLEN=%u", prefixlen
,
435 "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway
),
439 LOG_LINK_INTERFACE(link
),
440 LOG_LINK_MESSAGE(link
, "DHCPv4 address %u.%u.%u.%u/%u",
441 ADDRESS_FMT_VAL(address
),
443 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address
),
444 "PREFIXLEN=%u", prefixlen
,
447 link
->dhcp_lease
= sd_dhcp_lease_ref(lease
);
450 if (link
->network
->dhcp_use_mtu
) {
453 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
455 r
= link_set_mtu(link
, mtu
);
457 log_link_error_errno(link
, r
, "Failed to set MTU to %" PRIu16
": %m", mtu
);
461 if (link
->network
->dhcp_use_hostname
) {
462 const char *hostname
= NULL
;
464 if (link
->network
->dhcp_hostname
)
465 hostname
= link
->network
->dhcp_hostname
;
467 (void) sd_dhcp_lease_get_hostname(lease
, &hostname
);
470 r
= manager_set_hostname(link
->manager
, hostname
);
472 log_link_error_errno(link
, r
, "Failed to set transient hostname to '%s': %m", hostname
);
476 if (link
->network
->dhcp_use_timezone
) {
477 const char *tz
= NULL
;
479 (void) sd_dhcp_lease_get_timezone(link
->dhcp_lease
, &tz
);
482 r
= manager_set_timezone(link
->manager
, tz
);
484 log_link_error_errno(link
, r
, "Failed to set timezone to '%s': %m", tz
);
488 if (!link
->network
->dhcp_critical
) {
489 r
= sd_dhcp_lease_get_lifetime(link
->dhcp_lease
, &lifetime
);
491 log_link_warning_errno(link
, r
, "DHCP error: no lifetime: %m");
496 r
= dhcp4_update_address(link
, &address
, &netmask
, lifetime
);
498 log_link_warning_errno(link
, r
, "Could not update IP address: %m");
499 link_enter_failed(link
);
505 static void dhcp4_handler(sd_dhcp_client
*client
, int event
, void *userdata
) {
506 Link
*link
= userdata
;
510 assert(link
->network
);
511 assert(link
->manager
);
513 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
517 case SD_DHCP_CLIENT_EVENT_EXPIRED
:
518 case SD_DHCP_CLIENT_EVENT_STOP
:
519 case SD_DHCP_CLIENT_EVENT_IP_CHANGE
:
520 if (link
->network
->dhcp_critical
) {
521 log_link_error(link
, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
525 if (link
->dhcp_lease
) {
526 r
= dhcp_lease_lost(link
);
528 link_enter_failed(link
);
533 if (event
== SD_DHCP_CLIENT_EVENT_IP_CHANGE
) {
534 r
= dhcp_lease_acquired(client
, link
);
536 link_enter_failed(link
);
542 case SD_DHCP_CLIENT_EVENT_RENEW
:
543 r
= dhcp_lease_renew(client
, link
);
545 link_enter_failed(link
);
549 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
:
550 r
= dhcp_lease_acquired(client
, link
);
552 link_enter_failed(link
);
558 log_link_warning_errno(link
, event
, "DHCP error: Client failed: %m");
560 log_link_warning(link
, "DHCP unknown event: %i", event
);
567 static int dhcp4_set_hostname(Link
*link
) {
568 _cleanup_free_
char *hostname
= NULL
;
574 if (!link
->network
->dhcp_send_hostname
)
576 else if (link
->network
->dhcp_hostname
)
577 hn
= link
->network
->dhcp_hostname
;
579 r
= gethostname_strict(&hostname
);
580 if (r
< 0 && r
!= -ENXIO
) /* ENXIO: no hostname set or hostname is "localhost" */
586 return sd_dhcp_client_set_hostname(link
->dhcp_client
, hn
);
589 int dhcp4_configure(Link
*link
) {
593 assert(link
->network
);
594 assert(link
->network
->dhcp
& ADDRESS_FAMILY_IPV4
);
596 if (!link
->dhcp_client
) {
597 r
= sd_dhcp_client_new(&link
->dhcp_client
, link
->network
->dhcp_anonymize
);
602 r
= sd_dhcp_client_attach_event(link
->dhcp_client
, NULL
, 0);
606 r
= sd_dhcp_client_set_mac(link
->dhcp_client
,
607 (const uint8_t *) &link
->mac
,
608 sizeof (link
->mac
), ARPHRD_ETHER
);
612 r
= sd_dhcp_client_set_ifindex(link
->dhcp_client
, link
->ifindex
);
616 r
= sd_dhcp_client_set_callback(link
->dhcp_client
, dhcp4_handler
, link
);
620 r
= sd_dhcp_client_set_request_broadcast(link
->dhcp_client
,
621 link
->network
->dhcp_broadcast
);
626 r
= sd_dhcp_client_set_mtu(link
->dhcp_client
, link
->mtu
);
631 if (link
->network
->dhcp_use_mtu
) {
632 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
633 SD_DHCP_OPTION_INTERFACE_MTU
);
638 /* NOTE: even if this variable is called "use", it also "sends" PRL
639 * options, maybe there should be a different configuration variable
640 * to send or not route options?. */
641 /* NOTE: when using Anonymize=yes, routes PRL options are sent
642 * by default, so they don't need to be added here. */
643 if (link
->network
->dhcp_use_routes
&& !link
->network
->dhcp_anonymize
) {
644 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
645 SD_DHCP_OPTION_STATIC_ROUTE
);
648 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
,
649 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
);
654 if (link
->network
->dhcp_use_ntp
) {
655 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
, SD_DHCP_OPTION_NTP_SERVER
);
660 if (link
->network
->dhcp_use_timezone
) {
661 r
= sd_dhcp_client_set_request_option(link
->dhcp_client
, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
);
666 r
= dhcp4_set_hostname(link
);
670 if (link
->network
->dhcp_vendor_class_identifier
) {
671 r
= sd_dhcp_client_set_vendor_class_identifier(link
->dhcp_client
,
672 link
->network
->dhcp_vendor_class_identifier
);
677 if (link
->network
->dhcp_client_port
) {
678 r
= sd_dhcp_client_set_client_port(link
->dhcp_client
, link
->network
->dhcp_client_port
);
683 switch (link
->network
->dhcp_client_identifier
) {
684 case DHCP_CLIENT_ID_DUID
: {
685 /* If configured, apply user specified DUID and/or IAID */
686 const DUID
*duid
= link_duid(link
);
688 r
= sd_dhcp_client_set_iaid_duid(link
->dhcp_client
,
691 duid
->raw_data_len
> 0 ? duid
->raw_data
: NULL
,
697 case DHCP_CLIENT_ID_MAC
:
698 r
= sd_dhcp_client_set_client_id(link
->dhcp_client
,
700 (const uint8_t *) &link
->mac
,
706 assert_not_reached("Unknown client identifier type.");