]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/sd-dhcp-lease.c
resolved: pull in domain names from sd-network
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-lease.c
CommitLineData
a6cc569e
TG
1/***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
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 <stdlib.h>
22#include <errno.h>
23#include <string.h>
24#include <stdio.h>
25#include <net/ethernet.h>
fe8db0c5 26#include <arpa/inet.h>
a6cc569e
TG
27#include <sys/param.h>
28
29#include "util.h"
30#include "list.h"
fe8db0c5
TG
31#include "mkdir.h"
32#include "fileio.h"
a6cc569e
TG
33
34#include "dhcp-protocol.h"
35#include "dhcp-internal.h"
fe8db0c5
TG
36#include "dhcp-lease-internal.h"
37#include "sd-dhcp-lease.h"
a6cc569e 38#include "sd-dhcp-client.h"
09bee74d 39#include "network-internal.h"
a6cc569e
TG
40
41int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
42 assert_return(lease, -EINVAL);
43 assert_return(addr, -EINVAL);
44
45 addr->s_addr = lease->address;
46
47 return 0;
48}
49
68ceb9df
PF
50int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
51 assert_return(lease, -EINVAL);
52 assert_return(lease, -EINVAL);
53
54 *lifetime = lease->lifetime;
55
56 return 0;
57}
58
a6cc569e
TG
59int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
60 assert_return(lease, -EINVAL);
61 assert_return(mtu, -EINVAL);
62
63 if (lease->mtu)
64 *mtu = lease->mtu;
65 else
66 return -ENOENT;
67
68 return 0;
69}
70
a2ba62c7 71int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
a6cc569e
TG
72 assert_return(lease, -EINVAL);
73 assert_return(addr, -EINVAL);
a6cc569e
TG
74
75 if (lease->dns_size) {
a6cc569e 76 *addr = lease->dns;
a2ba62c7 77 return lease->dns_size;
a6cc569e
TG
78 } else
79 return -ENOENT;
80
81 return 0;
82}
83
a2ba62c7 84int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
46844696
TG
85 assert_return(lease, -EINVAL);
86 assert_return(addr, -EINVAL);
46844696
TG
87
88 if (lease->ntp_size) {
46844696 89 *addr = lease->ntp;
a2ba62c7 90 return lease->ntp_size;
46844696
TG
91 } else
92 return -ENOENT;
93
94 return 0;
95}
96
a6cc569e
TG
97int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
98 assert_return(lease, -EINVAL);
99 assert_return(domainname, -EINVAL);
100
101 if (lease->domainname)
102 *domainname = lease->domainname;
103 else
104 return -ENOENT;
105
106 return 0;
107}
108
109int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
110 assert_return(lease, -EINVAL);
111 assert_return(hostname, -EINVAL);
112
113 if (lease->hostname)
114 *hostname = lease->hostname;
115 else
116 return -ENOENT;
117
118 return 0;
119}
120
ce78df79
TG
121int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
122 assert_return(lease, -EINVAL);
123 assert_return(root_path, -EINVAL);
124
125 if (lease->root_path)
126 *root_path = lease->root_path;
127 else
128 return -ENOENT;
129
130 return 0;
131}
132
a6cc569e
TG
133int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
134 assert_return(lease, -EINVAL);
135 assert_return(addr, -EINVAL);
136
8ddbeaa2
UTL
137 if (lease->router != INADDR_ANY)
138 addr->s_addr = lease->router;
139 else
140 return -ENOENT;
a6cc569e
TG
141
142 return 0;
143}
144
145int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
146 assert_return(lease, -EINVAL);
147 assert_return(addr, -EINVAL);
148
149 addr->s_addr = lease->subnet_mask;
150
151 return 0;
152}
153
0ad853bc
TG
154int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) {
155 assert_return(lease, -EINVAL);
156 assert_return(addr, -EINVAL);
157
158 addr->s_addr = lease->server_address;
159
160 return 0;
161}
162
8e34a618
TG
163int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
164 assert_return(lease, -EINVAL);
165 assert_return(addr, -EINVAL);
166
167 addr->s_addr = lease->next_server;
168
169 return 0;
170}
171
a2ba62c7 172int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
e1ea665e
EY
173
174 assert_return(lease, -EINVAL);
175 assert_return(routes, -EINVAL);
e1ea665e
EY
176
177 if (lease->static_route_size) {
178 *routes = lease->static_route;
a2ba62c7 179 return lease->static_route_size;
e1ea665e
EY
180 } else
181 return -ENOENT;
182
183 return 0;
184}
185
a6cc569e
TG
186sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
187 if (lease)
188 assert_se(REFCNT_INC(lease->n_ref) >= 2);
189
190 return lease;
191}
192
193sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
194 if (lease && REFCNT_DEC(lease->n_ref) <= 0) {
195 free(lease->hostname);
196 free(lease->domainname);
197 free(lease->dns);
81d98a39 198 free(lease->ntp);
e1ea665e 199 free(lease->static_route);
a6cc569e
TG
200 free(lease);
201 }
202
203 return NULL;
204}
205
e140ae58
TG
206static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
207 be32_t val;
208
209 assert(option);
210 assert(ret);
211
212 if (len == 4) {
213 memcpy(&val, option, 4);
214 *ret = be32toh(val);
215
216 if (*ret < min)
217 *ret = min;
218 }
219}
220
f5c0c00f
TG
221static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) {
222 lease_parse_u32(option, len, (uint32_t *)ret, 0);
223}
224
e140ae58
TG
225static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
226 be16_t val;
227
228 assert(option);
229 assert(ret);
230
231 if (len == 2) {
232 memcpy(&val, option, 2);
233 *ret = be16toh(val);
234
235 if (*ret < min)
236 *ret = min;
237 }
238}
239
240static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
241 assert(option);
242 assert(ret);
243
244 if (len == 4)
245 memcpy(ret, option, 4);
246}
247
f5c0c00f
TG
248static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) {
249 assert(option);
250 assert(ret);
251
252 if (len == 1)
253 *ret = !!(*option);
254}
255
256static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) {
257 assert(option);
258 assert(ret);
259
260 if (len == 1) {
261 *ret = *option;
262
263 if (*ret < min)
264 *ret = min;
265 }
266}
267
e140ae58
TG
268static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
269 assert(option);
270 assert(ret);
271
272 if (len >= 1) {
273 char *string;
274
275 string = strndup((const char *)option, len);
276 if (!string)
277 return -errno;
278
279 free(*ret);
280 *ret = string;
281 }
282
283 return 0;
284}
285
f5c0c00f 286static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) {
e140ae58
TG
287 assert(option);
288 assert(ret);
289 assert(ret_size);
290
f5c0c00f 291 if (len && !(len % (4 * mult))) {
e140ae58
TG
292 size_t size;
293 struct in_addr *addresses;
294
295 size = len / 4;
296
297 addresses = newdup(struct in_addr, option, size);
298 if (!addresses)
299 return -ENOMEM;
300
301 free(*ret);
302 *ret = addresses;
303 *ret_size = size;
304 }
305
306 return 0;
307}
308
f5c0c00f
TG
309static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
310 return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1);
311}
312
313static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
314 return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2);
315}
316
e1ea665e
EY
317static int class_prefixlen(uint8_t msb_octet, uint8_t *ret) {
318 if (msb_octet < 128)
319 /* Class A */
320 *ret = 8;
321 else if (msb_octet < 192)
322 /* Class B */
323 *ret = 16;
324 else if (msb_octet < 224)
325 /* Class C */
326 *ret = 24;
327 else
328 /* Class D or E -- no subnet mask */
329 return -ERANGE;
330
331 return 0;
332}
333
334static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
335 size_t *routes_size, size_t *routes_allocated) {
336
337 struct in_addr addr;
338
339 assert(option);
340 assert(routes);
341 assert(routes_size);
342 assert(routes_allocated);
343
344 if (!len)
345 return 0;
346
347 if (len % 8 != 0)
348 return -EINVAL;
349
350 if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8)))
351 return -ENOMEM;
352
353 while (len >= 8) {
354 struct sd_dhcp_route *route = *routes + *routes_size;
355
356 if (class_prefixlen(*option, &route->dst_prefixlen) < 0) {
357 log_error("Failed to determine destination prefix length from class based IP, ignoring");
358 continue;
359 }
360
361 lease_parse_be32(option, 4, &addr.s_addr);
362 route->dst_addr = inet_makeaddr(inet_netof(addr), 0);
363 option += 4;
364
365 lease_parse_be32(option, 4, &route->gw_addr.s_addr);
366 option += 4;
367
368 len -= 8;
369 (*routes_size)++;
370 }
371
372 return 0;
373}
374
375/* parses RFC3442 Classless Static Route Option */
376static int lease_parse_classless_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
377 size_t *routes_size, size_t *routes_allocated) {
378
379 assert(option);
380 assert(routes);
381 assert(routes_size);
382 assert(routes_allocated);
383
384 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
385
386 while (len > 0) {
387 uint8_t dst_octets;
388 struct sd_dhcp_route *route;
389
390 if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1))
391 return -ENOMEM;
392
393 route = *routes + *routes_size;
394
395 dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1);
396 route->dst_prefixlen = *option;
397 option++;
398 len--;
399
400 /* can't have more than 4 octets in IPv4 */
401 if (dst_octets > 4 || len < dst_octets)
402 return -EINVAL;
403
404 route->dst_addr.s_addr = 0;
405 memcpy(&route->dst_addr.s_addr, option, dst_octets);
406 option += dst_octets;
407 len -= dst_octets;
408
409 if (len < 4)
410 return -EINVAL;
411
412 lease_parse_be32(option, 4, &route->gw_addr.s_addr);
413 option += 4;
414 len -= 4;
415
416 (*routes_size)++;
417 }
418
419 return 0;
420}
421
a6cc569e
TG
422int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
423 void *user_data) {
424 sd_dhcp_lease *lease = user_data;
e140ae58
TG
425 int r;
426
427 assert(lease);
a6cc569e
TG
428
429 switch(code) {
430
f5c0c00f
TG
431 case DHCP_OPTION_TIME_OFFSET:
432 lease_parse_s32(option, len, &lease->time_offset);
433
434 break;
435
436 case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT:
437 lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0);
438
439 break;
440
a6cc569e 441 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
e140ae58 442 lease_parse_u32(option, len, &lease->lifetime, 1);
a6cc569e
TG
443
444 break;
445
446 case DHCP_OPTION_SERVER_IDENTIFIER:
e140ae58 447 lease_parse_be32(option, len, &lease->server_address);
a6cc569e
TG
448
449 break;
450
451 case DHCP_OPTION_SUBNET_MASK:
e140ae58 452 lease_parse_be32(option, len, &lease->subnet_mask);
a6cc569e
TG
453
454 break;
455
f5c0c00f
TG
456 case DHCP_OPTION_BROADCAST:
457 lease_parse_be32(option, len, &lease->broadcast);
458
459 break;
460
a6cc569e 461 case DHCP_OPTION_ROUTER:
e140ae58 462 lease_parse_be32(option, len, &lease->router);
a6cc569e
TG
463
464 break;
465
466 case DHCP_OPTION_DOMAIN_NAME_SERVER:
e140ae58
TG
467 r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
468 if (r < 0)
469 return r;
46844696
TG
470
471 break;
472
473 case DHCP_OPTION_NTP_SERVER:
e140ae58
TG
474 r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
475 if (r < 0)
476 return r;
a6cc569e
TG
477
478 break;
479
f5c0c00f
TG
480 case DHCP_OPTION_POLICY_FILTER:
481 r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size);
482 if (r < 0)
483 return r;
484
485 break;
486
487 case DHCP_OPTION_STATIC_ROUTE:
e1ea665e
EY
488 r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size,
489 &lease->static_route_allocated);
f5c0c00f
TG
490 if (r < 0)
491 return r;
492
493 break;
494
a6cc569e 495 case DHCP_OPTION_INTERFACE_MTU:
e140ae58 496 lease_parse_u16(option, len, &lease->mtu, 68);
a6cc569e
TG
497
498 break;
499
f5c0c00f
TG
500 case DHCP_OPTION_INTERFACE_MDR:
501 lease_parse_u16(option, len, &lease->mdr, 576);
502
503 break;
504
505 case DHCP_OPTION_INTERFACE_TTL:
506 lease_parse_u8(option, len, &lease->ttl, 1);
507
508 break;
509
510 case DHCP_OPTION_BOOT_FILE_SIZE:
511 lease_parse_u16(option, len, &lease->boot_file_size, 0);
512
513 break;
514
a6cc569e 515 case DHCP_OPTION_DOMAIN_NAME:
e140ae58
TG
516 r = lease_parse_string(option, len, &lease->domainname);
517 if (r < 0)
518 return r;
a6cc569e
TG
519
520 break;
521
522 case DHCP_OPTION_HOST_NAME:
e140ae58
TG
523 r = lease_parse_string(option, len, &lease->hostname);
524 if (r < 0)
525 return r;
a6cc569e
TG
526
527 break;
528
ce78df79 529 case DHCP_OPTION_ROOT_PATH:
e140ae58
TG
530 r = lease_parse_string(option, len, &lease->root_path);
531 if (r < 0)
532 return r;
ce78df79
TG
533
534 break;
535
a6cc569e 536 case DHCP_OPTION_RENEWAL_T1_TIME:
e140ae58 537 lease_parse_u32(option, len, &lease->t1, 1);
a6cc569e
TG
538
539 break;
540
541 case DHCP_OPTION_REBINDING_T2_TIME:
e140ae58 542 lease_parse_u32(option, len, &lease->t2, 1);
a6cc569e 543
f5c0c00f
TG
544 break;
545
546 case DHCP_OPTION_ENABLE_IP_FORWARDING:
547 lease_parse_bool(option, len, &lease->ip_forward);
548
549 break;
550
551 case DHCP_OPTION_ENABLE_IP_FORWARDING_NL:
552 lease_parse_bool(option, len, &lease->ip_forward_non_local);
553
a6cc569e 554 break;
e1ea665e
EY
555
556 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
557 r = lease_parse_classless_routes(option, len, &lease->static_route, &lease->static_route_size,
558 &lease->static_route_allocated);
559 if (r < 0)
560 return r;
561
562 break;
a6cc569e
TG
563 }
564
565 return 0;
566}
567
568int dhcp_lease_new(sd_dhcp_lease **ret) {
6e00a806 569 sd_dhcp_lease *lease;
a6cc569e
TG
570
571 lease = new0(sd_dhcp_lease, 1);
572 if (!lease)
573 return -ENOMEM;
574
8ddbeaa2 575 lease->router = INADDR_ANY;
a6cc569e
TG
576 lease->n_ref = REFCNT_INIT;
577
578 *ret = lease;
a6cc569e
TG
579 return 0;
580}
fe8db0c5
TG
581
582int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
583 _cleanup_free_ char *temp_path = NULL;
584 _cleanup_fclose_ FILE *f = NULL;
fe8db0c5 585 struct in_addr address;
a2ba62c7 586 const struct in_addr *addresses;
fe8db0c5
TG
587 const char *string;
588 uint16_t mtu;
e1ea665e 589 struct sd_dhcp_route *routes;
fe8db0c5
TG
590 int r;
591
592 assert(lease);
593 assert(lease_file);
594
fe8db0c5
TG
595 r = fopen_temporary(lease_file, &f, &temp_path);
596 if (r < 0)
597 goto finish;
598
599 fchmod(fileno(f), 0644);
600
601 r = sd_dhcp_lease_get_address(lease, &address);
602 if (r < 0)
603 goto finish;
604
fe8db0c5
TG
605 fprintf(f,
606 "# This is private data. Do not parse.\n"
109731eb 607 "ADDRESS=%s\n", inet_ntoa(address));
fe8db0c5 608
fe8db0c5
TG
609 r = sd_dhcp_lease_get_netmask(lease, &address);
610 if (r < 0)
611 goto finish;
612
109731eb 613 fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
fe8db0c5 614
8ddbeaa2
UTL
615 r = sd_dhcp_lease_get_router(lease, &address);
616 if (r >= 0)
617 fprintf(f, "ROUTER=%s\n", inet_ntoa(address));
618
0ad853bc 619 r = sd_dhcp_lease_get_server_identifier(lease, &address);
109731eb
TG
620 if (r >= 0)
621 fprintf(f, "SERVER_ADDRESS=%s\n",
622 inet_ntoa(address));
0ad853bc 623
8e34a618 624 r = sd_dhcp_lease_get_next_server(lease, &address);
109731eb
TG
625 if (r >= 0)
626 fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address));
8e34a618 627
fe8db0c5
TG
628 r = sd_dhcp_lease_get_mtu(lease, &mtu);
629 if (r >= 0)
630 fprintf(f, "MTU=%" PRIu16 "\n", mtu);
631
b0e39c82 632 fputs("DNS=", f);
a2ba62c7 633 r = sd_dhcp_lease_get_dns(lease, &addresses);
109731eb 634 if (r >= 0)
b0e39c82
TG
635 serialize_in_addrs(f, addresses, r);
636 fputs("\n", f);
109731eb 637
b0e39c82 638 fputs("NTP=", f);
a2ba62c7 639 r = sd_dhcp_lease_get_ntp(lease, &addresses);
109731eb 640 if (r >= 0)
b0e39c82
TG
641 serialize_in_addrs(f, addresses, r);
642 fputs("\n", f);
fe8db0c5
TG
643
644 r = sd_dhcp_lease_get_domainname(lease, &string);
645 if (r >= 0)
646 fprintf(f, "DOMAINNAME=%s\n", string);
647
648 r = sd_dhcp_lease_get_hostname(lease, &string);
649 if (r >= 0)
650 fprintf(f, "HOSTNAME=%s\n", string);
651
ce78df79
TG
652 r = sd_dhcp_lease_get_root_path(lease, &string);
653 if (r >= 0)
654 fprintf(f, "ROOT_PATH=%s\n", string);
655
a2ba62c7 656 r = sd_dhcp_lease_get_routes(lease, &routes);
e1ea665e 657 if (r >= 0)
a2ba62c7 658 serialize_dhcp_routes(f, "ROUTES", routes, r);
e1ea665e 659
fe8db0c5
TG
660 r = 0;
661
662 fflush(f);
663
664 if (ferror(f) || rename(temp_path, lease_file) < 0) {
665 r = -errno;
666 unlink(lease_file);
667 unlink(temp_path);
668 }
669
670finish:
671 if (r < 0)
672 log_error("Failed to save lease data %s: %s", lease_file, strerror(-r));
673
674 return r;
675}
676
677int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) {
678 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
679 _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL,
8e34a618 680 *server_address = NULL, *next_server = NULL,
e1ea665e 681 *dns = NULL, *ntp = NULL, *mtu = NULL, *routes = NULL;
fe8db0c5
TG
682 struct in_addr addr;
683 int r;
684
685 assert(lease_file);
686 assert(ret);
687
688 r = dhcp_lease_new(&lease);
689 if (r < 0)
690 return r;
691
692 r = parse_env_file(lease_file, NEWLINE,
693 "ADDRESS", &address,
694 "ROUTER", &router,
695 "NETMASK", &netmask,
0ad853bc 696 "SERVER_IDENTIFIER", &server_address,
8e34a618 697 "NEXT_SERVER", &next_server,
109731eb
TG
698 "DNS", &dns,
699 "NTP", &ntp,
fe8db0c5
TG
700 "MTU", &mtu,
701 "DOMAINNAME", &lease->domainname,
702 "HOSTNAME", &lease->hostname,
ce78df79 703 "ROOT_PATH", &lease->root_path,
e1ea665e 704 "ROUTES", &routes,
fe8db0c5
TG
705 NULL);
706 if (r < 0) {
707 if (r == -ENOENT)
708 return 0;
709
710 log_error("Failed to read %s: %s", lease_file, strerror(-r));
711 return r;
712 }
713
714 r = inet_pton(AF_INET, address, &addr);
715 if (r < 0)
716 return r;
717
718 lease->address = addr.s_addr;
719
8ddbeaa2
UTL
720 if (router) {
721 r = inet_pton(AF_INET, router, &addr);
722 if (r < 0)
723 return r;
fe8db0c5 724
8ddbeaa2
UTL
725 lease->router = addr.s_addr;
726 }
fe8db0c5
TG
727
728 r = inet_pton(AF_INET, netmask, &addr);
729 if (r < 0)
730 return r;
731
732 lease->subnet_mask = addr.s_addr;
733
0ad853bc
TG
734 if (server_address) {
735 r = inet_pton(AF_INET, server_address, &addr);
736 if (r < 0)
737 return r;
738
739 lease->server_address = addr.s_addr;
740 }
741
8e34a618
TG
742 if (next_server) {
743 r = inet_pton(AF_INET, next_server, &addr);
744 if (r < 0)
745 return r;
746
747 lease->next_server = addr.s_addr;
748 }
749
109731eb 750 if (dns) {
a2ba62c7 751 r = deserialize_in_addrs(&lease->dns, dns);
109731eb
TG
752 if (r < 0)
753 return r;
a2ba62c7
LP
754
755 lease->dns_size = r;
109731eb
TG
756 }
757
758 if (ntp) {
a2ba62c7 759 r = deserialize_in_addrs(&lease->ntp, ntp);
109731eb
TG
760 if (r < 0)
761 return r;
a2ba62c7
LP
762
763 lease->ntp_size = r;
109731eb
TG
764 }
765
fe8db0c5
TG
766 if (mtu) {
767 uint16_t u;
768 if (sscanf(mtu, "%" SCNu16, &u) > 0)
769 lease->mtu = u;
770 }
771
e1ea665e
EY
772 if (routes) {
773 r = deserialize_dhcp_routes(&lease->static_route, &lease->static_route_size,
774 &lease->static_route_allocated, routes);
775 if (r < 0)
776 return r;
777 }
778
fe8db0c5
TG
779 *ret = lease;
780 lease = NULL;
781
782 return 0;
783}
9e64dd72
TG
784
785int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
786 uint32_t address;
787
788 assert(lease);
789 assert(lease->address != INADDR_ANY);
790
791 address = be32toh(lease->address);
792
793 /* fall back to the default subnet masks based on address class */
794
795 if ((address >> 31) == 0x0)
796 /* class A, leading bits: 0 */
797 lease->subnet_mask = htobe32(0xff000000);
798 else if ((address >> 30) == 0x2)
799 /* class B, leading bits 10 */
800 lease->subnet_mask = htobe32(0xffff0000);
801 else if ((address >> 29) == 0x6)
802 /* class C, leading bits 110 */
803 lease->subnet_mask = htobe32(0xffffff00);
804 else
805 /* class D or E, no default mask. give up */
806 return -ERANGE;
807
808 return 0;
809}