[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    dhcpd domain-search patch
From:       William Ahern <william () 25thandclement ! com>
Date:       2019-02-27 7:33:46
Message-ID: 20190227073346.GA44474 () wilbur ! 25thandClement ! com
[Download RAW message or body]

systemd's dhcp client doesn't accept the hack of putting multiple,
space-separated search domains in the domain-name option. The following
patch parses option domain-search as a list of host names and uses
dn_comp(3) from libc to compress the list for the on-wire option value.

Example dhcpd.conf usage:

  option domain-search openbsd.org, example.com, a.example.com;

Index: confpars.c
===================================================================
RCS file: /cvs/src/usr.sbin/dhcpd/confpars.c,v
retrieving revision 1.33
diff -u -p -r1.33 confpars.c
--- confpars.c	24 Apr 2017 14:58:36 -0000	1.33
+++ confpars.c	27 Feb 2019 07:23:41 -0000
@@ -43,7 +43,9 @@
 
 #include <net/if.h>
 
+#include <limits.h>
 #include <netdb.h>
+#include <resolv.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1207,6 +1209,12 @@ parse_option_param(FILE *cfile, struct g
 					tree = tree_concat(tree, tree_const(
 					    buf, (cprefix + 7) / 8));
 				break;
+			case 'Z':
+				t = parse_domain_and_comp(cfile, uniform);
+				if (!t)
+					return;
+				tree = tree_concat(tree, t);
+				break;
 			default:
 				log_warnx("Bad format %c in "
 				    "parse_option_param.", *fmt);
@@ -1467,4 +1475,82 @@ parse_address_range(FILE *cfile, struct 
 
 	/* Create the new address range. */
 	new_address_range(low, high, subnet, dynamic);
+}
+
+static void push_domain_list(char ***domains, size_t *count, char *domain)
+{
+	*domains = reallocarray(*domains, *count + 1, sizeof **domains);
+	if (!*domains)
+		fatalx("Can't allocate domain list");
+
+	(*domains)[*count] = domain;
+	++*count;
+}
+
+static void
+free_domain_list(char **domains, size_t count)
+{
+	for (size_t i = 0; i < count; i++)
+		free(domains[i]);
+	free(domains);
+}
+
+struct tree *
+parse_domain_and_comp(FILE *cfile, int uniform)
+{
+	char **domains = NULL;
+	size_t count = 0;
+	unsigned char *buf = NULL;
+	size_t bufsiz = 0, bufn = 0;
+	unsigned char **bufptrs = NULL;
+	struct tree *rv = NULL;
+	int token;
+
+	do {
+		char *domain;
+
+		domain = parse_host_name(cfile);
+		if (!domain)
+			goto error;
+		push_domain_list(&domains, &count, domain);
+		/*
+		 * openbsd.org normally compresses to [7]openbsd[3]org[0]. 
+		 * +2 to string length provides space for leading and
+		 * trailing (root) prefix lengths not already accounted for
+		 * by dots, and also provides sufficient space for pointer
+		 * compression.
+		 */
+		bufsiz = bufsiz + 2 + strlen(domain);
+		token = peek_token(NULL, cfile);
+		if (token == ',')
+			token = next_token(NULL, cfile);
+	} while (uniform && token == ',');
+
+	buf = malloc(bufsiz);
+	if (!buf)
+		fatalx("Can't allocate compressed domain buffer");
+	bufptrs = calloc(count + 1, sizeof *bufptrs);
+	if (!bufptrs)
+		fatalx("Can't allocate compressed pointer list");
+	bufptrs[0] = buf;
+	
+	/* dn_comp takes an int for the output buffer size */
+	if (!(bufsiz <= INT_MAX))
+		fatalx("Size of compressed domain buffer too large");
+	for (size_t i = 0; i < count; i++) {
+		int n;
+
+		/* see bufsiz <= INT_MAX assertion, above */
+		n = dn_comp(domains[i], &buf[bufn], bufsiz - bufn, bufptrs, &bufptrs[count + 1]);
+		if (n == -1)
+			fatalx("Can't compress domain");
+		bufn += (size_t)n;
+	}
+
+	rv = tree_const(buf, bufn);
+error:
+	free_domain_list(domains, count);
+	free(buf);
+	free(bufptrs);
+	return rv;
 }
Index: dhcp.h
===================================================================
RCS file: /cvs/src/usr.sbin/dhcpd/dhcp.h,v
retrieving revision 1.10
diff -u -p -r1.10 dhcp.h
--- dhcp.h	21 Jan 2014 03:07:51 -0000	1.10
+++ dhcp.h	27 Feb 2019 07:23:41 -0000
@@ -171,6 +171,7 @@ 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
Index: dhcpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/dhcpd/dhcpd.h,v
retrieving revision 1.66
diff -u -p -r1.66 dhcpd.h
--- dhcpd.h	4 Aug 2017 02:01:46 -0000	1.66
+++ dhcpd.h	27 Feb 2019 07:23:41 -0000
@@ -371,6 +371,7 @@ time_t			 parse_date(FILE *);
 unsigned char		*parse_numeric_aggregate(FILE *, unsigned char *,
 			    int *, int, int, int);
 void			 convert_num(unsigned char *, char *, int, int);
+struct tree		*parse_domain_and_comp(FILE *, int);
 
 /* tree.c */
 pair			 cons(caddr_t, pair);
Index: tables.c
===================================================================
RCS file: /cvs/src/usr.sbin/dhcpd/tables.c,v
retrieving revision 1.13
diff -u -p -r1.13 tables.c
--- tables.c	13 Feb 2017 19:13:14 -0000	1.13
+++ tables.c	27 Feb 2019 07:23:41 -0000
@@ -193,7 +193,7 @@ struct option dhcp_options[256] = {
 	{ "option-116", "X",				&dhcp_universe, 116 },
 	{ "option-117", "X",				&dhcp_universe, 117 },
 	{ "option-118", "X",				&dhcp_universe, 118 },
-	{ "option-119", "X",				&dhcp_universe, 119 },
+	{ "domain-search", "ZA",			&dhcp_universe, 119 },
 	{ "option-120", "X",				&dhcp_universe, 120 },
 	{ "classless-static-routes", "CIA",		&dhcp_universe, 121 },
 	{ "option-122", "X",				&dhcp_universe, 122 },
@@ -367,6 +367,7 @@ unsigned char dhcp_option_default_priori
 	DHO_BOOT_SIZE,
 	DHO_MERIT_DUMP,
 	DHO_DOMAIN_NAME,
+	DHO_DOMAIN_SEARCH,
 	DHO_SWAP_SERVER,
 	DHO_ROOT_PATH,
 	DHO_EXTENSIONS_PATH,
@@ -412,7 +413,7 @@ unsigned char dhcp_option_default_priori
 	 80,  81,       83,  84,  85,  86,  87,  88,  89,
 	 90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
 	100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-	110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+	110, 111, 112, 113, 114, 115, 116, 117, 118,
 	120,      122, 123, 124, 125, 126, 127, 128, 129,
 	130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
 	140, 141, 142, 143, 144, 145, 146, 147, 148, 149,

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic