1/*	$NetBSD: tables.c,v 1.4 2022/04/03 01:10:58 christos Exp $	*/
2
3/* tables.c
4
5   Tables of information... */
6
7/*
8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1995-2003 by Internet Software Consortium
10 *
11 * This Source Code Form is subject to the terms of the Mozilla Public
12 * License, v. 2.0. If a copy of the MPL was not distributed with this
13 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 *   Internet Systems Consortium, Inc.
24 *   PO Box 360
25 *   Newmarket, NH 03857 USA
26 *   <info@isc.org>
27 *   https://www.isc.org/
28 *
29 */
30
31#include <sys/cdefs.h>
32__RCSID("$NetBSD: tables.c,v 1.4 2022/04/03 01:10:58 christos Exp $");
33
34#include "dhcpd.h"
35
36/* XXXDPN: Moved here from hash.c, when it moved to libomapi.  Not sure
37   where these really belong. */
38HASH_FUNCTIONS (group, const char *, struct group_object, group_hash_t,
39		group_reference, group_dereference, do_string_hash)
40HASH_FUNCTIONS (universe, const char *, struct universe, universe_hash_t, 0, 0,
41		do_case_hash)
42HASH_FUNCTIONS (option_name, const char *, struct option, option_name_hash_t,
43		option_reference, option_dereference, do_case_hash)
44HASH_FUNCTIONS (option_code, const unsigned *, struct option,
45		option_code_hash_t, option_reference, option_dereference,
46		do_number_hash)
47
48/* DHCP Option names, formats and codes, from RFC1533.
49
50   Format codes:
51
52   I - IPv4 address
53   6 - IPv6 address
54   l - 32-bit signed integer
55   L - 32-bit unsigned integer
56   s - 16-bit signed integer
57   S - 16-bit unsigned integer
58   b - 8-bit signed integer
59   B - 8-bit unsigned integer
60   t - ASCII text
61   T - Lease Time, 32-bit unsigned integer implying a number of seconds from
62       some event.  The special all-ones value means 'infinite'.  May either
63       be printed as a decimal, eg, "3600", or as this name, eg, "infinite".
64   f - flag (true or false)
65   A - array of all that precedes (e.g., fIA means array of records of
66       a flag and an IP address)
67   a - array of the preceding character (e.g., fIa means a single flag
68       followed by an array of IP addresses)
69   U - name of an option space (universe)
70   F - implicit flag - the presence of the option indicates that the
71       flag is true.
72   o - the preceding value is optional.
73   E - encapsulation, string or colon-separated hex list (the latter
74       two for parsing).   E is followed by a text string containing
75       the name of the option space to encapsulate, followed by a '.'.
76       If the E is immediately followed by '.', the applicable vendor
77       option space is used if one is defined.
78   e - If an encapsulation directive is not the first thing in the string,
79       the option scanner requires an efficient way to find the encapsulation.
80       This is done by placing a 'e' at the beginning of the option.   The
81       'e' has no other purpose, and is not required if 'E' is the first
82       thing in the option.
83   X - either an ASCII string or binary data.   On output, the string is
84       scanned to see if it's printable ASCII and, if so, output as a
85       quoted string.   If not, it's output as colon-separated hex.   On
86       input, the option can be specified either as a quoted string or as
87       a colon-separated hex list.
88   N - enumeration.   N is followed by a text string containing
89       the name of the set of enumeration values to parse or emit,
90       followed by a '.'.   The width of the data is specified in the
91       named enumeration.   Named enumerations are tracked in parse.c.
92   d - Domain name (e.g., FOO or FOO.BAR) no quotes,
93       on-wire format is RFC 1035.
94   D - Domain list (e.g., "example.com eng.example.com") quoted,
95       on-wire format is RFC 1035.
96   c - When following a 'D' atom, enables compression pointers.
97   Z - Zero-length option
98   k - Key name, unquoted string (e.g. mykey.com or some-text or abc123)
99       parsed with parse_host_name().
100*/
101
102struct universe dhcp_universe;
103static struct option dhcp_options[] = {
104	{ "subnet-mask", "I",			&dhcp_universe,   1, 1 },
105	{ "time-offset", "l",			&dhcp_universe,   2, 1 },
106	{ "routers", "IA",			&dhcp_universe,   3, 1 },
107	{ "time-servers", "IA",			&dhcp_universe,   4, 1 },
108	{ "ien116-name-servers", "IA",		&dhcp_universe,   5, 1 },
109	{ "domain-name-servers", "IA",		&dhcp_universe,   6, 1 },
110	{ "log-servers", "IA",			&dhcp_universe,   7, 1 },
111	{ "cookie-servers", "IA",		&dhcp_universe,   8, 1 },
112	{ "lpr-servers", "IA",			&dhcp_universe,   9, 1 },
113	{ "impress-servers", "IA",		&dhcp_universe,  10, 1 },
114	{ "resource-location-servers", "IA",	&dhcp_universe,  11, 1 },
115	{ "host-name", "t",			&dhcp_universe,  12, 1 },
116	{ "boot-size", "S",			&dhcp_universe,  13, 1 },
117	{ "merit-dump", "t",			&dhcp_universe,  14, 1 },
118	{ "domain-name", "t",			&dhcp_universe,  15, 1 },
119	{ "swap-server", "I",			&dhcp_universe,  16, 1 },
120	{ "root-path", "t",			&dhcp_universe,  17, 1 },
121	{ "extensions-path", "t",		&dhcp_universe,  18, 1 },
122	{ "ip-forwarding", "f",			&dhcp_universe,  19, 1 },
123	{ "non-local-source-routing", "f",	&dhcp_universe,  20, 1 },
124	{ "policy-filter", "IIA",		&dhcp_universe,  21, 1 },
125	{ "max-dgram-reassembly", "S",		&dhcp_universe,  22, 1 },
126	{ "default-ip-ttl", "B",		&dhcp_universe,  23, 1 },
127	{ "path-mtu-aging-timeout", "L",	&dhcp_universe,  24, 1 },
128	{ "path-mtu-plateau-table", "SA",	&dhcp_universe,  25, 1 },
129	{ "interface-mtu", "S",			&dhcp_universe,  26, 1 },
130	{ "all-subnets-local", "f",		&dhcp_universe,  27, 1 },
131	{ "broadcast-address", "I",		&dhcp_universe,  28, 1 },
132	{ "perform-mask-discovery", "f",	&dhcp_universe,  29, 1 },
133	{ "mask-supplier", "f",			&dhcp_universe,  30, 1 },
134	{ "router-discovery", "f",		&dhcp_universe,  31, 1 },
135	{ "router-solicitation-address", "I",	&dhcp_universe,  32, 1 },
136	{ "static-routes", "IIA",		&dhcp_universe,  33, 1 },
137	{ "trailer-encapsulation", "f",		&dhcp_universe,  34, 1 },
138	{ "arp-cache-timeout", "L",		&dhcp_universe,  35, 1 },
139	{ "ieee802-3-encapsulation", "f",	&dhcp_universe,  36, 1 },
140	{ "default-tcp-ttl", "B",		&dhcp_universe,  37, 1 },
141	{ "tcp-keepalive-interval", "L",	&dhcp_universe,  38, 1 },
142	{ "tcp-keepalive-garbage", "f",		&dhcp_universe,  39, 1 },
143	{ "nis-domain", "t",			&dhcp_universe,  40, 1 },
144	{ "nis-servers", "IA",			&dhcp_universe,  41, 1 },
145	{ "ntp-servers", "IA",			&dhcp_universe,  42, 1 },
146	{ "vendor-encapsulated-options", "E.",	&dhcp_universe,  43, 1 },
147	{ "netbios-name-servers", "IA",		&dhcp_universe,  44, 1 },
148	{ "netbios-dd-server", "IA",		&dhcp_universe,  45, 1 },
149	{ "netbios-node-type", "B",		&dhcp_universe,  46, 1 },
150	{ "netbios-scope", "t",			&dhcp_universe,  47, 1 },
151	{ "font-servers", "IA",			&dhcp_universe,  48, 1 },
152	{ "x-display-manager", "IA",		&dhcp_universe,  49, 1 },
153	{ "dhcp-requested-address", "I",	&dhcp_universe,  50, 1 },
154	{ "dhcp-lease-time", "L",		&dhcp_universe,  51, 1 },
155	{ "dhcp-option-overload", "B",		&dhcp_universe,  52, 1 },
156	{ "dhcp-message-type", "B",		&dhcp_universe,  53, 1 },
157	{ "dhcp-server-identifier", "I",	&dhcp_universe,  54, 1 },
158	{ "dhcp-parameter-request-list", "BA",	&dhcp_universe,  55, 1 },
159	{ "dhcp-message", "t",			&dhcp_universe,  56, 1 },
160	{ "dhcp-max-message-size", "S",		&dhcp_universe,  57, 1 },
161	{ "dhcp-renewal-time", "L",		&dhcp_universe,  58, 1 },
162	{ "dhcp-rebinding-time", "L",		&dhcp_universe,  59, 1 },
163	{ "vendor-class-identifier", "X",	&dhcp_universe,  60, 1 },
164	{ "dhcp-client-identifier", "X",	&dhcp_universe,  61, 1 },
165	{ "nwip-domain", "t",			&dhcp_universe,  62, 1 },
166	{ "nwip-suboptions", "Enwip.",		&dhcp_universe,  63, 1 },
167	{ "nisplus-domain", "t",		&dhcp_universe,  64, 1 },
168	{ "nisplus-servers", "IA",		&dhcp_universe,  65, 1 },
169	{ "tftp-server-name", "t",		&dhcp_universe,  66, 1 },
170	{ "bootfile-name", "t",			&dhcp_universe,  67, 1 },
171	{ "mobile-ip-home-agent", "IA",		&dhcp_universe,  68, 1 },
172	{ "smtp-server", "IA",			&dhcp_universe,  69, 1 },
173	{ "pop-server", "IA",			&dhcp_universe,  70, 1 },
174	{ "nntp-server", "IA",			&dhcp_universe,  71, 1 },
175	{ "www-server", "IA",			&dhcp_universe,  72, 1 },
176	{ "finger-server", "IA",		&dhcp_universe,  73, 1 },
177	{ "irc-server", "IA",			&dhcp_universe,  74, 1 },
178	{ "streettalk-server", "IA",		&dhcp_universe,  75, 1 },
179	{ "streettalk-directory-assistance-server", "IA",
180						&dhcp_universe,  76, 1 },
181	{ "user-class", "t",			&dhcp_universe,  77, 1 },
182	{ "slp-directory-agent", "fIa",		&dhcp_universe,  78, 1 },
183	{ "slp-service-scope", "fto",		&dhcp_universe,  79, 1 },
184	/* 80 is the zero-length rapid-commit (RFC 4039) */
185	{ "fqdn", "Efqdn.",			&dhcp_universe,  81, 1 },
186	{ "relay-agent-information", "Eagent.",	&dhcp_universe,  82, 1 },
187	/* 83 is iSNS (RFC 4174) */
188	/* 84 is unassigned */
189	{ "nds-servers", "IA",			&dhcp_universe,  85, 1 },
190	{ "nds-tree-name", "t",			&dhcp_universe,  86, 1 },
191	{ "nds-context", "t",			&dhcp_universe,  87, 1 },
192
193	/* Note: RFC4280 fails to identify if the DHCPv4 option is to use
194	 * compression pointers or not.  Assume not.
195	 */
196	{ "bcms-controller-names", "D",		&dhcp_universe,  88, 1 },
197	{ "bcms-controller-address", "Ia",	&dhcp_universe,  89, 1 },
198
199	/* 90 is the authentication option (RFC 3118) */
200
201	{ "client-last-transaction-time", "L",  &dhcp_universe,  91, 1 },
202	{ "associated-ip", "Ia",                &dhcp_universe,  92, 1 },
203#if defined(RFC4578_OPTIONS)
204	/* Defined by RFC 4578 */
205	{ "pxe-system-type", "Sa",		&dhcp_universe,  93, 1 },
206	{ "pxe-interface-id", "BBB",		&dhcp_universe,  94, 1 },
207	{ "pxe-client-id", "BX",		&dhcp_universe,  97, 1 },
208#endif
209	{ "uap-servers", "t",			&dhcp_universe,  98, 1 },
210#if defined(RFC4776_OPTIONS)
211        { "geoconf-civic", "X",                 &dhcp_universe, 99, 1 },
212#endif
213#if defined(RFC4833_OPTIONS)
214	{ "pcode", "t",				&dhcp_universe, 100, 1 },
215	{ "tcode", "t",				&dhcp_universe, 101, 1 },
216#endif
217#if defined(RFC8925_OPTIONS)
218	{ "v6-only-preferred", "L",		&dhcp_universe, 108, 1 },
219#endif
220	{ "netinfo-server-address", "Ia",	&dhcp_universe, 112, 1 },
221	{ "netinfo-server-tag", "t",		&dhcp_universe, 113, 1 },
222	{ "default-url", "t",			&dhcp_universe, 114, 1 },
223#if defined(RFC2563_OPTIONS)
224	{ "auto-config", "B",			&dhcp_universe, 116, 1 },
225#endif
226#if defined(RFC2937_OPTIONS)
227	{ "name-service-search", "Sa",		&dhcp_universe, 117, 1 },
228#endif
229	{ "subnet-selection", "I",		&dhcp_universe, 118, 1 },
230	{ "domain-search", "Dc",		&dhcp_universe, 119, 1 },
231	{ "vivco", "Evendor-class.",		&dhcp_universe, 124, 1 },
232	{ "vivso", "Evendor.",			&dhcp_universe, 125, 1 },
233#if 0
234	/* Referenced by RFC 4578.
235	 * DO NOT UNCOMMENT THESE DEFINITIONS: these names are placeholders
236	 * and will not be used in future versions of the software.
237	 */
238	{ "pxe-undefined-1", "X",		&dhcp_universe, 128, 1 },
239	{ "pxe-undefined-2", "X",		&dhcp_universe, 129, 1 },
240	{ "pxe-undefined-3", "X",		&dhcp_universe, 130, 1 },
241	{ "pxe-undefined-4", "X",		&dhcp_universe, 131, 1 },
242	{ "pxe-undefined-5", "X",		&dhcp_universe, 132, 1 },
243	{ "pxe-undefined-6", "X",		&dhcp_universe, 133, 1 },
244	{ "pxe-undefined-7", "X",		&dhcp_universe, 134, 1 },
245	{ "pxe-undefined-8", "X",		&dhcp_universe, 135, 1 },
246#endif
247#if defined(RFC5192_OPTIONS)
248	{"pana-agent", "Ia",			&dhcp_universe, 136, 1 },
249#endif
250#if defined(RFC5223_OPTIONS)
251	{"v4-lost", "d",			&dhcp_universe, 137, 1 },
252#endif
253#if defined(RFC5417_OPTIONS)
254	{"capwap-ac-v4", "Ia",			&dhcp_universe, 138, 1 },
255#endif
256#if defined(RFC6011_OPTIONS)
257	{ "sip-ua-cs-domains", "Dc",		&dhcp_universe, 141, 1 },
258#endif
259#if defined(RFC6153_OPTIONS)
260	{ "ipv4-address-andsf", "IA",		&dhcp_universe, 142, 1 },
261#endif
262#if defined(RFC6731_OPTIONS)
263        { "rdnss-selection", "BIID",		&dhcp_universe, 146, 1 },
264#endif
265#if defined(RFC5859_OPTIONS)
266	{ "tftp-server-address", "Ia",		&dhcp_universe, 150, 1 },
267#endif
268#if defined(RFC7618_OPTIONS)
269	{ "v4-portparams", "BBS",		&dhcp_universe, 159, 1 },
270#endif
271#if defined(RFC7710_OPTIONS)
272	{ "v4-captive-portal", "t",		&dhcp_universe, 160, 1 },
273#endif
274#if defined(RFC5071_OPTIONS)
275#if  0
276	/* Option 208 has been officially deprecated. Do NOT define it */
277	{ "pxelinux-magic", "BBBB",		&dhcp_universe, 208, 1 },
278#endif
279	{ "loader-configfile", "t",		&dhcp_universe, 209, 1 },
280	{ "loader-pathprefix", "t",		&dhcp_universe, 210, 1 },
281	{ "loader-reboottime", "L",		&dhcp_universe, 211, 1 },
282#endif
283#if defined(RFC5969_OPTIONS)
284        { "option-6rd", "BB6Ia",		&dhcp_universe, 212, 1 },
285#endif
286#if defined(RFC5986_OPTIONS)
287	{"v4-access-domain", "d",		&dhcp_universe, 213, 1 },
288#endif
289	{ NULL, NULL, NULL, 0, 0 }
290};
291
292struct universe nwip_universe;
293static struct option nwip_options[] = {
294	{ "illegal-1", "",			&nwip_universe,   1, 1 },
295	{ "illegal-2", "",			&nwip_universe,   2, 1 },
296	{ "illegal-3", "",			&nwip_universe,   3, 1 },
297	{ "illegal-4", "",			&nwip_universe,   4, 1 },
298	{ "nsq-broadcast", "f",			&nwip_universe,   5, 1 },
299	{ "preferred-dss", "IA",		&nwip_universe,   6, 1 },
300	{ "nearest-nwip-server", "IA",		&nwip_universe,   7, 1 },
301	{ "autoretries", "B",			&nwip_universe,   8, 1 },
302	{ "autoretry-secs", "B",		&nwip_universe,   9, 1 },
303	{ "nwip-1-1", "f",			&nwip_universe,  10, 1 },
304	{ "primary-dss", "I",			&nwip_universe,  11, 1 },
305	{ NULL, NULL, NULL, 0, 0 }
306};
307
308/* Note that the "FQDN suboption space" does not reflect the FQDN option
309 * format - rather, this is a handy "virtualization" of a flat option
310 * which makes manual configuration and presentation of some of its
311 * contents easier (each of these suboptions is a fixed-space field within
312 * the fqdn contents - domain and host names are derived from a common field,
313 * and differ in the left and right hand side of the leftmost dot, fqdn is
314 * the combination of the two).
315 *
316 * Note further that the DHCPv6 and DHCPv4 'fqdn' options use the same
317 * virtualized option space to store their work.
318 */
319
320struct universe fqdn_universe;
321struct universe fqdn6_universe;
322static struct option fqdn_options[] = {
323	{ "no-client-update", "f",		&fqdn_universe,   1, 1 },
324	{ "server-update", "f",			&fqdn_universe,   2, 1 },
325	{ "encoded", "f",			&fqdn_universe,   3, 1 },
326	{ "rcode1", "B",			&fqdn_universe,   4, 1 },
327	{ "rcode2", "B",			&fqdn_universe,   5, 1 },
328	{ "hostname", "t",			&fqdn_universe,   6, 1 },
329	{ "domainname", "t",			&fqdn_universe,   7, 1 },
330	{ "fqdn", "t",				&fqdn_universe,   8, 1 },
331	{ NULL, NULL, NULL, 0, 0 }
332};
333
334struct universe vendor_class_universe;
335static struct option vendor_class_options[] =  {
336	{ "isc", "X",			&vendor_class_universe,      2495, 1 },
337	{ NULL, NULL, NULL, 0, 0 }
338};
339
340struct universe vendor_universe;
341static struct option vendor_options[] = {
342	{ "isc", "Eisc.",		&vendor_universe,            2495, 1 },
343	{ NULL, NULL, NULL, 0, 0 }
344};
345
346struct universe isc_universe;
347static struct option isc_options [] = {
348	{ "media", "t",				&isc_universe,   1, 1 },
349	{ "update-assist", "X",			&isc_universe,   2, 1 },
350	{ NULL,	NULL, NULL, 0, 0 }
351};
352
353struct universe dhcpv6_universe;
354static struct option dhcpv6_options[] = {
355
356				/* RFC3315 OPTIONS */
357
358	/* Client and server DUIDs are opaque fields, but marking them
359	 * up somewhat makes configuration easier.
360	 */
361	{ "client-id", "X",			&dhcpv6_universe,  1, 1 },
362	{ "server-id", "X",			&dhcpv6_universe,  2, 1 },
363
364	/* ia-* options actually have at their ends a space for options
365	 * that are specific to this instance of the option.  We can not
366	 * handle this yet at this stage of development, so the encoding
367	 * of these options is unspecified ("X").
368	 */
369	{ "ia-na", "X",				&dhcpv6_universe,  3, 1 },
370	{ "ia-ta", "X",				&dhcpv6_universe,  4, 1 },
371	{ "ia-addr", "X",			&dhcpv6_universe,  5, 1 },
372
373	/* "oro" is DHCPv6 speak for "parameter-request-list" */
374	{ "oro", "SA",				&dhcpv6_universe,  6, 1 },
375
376	{ "preference", "B",			&dhcpv6_universe,  7, 1 },
377	{ "elapsed-time", "S",			&dhcpv6_universe,  8, 1 },
378	{ "relay-msg", "X",			&dhcpv6_universe,  9, 1 },
379
380	/* Option code 10 is curiously unassigned. */
381	/*
382	 * In draft-ietf-dhc-dhcpv6-25 there were two OPTION_CLIENT_MSG and
383	 * OPTION_SERVER_MSG options. They were eventually unified as
384	 * OPTION_RELAY_MSG, hence no option with value of 10.
385	 */
386#if 0
387	/* XXX: missing suitable atoms for the auth option.  We may want
388	 * to 'virtually encapsulate' this option a la the fqdn option
389	 * seeing as it is processed explicitly by the server and unlikely
390	 * to be configured by hand by users as such.
391	 */
392	{ "auth", "Nauth-protocol.Nauth-algorithm.Nrdm-type.LLX",
393						&dhcpv6_universe, 11, 1 },
394#endif
395	{ "unicast", "6",			&dhcpv6_universe, 12, 1 },
396	{ "status-code", "Nstatus-codes.to",	&dhcpv6_universe, 13, 1 },
397	{ "rapid-commit", "Z",			&dhcpv6_universe, 14, 1 },
398#if 0
399	/* XXX: user-class contents are of the form "StA" where the
400	 * integer describes the length of the text field.  We don't have
401	 * an atom for pre-determined-length octet strings yet, so we
402	 * can't quite do these two.
403	 */
404	{ "user-class", "X",			&dhcpv6_universe, 15, 1 },
405	{ "vendor-class", "X",			&dhcpv6_universe, 16, 1 },
406#endif
407	{ "vendor-opts", "Evsio.",		&dhcpv6_universe, 17, 1 },
408	{ "interface-id", "X",			&dhcpv6_universe, 18, 1 },
409	{ "reconf-msg", "Ndhcpv6-messages.",	&dhcpv6_universe, 19, 1 },
410	{ "reconf-accept", "Z",			&dhcpv6_universe, 20, 1 },
411
412				/* RFC3319 OPTIONS */
413
414	/* Of course: we would HAVE to have a different atom for
415	 * domain names without compression.  Typical.
416	 */
417	{ "sip-servers-names", "D",		&dhcpv6_universe, 21, 1 },
418	{ "sip-servers-addresses", "6A",	&dhcpv6_universe, 22, 1 },
419
420				/* RFC3646 OPTIONS */
421
422	{ "name-servers", "6A",			&dhcpv6_universe, 23, 1 },
423	{ "domain-search", "D",			&dhcpv6_universe, 24, 1 },
424
425				/* RFC3633 OPTIONS */
426
427	{ "ia-pd", "X",				&dhcpv6_universe, 25, 1 },
428	{ "ia-prefix", "X",			&dhcpv6_universe, 26, 1 },
429
430				/* RFC3898 OPTIONS */
431
432	{ "nis-servers", "6A", 			&dhcpv6_universe, 27, 1 },
433	{ "nisp-servers", "6A",			&dhcpv6_universe, 28, 1 },
434	{ "nis-domain-name", "D",		&dhcpv6_universe, 29, 1 },
435	{ "nisp-domain-name", "D",		&dhcpv6_universe, 30, 1 },
436
437				/* RFC4075 OPTIONS */
438	{ "sntp-servers", "6A",			&dhcpv6_universe, 31, 1 },
439
440				/* RFC4242 OPTIONS */
441
442	{ "info-refresh-time", "T",		&dhcpv6_universe, 32, 1 },
443
444				/* RFC4280 OPTIONS */
445
446	{ "bcms-server-d", "D",			&dhcpv6_universe, 33, 1 },
447	{ "bcms-server-a", "6A",		&dhcpv6_universe, 34, 1 },
448
449	/* Note that 35 is not assigned. */
450
451#if defined(RFC4776_OPTIONS)
452			/* RFC4776 OPTIONS */
453
454	{ "geoconf-civic", "X",			&dhcpv6_universe, 36, 1 },
455#endif
456
457				/* RFC4649 OPTIONS */
458
459	/* The remote-id option looks like the VSIO option, but for all
460	 * intents and purposes we only need to treat the entire field
461	 * like a globally unique identifier (and if we create such an
462	 * option, ensure the first 4 bytes are our enterprise-id followed
463	 * by a globally unique ID so long as you're within that enterprise
464	 * id).  So we'll use "X" for now unless someone grumbles.
465	 */
466	{ "remote-id", "X",			&dhcpv6_universe, 37, 1 },
467
468				/* RFC4580 OPTIONS */
469
470	{ "subscriber-id", "X",			&dhcpv6_universe, 38, 1 },
471
472				/* RFC4704 OPTIONS */
473
474	/* The DHCPv6 FQDN option is...weird.
475	 *
476	 * We use the same "virtual" encapsulated space as DHCPv4's FQDN
477	 * option, so it can all be configured in one place.  Since the
478	 * options system does not support multiple inheritance, we use
479	 * a 'shill' layer to perform the different protocol conversions,
480	 * and to redirect any queries in the DHCPv4 FQDN's space.
481	 */
482	{ "fqdn", "Efqdn6-if-you-see-me-its-a-bug-bug-bug.",
483						&dhcpv6_universe, 39, 1 },
484
485
486			/* RFC5192 */
487#if defined(RFC5192_OPTIONS)
488	{ "pana-agent", "6A",			&dhcpv6_universe, 40, 1 },
489#endif
490
491			/* RFC4833 OPTIONS */
492#if defined(RFC4833_OPTIONS)
493	{ "new-posix-timezone", "t",		&dhcpv6_universe, 41, 1 },
494	{ "new-tzdb-timezone", "t",		&dhcpv6_universe, 42, 1 },
495#endif
496
497			/* RFC4994 OPTIONS */
498#if defined(RFC4994_OPTIONS)
499	{ "ero", "SA",				&dhcpv6_universe, 43, 1 },
500#endif
501
502			/* RFC5007 OPTIONS */
503
504	{ "lq-query", "X",			&dhcpv6_universe, 44, 1 },
505	{ "client-data", "X",			&dhcpv6_universe, 45, 1 },
506	{ "clt-time", "L",			&dhcpv6_universe, 46, 1 },
507	{ "lq-relay-data", "6X",		&dhcpv6_universe, 47, 1 },
508	{ "lq-client-link", "6A",		&dhcpv6_universe, 48, 1 },
509
510			/* RFC5223 OPTIONS */
511#if defined(RFC5223_OPTIONS)
512	{ "v6-lost", "d",			&dhcpv6_universe, 51, 1 },
513#endif
514
515			/* RFC5417 OPTIONS */
516#if defined(RFC5417_OPTIONS)
517	{ "capwap-ac-v6", "6a",			&dhcpv6_universe, 52, 1 },
518#endif
519
520			/* RFC5460 OPTIONS */
521#if defined(RFC5460_OPTIONS)
522	{ "relay-id", "X",			&dhcpv6_universe, 53, 1 },
523#endif
524
525			/* RFC5986 OPTIONS */
526#if defined(RFC5986_OPTIONS)
527	{ "v6-access-domain", "d",		&dhcpv6_universe, 57, 1 },
528#endif
529
530			/* RFC6011 OPTIONS */
531#if defined(RFC6011_OPTIONS)
532	{ "sip-ua-cs-list", "D",		&dhcpv6_universe, 58, 1 },
533#endif
534
535			/* RFC5970 OPTIONS */
536#if defined(RFC5970_OPTIONS)
537	{ "bootfile-url", "t",			&dhcpv6_universe, 59, 1 },
538	{ "bootfile-param", "X",		&dhcpv6_universe, 60, 1 },
539	{ "client-arch-type", "SA",		&dhcpv6_universe, 61, 1 },
540	{ "nii", "BBB",				&dhcpv6_universe, 62, 1 },
541#endif
542
543			/* RFC6334 OPTIONS */
544#if defined(RFC6334_OPTIONS)
545	{ "aftr-name", "d",			&dhcpv6_universe, 64, 1 },
546#endif
547
548			/* RFC6440 OPTIONS */
549#if defined(RFC6440_OPTIONS)
550	{ "erp-local-domain-name", "d",		&dhcpv6_universe, 65, 1 },
551#endif
552
553			/* RFC6731 OPTIONS */
554#if defined(RFC6731_OPTIONS)
555	{ "rdnss-selection", "6BD",		&dhcpv6_universe, 74, 1 },
556#endif
557
558			/* RFC6939 OPTIONS */
559#if defined(RFC6939_OPTIONS)
560	{ "client-linklayer-addr", "X",		&dhcpv6_universe, 79, 1 },
561#endif
562
563			/* RFC6977 OPTIONS */
564#if defined(RFC6977_OPTIONS)
565	{ "link-address", "6",			&dhcpv6_universe, 80, 1 },
566#endif
567
568			/* RFC7083 OPTIONS */
569#if defined(RFC7083_OPTIONS)
570	{ "solmax-rt", "L",			&dhcpv6_universe, 82, 1 },
571	{ "inf-max-rt", "L",			&dhcpv6_universe, 83, 1 },
572#endif
573
574			/* RFC7341 OPTIONS */
575#if defined(RFC7341_OPTIONS)
576	{ "dhcpv4-msg", "X",			&dhcpv6_universe, 87, 1 },
577	{ "dhcp4-o-dhcp6-server", "6A",		&dhcpv6_universe, 88, 1 },
578#endif
579
580#if defined(RFC7710_OPTIONS)
581	{ "v6-captive-portal", "t",		&dhcpv6_universe, 103, 1 },
582#endif
583
584	{ "relay-source-port", "S",		&dhcpv6_universe, 135, 1 },
585
586#if defined(RFC6153_OPTIONS)
587	{ "ipv6-address-andsf", "6A",		&dhcpv6_universe, 143, 1 },
588#endif
589
590	{ NULL, NULL, NULL, 0, 0 }
591};
592
593struct enumeration_value dhcpv6_duid_type_values[] = {
594	{ "duid-llt",	DUID_LLT },  /* Link-Local Plus Time */
595	{ "duid-en",	DUID_EN },   /* DUID based upon enterprise-ID. */
596	{ "duid-ll",	DUID_LL },   /* DUID from Link Local address only. */
597	{ "duid-uuid",	DUID_UUID }, /* DUID based upon UUID */
598	{ NULL, 0 }
599};
600
601struct enumeration dhcpv6_duid_types = {
602	NULL,
603	"duid-types", 2,
604	dhcpv6_duid_type_values
605};
606
607struct enumeration_value dhcpv6_status_code_values[] = {
608	{ "success",	  0 }, /* Success				*/
609	{ "UnspecFail",	  1 }, /* Failure, for unspecified reasons.	*/
610	{ "NoAddrsAvail", 2 }, /* Server has no addresses to assign.	*/
611	{ "NoBinding",	  3 }, /* Client record (binding) unavailable.	*/
612	{ "NotOnLink",	  4 }, /* Bad prefix for the link.		*/
613	{ "UseMulticast", 5 }, /* Not just good advice.  It's the law.	*/
614	{ "NoPrefixAvail", 6 }, /* Server has no prefixes to assign.	*/
615	{ "UnknownQueryType", 7 }, /* Query-type unknown/unsupported.	*/
616	{ "MalformedQuery", 8 }, /* Leasequery not valid.		*/
617	{ "NotConfigured", 9 }, /* The target address is not in config.	*/
618	{ "NotAllowed",  10 }, /* Server doesn't allow the leasequery.	*/
619	{ "QueryTerminated", 11 }, /* Leasequery terminated.		*/
620	{ NULL, 0 }
621};
622
623struct enumeration dhcpv6_status_codes = {
624	NULL,
625	"status-codes", 2,
626	dhcpv6_status_code_values
627};
628
629struct enumeration_value lq6_query_type_values[] = {
630	{ "query-by-address", 1 },
631	{ "query-by-clientid", 2 },
632	{ "query-by-relay-id", 3 },
633	{ "query-by-link-address", 4 },
634	{ "query-by-remote-id", 5 },
635	{ NULL, 0 }
636};
637
638struct enumeration lq6_query_types = {
639	NULL,
640	"query-types", 2,
641	lq6_query_type_values
642};
643
644struct enumeration_value dhcpv6_message_values[] = {
645	{ "SOLICIT", 1 },
646	{ "ADVERTISE", 2 },
647	{ "REQUEST", 3 },
648	{ "CONFIRM", 4 },
649	{ "RENEW", 5 },
650	{ "REBIND", 6 },
651	{ "REPLY", 7 },
652	{ "RELEASE", 8 },
653	{ "DECLINE", 9 },
654	{ "RECONFIGURE", 10 },
655	{ "INFORMATION-REQUEST", 11 },
656	{ "RELAY-FORW", 12 },
657	{ "RELAY-REPL", 13 },
658	{ "LEASEQUERY", 14 },
659	{ "LEASEQUERY-REPLY", 15 },
660	{ "LEASEQUERY-DONE", 16 },
661	{ "LEASEQUERY-DATA", 17 },
662	{ "RECONFIGURE-REQUEST", 18 },
663	{ "RECONFIGURE-REPLY", 19 },
664	{ "DHCPV4-QUERY", 20 },
665	{ "DHCPV4-RESPONSE", 21 },
666	{ NULL, 0 }
667};
668
669/* Some code refers to a different table. */
670const char *dhcpv6_type_names[] = {
671	NULL,
672	"Solicit",
673	"Advertise",
674	"Request",
675	"Confirm",
676	"Renew",
677	"Rebind",
678	"Reply",
679	"Release",
680	"Decline",
681	"Reconfigure",
682	"Information-request",
683	"Relay-forward",
684	"Relay-reply",
685	"Leasequery",
686	"Leasequery-reply",
687	"Leasequery-done",
688	"Leasequery-data",
689	"Reconfigure-request",
690	"Reconfigure-reply",
691	"Dhcpv4-query",
692	"Dhcpv4-response"
693};
694const int dhcpv6_type_name_max =
695	(sizeof(dhcpv6_type_names) / sizeof(dhcpv6_type_names[0]));
696
697struct enumeration dhcpv6_messages = {
698	NULL,
699	"dhcpv6-messages", 1,
700	dhcpv6_message_values
701};
702
703struct universe vsio_universe;
704static struct option vsio_options[] = {
705	{ "isc", "Eisc6.",		&vsio_universe,		     2495, 1 },
706	{ NULL, NULL, NULL, 0, 0 }
707};
708
709struct universe isc6_universe;
710static struct option isc6_options[] = {
711	{ "media", "t",				&isc6_universe,     1, 1 },
712	{ "update-assist", "X",			&isc6_universe,     2, 1 },
713	{ "4o6-interface", "t",			&isc6_universe, 60000, 1 },
714	{ "4o6-source-address", "6",		&isc6_universe, 60001, 1 },
715	{ NULL, NULL, NULL, 0, 0 }
716};
717
718const char *hardware_types [] = {
719	"unknown-0",
720	"ethernet",
721	"unknown-2",
722	"unknown-3",
723	"unknown-4",
724	"unknown-5",
725	"token-ring",
726	"unknown-7",
727	"fddi",
728	"unknown-9",
729	"unknown-10",
730	"unknown-11",
731	"unknown-12",
732	"unknown-13",
733	"unknown-14",
734	"unknown-15",
735	"unknown-16",
736	"unknown-17",
737	"unknown-18",
738	"unknown-19",
739	"unknown-20",
740	"unknown-21",
741	"unknown-22",
742	"unknown-23",
743	"unknown-24",
744	"unknown-25",
745	"unknown-26",
746	"unknown-27",
747	"unknown-28",
748	"unknown-29",
749	"unknown-30",
750	"unknown-31",
751	"infiniband",
752	"unknown-33",
753	"unknown-34",
754	"unknown-35",
755	"unknown-36",
756	"unknown-37",
757	"unknown-38",
758	"unknown-39",
759	"unknown-40",
760	"unknown-41",
761	"unknown-42",
762	"unknown-43",
763	"unknown-44",
764	"unknown-45",
765	"unknown-46",
766	"unknown-47",
767	"unknown-48",
768	"unknown-49",
769	"unknown-50",
770	"unknown-51",
771	"unknown-52",
772	"unknown-53",
773	"unknown-54",
774	"unknown-55",
775	"unknown-56",
776	"unknown-57",
777	"unknown-58",
778	"unknown-59",
779	"unknown-60",
780	"unknown-61",
781	"unknown-62",
782	"unknown-63",
783	"unknown-64",
784	"unknown-65",
785	"unknown-66",
786	"unknown-67",
787	"unknown-68",
788	"unknown-69",
789	"unknown-70",
790	"unknown-71",
791	"unknown-72",
792	"unknown-73",
793	"unknown-74",
794	"unknown-75",
795	"unknown-76",
796	"unknown-77",
797	"unknown-78",
798	"unknown-79",
799	"unknown-80",
800	"unknown-81",
801	"unknown-82",
802	"unknown-83",
803	"unknown-84",
804	"unknown-85",
805	"unknown-86",
806	"unknown-87",
807	"unknown-88",
808	"unknown-89",
809	"unknown-90",
810	"unknown-91",
811	"unknown-92",
812	"unknown-93",
813	"unknown-94",
814	"unknown-95",
815	"unknown-96",
816	"unknown-97",
817	"unknown-98",
818	"unknown-99",
819	"unknown-100",
820	"unknown-101",
821	"unknown-102",
822	"unknown-103",
823	"unknown-104",
824	"unknown-105",
825	"unknown-106",
826	"unknown-107",
827	"unknown-108",
828	"unknown-109",
829	"unknown-110",
830	"unknown-111",
831	"unknown-112",
832	"unknown-113",
833	"unknown-114",
834	"unknown-115",
835	"unknown-116",
836	"unknown-117",
837	"unknown-118",
838	"unknown-119",
839	"unknown-120",
840	"unknown-121",
841	"unknown-122",
842	"unknown-123",
843	"unknown-124",
844	"unknown-125",
845	"unknown-126",
846	"unknown-127",
847	"unknown-128",
848	"unknown-129",
849	"unknown-130",
850	"unknown-131",
851	"unknown-132",
852	"unknown-133",
853	"unknown-134",
854	"unknown-135",
855	"unknown-136",
856	"unknown-137",
857	"unknown-138",
858	"unknown-139",
859	"unknown-140",
860	"unknown-141",
861	"unknown-142",
862	"unknown-143",
863	"unknown-144",
864	"unknown-145",
865	"unknown-146",
866	"unknown-147",
867	"unknown-148",
868	"unknown-149",
869	"unknown-150",
870	"unknown-151",
871	"unknown-152",
872	"unknown-153",
873	"unknown-154",
874	"unknown-155",
875	"unknown-156",
876	"unknown-157",
877	"unknown-158",
878	"unknown-159",
879	"unknown-160",
880	"unknown-161",
881	"unknown-162",
882	"unknown-163",
883	"unknown-164",
884	"unknown-165",
885	"unknown-166",
886	"unknown-167",
887	"unknown-168",
888	"unknown-169",
889	"unknown-170",
890	"unknown-171",
891	"unknown-172",
892	"unknown-173",
893	"unknown-174",
894	"unknown-175",
895	"unknown-176",
896	"unknown-177",
897	"unknown-178",
898	"unknown-179",
899	"unknown-180",
900	"unknown-181",
901	"unknown-182",
902	"unknown-183",
903	"unknown-184",
904	"unknown-185",
905	"unknown-186",
906	"unknown-187",
907	"unknown-188",
908	"unknown-189",
909	"unknown-190",
910	"unknown-191",
911	"unknown-192",
912	"unknown-193",
913	"unknown-194",
914	"unknown-195",
915	"unknown-196",
916	"unknown-197",
917	"unknown-198",
918	"unknown-199",
919	"unknown-200",
920	"unknown-201",
921	"unknown-202",
922	"unknown-203",
923	"unknown-204",
924	"unknown-205",
925	"unknown-206",
926	"unknown-207",
927	"unknown-208",
928	"unknown-209",
929	"unknown-210",
930	"unknown-211",
931	"unknown-212",
932	"unknown-213",
933	"unknown-214",
934	"unknown-215",
935	"unknown-216",
936	"unknown-217",
937	"unknown-218",
938	"unknown-219",
939	"unknown-220",
940	"unknown-221",
941	"unknown-222",
942	"unknown-223",
943	"unknown-224",
944	"unknown-225",
945	"unknown-226",
946	"unknown-227",
947	"unknown-228",
948	"unknown-229",
949	"unknown-230",
950	"unknown-231",
951	"unknown-232",
952	"unknown-233",
953	"unknown-234",
954	"unknown-235",
955	"unknown-236",
956	"unknown-237",
957	"unknown-238",
958	"unknown-239",
959	"unknown-240",
960	"unknown-241",
961	"unknown-242",
962	"unknown-243",
963	"unknown-244",
964	"unknown-245",
965	"unknown-246",
966	"unknown-247",
967	"unknown-248",
968	"unknown-249",
969	"unknown-250",
970	"unknown-251",
971	"unknown-252",
972	"unknown-253",
973	"unknown-254",
974	"unknown-255" };
975
976universe_hash_t *universe_hash;
977struct universe **universes;
978int universe_count, universe_max;
979
980/* Universe containing names of configuration options, which, rather than
981   writing "option universe-name.option-name ...;", can be set by writing
982   "option-name ...;". */
983
984struct universe *config_universe;
985
986/* XXX: omapi must die...all the below keeps us from having to make the
987 * option structures omapi typed objects, which is a bigger headache.
988 */
989
990char *default_option_format = (char *) "X";
991
992/* Must match hash_reference/dereference types in omapip/hash.h. */
993int
994option_reference(struct option **dest, struct option *src,
995	         const char * file, int line)
996{
997	if (!dest || !src)
998	        return DHCP_R_INVALIDARG;
999
1000	if (*dest) {
1001#if defined(POINTER_DEBUG)
1002	        log_fatal("%s(%d): reference store into non-null pointer!",
1003	                  file, line);
1004#else
1005	        return DHCP_R_INVALIDARG;
1006#endif
1007	}
1008
1009	*dest = src;
1010	src->refcnt++;
1011	rc_register(file, line, dest, src, src->refcnt, 0, RC_MISC);
1012	return(ISC_R_SUCCESS);
1013}
1014
1015int
1016option_dereference(struct option **dest, const char *file, int line)
1017{
1018	if (!dest)
1019	        return DHCP_R_INVALIDARG;
1020
1021	if (!*dest) {
1022#if defined (POINTER_DEBUG)
1023	        log_fatal("%s(%d): dereference of null pointer!", file, line);
1024#else
1025	        return DHCP_R_INVALIDARG;
1026#endif
1027	}
1028
1029	if ((*dest)->refcnt <= 0) {
1030#if defined (POINTER_DEBUG)
1031	        log_fatal("%s(%d): dereference of <= 0 refcnt!", file, line);
1032#else
1033	        return DHCP_R_INVALIDARG;
1034#endif
1035	}
1036
1037	(*dest)->refcnt--;
1038
1039	rc_register(file, line, dest, (*dest), (*dest)->refcnt, 1, RC_MISC);
1040
1041	if ((*dest)->refcnt == 0) {
1042		/* The option name may be packed in the same alloc as the
1043		 * option structure.
1044		 */
1045	        if ((char *) (*dest)->name != (char *) ((*dest) + 1))
1046	                dfree((char *) (*dest)->name, file, line);
1047
1048		/* It's either a user-configured format (allocated), or the
1049		 * default static format.
1050		 */
1051		if (((*dest)->format != NULL) &&
1052		    ((*dest)->format != default_option_format)) {
1053			dfree((char *) (*dest)->format, file, line);
1054		}
1055
1056	        dfree(*dest, file, line);
1057	}
1058
1059	*dest = NULL;
1060	return ISC_R_SUCCESS;
1061}
1062
1063void initialize_common_option_spaces()
1064{
1065	unsigned code;
1066	int i;
1067
1068	/* The 'universes' table is dynamically grown to contain
1069	 * universe as they're configured - except during startup.
1070	 * Since we know how many we put down in .c files, we can
1071	 * allocate a more-than-right-sized buffer now, leaving some
1072	 * space for user-configured option spaces.
1073	 *
1074	 * 1: dhcp_universe (dhcpv4 options)
1075	 * 2: nwip_universe (dhcpv4 NWIP option)
1076	 * 3: fqdn_universe (dhcpv4 fqdn option - reusable for v6)
1077	 * 4: vendor_class_universe (VIVCO)
1078	 * 5: vendor_universe (VIVSO)
1079	 * 6: isc_universe (dhcpv4 isc config space)
1080	 * 7: dhcpv6_universe (dhcpv6 options)
1081	 * 8: vsio_universe (DHCPv6 Vendor-Identified space)
1082	 * 9: isc6_universe (ISC's Vendor universe in DHCPv6 VSIO)
1083	 * 10: fqdn6_universe (dhcpv6 fqdn option shill to v4)
1084	 * 11: agent_universe (dhcpv4 relay agent - see server/stables.c)
1085	 * 12: server_universe (server's config, see server/stables.c)
1086	 * 13: user-config
1087	 * 14: more user-config
1088	 * 15: more user-config
1089	 * 16: more user-config
1090	 */
1091	universe_max = 16;
1092	i = universe_max * sizeof(struct universe *);
1093	if (i <= 0)
1094		log_fatal("Ludicrous initial size option space table.");
1095	universes = dmalloc(i, MDL);
1096	if (universes == NULL)
1097		log_fatal("Can't allocate option space table.");
1098	memset(universes, 0, i);
1099
1100	/* Set up the DHCP option universe... */
1101	dhcp_universe.name = "dhcp";
1102	dhcp_universe.concat_duplicates = 1;
1103	dhcp_universe.lookup_func = lookup_hashed_option;
1104	dhcp_universe.option_state_dereference =
1105		hashed_option_state_dereference;
1106	dhcp_universe.save_func = save_hashed_option;
1107	dhcp_universe.delete_func = delete_hashed_option;
1108	dhcp_universe.encapsulate = hashed_option_space_encapsulate;
1109	dhcp_universe.foreach = hashed_option_space_foreach;
1110	dhcp_universe.decode = parse_option_buffer;
1111	dhcp_universe.length_size = 1;
1112	dhcp_universe.tag_size = 1;
1113	dhcp_universe.get_tag = getUChar;
1114	dhcp_universe.store_tag = putUChar;
1115	dhcp_universe.get_length = getUChar;
1116	dhcp_universe.store_length = putUChar;
1117	dhcp_universe.site_code_min = 0;
1118	dhcp_universe.end = DHO_END;
1119	dhcp_universe.index = universe_count++;
1120	universes [dhcp_universe.index] = &dhcp_universe;
1121	if (!option_name_new_hash(&dhcp_universe.name_hash,
1122				  BYTE_NAME_HASH_SIZE, MDL) ||
1123	    !option_code_new_hash(&dhcp_universe.code_hash,
1124				  BYTE_CODE_HASH_SIZE, MDL))
1125		log_fatal ("Can't allocate dhcp option hash table.");
1126	for (i = 0 ; dhcp_options[i].name ; i++) {
1127		option_code_hash_add(dhcp_universe.code_hash,
1128				     &dhcp_options[i].code, 0,
1129				     &dhcp_options[i], MDL);
1130		option_name_hash_add(dhcp_universe.name_hash,
1131				     dhcp_options [i].name, 0,
1132				     &dhcp_options [i], MDL);
1133	}
1134#if defined(REPORT_HASH_PERFORMANCE)
1135	log_info("DHCP name hash: %s",
1136		 option_name_hash_report(dhcp_universe.name_hash));
1137	log_info("DHCP code hash: %s",
1138		 option_code_hash_report(dhcp_universe.code_hash));
1139#endif
1140
1141	/* Set up the Novell option universe (for option 63)... */
1142	nwip_universe.name = "nwip";
1143	nwip_universe.concat_duplicates = 0; /* XXX: reference? */
1144	nwip_universe.lookup_func = lookup_linked_option;
1145	nwip_universe.option_state_dereference =
1146		linked_option_state_dereference;
1147	nwip_universe.save_func = save_linked_option;
1148	nwip_universe.delete_func = delete_linked_option;
1149	nwip_universe.encapsulate = nwip_option_space_encapsulate;
1150	nwip_universe.foreach = linked_option_space_foreach;
1151	nwip_universe.decode = parse_option_buffer;
1152	nwip_universe.length_size = 1;
1153	nwip_universe.tag_size = 1;
1154	nwip_universe.get_tag = getUChar;
1155	nwip_universe.store_tag = putUChar;
1156	nwip_universe.get_length = getUChar;
1157	nwip_universe.store_length = putUChar;
1158	nwip_universe.site_code_min = 0;
1159	nwip_universe.end = 0;
1160	code = DHO_NWIP_SUBOPTIONS;
1161	nwip_universe.enc_opt = NULL;
1162	if (!option_code_hash_lookup(&nwip_universe.enc_opt,
1163				     dhcp_universe.code_hash, &code, 0, MDL))
1164		log_fatal("Unable to find NWIP parent option (%s:%d).", MDL);
1165	nwip_universe.index = universe_count++;
1166	universes [nwip_universe.index] = &nwip_universe;
1167	if (!option_name_new_hash(&nwip_universe.name_hash,
1168				  NWIP_HASH_SIZE, MDL) ||
1169	    !option_code_new_hash(&nwip_universe.code_hash,
1170				  NWIP_HASH_SIZE, MDL))
1171		log_fatal ("Can't allocate nwip option hash table.");
1172	for (i = 0 ; nwip_options[i].name ; i++) {
1173		option_code_hash_add(nwip_universe.code_hash,
1174				     &nwip_options[i].code, 0,
1175				     &nwip_options[i], MDL);
1176		option_name_hash_add(nwip_universe.name_hash,
1177				     nwip_options[i].name, 0,
1178				     &nwip_options[i], MDL);
1179	}
1180#if defined(REPORT_HASH_PERFORMANCE)
1181	log_info("NWIP name hash: %s",
1182		 option_name_hash_report(nwip_universe.name_hash));
1183	log_info("NWIP code hash: %s",
1184		 option_code_hash_report(nwip_universe.code_hash));
1185#endif
1186
1187	/* Set up the FQDN option universe... */
1188	fqdn_universe.name = "fqdn";
1189	fqdn_universe.concat_duplicates = 0;
1190	fqdn_universe.lookup_func = lookup_linked_option;
1191	fqdn_universe.option_state_dereference =
1192		linked_option_state_dereference;
1193	fqdn_universe.save_func = save_linked_option;
1194	fqdn_universe.delete_func = delete_linked_option;
1195	fqdn_universe.encapsulate = fqdn_option_space_encapsulate;
1196	fqdn_universe.foreach = linked_option_space_foreach;
1197	fqdn_universe.decode = fqdn_universe_decode;
1198	fqdn_universe.length_size = 1;
1199	fqdn_universe.tag_size = 1;
1200	fqdn_universe.get_tag = getUChar;
1201	fqdn_universe.store_tag = putUChar;
1202	fqdn_universe.get_length = getUChar;
1203	fqdn_universe.store_length = putUChar;
1204	fqdn_universe.site_code_min = 0;
1205	fqdn_universe.end = 0;
1206	fqdn_universe.index = universe_count++;
1207	code = DHO_FQDN;
1208	fqdn_universe.enc_opt = NULL;
1209	if (!option_code_hash_lookup(&fqdn_universe.enc_opt,
1210				     dhcp_universe.code_hash, &code, 0, MDL))
1211		log_fatal("Unable to find FQDN parent option (%s:%d).", MDL);
1212	universes [fqdn_universe.index] = &fqdn_universe;
1213	if (!option_name_new_hash(&fqdn_universe.name_hash,
1214				  FQDN_HASH_SIZE, MDL) ||
1215	    !option_code_new_hash(&fqdn_universe.code_hash,
1216				  FQDN_HASH_SIZE, MDL))
1217		log_fatal ("Can't allocate fqdn option hash table.");
1218	for (i = 0 ; fqdn_options[i].name ; i++) {
1219		option_code_hash_add(fqdn_universe.code_hash,
1220				     &fqdn_options[i].code, 0,
1221				     &fqdn_options[i], MDL);
1222		option_name_hash_add(fqdn_universe.name_hash,
1223				     fqdn_options[i].name, 0,
1224				     &fqdn_options[i], MDL);
1225	}
1226#if defined(REPORT_HASH_PERFORMANCE)
1227	log_info("FQDN name hash: %s",
1228		 option_name_hash_report(fqdn_universe.name_hash));
1229	log_info("FQDN code hash: %s",
1230		 option_code_hash_report(fqdn_universe.code_hash));
1231#endif
1232
1233        /* Set up the Vendor Identified Vendor Class options (for option
1234	 * 125)...
1235	 */
1236        vendor_class_universe.name = "vendor-class";
1237	vendor_class_universe.concat_duplicates = 0; /* XXX: reference? */
1238        vendor_class_universe.lookup_func = lookup_hashed_option;
1239        vendor_class_universe.option_state_dereference =
1240                hashed_option_state_dereference;
1241        vendor_class_universe.save_func = save_hashed_option;
1242        vendor_class_universe.delete_func = delete_hashed_option;
1243        vendor_class_universe.encapsulate = hashed_option_space_encapsulate;
1244        vendor_class_universe.foreach = hashed_option_space_foreach;
1245        vendor_class_universe.decode = parse_option_buffer;
1246        vendor_class_universe.length_size = 1;
1247        vendor_class_universe.tag_size = 4;
1248	vendor_class_universe.get_tag = getULong;
1249        vendor_class_universe.store_tag = putULong;
1250	vendor_class_universe.get_length = getUChar;
1251        vendor_class_universe.store_length = putUChar;
1252	vendor_class_universe.site_code_min = 0;
1253	vendor_class_universe.end = 0;
1254	code = DHO_VIVCO_SUBOPTIONS;
1255	vendor_class_universe.enc_opt = NULL;
1256	if (!option_code_hash_lookup(&vendor_class_universe.enc_opt,
1257				     dhcp_universe.code_hash, &code, 0, MDL))
1258		log_fatal("Unable to find VIVCO parent option (%s:%d).", MDL);
1259        vendor_class_universe.index = universe_count++;
1260        universes[vendor_class_universe.index] = &vendor_class_universe;
1261        if (!option_name_new_hash(&vendor_class_universe.name_hash,
1262				  VIVCO_HASH_SIZE, MDL) ||
1263	    !option_code_new_hash(&vendor_class_universe.code_hash,
1264				  VIVCO_HASH_SIZE, MDL))
1265                log_fatal("Can't allocate Vendor Identified Vendor Class "
1266			  "option hash table.");
1267        for (i = 0 ; vendor_class_options[i].name ; i++) {
1268		option_code_hash_add(vendor_class_universe.code_hash,
1269				     &vendor_class_options[i].code, 0,
1270				     &vendor_class_options[i], MDL);
1271                option_name_hash_add(vendor_class_universe.name_hash,
1272                                     vendor_class_options[i].name, 0,
1273                                     &vendor_class_options[i], MDL);
1274        }
1275#if defined(REPORT_HASH_PERFORMANCE)
1276	log_info("VIVCO name hash: %s",
1277		 option_name_hash_report(vendor_class_universe.name_hash));
1278	log_info("VIVCO code hash: %s",
1279		 option_code_hash_report(vendor_class_universe.code_hash));
1280#endif
1281
1282        /* Set up the Vendor Identified Vendor Sub-options (option 126)... */
1283        vendor_universe.name = "vendor";
1284	vendor_universe.concat_duplicates = 0; /* XXX: reference? */
1285        vendor_universe.lookup_func = lookup_hashed_option;
1286        vendor_universe.option_state_dereference =
1287                hashed_option_state_dereference;
1288        vendor_universe.save_func = save_hashed_option;
1289        vendor_universe.delete_func = delete_hashed_option;
1290        vendor_universe.encapsulate = hashed_option_space_encapsulate;
1291        vendor_universe.foreach = hashed_option_space_foreach;
1292        vendor_universe.decode = parse_option_buffer;
1293        vendor_universe.length_size = 1;
1294        vendor_universe.tag_size = 4;
1295	vendor_universe.get_tag = getULong;
1296        vendor_universe.store_tag = putULong;
1297	vendor_universe.get_length = getUChar;
1298        vendor_universe.store_length = putUChar;
1299	vendor_universe.site_code_min = 0;
1300	vendor_universe.end = 0;
1301	code = DHO_VIVSO_SUBOPTIONS;
1302	vendor_universe.enc_opt = NULL;
1303	if (!option_code_hash_lookup(&vendor_universe.enc_opt,
1304				     dhcp_universe.code_hash, &code, 0, MDL))
1305		log_fatal("Unable to find VIVSO parent option (%s:%d).", MDL);
1306        vendor_universe.index = universe_count++;
1307        universes[vendor_universe.index] = &vendor_universe;
1308        if (!option_name_new_hash(&vendor_universe.name_hash,
1309				  VIVSO_HASH_SIZE, MDL) ||
1310	    !option_code_new_hash(&vendor_universe.code_hash,
1311				  VIVSO_HASH_SIZE, MDL))
1312                log_fatal("Can't allocate Vendor Identified Vendor Sub-"
1313			  "options hash table.");
1314        for (i = 0 ; vendor_options[i].name ; i++) {
1315                option_code_hash_add(vendor_universe.code_hash,
1316				     &vendor_options[i].code, 0,
1317				     &vendor_options[i], MDL);
1318                option_name_hash_add(vendor_universe.name_hash,
1319				     vendor_options[i].name, 0,
1320				     &vendor_options[i], MDL);
1321        }
1322#if defined(REPORT_HASH_PERFORMANCE)
1323	log_info("VIVSO name hash: %s",
1324		 option_name_hash_report(vendor_universe.name_hash));
1325	log_info("VIVSO code hash: %s",
1326		 option_code_hash_report(vendor_universe.code_hash));
1327#endif
1328
1329        /* Set up the ISC Vendor-option universe (for option 125.2495)... */
1330        isc_universe.name = "isc";
1331	isc_universe.concat_duplicates = 0; /* XXX: check VIVSO ref */
1332        isc_universe.lookup_func = lookup_linked_option;
1333        isc_universe.option_state_dereference =
1334                linked_option_state_dereference;
1335        isc_universe.save_func = save_linked_option;
1336        isc_universe.delete_func = delete_linked_option;
1337        isc_universe.encapsulate = linked_option_space_encapsulate;
1338        isc_universe.foreach = linked_option_space_foreach;
1339        isc_universe.decode = parse_option_buffer;
1340        isc_universe.length_size = 2;
1341        isc_universe.tag_size = 2;
1342	isc_universe.get_tag = getUShort;
1343        isc_universe.store_tag = putUShort;
1344	isc_universe.get_length = getUShort;
1345        isc_universe.store_length = putUShort;
1346	isc_universe.site_code_min = 0;
1347	isc_universe.end = 0;
1348	code = VENDOR_ISC_SUBOPTIONS;
1349	isc_universe.enc_opt = NULL;
1350	if (!option_code_hash_lookup(&isc_universe.enc_opt,
1351				     vendor_universe.code_hash, &code, 0, MDL))
1352		log_fatal("Unable to find ISC parent option (%s:%d).", MDL);
1353        isc_universe.index = universe_count++;
1354        universes[isc_universe.index] = &isc_universe;
1355        if (!option_name_new_hash(&isc_universe.name_hash,
1356				  VIV_ISC_HASH_SIZE, MDL) ||
1357	    !option_code_new_hash(&isc_universe.code_hash,
1358				  VIV_ISC_HASH_SIZE, MDL))
1359                log_fatal("Can't allocate ISC Vendor options hash table.");
1360        for (i = 0 ; isc_options[i].name ; i++) {
1361		option_code_hash_add(isc_universe.code_hash,
1362				     &isc_options[i].code, 0,
1363				     &isc_options[i], MDL);
1364                option_name_hash_add(isc_universe.name_hash,
1365                                     isc_options[i].name, 0,
1366                                     &isc_options[i], MDL);
1367        }
1368#if defined(REPORT_HASH_PERFORMANCE)
1369	log_info("ISC name hash: %s",
1370		 option_name_hash_report(isc_universe.name_hash));
1371	log_info("ISC code hash: %s",
1372		 option_code_hash_report(isc_universe.code_hash));
1373#endif
1374
1375	/* Set up the DHCPv6 root universe. */
1376	dhcpv6_universe.name = "dhcp6";
1377	dhcpv6_universe.concat_duplicates = 0;
1378	dhcpv6_universe.lookup_func = lookup_hashed_option;
1379	dhcpv6_universe.option_state_dereference =
1380		hashed_option_state_dereference;
1381	dhcpv6_universe.save_func = save_hashed_option;
1382	dhcpv6_universe.delete_func = delete_hashed_option;
1383	dhcpv6_universe.encapsulate = hashed_option_space_encapsulate;
1384	dhcpv6_universe.foreach = hashed_option_space_foreach;
1385	dhcpv6_universe.decode = parse_option_buffer;
1386	dhcpv6_universe.length_size = 2;
1387	dhcpv6_universe.tag_size = 2;
1388	dhcpv6_universe.get_tag = getUShort;
1389	dhcpv6_universe.store_tag = putUShort;
1390	dhcpv6_universe.get_length = getUShort;
1391	dhcpv6_universe.store_length = putUShort;
1392	dhcpv6_universe.site_code_min = 0;
1393	/* DHCPv6 has no END option. */
1394	dhcpv6_universe.end = 0x00;
1395	dhcpv6_universe.index = universe_count++;
1396	universes[dhcpv6_universe.index] = &dhcpv6_universe;
1397	if (!option_name_new_hash(&dhcpv6_universe.name_hash,
1398				  WORD_NAME_HASH_SIZE, MDL) ||
1399	    !option_code_new_hash(&dhcpv6_universe.code_hash,
1400				  WORD_CODE_HASH_SIZE, MDL))
1401		log_fatal("Can't allocate dhcpv6 option hash tables.");
1402	for (i = 0 ; dhcpv6_options[i].name ; i++) {
1403		option_code_hash_add(dhcpv6_universe.code_hash,
1404				     &dhcpv6_options[i].code, 0,
1405				     &dhcpv6_options[i], MDL);
1406		option_name_hash_add(dhcpv6_universe.name_hash,
1407				     dhcpv6_options[i].name, 0,
1408				     &dhcpv6_options[i], MDL);
1409	}
1410
1411	/* Add DHCPv6 protocol enumeration sets. */
1412	add_enumeration(&dhcpv6_duid_types);
1413	add_enumeration(&dhcpv6_status_codes);
1414	add_enumeration(&dhcpv6_messages);
1415
1416	/* Set up DHCPv6 VSIO universe. */
1417	vsio_universe.name = "vsio";
1418	vsio_universe.concat_duplicates = 0;
1419	vsio_universe.lookup_func = lookup_hashed_option;
1420	vsio_universe.option_state_dereference =
1421		hashed_option_state_dereference;
1422	vsio_universe.save_func = save_hashed_option;
1423	vsio_universe.delete_func = delete_hashed_option;
1424	vsio_universe.encapsulate = hashed_option_space_encapsulate;
1425	vsio_universe.foreach = hashed_option_space_foreach;
1426	vsio_universe.decode = parse_option_buffer;
1427	vsio_universe.length_size = 0;
1428	vsio_universe.tag_size = 4;
1429	vsio_universe.get_tag = getULong;
1430	vsio_universe.store_tag = putULong;
1431	vsio_universe.get_length = NULL;
1432	vsio_universe.store_length = NULL;
1433	vsio_universe.site_code_min = 0;
1434	/* No END option. */
1435	vsio_universe.end = 0x00;
1436	code = D6O_VENDOR_OPTS;
1437	if (!option_code_hash_lookup(&vsio_universe.enc_opt,
1438				     dhcpv6_universe.code_hash, &code, 0, MDL))
1439		log_fatal("Unable to find VSIO parent option (%s:%d).", MDL);
1440	vsio_universe.index = universe_count++;
1441	universes[vsio_universe.index] = &vsio_universe;
1442	if (!option_name_new_hash(&vsio_universe.name_hash,
1443				  VSIO_HASH_SIZE, MDL) ||
1444	    !option_code_new_hash(&vsio_universe.code_hash,
1445				  VSIO_HASH_SIZE, MDL))
1446		log_fatal("Can't allocate Vendor Specific Information "
1447			  "Options space.");
1448	for (i = 0 ; vsio_options[i].name != NULL ; i++) {
1449		option_code_hash_add(vsio_universe.code_hash,
1450				     &vsio_options[i].code, 0,
1451				     &vsio_options[i], MDL);
1452		option_name_hash_add(vsio_universe.name_hash,
1453				     vsio_options[i].name, 0,
1454				     &vsio_options[i], MDL);
1455	}
1456
1457	/* Add ISC VSIO sub-sub-option space. */
1458	isc6_universe.name = "isc6";
1459	isc6_universe.concat_duplicates = 0;
1460	isc6_universe.lookup_func = lookup_hashed_option;
1461	isc6_universe.option_state_dereference =
1462		hashed_option_state_dereference;
1463	isc6_universe.save_func = save_hashed_option;
1464	isc6_universe.delete_func = delete_hashed_option;
1465	isc6_universe.encapsulate = hashed_option_space_encapsulate;
1466	isc6_universe.foreach = hashed_option_space_foreach;
1467	isc6_universe.decode = parse_option_buffer;
1468	isc6_universe.length_size = 0;
1469	isc6_universe.tag_size = 4;
1470	isc6_universe.get_tag = getULong;
1471	isc6_universe.store_tag = putULong;
1472	isc6_universe.get_length = NULL;
1473	isc6_universe.store_length = NULL;
1474	isc6_universe.site_code_min = 0;
1475	/* No END option. */
1476	isc6_universe.end = 0x00;
1477	code = 2495;
1478	if (!option_code_hash_lookup(&isc6_universe.enc_opt,
1479				     vsio_universe.code_hash, &code, 0, MDL))
1480		log_fatal("Unable to find ISC parent option (%s:%d).", MDL);
1481	isc6_universe.index = universe_count++;
1482	universes[isc6_universe.index] = &isc6_universe;
1483	if (!option_name_new_hash(&isc6_universe.name_hash,
1484				  VIV_ISC_HASH_SIZE, MDL) ||
1485	    !option_code_new_hash(&isc6_universe.code_hash,
1486				  VIV_ISC_HASH_SIZE, MDL))
1487		log_fatal("Can't allocate Vendor Specific Information "
1488			  "Options space.");
1489	for (i = 0 ; isc6_options[i].name != NULL ; i++) {
1490		option_code_hash_add(isc6_universe.code_hash,
1491				     &isc6_options[i].code, 0,
1492				     &isc6_options[i], MDL);
1493		option_name_hash_add(isc6_universe.name_hash,
1494				     isc6_options[i].name, 0,
1495				     &isc6_options[i], MDL);
1496	}
1497
1498	/* The fqdn6 option space is a protocol-wrapper shill for the
1499	 * old DHCPv4 space.
1500	 */
1501	fqdn6_universe.name = "fqdn6-if-you-see-me-its-a-bug-bug-bug";
1502	fqdn6_universe.lookup_func = lookup_fqdn6_option;
1503	fqdn6_universe.option_state_dereference = NULL; /* Covered by v4. */
1504	fqdn6_universe.save_func = save_fqdn6_option;
1505	fqdn6_universe.delete_func = delete_fqdn6_option;
1506	fqdn6_universe.encapsulate = fqdn6_option_space_encapsulate;
1507	fqdn6_universe.foreach = fqdn6_option_space_foreach;
1508	fqdn6_universe.decode = fqdn6_universe_decode;
1509	/* This is not a 'normal' encapsulated space, so these values are
1510	 * meaningless.
1511	 */
1512	fqdn6_universe.length_size = 0;
1513	fqdn6_universe.tag_size = 0;
1514	fqdn6_universe.get_tag = NULL;
1515	fqdn6_universe.store_tag = NULL;
1516	fqdn6_universe.get_length = NULL;
1517	fqdn6_universe.store_length = NULL;
1518	fqdn6_universe.site_code_min = 0;
1519	fqdn6_universe.end = 0;
1520	fqdn6_universe.index = universe_count++;
1521	code = D6O_CLIENT_FQDN;
1522	fqdn6_universe.enc_opt = NULL;
1523	if (!option_code_hash_lookup(&fqdn6_universe.enc_opt,
1524				     dhcpv6_universe.code_hash, &code, 0, MDL))
1525		log_fatal("Unable to find FQDN v6 parent option. (%s:%d).",
1526			  MDL);
1527	universes[fqdn6_universe.index] = &fqdn6_universe;
1528	/* The fqdn6 space shares the same option space as the v4 space.
1529	 * So there are no name or code hashes on the v6 side.
1530	 */
1531	fqdn6_universe.name_hash = NULL;
1532	fqdn6_universe.code_hash = NULL;
1533
1534
1535	/* Set up the hash of DHCPv4 universes. */
1536	universe_new_hash(&universe_hash, UNIVERSE_HASH_SIZE, MDL);
1537	universe_hash_add(universe_hash, dhcp_universe.name, 0,
1538			  &dhcp_universe, MDL);
1539	universe_hash_add(universe_hash, nwip_universe.name, 0,
1540			  &nwip_universe, MDL);
1541	universe_hash_add(universe_hash, fqdn_universe.name, 0,
1542			  &fqdn_universe, MDL);
1543	universe_hash_add(universe_hash, vendor_class_universe.name, 0,
1544			  &vendor_class_universe, MDL);
1545	universe_hash_add(universe_hash, vendor_universe.name, 0,
1546			  &vendor_universe, MDL);
1547	universe_hash_add(universe_hash, isc_universe.name, 0,
1548			  &isc_universe, MDL);
1549
1550	/* Set up hashes for DHCPv6 universes. */
1551	universe_hash_add(universe_hash, dhcpv6_universe.name, 0,
1552			  &dhcpv6_universe, MDL);
1553	universe_hash_add(universe_hash, vsio_universe.name, 0,
1554			  &vsio_universe, MDL);
1555	universe_hash_add(universe_hash, isc6_universe.name, 0,
1556			  &isc6_universe, MDL);
1557	/* previously this wasn't necessary, now that we can send
1558	 * v6 encapsulated options it is.
1559	 */
1560	universe_hash_add(universe_hash, fqdn6_universe.name, 0,
1561			  &fqdn6_universe, MDL);
1562
1563}
1564