2 __RCSID("$NetBSD: dhcp-common.c,v 1.10 2015/07/09 10:15:34 roy Exp $");
5 * dhcpcd - DHCP client daemon
6 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/utsname.h>
33 #include <arpa/nameser.h>
46 #include "dhcp-common.h"
51 /* Support very old arpa/nameser.h as found in OpenBSD */
53 #define NS_MAXCDNAME MAXCDNAME
54 #define NS_MAXDNAME MAXDNAME
55 #define NS_MAXLABEL MAXLABEL
59 dhcp_print_option_encoding(const struct dhcp_opt
*opt
, int cols
)
67 if (opt
->type
& EMBED
)
69 if (opt
->type
& ENCAP
)
71 if (opt
->type
& INDEX
)
73 if (opt
->type
& ARRAY
)
75 if (opt
->type
& UINT8
)
77 else if (opt
->type
& UINT16
)
79 else if (opt
->type
& SINT16
)
81 else if (opt
->type
& UINT32
)
83 else if (opt
->type
& SINT32
)
85 else if (opt
->type
& ADDRIPV4
)
87 else if (opt
->type
& ADDRIPV6
)
88 printf(" ip6address");
89 else if (opt
->type
& FLAG
)
91 else if (opt
->type
& BITFLAG
)
93 else if (opt
->type
& RFC1035
)
95 else if (opt
->type
& DOMAIN
)
97 else if (opt
->type
& ASCII
)
99 else if (opt
->type
& RAW
)
101 else if (opt
->type
& BINHEX
)
103 else if (opt
->type
& STRING
)
105 if (opt
->type
& RFC3361
)
107 if (opt
->type
& RFC3442
)
109 if (opt
->type
& RFC5969
)
111 if (opt
->type
& REQUEST
)
113 if (opt
->type
& NOREQ
)
114 printf(" norequest");
119 vivso_find(uint32_t iana_en
, const void *arg
)
121 const struct interface
*ifp
;
123 struct dhcp_opt
*opt
;
126 for (i
= 0, opt
= ifp
->options
->vivso_override
;
127 i
< ifp
->options
->vivso_override_len
;
129 if (opt
->option
== iana_en
)
131 for (i
= 0, opt
= ifp
->ctx
->vivso
;
132 i
< ifp
->ctx
->vivso_len
;
134 if (opt
->option
== iana_en
)
140 dhcp_vendor(char *str
, size_t len
)
146 if (uname(&utn
) != 0)
147 return (ssize_t
)snprintf(str
, len
, "%s-%s",
151 "%s-%s:%s-%s:%s", PACKAGE
, VERSION
,
152 utn
.sysname
, utn
.release
, utn
.machine
);
153 if (l
== -1 || (size_t)(l
+ 1) > len
)
157 l
= if_machinearch(p
, len
);
158 if (l
== -1 || (size_t)(l
+ 1) > len
)
165 make_option_mask(const struct dhcp_opt
*dopts
, size_t dopts_len
,
166 const struct dhcp_opt
*odopts
, size_t odopts_len
,
167 uint8_t *mask
, const char *opts
, int add
)
170 const struct dhcp_opt
*opt
;
177 o
= p
= strdup(opts
);
178 while ((token
= strsep(&p
, ", "))) {
182 for (i
= 0, opt
= odopts
; i
< odopts_len
; i
++, opt
++) {
183 if (strcmp(opt
->var
, token
) == 0)
186 n
= (unsigned int)strtou(token
, NULL
, 0,
188 if (e
== 0 && opt
->option
== n
)
195 for (i
= 0, opt
= dopts
; i
< dopts_len
; i
++, opt
++) {
196 if (strcmp(opt
->var
, token
) == 0)
199 n
= (unsigned int)strtou(token
, NULL
, 0,
201 if (e
== 0 && opt
->option
== n
)
208 if (!match
|| !opt
->option
) {
213 if (add
== 2 && !(opt
->type
& ADDRIPV4
)) {
218 if (add
== 1 || add
== 2)
219 add_option_mask(mask
, opt
->option
);
221 del_option_mask(mask
, opt
->option
);
228 encode_rfc1035(const char *src
, uint8_t *dst
)
235 if (src
== NULL
|| *src
== '\0')
242 /* Silence bogus GCC warnings */
248 for (; *src
; src
++) {
252 /* Skip the trailing . */
257 *lp
= (uint8_t)(p
- lp
- 1);
263 *p
++ = (uint8_t)*src
;
268 *lp
= (uint8_t)(p
- lp
- 1);
279 /* Decode an RFC1035 DNS search order option into a space
280 * separated string. Returns length of string (including
281 * terminating zero) or zero on error. out may be NULL
282 * to just determine output length. */
284 decode_rfc1035(char *out
, size_t len
, const uint8_t *p
, size_t pl
)
287 size_t start_len
, l
, count
;
288 const uint8_t *r
, *q
= p
, *e
;
292 if (pl
> NS_MAXCDNAME
) {
305 /* Check we are inside our length again in-case
306 * the name isn't fully qualified (ie, not terminated) */
307 while (q
< e
&& (l
= (size_t)*q
++)) {
309 if (ltype
== 0x80 || ltype
== 0x40) {
310 /* Currently reserved for future use as noted
311 * in RFC1035 4.1.4 as the 10 and 01
316 else if (ltype
== 0xc0) { /* pointer */
323 /* save source of first jump. */
337 /* straightforward name segment, add with '.' */
348 if (l
+ 1 > NS_MAXLABEL
) {
361 /* change last dot to space */
362 if (out
&& out
!= start
)
368 /* change last space to zero terminator */
372 else if (start_len
> 0)
377 /* Don't count the trailing NUL */
379 if (count
> NS_MAXDNAME
) {
383 return (ssize_t
)count
;
386 /* Check for a valid domain name as per RFC1123 with the exception of
387 * allowing - and _ (but not at start or end) as they seem to be widely used. */
389 valid_domainname(char *lbl
, int type
)
393 int start
, len
, errset
;
395 if (lbl
== NULL
|| *lbl
== '\0') {
405 c
= (unsigned char)*lbl
++;
409 if (lbl
- 1 == slbl
) /* No space at start */
413 /* Skip to the next label */
428 if (((c
== '-' || c
== '_') &&
429 !start
&& *lbl
!= ' ' && *lbl
!= '\0') ||
432 if (++len
> NS_MAXLABEL
) {
446 /* At least one valid domain, return it */
454 * Prints a chunk of data to a string.
455 * PS_SHELL goes as it is these days, it's upto the target to validate it.
456 * PS_SAFE has all non ascii and non printables changes to escaped octal.
458 static const char hexchrs
[] = "0123456789abcdef";
460 print_string(char *dst
, size_t len
, int type
, const uint8_t *data
, size_t dl
)
475 if (len
== 0 || len
== 1) {
479 *dst
++ = hexchrs
[(c
& 0xF0) >> 4];
480 *dst
++ = hexchrs
[(c
& 0x0F)];
486 if (type
& ASCII
&& (!isascii(c
))) {
490 if (!(type
& (ASCII
| RAW
| ESCSTRING
| ESCFILE
)) /* plain */ &&
491 (!isascii(c
) && !isprint(c
)))
496 if ((type
& (ESCSTRING
| ESCFILE
) &&
497 (c
== '\\' || !isascii(c
) || !isprint(c
))) ||
498 (type
& ESCFILE
&& (c
== '/' || c
== ' ')))
503 if (len
== 0 || len
== 1) {
507 *dst
++ = '\\'; *dst
++ = '\\';
519 *dst
++ = (char)(((c
>> 6) & 03) + '0');
520 *dst
++ = (char)(((c
>> 3) & 07) + '0');
521 *dst
++ = (char)(( c
& 07) + '0');
546 /* Now we've printed it, validate the domain */
547 if (type
& DOMAIN
&& !valid_domainname(odst
, type
)) {
554 return (ssize_t
)bytes
;
560 dhcp_optlen(const struct dhcp_opt
*opt
, size_t dl
)
564 if (opt
->type
== 0 ||
565 opt
->type
& (STRING
| BINHEX
| RFC3442
| RFC5969
))
568 if ((size_t)opt
->len
> dl
)
570 return (ssize_t
)opt
->len
;
575 if ((opt
->type
& (ADDRIPV4
| ARRAY
)) == (ADDRIPV4
| ARRAY
)) {
578 return (ssize_t
)(dl
- (dl
% ADDRSZ
));
581 if ((opt
->type
& (ADDRIPV6
| ARRAY
)) == (ADDRIPV6
| ARRAY
)) {
584 return (ssize_t
)(dl
- (dl
% ADDR6SZ
));
587 if (opt
->type
& (UINT32
| ADDRIPV4
))
588 sz
= sizeof(uint32_t);
589 else if (opt
->type
& UINT16
)
590 sz
= sizeof(uint16_t);
591 else if (opt
->type
& (UINT8
| BITFLAG
))
592 sz
= sizeof(uint8_t);
593 else if (opt
->type
& ADDRIPV6
)
596 /* If we don't know the size, assume it's valid */
598 return dl
< sz
? -1 : (ssize_t
)sz
;
602 print_option(char *s
, size_t len
, const struct dhcp_opt
*opt
,
603 const uint8_t *data
, size_t dl
, const char *ifname
)
605 const uint8_t *e
, *t
;
611 ssize_t bytes
= 0, sl
;
619 if (opt
->type
& RFC1035
) {
620 sl
= decode_rfc1035(NULL
, 0, data
, dl
);
621 if (sl
== 0 || sl
== -1)
627 decode_rfc1035(tmp
, l
, data
, dl
);
628 sl
= print_string(s
, len
, opt
->type
, (uint8_t *)tmp
, l
- 1);
634 if (opt
->type
& RFC3361
) {
635 if ((tmp
= decode_rfc3361(data
, dl
)) == NULL
)
638 sl
= print_string(s
, len
, opt
->type
, (uint8_t *)tmp
, l
);
643 if (opt
->type
& RFC3442
)
644 return decode_rfc3442(s
, len
, data
, dl
);
646 if (opt
->type
& RFC5969
)
647 return decode_rfc5969(s
, len
, data
, dl
);
650 if (opt
->type
& STRING
)
651 return print_string(s
, len
, opt
->type
, data
, dl
);
653 if (opt
->type
& FLAG
) {
661 if (opt
->type
& BITFLAG
) {
662 /* bitflags are a string, MSB first, such as ABCDEFGH
663 * where A is 10000000, B is 01000000, etc. */
665 for (l
= 0, sl
= sizeof(opt
->bitflags
) - 1;
666 l
< sizeof(opt
->bitflags
);
669 /* Don't print NULL or 0 flags */
670 if (opt
->bitflags
[l
] != '\0' &&
671 opt
->bitflags
[l
] != '0' &&
675 *s
++ = opt
->bitflags
[l
];
685 if (opt
->type
& UINT8
)
687 else if (opt
->type
& UINT16
) {
690 } else if (opt
->type
& SINT16
) {
693 } else if (opt
->type
& UINT32
) {
696 } else if (opt
->type
& SINT32
) {
699 } else if (opt
->type
& ADDRIPV4
) {
704 else if (opt
->type
& ADDRIPV6
) {
710 sl
= ipv6_printaddr(NULL
, 0, data
, ifname
);
722 return (ssize_t
)(l
* dl
);
733 if (opt
->type
& UINT8
) {
734 sl
= snprintf(s
, len
, "%u", *data
);
736 } else if (opt
->type
& UINT16
) {
737 memcpy(&u16
, data
, sizeof(u16
));
739 sl
= snprintf(s
, len
, "%u", u16
);
741 } else if (opt
->type
& SINT16
) {
742 memcpy(&u16
, data
, sizeof(u16
));
743 s16
= (int16_t)ntohs(u16
);
744 sl
= snprintf(s
, len
, "%d", s16
);
746 } else if (opt
->type
& UINT32
) {
747 memcpy(&u32
, data
, sizeof(u32
));
749 sl
= snprintf(s
, len
, "%u", u32
);
751 } else if (opt
->type
& SINT32
) {
752 memcpy(&u32
, data
, sizeof(u32
));
753 s32
= (int32_t)ntohl(u32
);
754 sl
= snprintf(s
, len
, "%d", s32
);
756 } else if (opt
->type
& ADDRIPV4
) {
757 memcpy(&addr
.s_addr
, data
, sizeof(addr
.s_addr
));
758 sl
= snprintf(s
, len
, "%s", inet_ntoa(addr
));
759 data
+= sizeof(addr
.s_addr
);
762 else if (opt
->type
& ADDRIPV6
) {
765 r
= ipv6_printaddr(s
, len
, data
, ifname
);
784 dhcp_set_leasefile(char *leasefile
, size_t len
, int family
,
785 const struct interface
*ifp
)
789 if (ifp
->name
[0] == '\0') {
790 strlcpy(leasefile
, ifp
->ctx
->pidfile
, len
);
805 print_string(ssid
+ 1, sizeof(ssid
) - 1,
807 (const uint8_t *)ifp
->ssid
, ifp
->ssid_len
);
810 return snprintf(leasefile
, len
,
811 family
== AF_INET
? LEASEFILE
: LEASEFILE6
,
816 dhcp_envoption1(struct dhcpcd_ctx
*ctx
, char **env
, const char *prefix
,
817 const struct dhcp_opt
*opt
, int vname
, const uint8_t *od
, size_t ol
,
824 if (opt
->len
&& opt
->len
< ol
)
826 len
= print_option(NULL
, 0, opt
, od
, ol
, ifname
);
830 e
= strlen(opt
->var
) + 1;
835 e
+= (size_t)len
+ 2;
838 v
= val
= *env
= malloc(e
);
840 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
844 v
+= snprintf(val
, e
, "%s_%s=", prefix
, opt
->var
);
846 v
+= snprintf(val
, e
, "%s=", prefix
);
848 print_option(v
, (size_t)len
+ 1, opt
, od
, ol
, ifname
);
853 dhcp_envoption(struct dhcpcd_ctx
*ctx
, char **env
, const char *prefix
,
854 const char *ifname
, struct dhcp_opt
*opt
,
855 const uint8_t *(*dgetopt
)(struct dhcpcd_ctx
*,
856 size_t *, unsigned int *, size_t *,
857 const uint8_t *, size_t, struct dhcp_opt
**),
858 const uint8_t *od
, size_t ol
)
860 size_t e
, i
, n
, eos
, eol
;
865 struct dhcp_opt
*eopt
, *oopt
;
868 /* If no embedded or encapsulated options, it's easy */
869 if (opt
->embopts_len
== 0 && opt
->encopts_len
== 0) {
870 if (!(opt
->type
& RESERVED
) &&
871 dhcp_envoption1(ctx
, env
== NULL
? NULL
: &env
[0],
872 prefix
, opt
, 1, od
, ol
, ifname
))
877 /* Create a new prefix based on the option */
879 if (opt
->type
& INDEX
) {
880 if (opt
->index
> 999) {
882 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
886 e
= strlen(prefix
) + strlen(opt
->var
) + 2 +
887 (opt
->type
& INDEX
? 3 : 0);
890 logger(ctx
, LOG_ERR
, "%s: %m", __func__
);
893 if (opt
->type
& INDEX
)
894 snprintf(pfx
, e
, "%s_%s%d", prefix
,
895 opt
->var
, ++opt
->index
);
897 snprintf(pfx
, e
, "%s_%s", prefix
, opt
->var
);
901 /* Embedded options are always processed first as that
902 * is a fixed layout */
904 for (i
= 0, eopt
= opt
->embopts
; i
< opt
->embopts_len
; i
++, eopt
++) {
905 eo
= dhcp_optlen(eopt
, ol
);
909 "%s: %s: malformed embedded option %d:%d",
910 ifname
, __func__
, opt
->option
,
915 /* An option was expected, but there is no data
917 * This may not be an error as some options like
918 * DHCP FQDN in RFC4702 have a string as the last
919 * option which is optional.
920 * FIXME: Add an flag to the options to indicate
921 * wether this is allowable or not. */
923 (ol
!= 0 || i
+ 1 < opt
->embopts_len
))
925 "%s: %s: malformed embedded option %d:%d",
926 ifname
, __func__
, opt
->option
,
930 /* Use the option prefix if the embedded option
932 * This avoids new_fqdn_fqdn which would be silly. */
933 if (!(eopt
->type
& RESERVED
)) {
934 ov
= strcmp(opt
->var
, eopt
->var
);
935 if (dhcp_envoption1(ctx
, env
== NULL
? NULL
: &env
[n
],
936 pfx
, eopt
, ov
, od
, (size_t)eo
, ifname
))
943 /* Enumerate our encapsulated options */
944 if (opt
->encopts_len
&& ol
> 0) {
945 /* Zero any option indexes
946 * We assume that referenced encapsulated options are NEVER
947 * recursive as the index order could break. */
948 for (i
= 0, eopt
= opt
->encopts
;
949 i
< opt
->encopts_len
;
953 if (eopt
->type
& OPTION
) {
954 dgetopt(ctx
, NULL
, &eoc
, NULL
, NULL
, 0, &oopt
);
960 while ((eod
= dgetopt(ctx
, &eos
, &eoc
, &eol
, od
, ol
, &oopt
))) {
961 for (i
= 0, eopt
= opt
->encopts
;
962 i
< opt
->encopts_len
;
965 if (eopt
->option
== eoc
) {
966 if (eopt
->type
& OPTION
) {
971 n
+= dhcp_envoption(ctx
,
972 env
== NULL
? NULL
: &env
[n
], pfx
,
974 eopt
->type
& OPTION
? oopt
: eopt
,
988 /* Return number of options found */
993 dhcp_zero_index(struct dhcp_opt
*opt
)
999 for (i
= 0, o
= opt
->embopts
; i
< opt
->embopts_len
; i
++, o
++)
1001 for (i
= 0, o
= opt
->encopts
; i
< opt
->encopts_len
; i
++, o
++)