+++ /dev/null
-/* $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $ */
-
-/*-
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*-
- * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * HEAVILY trimmed down for use only in dhcpcd.
- * Please use the source in NetBSD for a fuller working copy.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "svis.h"
-
-#undef BELL
-#define BELL '\a'
-
-#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
-
-/*
- * This is do_vis, the central code of vis.
- * dst: Pointer to the destination buffer
- * c: Character to encode
- * flag: Flag word
- * nextc: The character following 'c'
- * extra: Pointer to the list of extra characters to be
- * backslash-protected.
- */
-char *
-svis(char *dst, int c, int flag, int nextc, const char *extra)
-{
- int isextra;
-
- isextra = strchr(extra, c) != NULL;
- if (!isextra && isascii(c) && (isgraph(c) || iswhite(c))) {
- *dst++ = (char)c;
- return dst;
- }
- if (flag & VIS_CSTYLE) {
- switch (c) {
- case '\n':
- *dst++ = '\\'; *dst++ = 'n';
- return dst;
- case '\r':
- *dst++ = '\\'; *dst++ = 'r';
- return dst;
- case '\b':
- *dst++ = '\\'; *dst++ = 'b';
- return dst;
- case BELL:
- *dst++ = '\\'; *dst++ = 'a';
- return dst;
- case '\v':
- *dst++ = '\\'; *dst++ = 'v';
- return dst;
- case '\t':
- *dst++ = '\\'; *dst++ = 't';
- return dst;
- case '\f':
- *dst++ = '\\'; *dst++ = 'f';
- return dst;
- case ' ':
- *dst++ = '\\'; *dst++ = 's';
- return dst;
- case '\0':
- *dst++ = '\\'; *dst++ = '0';
- if (isoctal(nextc)) {
- *dst++ = '0';
- *dst++ = '0';
- }
- return dst;
- case '$': /* vis(1) - l */
- break;
- default:
- if (isgraph(c)) {
- *dst++ = '\\'; *dst++ = (char)c;
- return dst;
- }
- }
- }
-
- *dst++ = '\\';
- if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
- *dst++ = (((unsigned char)c >> 6) & 03) + '0';
- *dst++ = (((unsigned char)c >> 3) & 07) + '0';
- *dst++ = ( (unsigned char)c & 07) + '0';
- } else {
- if (c & 0200) {
- c &= 0177; *dst++ = 'M';
- }
-
- if (iscntrl(c)) {
- *dst++ = '^';
- if (c == 0177)
- *dst++ = '?';
- else
- *dst++ = (char)c + '@';
- } else {
- *dst++ = '-'; *dst++ = (char)c;
- }
- }
- return dst;
-}
-
-char *
-vis(char *dst, int c, int flag, int nextc)
-{
-
- return svis(dst, c, flag, nextc, "");
-}
+++ /dev/null
-#ifndef SVIS_H
-#define SVIS_H
-
-#define VIS_OCTAL 0x0001 /* use octal \ddd format */
-#define VIS_CSTYLE 0x0002 /* use \[nrft0..] where appropiate */
-
-char *vis(char *dst, int c, int flag, int nextc);
-char *svis(char *dst, int c, int flag, int nextc, const char *meta);
-
-#endif
--without-md5) MD5=no;;
--without-sha2) SHA2=no;;
--without-sha256) SHA2=no;;
- --without-svis) SVIS=no;;
--without-dev) DEV=no;;
--without-udev) UDEV=no;;
--serviceexists) SERVICEEXISTS=$var;;
echo "#include \"compat/strlcpy.h\"" >>$CONFIG_H
fi
-if [ -z "$SVIS" ]; then
- printf "Testing for svis ... "
- cat <<EOF >_svis.c
-#include <vis.h>
-int main(void) {
- char s[10];
- svis(s, 1, 2, 3, s);
- return 0;
-}
-EOF
- if $XCC _svis.c -o _svis 2>&3; then
- SVIS=yes
- else
- SVIS=no
- fi
- echo "$SVIS"
- rm -f _svis.c _svis
-fi
-if [ "$SVIS" = no ]; then
- echo "COMPAT_SRCS+= compat/svis.c" >>$CONFIG_MK
- echo "#include \"compat/svis.h\"" >>$CONFIG_H
-else
- echo "#define HAVE_VIS_H" >>$CONFIG_H
-fi
-
if [ -z "$DPRINTF" ]; then
printf "Testing for dprintf ... "
cat <<EOF >_dprintf.c
#include "config.h"
-#ifdef HAVE_VIS_H
-#include <vis.h>
-#endif
-
#include "common.h"
#include "dhcp-common.h"
#include "dhcp.h"
#include "if.h"
#include "ipv6.h"
+void
+dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols)
+{
+
+ while (cols < 40) {
+ putchar(' ');
+ cols++;
+ }
+ putchar('\t');
+ if (opt->type & EMBED)
+ printf(" embed");
+ if (opt->type & ENCAP)
+ printf(" encap");
+ if (opt->type & INDEX)
+ printf(" index");
+ if (opt->type & ARRAY)
+ printf(" array");
+ if (opt->type & UINT8)
+ printf(" byte");
+ else if (opt->type & UINT16)
+ printf(" uint16");
+ else if (opt->type & SINT16)
+ printf(" sint16");
+ else if (opt->type & UINT32)
+ printf(" uint32");
+ else if (opt->type & SINT32)
+ printf(" sint32");
+ else if (opt->type & ADDRIPV4)
+ printf(" ipaddress");
+ else if (opt->type & ADDRIPV6)
+ printf(" ip6address");
+ else if (opt->type & FLAG)
+ printf(" flag");
+ else if (opt->type & RFC3397)
+ printf(" domain");
+ else if (opt->type & DOMAIN)
+ printf(" dname");
+ else if (opt->type & ASCII)
+ printf(" ascii");
+ else if (opt->type & RAW)
+ printf(" raw");
+ else if (opt->type & BINHEX)
+ printf(" binhex");
+ else if (opt->type & STRING)
+ printf(" string");
+ if (opt->type & RFC3361)
+ printf(" rfc3361");
+ if (opt->type & RFC3442)
+ printf(" rfc3442");
+ if (opt->type & RFC5969)
+ printf(" rfc5969");
+ if (opt->type & REQUEST)
+ printf(" request");
+ if (opt->type & NOREQ)
+ printf(" norequest");
+ putchar('\n');
+}
+
struct dhcp_opt *
vivso_find(uint32_t iana_en, const void *arg)
{
return (ssize_t)count;
}
-/*
- * Escape these characters to avoid any nastiness passing to a POSIX shell.
- * See IEEE Std 1003.1, 2004 Shell Command Language, 2.2 Quoting
- * space is not escaped.
- */
-#define ESCAPE_CHARS "|&;<>()$`\\\"'\t\n"
-#define ESCAPE_EXTRA "*?[#~=%"
+/* Check for a valid domain name as per RFC1123 with the exception of
+ * allowing - and _ (but not at start or end) as they seem to be widely used. */
+static int
+valid_domainname(char *lbl, int type)
+{
+ char *slbl, *lst;
+ unsigned char c;
+ int start, len, errset;
+
+ if (lbl == NULL || *lbl == '\0') {
+ errno = EINVAL;
+ return 0;
+ }
+
+ slbl = lbl;
+ lst = NULL;
+ start = 1;
+ len = errset = 0;
+ for (;;) {
+ c = (unsigned char)*lbl++;
+ if (c == '\0')
+ return 1;
+ if (c == ' ') {
+ if (lbl - 1 == slbl) /* No space at start */
+ break;
+ if (!(type & ARRAY))
+ break;
+ /* Skip to the next label */
+ if (!start) {
+ start = 1;
+ lst = lbl - 1;
+ }
+ if (len)
+ len = 0;
+ continue;
+ }
+ if (c == '.') {
+ if (*lbl == '.')
+ break;
+ len = 0;
+ continue;
+ }
+ if (((c == '-' || c == '_') &&
+ !start && *lbl != ' ' && *lbl != '\0') ||
+ isalnum(c))
+ {
+ if (++len > 63) {
+ errno = ERANGE;
+ errset = 1;
+ break;
+ }
+ } else
+ break;
+ if (start)
+ start = 0;
+ }
+
+ if (!errset)
+ errno = EINVAL;
+ if (lst) {
+ /* At least one valid domain, return it */
+ *lst = '\0';
+ return 1;
+ }
+ return 0;
+}
/*
* Prints a chunk of data to a string.
- * Escapes some characters defnined above to try and avoid any loopholes
- * in the shell we're passing to.
- * Any non visible characters are escaped as an octal number.
+ * PS_SHELL goes as it is these days, it's upto the target to validate it.
+ * PS_SAFE has all non ascii and non printables changes to escaped octal.
*/
+static const char hexchrs[] = "0123456789abcdef";
ssize_t
-print_string(char *s, size_t len, int flags, const uint8_t *data, size_t dl)
+print_string(char *dst, size_t len, int type, const uint8_t *data, size_t dl)
{
+ char *odst;
uint8_t c;
- const uint8_t *e, *p;
+ const uint8_t *e;
size_t bytes;
- char v[5], *vp, *ve;
+ odst = dst;
bytes = 0;
e = data + dl;
+
while (data < e) {
c = *data++;
- if (c == '\0') {
- /* If rest is all NULL, skip it. */
- for (p = data; p < e; p++)
- if (*p != '\0')
- break;
- if (p == e)
- break;
+ if (type & BINHEX) {
+ if (dst) {
+ if (len == 0 || len == 1) {
+ errno = ENOSPC;
+ return -1;
+ }
+ *dst++ = hexchrs[(c & 0xF0) >> 4];
+ *dst++ = hexchrs[(c & 0x0F)];
+ len -= 2;
+ }
+ bytes += 2;
+ continue;
}
- if (flags & PS_SHELL)
- ve = svis(v, c, VIS_CSTYLE | VIS_OCTAL,
- data <= e ? *data : 0, ESCAPE_CHARS ESCAPE_EXTRA);
- else
- ve = vis(v, c, VIS_CSTYLE | VIS_OCTAL,
- data <= e ? *data : 0);
- bytes += (size_t)(ve - v);
- if (s && len < bytes + 1) {
- errno = ENOBUFS;
- return -1;
+ if (type & ASCII && (!isascii(c))) {
+ errno = EINVAL;
+ break;
}
- if (s) {
- vp = v;
- while (vp != ve)
- *s++ = *vp++;
+ if (!(type & (ASCII | RAW | ESCSTRING)) /*plain string */ &&
+ (!isascii(c) && !isprint(c)))
+ {
+ errno = EINVAL;
+ break;
+ }
+ if (type & ESCSTRING &&
+ (c == '\\' || !isascii(c) || !isprint(c)))
+ {
+ errno = EINVAL;
+ if (c == '\\') {
+ if (len == 0 || len == 1) {
+ errno = ENOSPC;
+ return -1;
+ }
+ if (dst) {
+ *dst++ = '\\'; *dst++ = '\\';
+ len -= 2;
+ }
+ bytes += 2;
+ continue;
+ }
+ if (dst) {
+ if (len < 5) {
+ errno = ENOSPC;
+ return -1;
+ }
+ *dst++ = '\\';
+ *dst++ = (((unsigned char)c >> 6) & 03) + '0';
+ *dst++ = (((unsigned char)c >> 3) & 07) + '0';
+ *dst++ = ( (unsigned char)c & 07) + '0';
+ len -= 4;
+ }
+ bytes += 4;
+ } else {
+ if (dst) {
+ if (len == 0) {
+ errno = ENOSPC;
+ return -1;
+ }
+ *dst++ = (char)c;
+ len--;
+ }
+ bytes++;
}
}
/* NULL */
- if (s)
- *s = '\0';
+ if (dst) {
+ if (len == 0) {
+ errno = ENOSPC;
+ return -1;
+ }
+ *dst = '\0';
+
+ /* Now we've printed it, validate the domain */
+ if (type & DOMAIN && !valid_domainname(odst, type)) {
+ *odst = '\0';
+ return 1;
+ }
+
+ }
bytes++;
+
return (ssize_t)bytes;
}
if (tmp == NULL)
return -1;
decode_rfc3397(tmp, l, data, dl);
- sl = print_string(s, len, PS_SHELL, (uint8_t *)tmp, l - 1);
+ sl = print_string(s, len, type, (uint8_t *)tmp, l - 1);
free(tmp);
return sl;
}
if ((tmp = decode_rfc3361(data, dl)) == NULL)
return -1;
l = strlen(tmp);
- sl = print_string(s, len, PS_SHELL, (uint8_t *)tmp, l);
+ sl = print_string(s, len, type, (uint8_t *)tmp, l);
free(tmp);
return sl;
}
return decode_rfc5969(s, len, data, dl);
#endif
- if (type & STRING) {
- /* Some DHCP servers return NULL strings */
- if (*data == '\0')
- return 0;
- return print_string(s, len, PS_SHELL, data, dl);
- }
+ if (type & STRING)
+ return print_string(s, len, type, data, dl);
if (type & FLAG) {
if (s) {
return (ssize_t)(l + 1);
}
#endif
- else if (type & BINHEX) {
- l = 2;
- } else {
+ else {
errno = EINVAL;
return -1;
}
t = data;
e = data + dl;
while (data < e) {
- if (data != t && type != BINHEX) {
+ if (data != t) {
*s++ = ' ';
bytes++;
len--;
data += 16;
}
#endif
- else if (type & BINHEX) {
- sl = snprintf(s, len, "%.2x", data[0]);
- data++;
- } else
+ else
sl = 0;
len -= (size_t)sl;
bytes += sl;
#define ENCAP (1 << 18)
#define INDEX (1 << 19)
#define OPTION (1 << 20)
-
-/* Print string flags */
-#define PS_SHELL (1 << 0)
+#define DOMAIN (1 << 21)
+#define ASCII (1 << 22)
+#define RAW (1 << 23)
+#define ESCSTRING (1 << 24)
struct dhcp_opt {
uint32_t option; /* Also used for IANA Enterpise Number */
ssize_t dhcp_vendor(char *, size_t);
+void dhcp_print_option_encoding(const struct dhcp_opt *opt, int cols);
#define add_option_mask(var, val) (var[val >> 3] |= 1 << (val & 7))
#define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
#define has_option_mask(var, val) (var[val >> 3] & (1 << (val & 7)))
const char * const *p;
size_t i, j;
const struct dhcp_opt *opt, *opt2;
+ int cols;
for (p = dhcp_params; *p; p++)
printf(" %s\n", *p);
for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
if (opt->option == opt2->option)
break;
- if (j == opts_len)
- printf("%03d %s\n", opt->option, opt->var);
+ if (j == opts_len) {
+ cols = printf("%03d %s", opt->option, opt->var);
+ dhcp_print_option_encoding(opt, cols);
+ }
+ }
+ for (i = 0, opt = opts; i < opts_len; i++, opt++) {
+ cols = printf("%03d %s", opt->option, opt->var);
+ dhcp_print_option_encoding(opt, cols);
}
- for (i = 0, opt = opts; i < opts_len; i++, opt++)
- printf("%03d %s\n", opt->option, opt->var);
}
#define get_option_raw(ctx, dhcp, opt) get_option(ctx, dhcp, opt, NULL)
}
if (*dhcp->bootfile && !(overl & 1)) {
- print_string(safe, sizeof(safe), PS_SHELL,
+ print_string(safe, sizeof(safe), STRING,
dhcp->bootfile, sizeof(dhcp->bootfile));
setvar(&ep, prefix, "filename", safe);
}
if (*dhcp->servername && !(overl & 2)) {
- print_string(safe, sizeof(safe), PS_SHELL,
+ print_string(safe, sizeof(safe), STRING | DOMAIN,
dhcp->servername, sizeof(dhcp->servername));
setvar(&ep, prefix, "server_name", safe);
}
free(a);
return;
}
- print_string(tmp, tmpl, 0, (uint8_t *)a, al);
+ print_string(tmp, tmpl, STRING, (uint8_t *)a, al);
free(a);
a = tmp;
}
tfrom = "from";
r = get_option_addr(iface->ctx, &addr, dhcp, DHO_SERVERID);
if (dhcp->servername[0] && r == 0) {
- print_string(sname, sizeof(sname), 0,
+ print_string(sname, sizeof(sname), STRING,
dhcp->servername, strlen((const char *)dhcp->servername));
if (a == NULL)
syslog(lvl, "%s: %s %s %s `%s'", iface->name, msg,
{
size_t i, j;
const struct dhcp_opt *opt, *opt2;
+ int cols;
for (i = 0, opt = ctx->dhcp6_opts;
i < ctx->dhcp6_opts_len; i++, opt++)
for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
if (opt2->option == opt->option)
break;
- if (j == opts_len)
- printf("%05d %s\n", opt->option, opt->var);
+ if (j == opts_len) {
+ cols = printf("%05d %s", opt->option, opt->var);
+ dhcp_print_option_encoding(opt, cols);
+ }
+ }
+ for (i = 0, opt = opts; i < opts_len; i++, opt++) {
+ cols = printf("%05d %s", opt->option, opt->var);
+ dhcp_print_option_encoding(opt, cols);
}
- for (i = 0, opt = opts; i < opts_len; i++, opt++)
- printf("%05d %s\n", opt->option, opt->var);
}
static size_t
define 9 array ipaddress lpr_servers
define 10 array ipaddress impress_servers
define 11 array ipaddress resource_location_servers
-define 12 string host_name
+define 12 dname host_name
define 13 uint16 boot_size
define 14 string merit_dump
-define 15 string domain_name
+# Technically domain_name is not an array, but many servers expect clients
+# to treat it as one.
+define 15 array dname domain_name
define 16 ipaddress swap_server
define 17 string root_path
define 18 string extensions_path
define 40 string nis_domain
define 41 array ipaddress nis_servers
define 42 array ipaddress ntp_servers
-define 43 string vendor_encapsulated_options
+define 43 binhex vendor_encapsulated_options
define 44 array ipaddress netbios_name_servers
define 45 ipaddress netbios_dd_server
define 46 byte netbios_node_type
define 61 binhex dhcp_client_identifier
define 64 string nisplus_domain
define 65 array ipaddress nisplus_servers
-define 66 string tftp_server_name
+define 66 dname tftp_server_name
define 67 string bootfile_name
define 68 array ipaddress mobile_ip_home_agent
define 69 array ipaddress smtp_server
define 76 array ipaddress streettalk_directory_assistance_server
# DHCP User Class, RFC3004
-define 77 string user_class
+define 77 binhex user_class
# DHCP SLP Directory Agent, RFC2610
define 78 embed slp_agent
embed array ipaddress address
define 79 embed slp_service
embed byte mandatory
-embed string scope_list
+embed ascii scope_list
# DHCP Rapid Commit, RFC4039
define 80 norequest flag rapid_commit
# DHCP Novell Directory Services, RFC2241
define 85 array ipaddress nds_servers
-define 86 string nds_tree_name
-define 87 string nds_context
+define 86 raw nds_tree_name
+define 87 raw nds_context
# DHCP Broadcast and Multicast Control Server, RFC4280
-define 88 domain bcms_controller_names
+define 88 array domain bcms_controller_names
define 89 array ipaddress bcms_controller_address
# DHCP Authentication, RFC3118
define 118 ipaddress subnet_selection
# DHCP Domain Search, RFC3397
-define 119 domain domain_search
+define 119 array domain domain_search
# DHCP Session Initiated Protocol Servers, RFC3361
define 120 rfc3361 sip_server
encap 3 domain es
# DHCP SIP UA, RFC6011
-define 141 domain sip_ua_cs_list
+define 141 array domain sip_ua_cs_list
# DHCP ANDSF, RFC6153
define 142 array ipaddress andsf
embed byte prf
embed ipaddress primary
embed ipaddress secondary
-embed domain domains
+embed array domain domains
# Options 147, 148 and 149 are unused, RFC3942
define6 20 flag reconfigure_accept
# DHCPv6 Session Initiation Protocol Options, RFC3319
-define6 21 domain sip_servers_names
+define6 21 array domain sip_servers_names
define6 22 array ip6address sip_servers_addresses
# DHCPv6 DNS Configuration Options, RFC3646
define6 23 array ip6address name_servers
-define6 24 domain domain_search
+define6 24 array domain domain_search
# DHCPv6 Prefix Options, RFC6603
define6 25 norequest index embed ia_pd
# DHCPv6 Network Information Service Options, RFC3898
define6 27 array ip6address nis_servers
define6 28 array ip6address nisp_servers
-define6 29 domain nis_domain_name
-define6 30 domain nisp_domain_name
+define6 29 string nis_domain_name
+define6 30 string nisp_domain_name
# DHCPv6 Simple Network Time Protocol Servers Option, RFC4075
define6 31 array ip6address sntp_servers
define6 32 uint32 info_refresh_time
# DHCPv6 Broadcast and Multicast Control Server, RFC4280
-define6 33 domain bcms_server_d
+define6 33 array domain bcms_server_d
define6 34 array ip6address bcms_server_a
# DHCP Civic Addresses Configuration Information, RFC4776
define6 57 domain access_domain
# DHCPv6 SIP UA, RFC6011
-define6 58 domain sip_ua_cs_list
+define6 58 array domain sip_ua_cs_list
# DHCPv6 Network Boot, RFC5970
define6 59 string bootfile_url
define6 74 embed rdnss_selection
embed ip6address server
embed byte prf
-embed domain domains
+embed array domain domains
# DHCPv6 Kerberos, RFC6784
-define6 75 domain krb_principal_name
-define6 76 domain krb_realm_name
+define6 75 string krb_principal_name
+define6 76 string krb_realm_name
define6 78 embed krb_kdc
embed uint16 priority
embed uint16 weight
embed byte transport_type
embed uint16 port
embed ip6address address
-embed domain realm_name
+embed string realm_name
# DHCPv6 Client Link-Layer Address, RFC6939
# Section 7 states that clients MUST ignore the option 79
if [ "$reason" = "TEST" ]; then
set | grep "^\(interface\|pid\|reason\|skip_hooks\)=" | sort
- set | grep "^if\(carrier\|flags\|mtu\|wireless\)=" | sort
+ set | grep "^if\(carrier\|flags\|mtu\|wireless\|ssid\)=" | sort
set | grep "^\(new_\|old_\|ra_count=\|ra[0-9]*_\)" | sort
exit 0
fi
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 26, 2014
+.Dd August 1, 2014
.Dt DHCPCD-RUN-HOOKS 8
.Os
.Sh NAME
.It Ev $ifmtu
.Ev $interface
MTU.
+.It Ev $ifssid
+the name of the SSID the
+.Ev interface
+is connected to.
.It Ev $interface_order
A list of interfaces, in order of preference.
.It Ev $if_up
.It Ev $profile
the name of the profile selected from
.Xr dhcpcd.conf 5 .
-.It Ev $new_ssid
-the name of the SSID the
-.Ev interface
-is connected to.
-.It Ev $old_ssid
-the name of the SSID the
-.Ev interface
-was connected to.
.It Ev $new_dhcp6_prefix
space separated list of delegated prefixes.
.El
Please report them to
.Lk http://roy.marples.name/projects/dhcpcd
.Sh SECURITY CONSIDERATIONS
-Little validation of DHCP options is done in dhcpcd itself.
-Instead, it is up to the hooks to handle any validation needed.
-To this end, some helper functions are provided, such as valid_domainname as
-used by the
-.Pa 20-resolv.conf
-hook to ensure that the hostname is not set to an invalid value.
-valid_path is also provided, but is currently unused by a stock hook script.
+.Nm dhcpcd
+will validate the content of each option against its encoding.
+For string, ascii, raw or binhex encoding it's up to the user to validate it
+for the intended purpose.
+.Pp
+When used in a shell script, each variable must be quoted correctly.
for details on how these scripts work.
.Nm
currently ignores the exit code of the script.
-.Pp
-.Nm
-converts all binary variables passed from the DHCP/RA message by
-encoding them as hex strings of the format XX:XX.
-This be decoded back into the raw binary form using
-.Xr dhcpcd-decode 8
-like so:
-.D1 dhcpcd-decode -x \*q$variable_name\*q
-or
-.D1 printf \*q%s\*q \*q$variable_name\*q | \e
-.D1 sed -e 's/://g' -e 's/\e([0-9A-F]\e{2\e}\e)/\e\e\e\e\e\ex\e1/gI' | \e
-.D1 xargs printf
-.Pp
-.Nm
-sanitises each string variable passed from the DHCP/RA message by encoding non
-printable characters in C style where possible, or escaped octal when not.
-The following characters are also escaped in C style (except for $ in octal):
-.D1 | \*[Am] \&; \*[Lt] \*[Gt] \&( \&) $ ` \e \*q ' \
-\*[Lt]tab\*[Gt] \*[Lt]newline\*[Gt]
-.D1 * \&? \&[ # ~ = %
-.Pp
-It is possible to reverse this encoding by passing the variable to
-.Xr dhcpcd-decode 8 ,
-like so:
-.D1 dhcpcd-decode \*q$variable_name\*q
-or to
-.Xr unvis 1
-like so:
-.D1 printf \*q%s\*q \*q$variable_name\*q | unvis
-.Pp
-To remove the shell escaped character encoding but keep the non printable
-character octal escaped and C style encoding you can do this:
-.D1 dhcpcd-decode -s \*q$variable-name\*q
-or
-.D1 printf \*q%s\*q \*q$variable_name\*q | unvis | vis -c
-.Pp
-If you have neither
-.Xr dhcpcd-decode 8
-or a working
-.Xr unvis 1 ,
-then the shell builtin eval could be used:
-.D1 eval \*q$variable_name\*q
-but that does not work well with any non printable characters and the $
-character.
.Ss Fine tuning
You can fine-tune the behaviour of
.Nm
.Xr if_nametoindex 3 ,
.Xr dhcpcd.conf 5 ,
.Xr resolv.conf 5 ,
-.Xr dhcpcd-decode 8 ,
.Xr dhcpcd-run-hooks 8 ,
.Xr resolvconf 8
.Sh STANDARDS
if (ifp->ssid_len) {
ssize_t r;
- r = print_string(pssid, sizeof(pssid), 0,
+ r = print_string(pssid, sizeof(pssid), ESCSTRING,
ifp->ssid, ifp->ssid_len);
if (r == -1) {
syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__);
.It Ic ip6address
An IPv6 address, 16 bytes
.It Ic string Op : Ic length
-A shell escaped string (binary data escaped as octal)
+A NVT ASCII string of printable characters.
.It Ic byte
A byte
.It Ic int16
A fixed value (1) to indicate that the option is present, 0 bytes
.It Ic domain
A RFC 3397 encoded string
+.It Ic dname
+A RFC 1035 validated string
.It Ic binhex Op : Ic length
Binary data expressed as hexadecimal
.It Ic embed
t |= SINT32;
else if (strcasecmp(arg, "flag") == 0)
t |= FLAG;
+ else if (strcasecmp(arg, "raw") == 0)
+ t |= STRING | RAW;
+ else if (strcasecmp(arg, "ascii") == 0)
+ t |= STRING | ASCII;
else if (strcasecmp(arg, "domain") == 0)
- t |= STRING | RFC3397;
+ t |= STRING | DOMAIN | RFC3397;
+ else if (strcasecmp(arg, "dname") == 0)
+ t |= STRING | DOMAIN;
else if (strcasecmp(arg, "binhex") == 0)
- t |= BINHEX;
+ t |= STRING | BINHEX;
else if (strcasecmp(arg, "embed") == 0)
t |= EMBED;
else if (strcasecmp(arg, "encap") == 0)
"ignoring length for type `%s'", arg);
l = 0;
}
- if (t & ARRAY && t & (STRING | BINHEX)) {
+ if (t & ARRAY && t & (STRING | BINHEX) &&
+ !(t & (RFC3397 | DOMAIN)))
+ {
syslog(LOG_WARNING, "ignoring array for strings");
t &= ~ARRAY;
}
decode_rfc3397(tmp, l, op, n);
l -= 1;
n = (size_t)print_string(NULL, 0,
- PS_SHELL, (const uint8_t *)tmp, l);
+ STRING | ARRAY | DOMAIN,
+ (const uint8_t *)tmp, l);
opt = malloc(n);
- if (opt)
- print_string(opt, n, PS_SHELL,
+ if (opt) {
+ print_string(opt, n,
+ STRING | ARRAY | DOMAIN,
(const uint8_t *)tmp, l);
- else
+ } else
syslog(LOG_ERR, "%s: %m",
__func__);
free(tmp);
snprintf(env[elen++], e, "profile=%s", ifp->profile);
}
if (ifp->wireless) {
- const char *pfx;
+ static const char *pfx = "ifssid=";
size_t pfx_len;
ssize_t psl;
- if (strcmp(reason, "CARRIER") == 0)
- pfx = "new_ssid=";
- else if (strcmp(reason, "NOCARRIER") == 0)
- pfx = "old_ssid=";
- else
- pfx = "if_ssid=";
-
pfx_len = strlen(pfx);
- psl = print_string(NULL, 0, PS_SHELL,
+ psl = print_string(NULL, 0, ESCSTRING,
(const uint8_t *)ifp->ssid, ifp->ssid_len);
if (psl != -1) {
EMALLOC(elen, pfx_len + (size_t)psl + 1);
memcpy(env[elen], pfx, pfx_len);
print_string(env[elen] + pfx_len, (size_t)psl,
- PS_SHELL,
+ ESCSTRING,
(const uint8_t *)ifp->ssid, ifp->ssid_len);
elen++;
}