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