Search" if supplied by the server.
Requested by a few. Original diff from Ray Lai via tech@.
Tested & ok claudio@
-/* $OpenBSD: clparse.c,v 1.92 2015/05/18 17:51:21 krw Exp $ */
+/* $OpenBSD: clparse.c,v 1.93 2015/10/26 16:32:33 krw Exp $ */
/* Parser for dhclient config and lease files. */
[config->requested_option_count++] = DHO_ROUTERS;
config->requested_options
[config->requested_option_count++] = DHO_DOMAIN_NAME;
+ config->requested_options
+ [config->requested_option_count++] = DHO_DOMAIN_SEARCH;
config->requested_options
[config->requested_option_count++] = DHO_DOMAIN_NAME_SERVERS;
config->requested_options
-/* $OpenBSD: dhclient.c,v 1.364 2015/09/08 17:19:20 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.365 2015/10/26 16:32:33 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
void fork_privchld(int, int);
void get_ifname(char *);
char *resolv_conf_contents(struct option_data *,
- struct option_data *);
+ struct option_data *, struct option_data *);
void write_resolv_conf(u_int8_t *, size_t);
void write_option_db(u_int8_t *, size_t);
}
client->new->resolv_conf = resolv_conf_contents(
- &options[DHO_DOMAIN_NAME], &options[DHO_DOMAIN_NAME_SERVERS]);
+ &options[DHO_DOMAIN_NAME], &options[DHO_DOMAIN_NAME_SERVERS],
+ &options[DHO_DOMAIN_SEARCH]);
/* Replace the old active lease with the new one. */
client->active = client->new;
packet_to_lease(struct in_addr client_addr, struct option_data *options)
{
struct client_lease *lease;
- char *pretty;
- int i;
+ char *pretty, *buf;
+ int i, sz;
lease = calloc(1, sizeof(struct client_lease));
if (!lease) {
if (strlen(pretty) == 0)
continue;
switch (i) {
+ case DHO_DOMAIN_SEARCH:
+ /* Must decode the option into text to check names. */
+ buf = calloc(1, DHCP_DOMAIN_SEARCH_LEN);
+ if (buf == NULL)
+ error("No memory to decode domain search");
+ sz = pretty_print_domain_search(buf,
+ DHCP_DOMAIN_SEARCH_LEN,
+ options[i].data, options[i].len);
+ if (strlen(buf) == 0)
+ continue;
+ if (sz == -1 || !res_hnok_list(buf))
+ warning("Bogus data for option %s",
+ dhcp_options[i].name);
+ free(buf);
+ break;
case DHO_DOMAIN_NAME:
/*
* Allow deviant but historically blessed
}
/*
- * resolv_conf(5) says a max of 6 domains and total length of 1024 bytes are
- * acceptable for the 'search' statement.
+ * resolv_conf(5) says a max of DHCP_DOMAIN_SEARCH_CNT domains and total
+ * length of DHCP_DOMAIN_SEARCH_LEN bytes are acceptable for the 'search'
+ * statement.
*/
int
res_hnok_list(const char *names)
char *dupnames, *hn, *inputstring;
int count;
- if (strlen(names) >= 1024)
+ if (strlen(names) >= DHCP_DOMAIN_SEARCH_LEN)
return (0);
dupnames = inputstring = strdup(names);
if (res_hnok(hn) == 0)
break;
count++;
- if (count > 6)
+ if (count > DHCP_DOMAIN_SEARCH_CNT)
break;
}
*/
char *
resolv_conf_contents(struct option_data *domainname,
- struct option_data *nameservers)
+ struct option_data *nameservers, struct option_data *domainsearch)
{
- char *dn, *ns, *nss[MAXNS], *contents, *courtesy, *p;
+ char *dn, *ns, *nss[MAXNS], *contents, *courtesy, *p, *buf;
size_t len;
- int i, rslt;
+ int i, rslt, sz;
memset(nss, 0, sizeof(nss));
- if (domainname->len) {
+ if (domainsearch->len) {
+ buf = calloc(1, DHCP_DOMAIN_SEARCH_LEN);
+ if (buf == NULL)
+ error("No memory to decode domain search");
+ sz = pretty_print_domain_search(buf, DHCP_DOMAIN_SEARCH_LEN,
+ domainsearch->data, domainsearch->len);
+ if (sz == -1)
+ dn = strdup("");
+ else {
+ rslt = asprintf(&dn, "search %s\n", buf);
+ if (rslt == -1)
+ dn = NULL;
+ }
+ free(buf);
+ } else if (domainname->len) {
rslt = asprintf(&dn, "search %s\n",
pretty_print_option(DHO_DOMAIN_NAME, domainname, 0));
if (rslt == -1)
-/* $OpenBSD: dhcp.h,v 1.17 2014/01/21 03:07:50 krw Exp $ */
+/* $OpenBSD: dhcp.h,v 1.18 2015/10/26 16:32:33 krw Exp $ */
/* Protocol structures. */
#define DHCP_MTU_MAX 1500
#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
+/* Respect historical limits on 'search' line in resolv.conf(5) */
+#define DHCP_DOMAIN_SEARCH_LEN 1024
+#define DHCP_DOMAIN_SEARCH_CNT 6
+
#define BOOTP_MIN_LEN 300
struct dhcp_packet {
#define DHO_NDS_SERVERS 85
#define DHO_NDS_TREE_NAME 86
#define DHO_NDS_CONTEXT 87
+#define DHO_DOMAIN_SEARCH 119
#define DHO_CLASSLESS_STATIC_ROUTES 121
#define DHO_TFTP_CONFIG_FILE 144
#define DHO_VOIP_CONFIGURATION_SERVER 150
-/* $OpenBSD: dhcpd.h,v 1.151 2015/08/19 17:52:10 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.152 2015/10/26 16:32:33 krw Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
int pretty_print_string(unsigned char *, size_t, unsigned char *, size_t, int);
int pretty_print_classless_routes(unsigned char *, size_t, unsigned char *,
size_t);
+int pretty_print_domain_search(unsigned char *, size_t, unsigned char *,
+ size_t);
void do_packet(unsigned int, struct in_addr, struct ether_addr *);
/* errwarn.c */
-/* $OpenBSD: options.c,v 1.73 2014/10/27 17:01:28 krw Exp $ */
+/* $OpenBSD: options.c,v 1.74 2015/10/26 16:32:33 krw Exp $ */
/* DHCP options parsing and reassembly. */
#include <vis.h>
int parse_option_buffer(struct option_data *, unsigned char *, int);
+int expand_search_domain_name(unsigned char *, size_t, int *, unsigned char *);
/*
* Parse options out of the specified buffer, storing addresses of
return (total);
}
+int
+expand_search_domain_name(unsigned char *src, size_t srclen, int *offset,
+ unsigned char *domain_search)
+{
+ int domain_name_len, i, label_len, pointer, pointed_len;
+ char *cursor;
+
+ cursor = domain_search + strlen(domain_search);
+ domain_name_len = 0;
+
+ i = *offset;
+ while (i <= srclen) {
+ label_len = src[i];
+ if (label_len == 0) {
+ /*
+ * A zero-length label marks the end of this
+ * domain name.
+ */
+ *offset = i + 1;
+ return (domain_name_len);
+ } else if (label_len & 0xC0) {
+ /* This is a pointer to another list of labels. */
+ if (i + 1 >= srclen) {
+ /* The pointer is truncated. */
+ warning("Truncated pointer in DHCP Domain "
+ "Search option.");
+ return (-1);
+ }
+
+ pointer = ((label_len & ~(0xC0)) << 8) + src[i + 1];
+ if (pointer >= *offset) {
+ /*
+ * The pointer must indicates a prior
+ * occurance.
+ */
+ warning("Invalid forward pointer in DHCP "
+ "Domain Search option compression.");
+ return (-1);
+ }
+
+ pointed_len = expand_search_domain_name(src, srclen,
+ &pointer, domain_search);
+ domain_name_len += pointed_len;
+
+ *offset = i + 2;
+ return (domain_name_len);
+ }
+ if (i + label_len + 1 > srclen) {
+ warning("Truncated label in DHCP Domain Search "
+ "option.");
+ return (-1);
+ }
+ /*
+ * Update the domain name length with the length of the
+ * current label, plus a trailing dot ('.').
+ */
+ domain_name_len += label_len + 1;
+
+ if (strlen(domain_search) + domain_name_len >=
+ DHCP_DOMAIN_SEARCH_LEN) {
+ warning("Domain search list too long.");
+ return (-1);
+ }
+
+ /* Copy the label found. */
+ memcpy(cursor, src + i + 1, label_len);
+ cursor[label_len] = '.';
+
+ /* Move cursor. */
+ i += label_len + 1;
+ cursor += label_len + 1;
+ }
+
+ warning("Truncated DHCP Domain Search option.");
+
+ return (-1);
+}
+
+/*
+ * Must special case DHO_DOMAIN_SEARCH because it is encoded as described
+ * in RFC 1035 section 4.1.4.
+ */
+int
+pretty_print_domain_search(unsigned char *dst, size_t dstlen,
+ unsigned char *src, size_t srclen)
+{
+ int offset, len, expanded_len, domains;
+ unsigned char *domain_search, *cursor;
+
+ domain_search = calloc(1, DHCP_DOMAIN_SEARCH_LEN);
+ if (domain_search == NULL)
+ error("Can't allocate storage for expanded domain-search\n");
+
+ /* Compute expanded length. */
+ expanded_len = len = 0;
+ domains = 0;
+ offset = 0;
+ while (offset < srclen) {
+ cursor = domain_search + strlen(domain_search);
+ if (domain_search[0]) {
+ *cursor = ' ';
+ expanded_len++;
+ }
+ len = expand_search_domain_name(src, srclen, &offset,
+ domain_search);
+ if (len == -1) {
+ free(domain_search);
+ return (-1);
+ }
+ domains++;
+ expanded_len += len;
+ if (domains > DHCP_DOMAIN_SEARCH_CNT) {
+ free(domain_search);
+ return (-1);
+ }
+ }
+
+ strlcat(dst, domain_search, dstlen);
+ free(domain_search);
+
+ return (0);
+}
+
/*
* Format the specified option so that a human can easily read it.
*/
-/* $OpenBSD: tables.c,v 1.18 2014/01/21 03:07:50 krw Exp $ */
+/* $OpenBSD: tables.c,v 1.19 2015/10/26 16:32:33 krw Exp $ */
/* Tables of information. */
/* 116 */ { "option-116", "X" },
/* 117 */ { "option-117", "X" },
/* 118 */ { "option-118", "X" },
- /* 119 */ { "option-119", "X" },
+ /* 119 */ { "domain-search", "X" },
/* 120 */ { "option-120", "X" },
/* 121 */ { "classless-static-routes", "CIA" },
/* 122 */ { "option-122", "X" },