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