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