]>
Commit | Line | Data |
---|---|---|
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 | |
41 | int 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 |
50 | int 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 |
59 | int 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 | ||
71 | int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, struct in_addr **addr, size_t *addr_size) { | |
72 | assert_return(lease, -EINVAL); | |
73 | assert_return(addr, -EINVAL); | |
74 | assert_return(addr_size, -EINVAL); | |
75 | ||
76 | if (lease->dns_size) { | |
77 | *addr_size = lease->dns_size; | |
78 | *addr = lease->dns; | |
79 | } else | |
80 | return -ENOENT; | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
46844696 TG |
85 | int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, struct in_addr **addr, size_t *addr_size) { |
86 | assert_return(lease, -EINVAL); | |
87 | assert_return(addr, -EINVAL); | |
88 | assert_return(addr_size, -EINVAL); | |
89 | ||
90 | if (lease->ntp_size) { | |
91 | *addr_size = lease->ntp_size; | |
92 | *addr = lease->ntp; | |
93 | } else | |
94 | return -ENOENT; | |
95 | ||
96 | return 0; | |
97 | } | |
98 | ||
a6cc569e TG |
99 | int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { |
100 | assert_return(lease, -EINVAL); | |
101 | assert_return(domainname, -EINVAL); | |
102 | ||
103 | if (lease->domainname) | |
104 | *domainname = lease->domainname; | |
105 | else | |
106 | return -ENOENT; | |
107 | ||
108 | return 0; | |
109 | } | |
110 | ||
111 | int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) { | |
112 | assert_return(lease, -EINVAL); | |
113 | assert_return(hostname, -EINVAL); | |
114 | ||
115 | if (lease->hostname) | |
116 | *hostname = lease->hostname; | |
117 | else | |
118 | return -ENOENT; | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
ce78df79 TG |
123 | int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) { |
124 | assert_return(lease, -EINVAL); | |
125 | assert_return(root_path, -EINVAL); | |
126 | ||
127 | if (lease->root_path) | |
128 | *root_path = lease->root_path; | |
129 | else | |
130 | return -ENOENT; | |
131 | ||
132 | return 0; | |
133 | } | |
134 | ||
a6cc569e TG |
135 | int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) { |
136 | assert_return(lease, -EINVAL); | |
137 | assert_return(addr, -EINVAL); | |
138 | ||
8ddbeaa2 UTL |
139 | if (lease->router != INADDR_ANY) |
140 | addr->s_addr = lease->router; | |
141 | else | |
142 | return -ENOENT; | |
a6cc569e TG |
143 | |
144 | return 0; | |
145 | } | |
146 | ||
147 | int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) { | |
148 | assert_return(lease, -EINVAL); | |
149 | assert_return(addr, -EINVAL); | |
150 | ||
151 | addr->s_addr = lease->subnet_mask; | |
152 | ||
153 | return 0; | |
154 | } | |
155 | ||
0ad853bc TG |
156 | int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) { |
157 | assert_return(lease, -EINVAL); | |
158 | assert_return(addr, -EINVAL); | |
159 | ||
160 | addr->s_addr = lease->server_address; | |
161 | ||
162 | return 0; | |
163 | } | |
164 | ||
8e34a618 TG |
165 | int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) { |
166 | assert_return(lease, -EINVAL); | |
167 | assert_return(addr, -EINVAL); | |
168 | ||
169 | addr->s_addr = lease->next_server; | |
170 | ||
171 | return 0; | |
172 | } | |
173 | ||
a6cc569e TG |
174 | sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) { |
175 | if (lease) | |
176 | assert_se(REFCNT_INC(lease->n_ref) >= 2); | |
177 | ||
178 | return lease; | |
179 | } | |
180 | ||
181 | sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { | |
182 | if (lease && REFCNT_DEC(lease->n_ref) <= 0) { | |
183 | free(lease->hostname); | |
184 | free(lease->domainname); | |
185 | free(lease->dns); | |
81d98a39 | 186 | free(lease->ntp); |
a6cc569e TG |
187 | free(lease); |
188 | } | |
189 | ||
190 | return NULL; | |
191 | } | |
192 | ||
e140ae58 TG |
193 | static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { |
194 | be32_t val; | |
195 | ||
196 | assert(option); | |
197 | assert(ret); | |
198 | ||
199 | if (len == 4) { | |
200 | memcpy(&val, option, 4); | |
201 | *ret = be32toh(val); | |
202 | ||
203 | if (*ret < min) | |
204 | *ret = min; | |
205 | } | |
206 | } | |
207 | ||
f5c0c00f TG |
208 | static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) { |
209 | lease_parse_u32(option, len, (uint32_t *)ret, 0); | |
210 | } | |
211 | ||
e140ae58 TG |
212 | static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { |
213 | be16_t val; | |
214 | ||
215 | assert(option); | |
216 | assert(ret); | |
217 | ||
218 | if (len == 2) { | |
219 | memcpy(&val, option, 2); | |
220 | *ret = be16toh(val); | |
221 | ||
222 | if (*ret < min) | |
223 | *ret = min; | |
224 | } | |
225 | } | |
226 | ||
227 | static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) { | |
228 | assert(option); | |
229 | assert(ret); | |
230 | ||
231 | if (len == 4) | |
232 | memcpy(ret, option, 4); | |
233 | } | |
234 | ||
f5c0c00f TG |
235 | static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) { |
236 | assert(option); | |
237 | assert(ret); | |
238 | ||
239 | if (len == 1) | |
240 | *ret = !!(*option); | |
241 | } | |
242 | ||
243 | static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) { | |
244 | assert(option); | |
245 | assert(ret); | |
246 | ||
247 | if (len == 1) { | |
248 | *ret = *option; | |
249 | ||
250 | if (*ret < min) | |
251 | *ret = min; | |
252 | } | |
253 | } | |
254 | ||
e140ae58 TG |
255 | static int lease_parse_string(const uint8_t *option, size_t len, char **ret) { |
256 | assert(option); | |
257 | assert(ret); | |
258 | ||
259 | if (len >= 1) { | |
260 | char *string; | |
261 | ||
262 | string = strndup((const char *)option, len); | |
263 | if (!string) | |
264 | return -errno; | |
265 | ||
266 | free(*ret); | |
267 | *ret = string; | |
268 | } | |
269 | ||
270 | return 0; | |
271 | } | |
272 | ||
f5c0c00f | 273 | static 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 |
274 | assert(option); |
275 | assert(ret); | |
276 | assert(ret_size); | |
277 | ||
f5c0c00f | 278 | if (len && !(len % (4 * mult))) { |
e140ae58 TG |
279 | size_t size; |
280 | struct in_addr *addresses; | |
281 | ||
282 | size = len / 4; | |
283 | ||
284 | addresses = newdup(struct in_addr, option, size); | |
285 | if (!addresses) | |
286 | return -ENOMEM; | |
287 | ||
288 | free(*ret); | |
289 | *ret = addresses; | |
290 | *ret_size = size; | |
291 | } | |
292 | ||
293 | return 0; | |
294 | } | |
295 | ||
f5c0c00f TG |
296 | static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) { |
297 | return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1); | |
298 | } | |
299 | ||
300 | static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) { | |
301 | return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2); | |
302 | } | |
303 | ||
a6cc569e TG |
304 | int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, |
305 | void *user_data) { | |
306 | sd_dhcp_lease *lease = user_data; | |
e140ae58 TG |
307 | int r; |
308 | ||
309 | assert(lease); | |
a6cc569e TG |
310 | |
311 | switch(code) { | |
312 | ||
f5c0c00f TG |
313 | case DHCP_OPTION_TIME_OFFSET: |
314 | lease_parse_s32(option, len, &lease->time_offset); | |
315 | ||
316 | break; | |
317 | ||
318 | case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT: | |
319 | lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0); | |
320 | ||
321 | break; | |
322 | ||
a6cc569e | 323 | case DHCP_OPTION_IP_ADDRESS_LEASE_TIME: |
e140ae58 | 324 | lease_parse_u32(option, len, &lease->lifetime, 1); |
a6cc569e TG |
325 | |
326 | break; | |
327 | ||
328 | case DHCP_OPTION_SERVER_IDENTIFIER: | |
e140ae58 | 329 | lease_parse_be32(option, len, &lease->server_address); |
a6cc569e TG |
330 | |
331 | break; | |
332 | ||
333 | case DHCP_OPTION_SUBNET_MASK: | |
e140ae58 | 334 | lease_parse_be32(option, len, &lease->subnet_mask); |
a6cc569e TG |
335 | |
336 | break; | |
337 | ||
f5c0c00f TG |
338 | case DHCP_OPTION_BROADCAST: |
339 | lease_parse_be32(option, len, &lease->broadcast); | |
340 | ||
341 | break; | |
342 | ||
a6cc569e | 343 | case DHCP_OPTION_ROUTER: |
e140ae58 | 344 | lease_parse_be32(option, len, &lease->router); |
a6cc569e TG |
345 | |
346 | break; | |
347 | ||
348 | case DHCP_OPTION_DOMAIN_NAME_SERVER: | |
e140ae58 TG |
349 | r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size); |
350 | if (r < 0) | |
351 | return r; | |
46844696 TG |
352 | |
353 | break; | |
354 | ||
355 | case DHCP_OPTION_NTP_SERVER: | |
e140ae58 TG |
356 | r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size); |
357 | if (r < 0) | |
358 | return r; | |
a6cc569e TG |
359 | |
360 | break; | |
361 | ||
f5c0c00f TG |
362 | case DHCP_OPTION_POLICY_FILTER: |
363 | r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size); | |
364 | if (r < 0) | |
365 | return r; | |
366 | ||
367 | break; | |
368 | ||
369 | case DHCP_OPTION_STATIC_ROUTE: | |
370 | r = lease_parse_in_addrs_pairs(option, len, &lease->static_route, &lease->static_route_size); | |
371 | if (r < 0) | |
372 | return r; | |
373 | ||
374 | break; | |
375 | ||
a6cc569e | 376 | case DHCP_OPTION_INTERFACE_MTU: |
e140ae58 | 377 | lease_parse_u16(option, len, &lease->mtu, 68); |
a6cc569e TG |
378 | |
379 | break; | |
380 | ||
f5c0c00f TG |
381 | case DHCP_OPTION_INTERFACE_MDR: |
382 | lease_parse_u16(option, len, &lease->mdr, 576); | |
383 | ||
384 | break; | |
385 | ||
386 | case DHCP_OPTION_INTERFACE_TTL: | |
387 | lease_parse_u8(option, len, &lease->ttl, 1); | |
388 | ||
389 | break; | |
390 | ||
391 | case DHCP_OPTION_BOOT_FILE_SIZE: | |
392 | lease_parse_u16(option, len, &lease->boot_file_size, 0); | |
393 | ||
394 | break; | |
395 | ||
a6cc569e | 396 | case DHCP_OPTION_DOMAIN_NAME: |
e140ae58 TG |
397 | r = lease_parse_string(option, len, &lease->domainname); |
398 | if (r < 0) | |
399 | return r; | |
a6cc569e TG |
400 | |
401 | break; | |
402 | ||
403 | case DHCP_OPTION_HOST_NAME: | |
e140ae58 TG |
404 | r = lease_parse_string(option, len, &lease->hostname); |
405 | if (r < 0) | |
406 | return r; | |
a6cc569e TG |
407 | |
408 | break; | |
409 | ||
ce78df79 | 410 | case DHCP_OPTION_ROOT_PATH: |
e140ae58 TG |
411 | r = lease_parse_string(option, len, &lease->root_path); |
412 | if (r < 0) | |
413 | return r; | |
ce78df79 TG |
414 | |
415 | break; | |
416 | ||
a6cc569e | 417 | case DHCP_OPTION_RENEWAL_T1_TIME: |
e140ae58 | 418 | lease_parse_u32(option, len, &lease->t1, 1); |
a6cc569e TG |
419 | |
420 | break; | |
421 | ||
422 | case DHCP_OPTION_REBINDING_T2_TIME: | |
e140ae58 | 423 | lease_parse_u32(option, len, &lease->t2, 1); |
a6cc569e | 424 | |
f5c0c00f TG |
425 | break; |
426 | ||
427 | case DHCP_OPTION_ENABLE_IP_FORWARDING: | |
428 | lease_parse_bool(option, len, &lease->ip_forward); | |
429 | ||
430 | break; | |
431 | ||
432 | case DHCP_OPTION_ENABLE_IP_FORWARDING_NL: | |
433 | lease_parse_bool(option, len, &lease->ip_forward_non_local); | |
434 | ||
a6cc569e TG |
435 | break; |
436 | } | |
437 | ||
438 | return 0; | |
439 | } | |
440 | ||
441 | int dhcp_lease_new(sd_dhcp_lease **ret) { | |
6e00a806 | 442 | sd_dhcp_lease *lease; |
a6cc569e TG |
443 | |
444 | lease = new0(sd_dhcp_lease, 1); | |
445 | if (!lease) | |
446 | return -ENOMEM; | |
447 | ||
8ddbeaa2 | 448 | lease->router = INADDR_ANY; |
a6cc569e TG |
449 | lease->n_ref = REFCNT_INIT; |
450 | ||
451 | *ret = lease; | |
a6cc569e TG |
452 | return 0; |
453 | } | |
fe8db0c5 TG |
454 | |
455 | int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { | |
456 | _cleanup_free_ char *temp_path = NULL; | |
457 | _cleanup_fclose_ FILE *f = NULL; | |
fe8db0c5 | 458 | struct in_addr address; |
109731eb TG |
459 | struct in_addr *addresses; |
460 | size_t addresses_size; | |
fe8db0c5 TG |
461 | const char *string; |
462 | uint16_t mtu; | |
463 | int r; | |
464 | ||
465 | assert(lease); | |
466 | assert(lease_file); | |
467 | ||
fe8db0c5 TG |
468 | r = fopen_temporary(lease_file, &f, &temp_path); |
469 | if (r < 0) | |
470 | goto finish; | |
471 | ||
472 | fchmod(fileno(f), 0644); | |
473 | ||
474 | r = sd_dhcp_lease_get_address(lease, &address); | |
475 | if (r < 0) | |
476 | goto finish; | |
477 | ||
fe8db0c5 TG |
478 | fprintf(f, |
479 | "# This is private data. Do not parse.\n" | |
109731eb | 480 | "ADDRESS=%s\n", inet_ntoa(address)); |
fe8db0c5 | 481 | |
fe8db0c5 TG |
482 | r = sd_dhcp_lease_get_netmask(lease, &address); |
483 | if (r < 0) | |
484 | goto finish; | |
485 | ||
109731eb | 486 | fprintf(f, "NETMASK=%s\n", inet_ntoa(address)); |
fe8db0c5 | 487 | |
8ddbeaa2 UTL |
488 | r = sd_dhcp_lease_get_router(lease, &address); |
489 | if (r >= 0) | |
490 | fprintf(f, "ROUTER=%s\n", inet_ntoa(address)); | |
491 | ||
0ad853bc | 492 | r = sd_dhcp_lease_get_server_identifier(lease, &address); |
109731eb TG |
493 | if (r >= 0) |
494 | fprintf(f, "SERVER_ADDRESS=%s\n", | |
495 | inet_ntoa(address)); | |
0ad853bc | 496 | |
8e34a618 | 497 | r = sd_dhcp_lease_get_next_server(lease, &address); |
109731eb TG |
498 | if (r >= 0) |
499 | fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address)); | |
8e34a618 | 500 | |
fe8db0c5 TG |
501 | r = sd_dhcp_lease_get_mtu(lease, &mtu); |
502 | if (r >= 0) | |
503 | fprintf(f, "MTU=%" PRIu16 "\n", mtu); | |
504 | ||
109731eb TG |
505 | r = sd_dhcp_lease_get_dns(lease, &addresses, &addresses_size); |
506 | if (r >= 0) | |
09bee74d | 507 | serialize_in_addrs(f, "DNS", addresses, addresses_size); |
109731eb TG |
508 | |
509 | r = sd_dhcp_lease_get_ntp(lease, &addresses, &addresses_size); | |
510 | if (r >= 0) | |
09bee74d | 511 | serialize_in_addrs(f, "NTP", addresses, addresses_size); |
fe8db0c5 TG |
512 | |
513 | r = sd_dhcp_lease_get_domainname(lease, &string); | |
514 | if (r >= 0) | |
515 | fprintf(f, "DOMAINNAME=%s\n", string); | |
516 | ||
517 | r = sd_dhcp_lease_get_hostname(lease, &string); | |
518 | if (r >= 0) | |
519 | fprintf(f, "HOSTNAME=%s\n", string); | |
520 | ||
ce78df79 TG |
521 | r = sd_dhcp_lease_get_root_path(lease, &string); |
522 | if (r >= 0) | |
523 | fprintf(f, "ROOT_PATH=%s\n", string); | |
524 | ||
fe8db0c5 TG |
525 | r = 0; |
526 | ||
527 | fflush(f); | |
528 | ||
529 | if (ferror(f) || rename(temp_path, lease_file) < 0) { | |
530 | r = -errno; | |
531 | unlink(lease_file); | |
532 | unlink(temp_path); | |
533 | } | |
534 | ||
535 | finish: | |
536 | if (r < 0) | |
537 | log_error("Failed to save lease data %s: %s", lease_file, strerror(-r)); | |
538 | ||
539 | return r; | |
540 | } | |
541 | ||
542 | int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) { | |
543 | _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL; | |
544 | _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL, | |
8e34a618 | 545 | *server_address = NULL, *next_server = NULL, |
109731eb | 546 | *dns = NULL, *ntp = NULL, *mtu = NULL; |
fe8db0c5 TG |
547 | struct in_addr addr; |
548 | int r; | |
549 | ||
550 | assert(lease_file); | |
551 | assert(ret); | |
552 | ||
553 | r = dhcp_lease_new(&lease); | |
554 | if (r < 0) | |
555 | return r; | |
556 | ||
557 | r = parse_env_file(lease_file, NEWLINE, | |
558 | "ADDRESS", &address, | |
559 | "ROUTER", &router, | |
560 | "NETMASK", &netmask, | |
0ad853bc | 561 | "SERVER_IDENTIFIER", &server_address, |
8e34a618 | 562 | "NEXT_SERVER", &next_server, |
109731eb TG |
563 | "DNS", &dns, |
564 | "NTP", &ntp, | |
fe8db0c5 TG |
565 | "MTU", &mtu, |
566 | "DOMAINNAME", &lease->domainname, | |
567 | "HOSTNAME", &lease->hostname, | |
ce78df79 | 568 | "ROOT_PATH", &lease->root_path, |
fe8db0c5 TG |
569 | NULL); |
570 | if (r < 0) { | |
571 | if (r == -ENOENT) | |
572 | return 0; | |
573 | ||
574 | log_error("Failed to read %s: %s", lease_file, strerror(-r)); | |
575 | return r; | |
576 | } | |
577 | ||
578 | r = inet_pton(AF_INET, address, &addr); | |
579 | if (r < 0) | |
580 | return r; | |
581 | ||
582 | lease->address = addr.s_addr; | |
583 | ||
8ddbeaa2 UTL |
584 | if (router) { |
585 | r = inet_pton(AF_INET, router, &addr); | |
586 | if (r < 0) | |
587 | return r; | |
fe8db0c5 | 588 | |
8ddbeaa2 UTL |
589 | lease->router = addr.s_addr; |
590 | } | |
fe8db0c5 TG |
591 | |
592 | r = inet_pton(AF_INET, netmask, &addr); | |
593 | if (r < 0) | |
594 | return r; | |
595 | ||
596 | lease->subnet_mask = addr.s_addr; | |
597 | ||
0ad853bc TG |
598 | if (server_address) { |
599 | r = inet_pton(AF_INET, server_address, &addr); | |
600 | if (r < 0) | |
601 | return r; | |
602 | ||
603 | lease->server_address = addr.s_addr; | |
604 | } | |
605 | ||
8e34a618 TG |
606 | if (next_server) { |
607 | r = inet_pton(AF_INET, next_server, &addr); | |
608 | if (r < 0) | |
609 | return r; | |
610 | ||
611 | lease->next_server = addr.s_addr; | |
612 | } | |
613 | ||
109731eb | 614 | if (dns) { |
09bee74d | 615 | r = deserialize_in_addrs(&lease->dns, &lease->dns_size, dns); |
109731eb TG |
616 | if (r < 0) |
617 | return r; | |
618 | } | |
619 | ||
620 | if (ntp) { | |
09bee74d | 621 | r = deserialize_in_addrs(&lease->ntp, &lease->ntp_size, dns); |
109731eb TG |
622 | if (r < 0) |
623 | return r; | |
624 | } | |
625 | ||
fe8db0c5 TG |
626 | if (mtu) { |
627 | uint16_t u; | |
628 | if (sscanf(mtu, "%" SCNu16, &u) > 0) | |
629 | lease->mtu = u; | |
630 | } | |
631 | ||
632 | *ret = lease; | |
633 | lease = NULL; | |
634 | ||
635 | return 0; | |
636 | } | |
9e64dd72 TG |
637 | |
638 | int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) { | |
639 | uint32_t address; | |
640 | ||
641 | assert(lease); | |
642 | assert(lease->address != INADDR_ANY); | |
643 | ||
644 | address = be32toh(lease->address); | |
645 | ||
646 | /* fall back to the default subnet masks based on address class */ | |
647 | ||
648 | if ((address >> 31) == 0x0) | |
649 | /* class A, leading bits: 0 */ | |
650 | lease->subnet_mask = htobe32(0xff000000); | |
651 | else if ((address >> 30) == 0x2) | |
652 | /* class B, leading bits 10 */ | |
653 | lease->subnet_mask = htobe32(0xffff0000); | |
654 | else if ((address >> 29) == 0x6) | |
655 | /* class C, leading bits 110 */ | |
656 | lease->subnet_mask = htobe32(0xffffff00); | |
657 | else | |
658 | /* class D or E, no default mask. give up */ | |
659 | return -ERANGE; | |
660 | ||
661 | return 0; | |
662 | } |