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