]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-dhcp4.c
DHCP DUID, IAID configuration options
[thirdparty/systemd.git] / src / network / networkd-dhcp4.c
CommitLineData
3c9b8860
TG
1/***
2 This file is part of systemd.
3
4 Copyright 2013-2014 Tom Gundersen <teg@jklm.no>
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include <netinet/ether.h>
21#include <linux/if.h>
22
b5efdb8a
LP
23#include "alloc-util.h"
24#include "dhcp-lease-internal.h"
958b66ea 25#include "hostname-util.h"
3c9b8860 26#include "network-internal.h"
b5efdb8a 27#include "networkd-link.h"
3c9b8860 28
1c4baffc 29static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860
TG
30 void *userdata) {
31 _cleanup_link_unref_ Link *link = userdata;
32 int r;
33
34 assert(link);
6cf4a01c 35 assert(link->dhcp4_messages > 0);
3c9b8860 36
313cefa1 37 link->dhcp4_messages--;
3c9b8860 38
1c4baffc 39 r = sd_netlink_message_get_errno(m);
3c9b8860 40 if (r < 0 && r != -EEXIST) {
f6b8196f 41 log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
3c9b8860
TG
42 link_enter_failed(link);
43 }
44
6cf4a01c 45 if (link->dhcp4_messages == 0) {
3c9b8860 46 link->dhcp4_configured = true;
8012cd39 47 link_check_ready(link);
3c9b8860
TG
48 }
49
50 return 1;
51}
52
53static int link_set_dhcp_routes(Link *link) {
54 struct in_addr gateway;
f8693fc7 55 _cleanup_free_ sd_dhcp_route **static_routes = NULL;
3c9b8860
TG
56 int r, n, i;
57
58 assert(link);
59 assert(link->dhcp_lease);
60
61 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
397d15fd 62 if (r < 0 && r != -ENODATA)
f6b8196f
LP
63 return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
64
3c9b8860 65 if (r >= 0) {
46b0c76e 66 struct in_addr address;
3c9b8860
TG
67 _cleanup_route_free_ Route *route = NULL;
68 _cleanup_route_free_ Route *route_gw = NULL;
69
46b0c76e 70 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
f6b8196f
LP
71 if (r < 0)
72 return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
46b0c76e 73
ed9e361a 74 r = route_new(&route);
f6b8196f
LP
75 if (r < 0)
76 return log_link_error_errno(link, r, "Could not allocate route: %m");
3c9b8860 77
ed9e361a
TG
78 route->protocol = RTPROT_DHCP;
79
80 r = route_new(&route_gw);
f6b8196f
LP
81 if (r < 0)
82 return log_link_error_errno(link, r, "Could not allocate route: %m");
3c9b8860
TG
83
84 /* The dhcp netmask may mask out the gateway. Add an explicit
85 * route for the gw host so that we can route no matter the
86 * netmask or existing kernel route tables. */
87 route_gw->family = AF_INET;
2ce40956 88 route_gw->dst.in = gateway;
3c9b8860 89 route_gw->dst_prefixlen = 32;
2ce40956 90 route_gw->prefsrc.in = address;
3c9b8860 91 route_gw->scope = RT_SCOPE_LINK;
ed9e361a 92 route_gw->protocol = RTPROT_DHCP;
86655331 93 route_gw->priority = link->network->dhcp_route_metric;
3c9b8860
TG
94
95 r = route_configure(route_gw, link, &dhcp4_route_handler);
f6b8196f
LP
96 if (r < 0)
97 return log_link_warning_errno(link, r, "Could not set host route: %m");
3c9b8860 98
313cefa1 99 link->dhcp4_messages++;
3c9b8860
TG
100
101 route->family = AF_INET;
2ce40956
TG
102 route->gw.in = gateway;
103 route->prefsrc.in = address;
86655331 104 route->priority = link->network->dhcp_route_metric;
3c9b8860
TG
105
106 r = route_configure(route, link, &dhcp4_route_handler);
107 if (r < 0) {
f6b8196f 108 log_link_warning_errno(link, r, "Could not set routes: %m");
3c9b8860
TG
109 link_enter_failed(link);
110 return r;
111 }
112
313cefa1 113 link->dhcp4_messages++;
3c9b8860
TG
114 }
115
116 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
397d15fd 117 if (n == -ENODATA)
3c9b8860 118 return 0;
f6b8196f
LP
119 if (n < 0)
120 return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m");
3c9b8860
TG
121
122 for (i = 0; i < n; i++) {
123 _cleanup_route_free_ Route *route = NULL;
124
ed9e361a 125 r = route_new(&route);
f6b8196f
LP
126 if (r < 0)
127 return log_link_error_errno(link, r, "Could not allocate route: %m");
3c9b8860
TG
128
129 route->family = AF_INET;
ed9e361a 130 route->protocol = RTPROT_DHCP;
f8693fc7
BG
131 assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
132 assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
133 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
86655331 134 route->priority = link->network->dhcp_route_metric;
3c9b8860
TG
135
136 r = route_configure(route, link, &dhcp4_route_handler);
f6b8196f
LP
137 if (r < 0)
138 return log_link_warning_errno(link, r, "Could not set host route: %m");
3c9b8860 139
313cefa1 140 link->dhcp4_messages++;
3c9b8860
TG
141 }
142
143 return 0;
144}
145
146static int dhcp_lease_lost(Link *link) {
147 _cleanup_address_free_ Address *address = NULL;
148 struct in_addr addr;
149 struct in_addr netmask;
150 struct in_addr gateway;
f414a269 151 unsigned prefixlen = 0;
3c9b8860
TG
152 int r;
153
154 assert(link);
155 assert(link->dhcp_lease);
156
79008bdd 157 log_link_warning(link, "DHCP lease lost");
3c9b8860 158
27cb34f5 159 if (link->network->dhcp_use_routes) {
f8693fc7 160 _cleanup_free_ sd_dhcp_route **routes = NULL;
3c9b8860
TG
161 int n, i;
162
163 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
164 if (n >= 0) {
165 for (i = 0; i < n; i++) {
166 _cleanup_route_free_ Route *route = NULL;
167
ed9e361a 168 r = route_new(&route);
3c9b8860
TG
169 if (r >= 0) {
170 route->family = AF_INET;
f8693fc7
BG
171 assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
172 assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
173 assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
3c9b8860 174
91b5f997
TG
175 route_remove(route, link,
176 &link_route_remove_handler);
3c9b8860
TG
177 }
178 }
179 }
180 }
181
f0213e37 182 r = address_new(&address);
3c9b8860
TG
183 if (r >= 0) {
184 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
185 if (r >= 0) {
186 _cleanup_route_free_ Route *route_gw = NULL;
187 _cleanup_route_free_ Route *route = NULL;
188
ed9e361a 189 r = route_new(&route_gw);
3c9b8860
TG
190 if (r >= 0) {
191 route_gw->family = AF_INET;
2ce40956 192 route_gw->dst.in = gateway;
3c9b8860
TG
193 route_gw->dst_prefixlen = 32;
194 route_gw->scope = RT_SCOPE_LINK;
195
91b5f997
TG
196 route_remove(route_gw, link,
197 &link_route_remove_handler);
3c9b8860
TG
198 }
199
ed9e361a 200 r = route_new(&route);
3c9b8860
TG
201 if (r >= 0) {
202 route->family = AF_INET;
2ce40956 203 route->gw.in = gateway;
3c9b8860 204
91b5f997
TG
205 route_remove(route, link,
206 &link_route_remove_handler);
3c9b8860
TG
207 }
208 }
209
f414a269
TG
210 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
211 if (r >= 0) {
212 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
213 if (r >= 0)
214 prefixlen = in_addr_netmask_to_prefixlen(&netmask);
3c9b8860 215
f414a269
TG
216 address->family = AF_INET;
217 address->in_addr.in = addr;
218 address->prefixlen = prefixlen;
3c9b8860 219
91b5f997 220 address_remove(address, link, &link_address_remove_handler);
f414a269 221 }
3c9b8860
TG
222 }
223
27cb34f5 224 if (link->network->dhcp_use_mtu) {
3c9b8860
TG
225 uint16_t mtu;
226
227 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
228 if (r >= 0 && link->original_mtu != mtu) {
229 r = link_set_mtu(link, link->original_mtu);
230 if (r < 0) {
79008bdd 231 log_link_warning(link,
3c9b8860
TG
232 "DHCP error: could not reset MTU");
233 link_enter_failed(link);
234 return r;
235 }
236 }
237 }
238
27cb34f5 239 if (link->network->dhcp_use_hostname) {
3c9b8860
TG
240 const char *hostname = NULL;
241
27cb34f5
LP
242 if (link->network->dhcp_hostname)
243 hostname = link->network->dhcp_hostname;
dce391e7
LP
244 else
245 (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
a7d0ef44 246
dce391e7
LP
247 if (hostname) {
248 /* If a hostname was set due to the lease, then unset it now. */
249 r = link_set_hostname(link, NULL);
3c9b8860 250 if (r < 0)
dce391e7 251 log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
3c9b8860
TG
252 }
253 }
254
255 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
6a3e5f6a 256 link_dirty(link);
3c9b8860
TG
257 link->dhcp4_configured = false;
258
259 return 0;
260}
261
1c4baffc 262static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860
TG
263 void *userdata) {
264 _cleanup_link_unref_ Link *link = userdata;
265 int r;
266
267 assert(link);
268
1c4baffc 269 r = sd_netlink_message_get_errno(m);
3c9b8860 270 if (r < 0 && r != -EEXIST) {
f6b8196f 271 log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
3c9b8860 272 link_enter_failed(link);
45af44d4 273 } else if (r >= 0)
200a0868 274 manager_rtnl_process_address(rtnl, m, link->manager);
3c9b8860
TG
275
276 link_set_dhcp_routes(link);
277
278 return 1;
279}
280
281static int dhcp4_update_address(Link *link,
282 struct in_addr *address,
283 struct in_addr *netmask,
284 uint32_t lifetime) {
285 _cleanup_address_free_ Address *addr = NULL;
286 unsigned prefixlen;
287 int r;
288
289 assert(address);
290 assert(netmask);
291 assert(lifetime);
292
293 prefixlen = in_addr_netmask_to_prefixlen(netmask);
294
f0213e37 295 r = address_new(&addr);
3c9b8860
TG
296 if (r < 0)
297 return r;
298
299 addr->family = AF_INET;
300 addr->in_addr.in.s_addr = address->s_addr;
301 addr->cinfo.ifa_prefered = lifetime;
302 addr->cinfo.ifa_valid = lifetime;
303 addr->prefixlen = prefixlen;
304 addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
305
66669078
TG
306 /* allow reusing an existing address and simply update its lifetime
307 * in case it already exists */
308 r = address_configure(addr, link, &dhcp4_address_handler, true);
3c9b8860
TG
309 if (r < 0)
310 return r;
311
312 return 0;
313}
314
315static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
316 sd_dhcp_lease *lease;
317 struct in_addr address;
318 struct in_addr netmask;
319 uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
320 int r;
321
322 assert(link);
323 assert(client);
324 assert(link->network);
325
326 r = sd_dhcp_client_get_lease(client, &lease);
f6b8196f
LP
327 if (r < 0)
328 return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
3c9b8860
TG
329
330 sd_dhcp_lease_unref(link->dhcp_lease);
331 link->dhcp4_configured = false;
e6b18ffa 332 link->dhcp_lease = sd_dhcp_lease_ref(lease);
6a3e5f6a 333 link_dirty(link);
3c9b8860
TG
334
335 r = sd_dhcp_lease_get_address(lease, &address);
f6b8196f
LP
336 if (r < 0)
337 return log_link_warning_errno(link, r, "DHCP error: no address: %m");
3c9b8860
TG
338
339 r = sd_dhcp_lease_get_netmask(lease, &netmask);
f6b8196f
LP
340 if (r < 0)
341 return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
3c9b8860
TG
342
343 if (!link->network->dhcp_critical) {
f6b8196f
LP
344 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
345 if (r < 0)
346 return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
3c9b8860
TG
347 }
348
349 r = dhcp4_update_address(link, &address, &netmask, lifetime);
350 if (r < 0) {
f6b8196f 351 log_link_warning_errno(link, r, "Could not update IP address: %m");
3c9b8860
TG
352 link_enter_failed(link);
353 return r;
354 }
355
356 return 0;
357}
358
359static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
360 sd_dhcp_lease *lease;
361 struct in_addr address;
362 struct in_addr netmask;
363 struct in_addr gateway;
364 unsigned prefixlen;
365 uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
366 int r;
367
368 assert(client);
369 assert(link);
370
371 r = sd_dhcp_client_get_lease(client, &lease);
f2341e0a 372 if (r < 0)
f6b8196f 373 return log_link_error_errno(link, r, "DHCP error: No lease: %m");
3c9b8860
TG
374
375 r = sd_dhcp_lease_get_address(lease, &address);
f2341e0a 376 if (r < 0)
f6b8196f 377 return log_link_error_errno(link, r, "DHCP error: No address: %m");
3c9b8860
TG
378
379 r = sd_dhcp_lease_get_netmask(lease, &netmask);
f2341e0a 380 if (r < 0)
f6b8196f 381 return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
3c9b8860
TG
382
383 prefixlen = in_addr_netmask_to_prefixlen(&netmask);
384
385 r = sd_dhcp_lease_get_router(lease, &gateway);
397d15fd 386 if (r < 0 && r != -ENODATA)
f6b8196f 387 return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
3c9b8860
TG
388
389 if (r >= 0)
f2341e0a
LP
390 log_struct(LOG_INFO,
391 LOG_LINK_INTERFACE(link),
392 LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
393 ADDRESS_FMT_VAL(address),
394 prefixlen,
395 ADDRESS_FMT_VAL(gateway)),
396 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
397 "PREFIXLEN=%u", prefixlen,
398 "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway),
399 NULL);
3c9b8860 400 else
f2341e0a
LP
401 log_struct(LOG_INFO,
402 LOG_LINK_INTERFACE(link),
403 LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
404 ADDRESS_FMT_VAL(address),
405 prefixlen),
406 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
407 "PREFIXLEN=%u", prefixlen,
408 NULL);
3c9b8860 409
e6b18ffa 410 link->dhcp_lease = sd_dhcp_lease_ref(lease);
6a3e5f6a 411 link_dirty(link);
3c9b8860 412
27cb34f5 413 if (link->network->dhcp_use_mtu) {
3c9b8860
TG
414 uint16_t mtu;
415
416 r = sd_dhcp_lease_get_mtu(lease, &mtu);
417 if (r >= 0) {
418 r = link_set_mtu(link, mtu);
419 if (r < 0)
f2341e0a 420 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
3c9b8860
TG
421 }
422 }
423
27cb34f5 424 if (link->network->dhcp_use_hostname) {
49f6e11e 425 const char *hostname = NULL;
3c9b8860 426
27cb34f5
LP
427 if (link->network->dhcp_hostname)
428 hostname = link->network->dhcp_hostname;
dce391e7
LP
429 else
430 (void) sd_dhcp_lease_get_hostname(lease, &hostname);
a7d0ef44 431
dce391e7 432 if (hostname) {
3c9b8860
TG
433 r = link_set_hostname(link, hostname);
434 if (r < 0)
f2341e0a 435 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
3c9b8860
TG
436 }
437 }
438
27cb34f5 439 if (link->network->dhcp_use_timezone) {
21b80ad1
LP
440 const char *tz = NULL;
441
442 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
443
444 if (tz) {
445 r = link_set_timezone(link, tz);
446 if (r < 0)
447 log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
448 }
449 }
450
3c9b8860 451 if (!link->network->dhcp_critical) {
f2341e0a 452 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
3c9b8860 453 if (r < 0) {
f2341e0a 454 log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
3c9b8860
TG
455 return r;
456 }
457 }
458
459 r = dhcp4_update_address(link, &address, &netmask, lifetime);
460 if (r < 0) {
f2341e0a 461 log_link_warning_errno(link, r, "Could not update IP address: %m");
3c9b8860
TG
462 link_enter_failed(link);
463 return r;
464 }
465
466 return 0;
467}
468static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
469 Link *link = userdata;
470 int r = 0;
471
472 assert(link);
473 assert(link->network);
474 assert(link->manager);
475
476 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
477 return;
478
479 switch (event) {
03748142
DH
480 case SD_DHCP_CLIENT_EVENT_EXPIRED:
481 case SD_DHCP_CLIENT_EVENT_STOP:
482 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
3c9b8860 483 if (link->network->dhcp_critical) {
f6b8196f 484 log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
3c9b8860
TG
485 return;
486 }
487
488 if (link->dhcp_lease) {
489 r = dhcp_lease_lost(link);
490 if (r < 0) {
491 link_enter_failed(link);
492 return;
493 }
494 }
495
03748142 496 if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) {
3c9b8860
TG
497 r = dhcp_lease_acquired(client, link);
498 if (r < 0) {
499 link_enter_failed(link);
500 return;
501 }
502 }
503
504 break;
03748142 505 case SD_DHCP_CLIENT_EVENT_RENEW:
3c9b8860
TG
506 r = dhcp_lease_renew(client, link);
507 if (r < 0) {
508 link_enter_failed(link);
509 return;
510 }
511 break;
03748142 512 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
3c9b8860
TG
513 r = dhcp_lease_acquired(client, link);
514 if (r < 0) {
515 link_enter_failed(link);
516 return;
517 }
518 break;
519 default:
520 if (event < 0)
f6b8196f 521 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
3c9b8860 522 else
f6b8196f 523 log_link_warning(link, "DHCP unknown event: %i", event);
3c9b8860
TG
524 break;
525 }
526
527 return;
528}
529
530int dhcp4_configure(Link *link) {
531 int r;
532
533 assert(link);
534 assert(link->network);
e0ee46f2 535 assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
3c9b8860 536
0bc70f1d
TG
537 if (!link->dhcp_client) {
538 r = sd_dhcp_client_new(&link->dhcp_client);
539 if (r < 0)
540 return r;
541 }
3c9b8860
TG
542
543 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
544 if (r < 0)
545 return r;
546
76253e73
DW
547 r = sd_dhcp_client_set_mac(link->dhcp_client,
548 (const uint8_t *) &link->mac,
549 sizeof (link->mac), ARPHRD_ETHER);
3c9b8860
TG
550 if (r < 0)
551 return r;
552
553 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
554 if (r < 0)
555 return r;
556
557 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
558 if (r < 0)
559 return r;
560
561 r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
562 link->network->dhcp_broadcast);
563 if (r < 0)
564 return r;
565
566 if (link->mtu) {
567 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
568 if (r < 0)
569 return r;
570 }
571
27cb34f5 572 if (link->network->dhcp_use_mtu) {
39745a5a 573 r = sd_dhcp_client_set_request_option(link->dhcp_client,
22805d92 574 SD_DHCP_OPTION_INTERFACE_MTU);
39745a5a
LP
575 if (r < 0)
576 return r;
3c9b8860
TG
577 }
578
27cb34f5 579 if (link->network->dhcp_use_routes) {
3c9b8860 580 r = sd_dhcp_client_set_request_option(link->dhcp_client,
22805d92 581 SD_DHCP_OPTION_STATIC_ROUTE);
3c9b8860
TG
582 if (r < 0)
583 return r;
584 r = sd_dhcp_client_set_request_option(link->dhcp_client,
22805d92 585 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
7d6884b6
TA
586 if (r < 0)
587 return r;
3c9b8860
TG
588 }
589
27cb34f5 590 /* Always acquire the timezone and NTP */
22805d92 591 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
4b7b5abb
LP
592 if (r < 0)
593 return r;
594
22805d92 595 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
8eb9058d
LP
596 if (r < 0)
597 return r;
598
27cb34f5 599 if (link->network->dhcp_send_hostname) {
3c9b8860 600 _cleanup_free_ char *hostname = NULL;
a7d0ef44
SS
601 const char *hn = NULL;
602
27cb34f5 603 if (!link->network->dhcp_hostname) {
a7d0ef44
SS
604 hostname = gethostname_malloc();
605 if (!hostname)
606 return -ENOMEM;
3c9b8860 607
a7d0ef44
SS
608 hn = hostname;
609 } else
27cb34f5 610 hn = link->network->dhcp_hostname;
3c9b8860 611
a7d0ef44
SS
612 if (!is_localhost(hn)) {
613 r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
3c9b8860
TG
614 if (r < 0)
615 return r;
616 }
617 }
618
619 if (link->network->dhcp_vendor_class_identifier) {
620 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
621 link->network->dhcp_vendor_class_identifier);
622 if (r < 0)
623 return r;
624 }
625
3e43b2cd
JJ
626 switch (link->network->dhcp_client_identifier) {
627 case DHCP_CLIENT_ID_DUID:
413708d1
VK
628 /* If configured, apply user specified DUID and/or IAID */
629 if (link->network->duid_type != _DUID_TYPE_INVALID)
630 r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
631 link->network->iaid,
632 link->network->dhcp_duid_type,
633 link->network->dhcp_duid,
634 link->network->dhcp_duid_len);
635 else
636 r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
637 link->network->iaid,
638 link->manager->dhcp_duid_type,
639 link->manager->dhcp_duid,
640 link->manager->dhcp_duid_len);
641 if (r < 0)
642 return r;
3e43b2cd
JJ
643 break;
644 case DHCP_CLIENT_ID_MAC:
645 r = sd_dhcp_client_set_client_id(link->dhcp_client,
646 ARPHRD_ETHER,
647 (const uint8_t *) &link->mac,
648 sizeof (link->mac));
649 if (r < 0)
650 return r;
651 break;
652 default:
653 assert_not_reached("Unknown client identifier type.");
654 }
655
3c9b8860
TG
656 return 0;
657}