]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-dhcp4.c
Merge pull request #7547 from hvenev/sysctl-no-net-default
[thirdparty/systemd.git] / src / network / networkd-dhcp4.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
6
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.
11
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.
16
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/>.
19 ***/
20
21 #include <netinet/ether.h>
22 #include <linux/if.h>
23
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"
35
36 static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
37 void *userdata) {
38 _cleanup_link_unref_ Link *link = userdata;
39 int r;
40
41 assert(link);
42 assert(link->dhcp4_messages > 0);
43
44 link->dhcp4_messages--;
45
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);
50 }
51
52 if (link->dhcp4_messages == 0) {
53 link->dhcp4_configured = true;
54 link_check_ready(link);
55 }
56
57 return 1;
58 }
59
60 static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
61 assert(route);
62 assert(self_addr);
63
64 if (in_addr_is_localhost(AF_INET, &route->dst) ||
65 (self_addr->s_addr && route->dst.in.s_addr == self_addr->s_addr))
66 return RT_SCOPE_HOST;
67 else if (in4_addr_is_null(&route->gw.in))
68 return RT_SCOPE_LINK;
69 else
70 return RT_SCOPE_UNIVERSE;
71 }
72
73 static int link_set_dhcp_routes(Link *link) {
74 struct in_addr gateway, address;
75 _cleanup_free_ sd_dhcp_route **static_routes = NULL;
76 int r, n, i;
77 uint32_t table;
78
79 assert(link);
80
81 if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */
82 return 0;
83
84 if (!link->network) /* link went down while we configured the IP addresses? */
85 return 0;
86
87 if (!link->network->dhcp_use_routes)
88 return 0;
89
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;
95
96 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
97 if (r < 0)
98 return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
99
100 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
101 if (n < 0)
102 log_link_debug_errno(link, n, "DHCP error: could not get routes: %m");
103
104 for (i = 0; i < n; i++) {
105 _cleanup_route_free_ Route *route = NULL;
106
107 r = route_new(&route);
108 if (r < 0)
109 return log_link_error_errno(link, r, "Could not allocate route: %m");
110
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);
119
120 r = route_configure(route, link, dhcp4_route_handler);
121 if (r < 0)
122 return log_link_warning_errno(link, r, "Could not set host route: %m");
123
124 link->dhcp4_messages++;
125 }
126
127 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
128 if (r == -ENODATA)
129 log_link_info_errno(link, r, "DHCP: No routes received from DHCP server: %m");
130 else if (r < 0)
131 log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
132
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;
138
139 r = route_new(&route);
140 if (r < 0)
141 return log_link_error_errno(link, r, "Could not allocate route: %m");
142
143 route->protocol = RTPROT_DHCP;
144
145 r = route_new(&route_gw);
146 if (r < 0)
147 return log_link_error_errno(link, r, "Could not allocate route: %m");
148
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;
160
161 r = route_configure(route_gw, link, dhcp4_route_handler);
162 if (r < 0)
163 return log_link_warning_errno(link, r, "Could not set host route: %m");
164
165 link->dhcp4_messages++;
166
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;
172
173 r = route_configure(route, link, dhcp4_route_handler);
174 if (r < 0) {
175 log_link_warning_errno(link, r, "Could not set routes: %m");
176 link_enter_failed(link);
177 return r;
178 }
179
180 link->dhcp4_messages++;
181 }
182
183 return 0;
184 }
185
186 static int dhcp_lease_lost(Link *link) {
187 _cleanup_address_free_ Address *address = NULL;
188 struct in_addr addr;
189 struct in_addr netmask;
190 struct in_addr gateway;
191 unsigned prefixlen = 0;
192 int r;
193
194 assert(link);
195 assert(link->dhcp_lease);
196
197 log_link_warning(link, "DHCP lease lost");
198
199 if (link->network->dhcp_use_routes) {
200 _cleanup_free_ sd_dhcp_route **routes = NULL;
201 int n, i;
202
203 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
204 if (n >= 0) {
205 for (i = 0; i < n; i++) {
206 _cleanup_route_free_ Route *route = NULL;
207
208 r = route_new(&route);
209 if (r >= 0) {
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);
214
215 route_remove(route, link,
216 link_route_remove_handler);
217 }
218 }
219 }
220 }
221
222 r = address_new(&address);
223 if (r >= 0) {
224 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
225 if (r >= 0) {
226 _cleanup_route_free_ Route *route_gw = NULL;
227 _cleanup_route_free_ Route *route = NULL;
228
229 r = route_new(&route_gw);
230 if (r >= 0) {
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;
235
236 route_remove(route_gw, link,
237 link_route_remove_handler);
238 }
239
240 r = route_new(&route);
241 if (r >= 0) {
242 route->family = AF_INET;
243 route->gw.in = gateway;
244
245 route_remove(route, link,
246 link_route_remove_handler);
247 }
248 }
249
250 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
251 if (r >= 0) {
252 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
253 if (r >= 0)
254 prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
255
256 address->family = AF_INET;
257 address->in_addr.in = addr;
258 address->prefixlen = prefixlen;
259
260 address_remove(address, link, link_address_remove_handler);
261 }
262 }
263
264 if (link->network->dhcp_use_mtu) {
265 uint16_t mtu;
266
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);
270 if (r < 0) {
271 log_link_warning(link,
272 "DHCP error: could not reset MTU");
273 link_enter_failed(link);
274 return r;
275 }
276 }
277 }
278
279 if (link->network->dhcp_use_hostname) {
280 const char *hostname = NULL;
281
282 if (link->network->dhcp_hostname)
283 hostname = link->network->dhcp_hostname;
284 else
285 (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
286
287 if (hostname) {
288 /* If a hostname was set due to the lease, then unset it now. */
289 r = manager_set_hostname(link->manager, NULL);
290 if (r < 0)
291 log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
292 }
293 }
294
295 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
296 link_dirty(link);
297 link->dhcp4_configured = false;
298
299 return 0;
300 }
301
302 static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
303 void *userdata) {
304 _cleanup_link_unref_ Link *link = userdata;
305 int r;
306
307 assert(link);
308
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);
313 } else if (r >= 0)
314 manager_rtnl_process_address(rtnl, m, link->manager);
315
316 link_set_dhcp_routes(link);
317
318 return 1;
319 }
320
321 static int dhcp4_update_address(Link *link,
322 struct in_addr *address,
323 struct in_addr *netmask,
324 uint32_t lifetime) {
325 _cleanup_address_free_ Address *addr = NULL;
326 unsigned prefixlen;
327 int r;
328
329 assert(address);
330 assert(netmask);
331 assert(lifetime);
332
333 prefixlen = in4_addr_netmask_to_prefixlen(netmask);
334
335 r = address_new(&addr);
336 if (r < 0)
337 return r;
338
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;
345
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);
349 if (r < 0)
350 return r;
351
352 return 0;
353 }
354
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;
360 int r;
361
362 assert(link);
363 assert(client);
364 assert(link->network);
365
366 r = sd_dhcp_client_get_lease(client, &lease);
367 if (r < 0)
368 return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
369
370 sd_dhcp_lease_unref(link->dhcp_lease);
371 link->dhcp4_configured = false;
372 link->dhcp_lease = sd_dhcp_lease_ref(lease);
373 link_dirty(link);
374
375 r = sd_dhcp_lease_get_address(lease, &address);
376 if (r < 0)
377 return log_link_warning_errno(link, r, "DHCP error: no address: %m");
378
379 r = sd_dhcp_lease_get_netmask(lease, &netmask);
380 if (r < 0)
381 return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
382
383 if (!link->network->dhcp_critical) {
384 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
385 if (r < 0)
386 return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
387 }
388
389 r = dhcp4_update_address(link, &address, &netmask, lifetime);
390 if (r < 0) {
391 log_link_warning_errno(link, r, "Could not update IP address: %m");
392 link_enter_failed(link);
393 return r;
394 }
395
396 return 0;
397 }
398
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;
404 unsigned prefixlen;
405 uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
406 int r;
407
408 assert(client);
409 assert(link);
410
411 r = sd_dhcp_client_get_lease(client, &lease);
412 if (r < 0)
413 return log_link_error_errno(link, r, "DHCP error: No lease: %m");
414
415 r = sd_dhcp_lease_get_address(lease, &address);
416 if (r < 0)
417 return log_link_error_errno(link, r, "DHCP error: No address: %m");
418
419 r = sd_dhcp_lease_get_netmask(lease, &netmask);
420 if (r < 0)
421 return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
422
423 prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
424
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");
428
429 if (r >= 0)
430 log_struct(LOG_INFO,
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),
434 prefixlen,
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),
439 NULL);
440 else
441 log_struct(LOG_INFO,
442 LOG_LINK_INTERFACE(link),
443 LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
444 ADDRESS_FMT_VAL(address),
445 prefixlen),
446 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
447 "PREFIXLEN=%u", prefixlen,
448 NULL);
449
450 link->dhcp_lease = sd_dhcp_lease_ref(lease);
451 link_dirty(link);
452
453 if (link->network->dhcp_use_mtu) {
454 uint16_t mtu;
455
456 r = sd_dhcp_lease_get_mtu(lease, &mtu);
457 if (r >= 0) {
458 r = link_set_mtu(link, mtu);
459 if (r < 0)
460 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
461 }
462 }
463
464 if (link->network->dhcp_use_hostname) {
465 const char *hostname = NULL;
466
467 if (link->network->dhcp_hostname)
468 hostname = link->network->dhcp_hostname;
469 else
470 (void) sd_dhcp_lease_get_hostname(lease, &hostname);
471
472 if (hostname) {
473 r = manager_set_hostname(link->manager, hostname);
474 if (r < 0)
475 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
476 }
477 }
478
479 if (link->network->dhcp_use_timezone) {
480 const char *tz = NULL;
481
482 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
483
484 if (tz) {
485 r = manager_set_timezone(link->manager, tz);
486 if (r < 0)
487 log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
488 }
489 }
490
491 if (!link->network->dhcp_critical) {
492 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
493 if (r < 0) {
494 log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
495 return r;
496 }
497 }
498
499 r = dhcp4_update_address(link, &address, &netmask, lifetime);
500 if (r < 0) {
501 log_link_warning_errno(link, r, "Could not update IP address: %m");
502 link_enter_failed(link);
503 return r;
504 }
505
506 return 0;
507 }
508 static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
509 Link *link = userdata;
510 int r = 0;
511
512 assert(link);
513 assert(link->network);
514 assert(link->manager);
515
516 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
517 return;
518
519 switch (event) {
520 case SD_DHCP_CLIENT_EVENT_EXPIRED:
521 case SD_DHCP_CLIENT_EVENT_STOP:
522 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
523 if (link->network->dhcp_critical) {
524 log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
525 return;
526 }
527
528 if (link->dhcp_lease) {
529 r = dhcp_lease_lost(link);
530 if (r < 0) {
531 link_enter_failed(link);
532 return;
533 }
534 }
535
536 if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) {
537 r = dhcp_lease_acquired(client, link);
538 if (r < 0) {
539 link_enter_failed(link);
540 return;
541 }
542 }
543
544 break;
545 case SD_DHCP_CLIENT_EVENT_RENEW:
546 r = dhcp_lease_renew(client, link);
547 if (r < 0) {
548 link_enter_failed(link);
549 return;
550 }
551 break;
552 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
553 r = dhcp_lease_acquired(client, link);
554 if (r < 0) {
555 link_enter_failed(link);
556 return;
557 }
558 break;
559 default:
560 if (event < 0)
561 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
562 else
563 log_link_warning(link, "DHCP unknown event: %i", event);
564 break;
565 }
566
567 return;
568 }
569
570 static int dhcp4_set_hostname(Link *link) {
571 _cleanup_free_ char *hostname = NULL;
572 const char *hn;
573 int r;
574
575 assert(link);
576
577 if (!link->network->dhcp_send_hostname)
578 hn = NULL;
579 else if (link->network->dhcp_hostname)
580 hn = link->network->dhcp_hostname;
581 else {
582 r = gethostname_strict(&hostname);
583 if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
584 return r;
585
586 hn = hostname;
587 }
588
589 return sd_dhcp_client_set_hostname(link->dhcp_client, hn);
590 }
591
592 static bool promote_secondaries_enabled(const char *ifname) {
593 _cleanup_free_ char *promote_secondaries_sysctl = NULL;
594 char *promote_secondaries_path;
595 int r;
596
597 promote_secondaries_path = strjoina("net/ipv4/conf/", ifname, "/promote_secondaries");
598 r = sysctl_read(promote_secondaries_path, &promote_secondaries_sysctl);
599 if (r < 0) {
600 log_debug_errno(r, "Cannot read sysctl %s", promote_secondaries_path);
601 return false;
602 }
603
604 truncate_nl(promote_secondaries_sysctl);
605 r = parse_boolean(promote_secondaries_sysctl);
606 if (r < 0)
607 log_warning_errno(r, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path, promote_secondaries_sysctl);
608 return r > 0;
609 }
610
611 /* dhcp4_set_promote_secondaries will ensure this interface has
612 * the "promote_secondaries" option in the kernel set. If this sysctl
613 * is not set DHCP will work only as long as the IP address does not
614 * changes between leases. The kernel will remove all secondary IP
615 * addresses of an interface otherwise. The way systemd-network works
616 * is that the new IP of a lease is added as a secondary IP and when
617 * the primary one expires it relies on the kernel to promote the
618 * secondary IP. See also https://github.com/systemd/systemd/issues/7163
619 */
620 int dhcp4_set_promote_secondaries(Link *link) {
621 int r;
622
623 assert(link);
624 assert(link->network);
625 assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
626
627 /* check if the kernel has promote_secondaries enabled for our
628 * interface. If it is not globally enabled or enabled for the
629 * specific interface we must either enable it.
630 */
631 if (!(promote_secondaries_enabled("all") || promote_secondaries_enabled(link->ifname))) {
632 char *promote_secondaries_path = NULL;
633
634 log_link_debug(link, "promote_secondaries is unset, setting it");
635 promote_secondaries_path = strjoina("net/ipv4/conf/", link->ifname, "/promote_secondaries");
636 r = sysctl_write(promote_secondaries_path, "1");
637 if (r < 0)
638 log_link_warning_errno(link, r, "cannot set sysctl %s to 1", promote_secondaries_path);
639 return r > 0;
640 }
641
642 return 0;
643 }
644
645 int dhcp4_configure(Link *link) {
646 int r;
647
648 assert(link);
649 assert(link->network);
650 assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
651
652 if (!link->dhcp_client) {
653 r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
654 if (r < 0)
655 return r;
656 }
657
658 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
659 if (r < 0)
660 return r;
661
662 r = sd_dhcp_client_set_mac(link->dhcp_client,
663 (const uint8_t *) &link->mac,
664 sizeof (link->mac), ARPHRD_ETHER);
665 if (r < 0)
666 return r;
667
668 r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex);
669 if (r < 0)
670 return r;
671
672 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
673 if (r < 0)
674 return r;
675
676 r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
677 link->network->dhcp_broadcast);
678 if (r < 0)
679 return r;
680
681 if (link->mtu) {
682 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
683 if (r < 0)
684 return r;
685 }
686
687 if (link->network->dhcp_use_mtu) {
688 r = sd_dhcp_client_set_request_option(link->dhcp_client,
689 SD_DHCP_OPTION_INTERFACE_MTU);
690 if (r < 0)
691 return r;
692 }
693
694 /* NOTE: even if this variable is called "use", it also "sends" PRL
695 * options, maybe there should be a different configuration variable
696 * to send or not route options?. */
697 /* NOTE: when using Anonymize=yes, routes PRL options are sent
698 * by default, so they don't need to be added here. */
699 if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) {
700 r = sd_dhcp_client_set_request_option(link->dhcp_client,
701 SD_DHCP_OPTION_STATIC_ROUTE);
702 if (r < 0)
703 return r;
704 r = sd_dhcp_client_set_request_option(link->dhcp_client,
705 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
706 if (r < 0)
707 return r;
708 }
709
710 if (link->network->dhcp_use_ntp) {
711 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
712 if (r < 0)
713 return r;
714 }
715
716 if (link->network->dhcp_use_timezone) {
717 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
718 if (r < 0)
719 return r;
720 }
721
722 r = dhcp4_set_hostname(link);
723 if (r < 0)
724 return r;
725
726 if (link->network->dhcp_vendor_class_identifier) {
727 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
728 link->network->dhcp_vendor_class_identifier);
729 if (r < 0)
730 return r;
731 }
732
733 if (link->network->dhcp_client_port) {
734 r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
735 if (r < 0)
736 return r;
737 }
738
739 switch (link->network->dhcp_client_identifier) {
740 case DHCP_CLIENT_ID_DUID: {
741 /* If configured, apply user specified DUID and/or IAID */
742 const DUID *duid = link_duid(link);
743
744 r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
745 link->network->iaid,
746 duid->type,
747 duid->raw_data_len > 0 ? duid->raw_data : NULL,
748 duid->raw_data_len);
749 if (r < 0)
750 return r;
751 break;
752 }
753 case DHCP_CLIENT_ID_MAC:
754 r = sd_dhcp_client_set_client_id(link->dhcp_client,
755 ARPHRD_ETHER,
756 (const uint8_t *) &link->mac,
757 sizeof(link->mac));
758 if (r < 0)
759 return r;
760 break;
761 default:
762 assert_not_reached("Unknown client identifier type.");
763 }
764
765 return 0;
766 }