1 /*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <ctype.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <syslog.h>
34 #include <unistd.h>
35
36 #include "config.h"
37 #include "common.h"
38 #include "dhcp.h"
39
40 #define REQUEST (1 << 0)
41 #define UINT8 (1 << 1)
42 #define UINT16 (1 << 2)
43 #define SINT16 (1 << 3)
44 #define UINT32 (1 << 4)
45 #define SINT32 (1 << 5)
46 #define IPV4 (1 << 6)
47 #define STRING (1 << 7)
48 #define PAIR (1 << 8)
49 #define ARRAY (1 << 9)
50 #define RFC3361 (1 << 10)
51 #define RFC3397 (1 << 11)
52 #define RFC3442 (1 << 12)
53 #define RFC5969 (1 << 13)
54
55 #define IPV4R IPV4 | REQUEST
56
57 #define DAD "Duplicate address detected"
58
59 /* Our aggregate option buffer.
60 * We ONLY use this when options are split, which for most purposes is
61 * practically never. See RFC3396 for details. */
62 static uint8_t *opt_buffer;
63
64 struct dhcp_opt {
65 uint8_t option;
66 int type;
67 const char *var;
68 };
69
70 static const struct dhcp_opt const dhcp_opts[] = {
71 { 1, IPV4 | REQUEST, "subnet_mask" },
72 /* RFC 3442 states that the CSR has to come before all other
73 * routes. For completeness, we also specify static routes,
74 * then routers. */
75 { 121, RFC3442, "classless_static_routes" },
76 { 249, RFC3442, "ms_classless_static_routes" },
77 { 33, IPV4 | ARRAY | REQUEST, "static_routes" },
78 { 3, IPV4 | ARRAY | REQUEST, "routers" },
79 { 2, UINT32, "time_offset" },
80 { 4, IPV4 | ARRAY, "time_servers" },
81 { 5, IPV4 | ARRAY, "ien116_name_servers" },
82 /* Explicitly include DNS in the list of parameters requested in the DNS request.
83 * Without this some DHCP servers may skip the DNS entries in the DHCP replies.*/
84 { 6, IPV4 | ARRAY | REQUEST, "domain_name_servers" },
85 { 7, IPV4 | ARRAY, "log_servers" },
86 { 8, IPV4 | ARRAY, "cookie_servers" },
87 { 9, IPV4 | ARRAY, "lpr_servers" },
88 { 10, IPV4 | ARRAY, "impress_servers" },
89 { 11, IPV4 | ARRAY, "resource_location_servers" },
90 { 12, STRING, "host_name" },
91 { 13, UINT16, "boot_size" },
92 { 14, STRING, "merit_dump" },
93 /* Explicitly include DNS in the list of parameters requested in the DNS request.
94 * Without this some DHCP servers may skip the DNS entries in the DHCP replies.*/
95 { 15, STRING | REQUEST, "domain_name" },
96 { 16, IPV4, "swap_server" },
97 { 17, STRING, "root_path" },
98 { 18, STRING, "extensions_path" },
99 { 19, UINT8, "ip_forwarding" },
100 { 20, UINT8, "non_local_source_routing" },
101 { 21, IPV4 | ARRAY, "policy_filter" },
102 { 22, SINT16, "max_dgram_reassembly" },
103 { 23, UINT16, "default_ip_ttl" },
104 { 24, UINT32, "path_mtu_aging_timeout" },
105 { 25, UINT16 | ARRAY, "path_mtu_plateau_table" },
106 { 26, UINT16, "interface_mtu" },
107 { 27, UINT8, "all_subnets_local" },
108 { 28, IPV4 | REQUEST, "broadcast_address" },
109 { 29, UINT8, "perform_mask_discovery" },
110 { 30, UINT8, "mask_supplier" },
111 { 31, UINT8, "router_discovery" },
112 { 32, IPV4, "router_solicitation_address" },
113 { 34, UINT8, "trailer_encapsulation" },
114 { 35, UINT32, "arp_cache_timeout" },
115 { 36, UINT16, "ieee802_3_encapsulation" },
116 { 37, UINT8, "default_tcp_ttl" },
117 { 38, UINT32, "tcp_keepalive_interval" },
118 { 39, UINT8, "tcp_keepalive_garbage" },
119 { 40, STRING, "nis_domain" },
120 { 41, IPV4 | ARRAY, "nis_servers" },
121 { 42, IPV4 | ARRAY, "ntp_servers" },
122 { 43, STRING, "vendor_encapsulated_options" },
123 { 44, IPV4 | ARRAY, "netbios_name_servers" },
124 { 45, IPV4, "netbios_dd_server" },
125 { 46, UINT8, "netbios_node_type" },
126 { 47, STRING, "netbios_scope" },
127 { 48, IPV4 | ARRAY, "font_servers" },
128 { 49, IPV4 | ARRAY, "x_display_manager" },
129 { 50, IPV4, "dhcp_requested_address" },
130 { 51, UINT32 | REQUEST, "dhcp_lease_time" },
131 { 52, UINT8, "dhcp_option_overload" },
132 { 53, UINT8, "dhcp_message_type" },
133 { 54, IPV4, "dhcp_server_identifier" },
134 { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" },
135 { 56, STRING, "dhcp_message" },
136 { 57, UINT16, "dhcp_max_message_size" },
137 { 58, UINT32 | REQUEST, "dhcp_renewal_time" },
138 { 59, UINT32 | REQUEST, "dhcp_rebinding_time" },
139 { 64, STRING, "nisplus_domain" },
140 { 65, IPV4 | ARRAY, "nisplus_servers" },
141 { 66, STRING, "tftp_server_name" },
142 { 67, STRING, "bootfile_name" },
143 { 68, IPV4 | ARRAY, "mobile_ip_home_agent" },
144 { 69, IPV4 | ARRAY, "smtp_server" },
145 { 70, IPV4 | ARRAY, "pop_server" },
146 { 71, IPV4 | ARRAY, "nntp_server" },
147 { 72, IPV4 | ARRAY, "www_server" },
148 { 73, IPV4 | ARRAY, "finger_server" },
149 { 74, IPV4 | ARRAY, "irc_server" },
150 { 75, IPV4 | ARRAY, "streettalk_server" },
151 { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" },
152 { 77, STRING, "user_class" },
153 { 81, STRING | RFC3397, "fqdn_name" },
154 { 85, IPV4 | ARRAY, "nds_servers" },
155 { 86, STRING, "nds_tree_name" },
156 { 87, STRING, "nds_context" },
157 { 88, STRING | RFC3397, "bcms_controller_names" },
158 { 89, IPV4 | ARRAY, "bcms_controller_address" },
159 { 91, UINT32, "client_last_transaction_time" },
160 { 92, IPV4 | ARRAY, "associated_ip" },
161 { 98, STRING, "uap_servers" },
162 { 112, IPV4 | ARRAY, "netinfo_server_address" },
163 { 113, STRING, "netinfo_server_tag" },
164 { 114, STRING, "default_url" },
165 { 118, IPV4, "subnet_selection" },
166 { 119, STRING | RFC3397, "domain_search" },
167 { 120, STRING | RFC3361, "sip_server" },
168 { 212, RFC5969, "sixrd" },
169 { 0, 0, NULL }
170 };
171
172 static const char *if_params[] = {
173 "interface",
174 "reason",
175 "pid",
176 "ifmetric",
177 "ifwireless",
178 "ifflags",
179 "profile",
180 "interface_order",
181 NULL
182 };
183
184 static const char *dhcp_params[] = {
185 "ip_address",
186 "subnet_cidr",
187 "network_number",
188 "ssid",
189 "filename",
190 "server_name",
191 NULL
192 };
193
194 void
print_options(void)195 print_options(void)
196 {
197 const struct dhcp_opt *opt;
198 const char **p;
199
200 for (p = if_params; *p; p++)
201 printf(" - %s\n", *p);
202
203 for (p = dhcp_params; *p; p++)
204 printf(" %s\n", *p);
205
206 for (opt = dhcp_opts; opt->option; opt++)
207 if (opt->var)
208 printf("%03d %s\n", opt->option, opt->var);
209 }
210
make_option_mask(uint8_t * mask,const char * opts,int add)211 int make_option_mask(uint8_t *mask, const char *opts, int add)
212 {
213 char *token, *o, *p, *t;
214 const struct dhcp_opt *opt;
215 int match, n;
216
217 o = p = xstrdup(opts);
218 while ((token = strsep(&p, ", "))) {
219 if (*token == '\0')
220 continue;
221 for (opt = dhcp_opts; opt->option; opt++) {
222 if (!opt->var)
223 continue;
224 match = 0;
225 if (strcmp(opt->var, token) == 0)
226 match = 1;
227 else {
228 errno = 0;
229 n = strtol(token, &t, 0);
230 if (errno == 0 && !*t)
231 if (opt->option == n)
232 match = 1;
233 }
234 if (match) {
235 if (add == 2 && !(opt->type & IPV4)) {
236 free(o);
237 errno = EINVAL;
238 return -1;
239 }
240 if (add == 1 || add == 2)
241 add_option_mask(mask,
242 opt->option);
243 else
244 del_option_mask(mask,
245 opt->option);
246 break;
247 }
248 }
249 if (!opt->option) {
250 free(o);
251 errno = ENOENT;
252 return -1;
253 }
254 }
255 free(o);
256 return 0;
257 }
258
259 static int
valid_length(uint8_t option,int dl,int * type)260 valid_length(uint8_t option, int dl, int *type)
261 {
262 const struct dhcp_opt *opt;
263 ssize_t sz;
264
265 if (dl == 0)
266 return -1;
267
268 for (opt = dhcp_opts; opt->option; opt++) {
269 if (opt->option != option)
270 continue;
271
272 if (type)
273 *type = opt->type;
274
275 if (opt->type == 0 ||
276 opt->type & (STRING | RFC3442 | RFC5969))
277 return 0;
278
279 sz = 0;
280 if (opt->type & (UINT32 | IPV4))
281 sz = sizeof(uint32_t);
282 if (opt->type & UINT16)
283 sz = sizeof(uint16_t);
284 if (opt->type & UINT8)
285 sz = sizeof(uint8_t);
286 if (opt->type & (IPV4 | ARRAY))
287 return dl % sz;
288 return (dl == sz ? 0 : -1);
289 }
290
291 /* unknown option, so let it pass */
292 return 0;
293 }
294
295 #ifdef DEBUG_MEMORY
296 static void
free_option_buffer(void)297 free_option_buffer(void)
298 {
299 free(opt_buffer);
300 }
301 #endif
302
303 #define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL)
304 static const uint8_t *
get_option(const struct dhcp_message * dhcp,uint8_t opt,int * len,int * type)305 get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
306 {
307 const uint8_t *p = dhcp->options;
308 const uint8_t *e = p + sizeof(dhcp->options);
309 uint8_t l, ol = 0;
310 uint8_t o = 0;
311 uint8_t overl = 0;
312 uint8_t *bp = NULL;
313 const uint8_t *op = NULL;
314 int bl = 0;
315
316 /* DHCP Options are in TLV format with T and L each being a single
317 * byte. In general, here we have p -> T, ol=p+1 -> L, op -> V.
318 * We must make sure there is enough room to read both T and L.
319 */
320 while (p + 1 < e) {
321 o = *p++;
322 if (o == opt) {
323 if (op) {
324 if (!opt_buffer) {
325 opt_buffer = xmalloc(sizeof(*dhcp));
326 #ifdef DEBUG_MEMORY
327 atexit(free_option_buffer);
328 #endif
329 }
330 if (!bp)
331 bp = opt_buffer;
332 memcpy(bp, op, ol);
333 bp += ol;
334 }
335 ol = (p + *p < e) ? *p : e - (p + 1);
336 op = p + 1;
337 bl += ol;
338 }
339 switch (o) {
340 case DHO_PAD:
341 continue;
342 case DHO_END:
343 if (overl & 1) {
344 /* bit 1 set means parse boot file */
345 overl &= ~1;
346 p = dhcp->bootfile;
347 e = p + sizeof(dhcp->bootfile);
348 } else if (overl & 2) {
349 /* bit 2 set means parse server name */
350 overl &= ~2;
351 p = dhcp->servername;
352 e = p + sizeof(dhcp->servername);
353 } else
354 goto exit;
355 break;
356 case DHO_OPTIONSOVERLOADED:
357 /* Ensure we only get this option once */
358 if (!overl)
359 overl = 0x80 | p[1];
360 break;
361 }
362 l = *p++;
363 p += l;
364 }
365
366 exit:
367 if (valid_length(opt, bl, type) == -1) {
368 errno = EINVAL;
369 return NULL;
370 }
371 if (len)
372 *len = bl;
373 if (bp) {
374 memcpy(bp, op, ol);
375 return (const uint8_t *)opt_buffer;
376 }
377 if (op)
378 return op;
379 errno = ENOENT;
380 return NULL;
381 }
382
383 int
get_option_addr(struct in_addr * a,const struct dhcp_message * dhcp,uint8_t option)384 get_option_addr(struct in_addr *a, const struct dhcp_message *dhcp,
385 uint8_t option)
386 {
387 const uint8_t *p = get_option_raw(dhcp, option);
388
389 if (!p)
390 return -1;
391 memcpy(&a->s_addr, p, sizeof(a->s_addr));
392 return 0;
393 }
394
395 int
get_option_uint32(uint32_t * i,const struct dhcp_message * dhcp,uint8_t option)396 get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option)
397 {
398 const uint8_t *p = get_option_raw(dhcp, option);
399 uint32_t d;
400
401 if (!p)
402 return -1;
403 memcpy(&d, p, sizeof(d));
404 *i = ntohl(d);
405 return 0;
406 }
407
408 int
get_option_uint16(uint16_t * i,const struct dhcp_message * dhcp,uint8_t option)409 get_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option)
410 {
411 const uint8_t *p = get_option_raw(dhcp, option);
412 uint16_t d;
413
414 if (!p)
415 return -1;
416 memcpy(&d, p, sizeof(d));
417 *i = ntohs(d);
418 return 0;
419 }
420
421 int
get_option_uint8(uint8_t * i,const struct dhcp_message * dhcp,uint8_t option)422 get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
423 {
424 const uint8_t *p = get_option_raw(dhcp, option);
425
426 if (!p)
427 return -1;
428 if (i)
429 *i = *(p);
430 return 0;
431 }
432
433 /* Decode an RFC3397 DNS search order option into a space
434 * separated string. Returns length of string (including
435 * terminating zero) or zero on error. out may be NULL
436 * to just determine output length. */
437 ssize_t
decode_rfc3397(char * out,ssize_t len,int pl,const uint8_t * p)438 decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p)
439 {
440 const uint8_t *r, *q = p;
441 int count = 0, l, hops;
442 uint8_t ltype;
443
444 while (q - p < pl) {
445 r = NULL;
446 hops = 0;
447 /* We check we are inside our length again incase
448 * the data is NOT terminated correctly. */
449 while ((l = *q++) && q - p < pl) {
450 ltype = l & 0xc0;
451 if (ltype == 0x80 || ltype == 0x40)
452 return 0;
453 else if (ltype == 0xc0) { /* pointer */
454 l = (l & 0x3f) << 8;
455 l |= *q++;
456 /* save source of first jump. */
457 if (!r)
458 r = q;
459 hops++;
460 if (hops > 255)
461 return 0;
462 q = p + l;
463 if (q - p >= pl)
464 return 0;
465 } else {
466 /* straightforward name segment, add with '.' */
467 count += l + 1;
468 if (out) {
469 if ((ssize_t)l + 1 > len) {
470 errno = ENOBUFS;
471 return -1;
472 }
473 memcpy(out, q, l);
474 out += l;
475 *out++ = '.';
476 len -= l;
477 len--;
478 }
479 q += l;
480 }
481 }
482 /* change last dot to space */
483 if (out)
484 *(out - 1) = ' ';
485 if (r)
486 q = r;
487 }
488
489 /* change last space to zero terminator */
490 if (out)
491 *(out - 1) = 0;
492
493 return count;
494 }
495
496 static ssize_t
decode_rfc3442(char * out,ssize_t len,int pl,const uint8_t * p)497 decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p)
498 {
499 const uint8_t *e;
500 ssize_t b, bytes = 0, ocets;
501 uint8_t cidr;
502 struct in_addr addr;
503 char *o = out;
504
505 /* Minimum is 5 -first is CIDR and a router length of 4 */
506 if (pl < 5) {
507 errno = EINVAL;
508 return -1;
509 }
510
511 e = p + pl;
512 while (p < e) {
513 cidr = *p++;
514 if (cidr > 32) {
515 errno = EINVAL;
516 return -1;
517 }
518 ocets = (cidr + 7) / 8;
519 if (!out) {
520 p += 4 + ocets;
521 bytes += ((4 * 4) * 2) + 4;
522 continue;
523 }
524 if ((((4 * 4) * 2) + 4) > len) {
525 errno = ENOBUFS;
526 return -1;
527 }
528 if (o != out) {
529 *o++ = ' ';
530 len--;
531 }
532 /* If we have ocets then we have a destination and netmask */
533 if (ocets > 0) {
534 addr.s_addr = 0;
535 memcpy(&addr.s_addr, p, ocets);
536 b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr);
537 p += ocets;
538 } else
539 b = snprintf(o, len, "0.0.0.0/0");
540 o += b;
541 len -= b;
542
543 /* Finally, snag the router */
544 memcpy(&addr.s_addr, p, 4);
545 p += 4;
546 b = snprintf(o, len, " %s", inet_ntoa(addr));
547 o += b;
548 len -= b;
549 }
550
551 if (out)
552 return o - out;
553 return bytes;
554 }
555
556 static struct rt *
decode_rfc3442_rt(int dl,const uint8_t * data)557 decode_rfc3442_rt(int dl, const uint8_t *data)
558 {
559 const uint8_t *p = data;
560 const uint8_t *e;
561 uint8_t cidr;
562 size_t ocets;
563 struct rt *routes = NULL;
564 struct rt *rt = NULL;
565
566 /* Minimum is 5 -first is CIDR and a router length of 4 */
567 if (dl < 5)
568 return NULL;
569
570 e = p + dl;
571 while (p < e) {
572 cidr = *p++;
573 if (cidr > 32) {
574 free_routes(routes);
575 errno = EINVAL;
576 return NULL;
577 }
578
579 if (rt) {
580 rt->next = xzalloc(sizeof(*rt));
581 rt = rt->next;
582 } else {
583 routes = rt = xzalloc(sizeof(*routes));
584 }
585 rt->next = NULL;
586
587 ocets = (cidr + 7) / 8;
588 /* If we have ocets then we have a destination and netmask */
589 if (ocets > 0) {
590 memcpy(&rt->dest.s_addr, p, ocets);
591 p += ocets;
592 rt->net.s_addr = htonl(~0U << (32 - cidr));
593 }
594
595 /* Finally, snag the router */
596 memcpy(&rt->gate.s_addr, p, 4);
597 p += 4;
598 }
599 return routes;
600 }
601
602 static char *
decode_rfc3361(int dl,const uint8_t * data)603 decode_rfc3361(int dl, const uint8_t *data)
604 {
605 uint8_t enc;
606 unsigned int l;
607 char *sip = NULL;
608 struct in_addr addr;
609 char *p;
610
611 if (dl < 2) {
612 errno = EINVAL;
613 return 0;
614 }
615
616 enc = *data++;
617 dl--;
618 switch (enc) {
619 case 0:
620 if ((l = decode_rfc3397(NULL, 0, dl, data)) > 0) {
621 sip = xmalloc(l);
622 decode_rfc3397(sip, l, dl, data);
623 }
624 break;
625 case 1:
626 if (dl == 0 || dl % 4 != 0) {
627 errno = EINVAL;
628 break;
629 }
630 addr.s_addr = INADDR_BROADCAST;
631 l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1;
632 sip = p = xmalloc(l);
633 while (dl != 0) {
634 memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
635 data += sizeof(addr.s_addr);
636 p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr));
637 dl -= sizeof(addr.s_addr);
638 }
639 *--p = '\0';
640 break;
641 default:
642 errno = EINVAL;
643 return 0;
644 }
645
646 return sip;
647 }
648
649 /* Decode an RFC5969 6rd order option into a space
650 * separated string. Returns length of string (including
651 * terminating zero) or zero on error. */
652 static ssize_t
decode_rfc5969(char * out,ssize_t len,int pl,const uint8_t * p)653 decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p)
654 {
655 uint8_t ipv4masklen, ipv6prefixlen;
656 uint8_t ipv6prefix[16];
657 uint8_t br[4];
658 int i;
659 ssize_t b, bytes = 0;
660
661 if (pl < 22) {
662 errno = EINVAL;
663 return 0;
664 }
665
666 ipv4masklen = *p++;
667 pl--;
668 ipv6prefixlen = *p++;
669 pl--;
670
671 for (i = 0; i < 16; i++) {
672 ipv6prefix[i] = *p++;
673 pl--;
674 }
675 if (out) {
676 b= snprintf(out, len,
677 "%d %d "
678 "%02x%02x:%02x%02x:"
679 "%02x%02x:%02x%02x:"
680 "%02x%02x:%02x%02x:"
681 "%02x%02x:%02x%02x",
682 ipv4masklen, ipv6prefixlen,
683 ipv6prefix[0], ipv6prefix[1], ipv6prefix[2], ipv6prefix[3],
684 ipv6prefix[4], ipv6prefix[5], ipv6prefix[6], ipv6prefix[7],
685 ipv6prefix[8], ipv6prefix[9], ipv6prefix[10],ipv6prefix[11],
686 ipv6prefix[12],ipv6prefix[13],ipv6prefix[14], ipv6prefix[15]
687 );
688
689 len -= b;
690 out += b;
691 bytes += b;
692 } else {
693 bytes += 16 * 2 + 8 + 2 + 1 + 2;
694 }
695
696 while (pl >= 4) {
697 br[0] = *p++;
698 br[1] = *p++;
699 br[2] = *p++;
700 br[3] = *p++;
701 pl -= 4;
702
703 if (out) {
704 b= snprintf(out, len, " %d.%d.%d.%d",
705 br[0], br[1], br[2], br[3]);
706 len -= b;
707 out += b;
708 bytes += b;
709 } else {
710 bytes += (4 * 4);
711 }
712 }
713
714 return bytes;
715 }
716
717 char *
get_option_string(const struct dhcp_message * dhcp,uint8_t option)718 get_option_string(const struct dhcp_message *dhcp, uint8_t option)
719 {
720 int type = 0;
721 int len;
722 const uint8_t *p;
723 char *s;
724
725 p = get_option(dhcp, option, &len, &type);
726 if (!p || *p == '\0')
727 return NULL;
728
729 if (type & RFC3397) {
730 type = decode_rfc3397(NULL, 0, len, p);
731 if (!type) {
732 errno = EINVAL;
733 return NULL;
734 }
735 s = xmalloc(sizeof(char) * type);
736 decode_rfc3397(s, type, len, p);
737 return s;
738 }
739
740 if (type & RFC3361)
741 return decode_rfc3361(len, p);
742
743 s = xmalloc(sizeof(char) * (len + 1));
744 memcpy(s, p, len);
745 s[len] = '\0';
746 return s;
747 }
748
749 /* This calculates the netmask that we should use for static routes.
750 * This IS different from the calculation used to calculate the netmask
751 * for an interface address. */
752 static uint32_t
route_netmask(uint32_t ip_in)753 route_netmask(uint32_t ip_in)
754 {
755 /* used to be unsigned long - check if error */
756 uint32_t p = ntohl(ip_in);
757 uint32_t t;
758
759 if (IN_CLASSA(p))
760 t = ~IN_CLASSA_NET;
761 else {
762 if (IN_CLASSB(p))
763 t = ~IN_CLASSB_NET;
764 else {
765 if (IN_CLASSC(p))
766 t = ~IN_CLASSC_NET;
767 else
768 t = 0;
769 }
770 }
771
772 while (t & p)
773 t >>= 1;
774
775 return (htonl(~t));
776 }
777
778 /* We need to obey routing options.
779 * If we have a CSR then we only use that.
780 * Otherwise we add static routes and then routers. */
781 struct rt *
get_option_routes(const struct dhcp_message * dhcp,const char * ifname,unsigned long long * opts)782 get_option_routes(const struct dhcp_message *dhcp,
783 const char *ifname, unsigned long long *opts)
784 {
785 const uint8_t *p;
786 const uint8_t *e;
787 struct rt *routes = NULL;
788 struct rt *route = NULL;
789 int len;
790
791 /* If we have CSR's then we MUST use these only */
792 p = get_option(dhcp, DHO_CSR, &len, NULL);
793 /* Check for crappy MS option */
794 if (!p)
795 p = get_option(dhcp, DHO_MSCSR, &len, NULL);
796 if (p) {
797 routes = decode_rfc3442_rt(len, p);
798 if (routes) {
799 if (!(*opts & DHCPCD_CSR_WARNED)) {
800 syslog(LOG_DEBUG,
801 "%s: using Classless Static Routes",
802 ifname);
803 *opts |= DHCPCD_CSR_WARNED;
804 }
805 return routes;
806 }
807 }
808
809 /* OK, get our static routes first. */
810 p = get_option(dhcp, DHO_STATICROUTE, &len, NULL);
811 if (p) {
812 e = p + len;
813 while (p < e) {
814 if (route) {
815 route->next = xmalloc(sizeof(*route));
816 route = route->next;
817 } else
818 routes = route = xmalloc(sizeof(*routes));
819 route->next = NULL;
820 memcpy(&route->dest.s_addr, p, 4);
821 p += 4;
822 memcpy(&route->gate.s_addr, p, 4);
823 p += 4;
824 route->net.s_addr = route_netmask(route->dest.s_addr);
825 }
826 }
827
828 /* Now grab our routers */
829 p = get_option(dhcp, DHO_ROUTER, &len, NULL);
830 if (p) {
831 e = p + len;
832 while (p < e) {
833 if (route) {
834 route->next = xzalloc(sizeof(*route));
835 route = route->next;
836 } else
837 routes = route = xzalloc(sizeof(*route));
838 memcpy(&route->gate.s_addr, p, 4);
839 p += 4;
840 }
841 }
842
843 return routes;
844 }
845
846 static size_t
encode_rfc1035(const char * src,uint8_t * dst)847 encode_rfc1035(const char *src, uint8_t *dst)
848 {
849 uint8_t *p = dst;
850 uint8_t *lp = p++;
851
852 if (*src == '\0')
853 return 0;
854 for (; *src; src++) {
855 if (*src == '\0')
856 break;
857 if (*src == '.') {
858 /* Skip the trailing . */
859 if (src[1] == '\0')
860 break;
861 *lp = p - lp - 1;
862 if (*lp == '\0')
863 return p - dst;
864 lp = p++;
865 } else
866 *p++ = (uint8_t)*src;
867 }
868 *lp = p - lp - 1;
869 *p++ = '\0';
870 return p - dst;
871 }
872
873 #define PUTADDR(_type, _val) \
874 { \
875 *p++ = _type; \
876 *p++ = 4; \
877 memcpy(p, &_val.s_addr, 4); \
878 p += 4; \
879 }
880
881 int
dhcp_message_add_addr(struct dhcp_message * dhcp,uint8_t type,struct in_addr addr)882 dhcp_message_add_addr(struct dhcp_message *dhcp,
883 uint8_t type, struct in_addr addr)
884 {
885 uint8_t *p;
886 size_t len;
887
888 p = dhcp->options;
889 while (*p != DHO_END) {
890 p++;
891 p += *p + 1;
892 }
893
894 len = p - (uint8_t *)dhcp;
895 if (len + 6 > sizeof(*dhcp)) {
896 errno = ENOMEM;
897 return -1;
898 }
899
900 PUTADDR(type, addr);
901 *p = DHO_END;
902 return 0;
903 }
904
905 ssize_t
make_message(struct dhcp_message ** message,const struct interface * iface,uint8_t type)906 make_message(struct dhcp_message **message,
907 const struct interface *iface,
908 uint8_t type)
909 {
910 struct dhcp_message *dhcp;
911 uint8_t *m, *lp, *p;
912 uint8_t *n_params = NULL;
913 time_t up = uptime() - iface->start_uptime;
914 uint32_t ul;
915 uint16_t sz;
916 size_t len;
917 const char *hp;
918 const struct dhcp_opt *opt;
919 const struct if_options *ifo = iface->state->options;
920 const struct dhcp_lease *lease = &iface->state->lease;
921
922 dhcp = xzalloc(sizeof (*dhcp));
923 m = (uint8_t *)dhcp;
924 p = dhcp->options;
925
926 if ((type == DHCP_INFORM || type == DHCP_RELEASE ||
927 (type == DHCP_REQUEST &&
928 iface->net.s_addr == lease->net.s_addr &&
929 (iface->state->new == NULL ||
930 iface->state->new->cookie == htonl(MAGIC_COOKIE)))))
931 {
932 dhcp->ciaddr = iface->addr.s_addr;
933 /* In-case we haven't actually configured the address yet */
934 if (type == DHCP_INFORM && iface->addr.s_addr == 0)
935 dhcp->ciaddr = lease->addr.s_addr;
936 }
937
938 dhcp->op = DHCP_BOOTREQUEST;
939 dhcp->hwtype = iface->family;
940 switch (iface->family) {
941 case ARPHRD_ETHER:
942 case ARPHRD_IEEE802:
943 dhcp->hwlen = iface->hwlen;
944 memcpy(&dhcp->chaddr, &iface->hwaddr, iface->hwlen);
945 break;
946 }
947
948 if (ifo->options & DHCPCD_BROADCAST &&
949 dhcp->ciaddr == 0 &&
950 type != DHCP_DECLINE &&
951 type != DHCP_RELEASE)
952 dhcp->flags = htons(BROADCAST_FLAG);
953
954 if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
955 if (up < 0 || up > (time_t)UINT16_MAX)
956 dhcp->secs = htons((uint16_t)UINT16_MAX);
957 else
958 dhcp->secs = htons(up);
959 }
960 dhcp->xid = iface->state->xid;
961 dhcp->cookie = htonl(MAGIC_COOKIE);
962
963 *p++ = DHO_MESSAGETYPE;
964 *p++ = 1;
965 *p++ = type;
966
967 if (iface->clientid) {
968 *p++ = DHO_CLIENTID;
969 memcpy(p, iface->clientid, iface->clientid[0] + 1);
970 p += iface->clientid[0] + 1;
971 }
972
973 if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) {
974 if (type == DHCP_DECLINE ||
975 (type == DHCP_REQUEST &&
976 lease->addr.s_addr != iface->addr.s_addr))
977 {
978 PUTADDR(DHO_IPADDRESS, lease->addr);
979 if (lease->server.s_addr)
980 PUTADDR(DHO_SERVERID, lease->server);
981 }
982
983 if (type == DHCP_RELEASE) {
984 if (lease->server.s_addr)
985 PUTADDR(DHO_SERVERID, lease->server);
986 }
987 }
988
989 if (type == DHCP_DECLINE) {
990 *p++ = DHO_MESSAGE;
991 len = strlen(DAD);
992 *p++ = len;
993 memcpy(p, DAD, len);
994 p += len;
995 }
996
997 if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST)
998 PUTADDR(DHO_IPADDRESS, ifo->req_addr);
999
1000 if (type == DHCP_DISCOVER ||
1001 type == DHCP_INFORM ||
1002 type == DHCP_REQUEST)
1003 {
1004 *p++ = DHO_MAXMESSAGESIZE;
1005 *p++ = 2;
1006 sz = get_mtu(iface->name);
1007 if (sz < MTU_MIN) {
1008 if (set_mtu(iface->name, MTU_MIN) == 0)
1009 sz = MTU_MIN;
1010 } else if (sz > MTU_MAX) {
1011 /* Even though our MTU could be greater than
1012 * MTU_MAX (1500) dhcpcd does not presently
1013 * handle DHCP packets any bigger. */
1014 sz = MTU_MAX;
1015 }
1016 sz = htons(sz);
1017 memcpy(p, &sz, 2);
1018 p += 2;
1019
1020 if (ifo->userclass[0]) {
1021 *p++ = DHO_USERCLASS;
1022 memcpy(p, ifo->userclass, ifo->userclass[0] + 1);
1023 p += ifo->userclass[0] + 1;
1024 }
1025
1026 if (ifo->vendorclassid[0]) {
1027 *p++ = DHO_VENDORCLASSID;
1028 memcpy(p, ifo->vendorclassid,
1029 ifo->vendorclassid[0] + 1);
1030 p += ifo->vendorclassid[0] + 1;
1031 }
1032
1033
1034 if (type != DHCP_INFORM) {
1035 if (ifo->leasetime != 0) {
1036 *p++ = DHO_LEASETIME;
1037 *p++ = 4;
1038 ul = htonl(ifo->leasetime);
1039 memcpy(p, &ul, 4);
1040 p += 4;
1041 }
1042 }
1043
1044 /* Regardless of RFC2132, we should always send a hostname
1045 * upto the first dot (the short hostname) as otherwise
1046 * confuses some DHCP servers when updating DNS.
1047 * The FQDN option should be used if a FQDN is required. */
1048 if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) {
1049 *p++ = DHO_HOSTNAME;
1050 hp = strchr(ifo->hostname, '.');
1051 if (hp)
1052 len = hp - ifo->hostname;
1053 else
1054 len = strlen(ifo->hostname);
1055 *p++ = len;
1056 memcpy(p, ifo->hostname, len);
1057 p += len;
1058 }
1059 if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) {
1060 /* IETF DHC-FQDN option (81), RFC4702 */
1061 *p++ = DHO_FQDN;
1062 lp = p;
1063 *p++ = 3;
1064 /*
1065 * Flags: 0000NEOS
1066 * S: 1 => Client requests Server to update
1067 * a RR in DNS as well as PTR
1068 * O: 1 => Server indicates to client that
1069 * DNS has been updated
1070 * E: 1 => Name data is DNS format
1071 * N: 1 => Client requests Server to not
1072 * update DNS
1073 */
1074 *p++ = (ifo->fqdn & 0x09) | 0x04;
1075 *p++ = 0; /* from server for PTR RR */
1076 *p++ = 0; /* from server for A RR if S=1 */
1077 ul = encode_rfc1035(ifo->hostname, p);
1078 *lp += ul;
1079 p += ul;
1080 }
1081
1082 /* vendor is already encoded correctly, so just add it */
1083 if (ifo->vendor[0]) {
1084 *p++ = DHO_VENDOR;
1085 memcpy(p, ifo->vendor, ifo->vendor[0] + 1);
1086 p += ifo->vendor[0] + 1;
1087 }
1088
1089 *p++ = DHO_PARAMETERREQUESTLIST;
1090 n_params = p;
1091 *p++ = 0;
1092 for (opt = dhcp_opts; opt->option; opt++) {
1093 if (!(opt->type & REQUEST ||
1094 has_option_mask(ifo->requestmask, opt->option)))
1095 continue;
1096 if (type == DHCP_INFORM &&
1097 (opt->option == DHO_RENEWALTIME ||
1098 opt->option == DHO_REBINDTIME))
1099 continue;
1100 *p++ = opt->option;
1101 }
1102 *n_params = p - n_params - 1;
1103 }
1104 *p++ = DHO_END;
1105
1106 #ifdef BOOTP_MESSAGE_LENTH_MIN
1107 /* Some crappy DHCP servers think they have to obey the BOOTP minimum
1108 * message length.
1109 * They are wrong, but we should still cater for them. */
1110 while (p - m < BOOTP_MESSAGE_LENTH_MIN)
1111 *p++ = DHO_PAD;
1112 #endif
1113
1114 *message = dhcp;
1115 return p - m;
1116 }
1117
1118 ssize_t
write_lease(const struct interface * iface,const struct dhcp_message * dhcp)1119 write_lease(const struct interface *iface, const struct dhcp_message *dhcp)
1120 {
1121 int fd;
1122 ssize_t bytes = sizeof(*dhcp);
1123 const uint8_t *p = dhcp->options;
1124 const uint8_t *e = p + sizeof(dhcp->options);
1125 uint8_t l;
1126 uint8_t o = 0;
1127
1128 /* We don't write BOOTP leases */
1129 if (is_bootp(dhcp)) {
1130 unlink(iface->leasefile);
1131 return 0;
1132 }
1133
1134 syslog(LOG_DEBUG, "%s: writing lease `%s'",
1135 iface->name, iface->leasefile);
1136
1137 fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444);
1138 #ifdef ANDROID
1139 if (fd == -1 && errno == EACCES) {
1140 /* the lease file might have been created when dhcpcd was running as root */
1141 unlink(iface->leasefile);
1142 fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0444);
1143 }
1144 #endif
1145 if (fd == -1) {
1146 syslog(LOG_ERR, "%s: open: %m", iface->name);
1147 return -1;
1148 }
1149
1150 /* Only write as much as we need */
1151 while (p < e) {
1152 o = *p;
1153 if (o == DHO_END) {
1154 bytes = p - (const uint8_t *)dhcp;
1155 break;
1156 }
1157 p++;
1158 if (o != DHO_PAD) {
1159 l = *p++;
1160 p += l;
1161 }
1162 }
1163 bytes = write(fd, dhcp, bytes);
1164 close(fd);
1165 return bytes;
1166 }
1167
1168 struct dhcp_message *
read_lease(const struct interface * iface)1169 read_lease(const struct interface *iface)
1170 {
1171 int fd;
1172 struct dhcp_message *dhcp;
1173 ssize_t bytes;
1174
1175 fd = open(iface->leasefile, O_RDONLY);
1176 if (fd == -1) {
1177 if (errno != ENOENT)
1178 syslog(LOG_ERR, "%s: open `%s': %m",
1179 iface->name, iface->leasefile);
1180 return NULL;
1181 }
1182 syslog(LOG_DEBUG, "%s: reading lease `%s'",
1183 iface->name, iface->leasefile);
1184 dhcp = xmalloc(sizeof(*dhcp));
1185 memset(dhcp, 0, sizeof(*dhcp));
1186 bytes = read(fd, dhcp, sizeof(*dhcp));
1187 close(fd);
1188 if (bytes < 0) {
1189 free(dhcp);
1190 dhcp = NULL;
1191 }
1192 return dhcp;
1193 }
1194
1195 static ssize_t
print_string(char * s,ssize_t len,int dl,const uint8_t * data)1196 print_string(char *s, ssize_t len, int dl, const uint8_t *data)
1197 {
1198 uint8_t c;
1199 const uint8_t *e, *p;
1200 ssize_t bytes = 0;
1201 ssize_t r;
1202
1203 e = data + dl;
1204 while (data < e) {
1205 c = *data++;
1206 if (c == '\0') {
1207 /* If rest is all NULL, skip it. */
1208 for (p = data; p < e; p++)
1209 if (*p != '\0')
1210 break;
1211 if (p == e)
1212 break;
1213 }
1214 if (!isascii(c) || !isprint(c)) {
1215 if (s) {
1216 if (len < 5) {
1217 errno = ENOBUFS;
1218 return -1;
1219 }
1220 r = snprintf(s, len, "\\%03o", c);
1221 len -= r;
1222 bytes += r;
1223 s += r;
1224 } else
1225 bytes += 4;
1226 continue;
1227 }
1228 switch (c) {
1229 case '"': /* FALLTHROUGH */
1230 case '\'': /* FALLTHROUGH */
1231 case '$': /* FALLTHROUGH */
1232 case '`': /* FALLTHROUGH */
1233 case '\\': /* FALLTHROUGH */
1234 case '|': /* FALLTHROUGH */
1235 case '&':
1236 if (s) {
1237 if (len < 3) {
1238 errno = ENOBUFS;
1239 return -1;
1240 }
1241 *s++ = '\\';
1242 len--;
1243 }
1244 bytes++;
1245 break;
1246 }
1247 if (s) {
1248 *s++ = c;
1249 len--;
1250 }
1251 bytes++;
1252 }
1253
1254 /* NULL */
1255 if (s)
1256 *s = '\0';
1257 bytes++;
1258 return bytes;
1259 }
1260
1261 static ssize_t
print_option(char * s,ssize_t len,int type,int dl,const uint8_t * data)1262 print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
1263 {
1264 const uint8_t *e, *t;
1265 uint16_t u16;
1266 int16_t s16;
1267 uint32_t u32;
1268 int32_t s32;
1269 struct in_addr addr;
1270 ssize_t bytes = 0;
1271 ssize_t l;
1272 char *tmp;
1273
1274 if (type & RFC3397) {
1275 l = decode_rfc3397(NULL, 0, dl, data);
1276 if (l < 1)
1277 return l;
1278 tmp = xmalloc(l);
1279 decode_rfc3397(tmp, l, dl, data);
1280 l = print_string(s, len, l - 1, (uint8_t *)tmp);
1281 free(tmp);
1282 return l;
1283 }
1284
1285 if (type & RFC3361) {
1286 if ((tmp = decode_rfc3361(dl, data)) == NULL)
1287 return -1;
1288 l = strlen(tmp);
1289 l = print_string(s, len, l - 1, (uint8_t *)tmp);
1290 free(tmp);
1291 return l;
1292 }
1293
1294 if (type & RFC3442)
1295 return decode_rfc3442(s, len, dl, data);
1296
1297 if (type & RFC5969)
1298 return decode_rfc5969(s, len, dl, data);
1299
1300 if (type & STRING) {
1301 /* Some DHCP servers return NULL strings */
1302 if (*data == '\0')
1303 return 0;
1304 return print_string(s, len, dl, data);
1305 }
1306
1307 if (!s) {
1308 if (type & UINT8)
1309 l = 3;
1310 else if (type & UINT16) {
1311 l = 5;
1312 dl /= 2;
1313 } else if (type & SINT16) {
1314 l = 6;
1315 dl /= 2;
1316 } else if (type & UINT32) {
1317 l = 10;
1318 dl /= 4;
1319 } else if (type & SINT32) {
1320 l = 11;
1321 dl /= 4;
1322 } else if (type & IPV4) {
1323 l = 16;
1324 dl /= 4;
1325 } else {
1326 errno = EINVAL;
1327 return -1;
1328 }
1329 return (l + 1) * dl;
1330 }
1331
1332 t = data;
1333 e = data + dl;
1334 while (data < e) {
1335 if (data != t) {
1336 *s++ = ' ';
1337 bytes++;
1338 len--;
1339 }
1340 if (type & UINT8) {
1341 l = snprintf(s, len, "%d", *data);
1342 data++;
1343 } else if (type & UINT16) {
1344 memcpy(&u16, data, sizeof(u16));
1345 u16 = ntohs(u16);
1346 l = snprintf(s, len, "%d", u16);
1347 data += sizeof(u16);
1348 } else if (type & SINT16) {
1349 memcpy(&s16, data, sizeof(s16));
1350 s16 = ntohs(s16);
1351 l = snprintf(s, len, "%d", s16);
1352 data += sizeof(s16);
1353 } else if (type & UINT32) {
1354 memcpy(&u32, data, sizeof(u32));
1355 u32 = ntohl(u32);
1356 l = snprintf(s, len, "%d", u32);
1357 data += sizeof(u32);
1358 } else if (type & SINT32) {
1359 memcpy(&s32, data, sizeof(s32));
1360 s32 = ntohl(s32);
1361 l = snprintf(s, len, "%d", s32);
1362 data += sizeof(s32);
1363 } else if (type & IPV4) {
1364 memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
1365 l = snprintf(s, len, "%s", inet_ntoa(addr));
1366 data += sizeof(addr.s_addr);
1367 } else
1368 l = 0;
1369 if (len <= l) {
1370 bytes += len;
1371 break;
1372 }
1373 len -= l;
1374 bytes += l;
1375 s += l;
1376 }
1377
1378 return bytes;
1379 }
1380
1381 ssize_t
configure_env(char ** env,const char * prefix,const struct dhcp_message * dhcp,const struct if_options * ifo)1382 configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
1383 const struct if_options *ifo)
1384 {
1385 unsigned int i;
1386 const uint8_t *p;
1387 int pl;
1388 struct in_addr addr;
1389 struct in_addr net;
1390 struct in_addr brd;
1391 char *val, *v;
1392 const struct dhcp_opt *opt;
1393 ssize_t len, e = 0;
1394 char **ep;
1395 char cidr[4];
1396 uint8_t overl = 0;
1397
1398 get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED);
1399
1400 if (!env) {
1401 for (opt = dhcp_opts; opt->option; opt++) {
1402 if (!opt->var)
1403 continue;
1404 if (has_option_mask(ifo->nomask, opt->option))
1405 continue;
1406 if (get_option_raw(dhcp, opt->option))
1407 e++;
1408 }
1409 if (dhcp->yiaddr || dhcp->ciaddr)
1410 e += 5;
1411 if (*dhcp->bootfile && !(overl & 1))
1412 e++;
1413 if (*dhcp->servername && !(overl & 2))
1414 e++;
1415 return e;
1416 }
1417
1418 ep = env;
1419 if (dhcp->yiaddr || dhcp->ciaddr) {
1420 /* Set some useful variables that we derive from the DHCP
1421 * message but are not necessarily in the options */
1422 addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr;
1423 setvar(&ep, prefix, "ip_address", inet_ntoa(addr));
1424 if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) {
1425 net.s_addr = get_netmask(addr.s_addr);
1426 setvar(&ep, prefix, "subnet_mask", inet_ntoa(net));
1427 }
1428 i = inet_ntocidr(net);
1429 snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net));
1430 setvar(&ep, prefix, "subnet_cidr", cidr);
1431 if (get_option_addr(&brd, dhcp, DHO_BROADCAST) == -1) {
1432 brd.s_addr = addr.s_addr | ~net.s_addr;
1433 setvar(&ep, prefix, "broadcast_address", inet_ntoa(brd));
1434 }
1435 addr.s_addr = dhcp->yiaddr & net.s_addr;
1436 setvar(&ep, prefix, "network_number", inet_ntoa(addr));
1437 }
1438
1439 if (*dhcp->bootfile && !(overl & 1))
1440 setvar(&ep, prefix, "filename", (const char *)dhcp->bootfile);
1441 if (*dhcp->servername && !(overl & 2))
1442 setvar(&ep, prefix, "server_name", (const char *)dhcp->servername);
1443
1444 for (opt = dhcp_opts; opt->option; opt++) {
1445 if (!opt->var)
1446 continue;
1447 if (has_option_mask(ifo->nomask, opt->option))
1448 continue;
1449 val = NULL;
1450 p = get_option(dhcp, opt->option, &pl, NULL);
1451 if (!p)
1452 continue;
1453 /* We only want the FQDN name */
1454 if (opt->option == DHO_FQDN) {
1455 p += 3;
1456 pl -= 3;
1457 }
1458 len = print_option(NULL, 0, opt->type, pl, p);
1459 if (len < 0)
1460 return -1;
1461 e = strlen(prefix) + strlen(opt->var) + len + 4;
1462 v = val = *ep++ = xmalloc(e);
1463 v += snprintf(val, e, "%s_%s=", prefix, opt->var);
1464 if (len != 0)
1465 print_option(v, len, opt->type, pl, p);
1466 }
1467
1468 return ep - env;
1469 }
1470
1471 void
get_lease(struct dhcp_lease * lease,const struct dhcp_message * dhcp)1472 get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp)
1473 {
1474 struct timeval now;
1475
1476 lease->cookie = dhcp->cookie;
1477 /* BOOTP does not set yiaddr for replies when ciaddr is set. */
1478 if (dhcp->yiaddr)
1479 lease->addr.s_addr = dhcp->yiaddr;
1480 else
1481 lease->addr.s_addr = dhcp->ciaddr;
1482 if (get_option_addr(&lease->net, dhcp, DHO_SUBNETMASK) == -1)
1483 lease->net.s_addr = get_netmask(lease->addr.s_addr);
1484 if (get_option_addr(&lease->brd, dhcp, DHO_BROADCAST) == -1)
1485 lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr;
1486 if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) {
1487 /* Ensure that we can use the lease */
1488 get_monotonic(&now);
1489 if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec)
1490 lease->leasetime = ~0U; /* Infinite lease */
1491 } else
1492 lease->leasetime = ~0U; /* Default to infinite lease */
1493 if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0)
1494 lease->renewaltime = 0;
1495 if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0)
1496 lease->rebindtime = 0;
1497 if (get_option_addr(&lease->server, dhcp, DHO_SERVERID) != 0)
1498 lease->server.s_addr = INADDR_ANY;
1499 }
1500