]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Varying option space code and length bit widths (8/16/32) are now
authorDavid Hankins <dhankins@isc.org>
Thu, 1 Jun 2006 20:23:18 +0000 (20:23 +0000)
committerDavid Hankins <dhankins@isc.org>
Thu, 1 Jun 2006 20:23:18 +0000 (20:23 +0000)
  supported.  This is a milestone in acheiving RFC 3925 "VIVSO" and
  DHCPv6 support. [ISC-Bugs #15979]

28 files changed:
RELNOTES
client/clparse.c
client/dhclient.c
common/alloc.c
common/conflex.c
common/dhcp-options.5
common/dns.c
common/memory.c
common/options.c
common/parse.c
common/tables.c
common/tree.c
includes/dhcp.h
includes/dhcpd.h
includes/dhctoken.h
includes/omapip/hash.h
includes/tree.h
omapip/auth.c
omapip/hash.c
server/bootp.c
server/class.c
server/confpars.c
server/db.c
server/ddns.c
server/dhcp.c
server/mdb.c
server/omapi.c
server/stables.c

index 4cd3ddfa6a28e09463c687098837884509aa19a1..d202be27e7384a137fb5c26318978ef0119b949f 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -95,6 +95,10 @@ and for prodding me into improving it.
   appear at the parameter request list.  Up until now it had ultimate
   priority over the client's parameter request list.
 
+- Varying option space code and length bit widths (8/16/32) are now
+  supported.  This is a milestone in acheiving RFC 3925 "VIVSO" and
+  DHCPv6 support.
+
                        Changes since 3.0.4
 
 - A warning that host statements declared within subnet or shared-network
index 4af95e15c8aabea5a0da9eb40cafa288fc4d9e52..b19c81ce714195e5224cc8a81e91e5048a073bdd 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: clparse.c,v 1.66 2006/05/15 15:07:49 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: clparse.c,v 1.67 2006/06/01 20:23:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -239,7 +239,7 @@ void parse_client_statement (cfile, ip, config)
 {
        int token;
        const char *val;
-       struct option *option;
+       struct option *option = NULL;
        struct executable_statement *stmt, **p;
        enum statement_op op;
        int lose;
@@ -363,15 +363,15 @@ void parse_client_statement (cfile, ip, config)
                        return;
                }
 
-               option = parse_option_name (cfile, 1, &known);
-               if (!option)
+               status = parse_option_name(cfile, 1, &known, &option);
+               if (status != ISC_R_SUCCESS || option == NULL)
                        return;
 
                token = next_token (&val, (unsigned *)0, cfile);
                if (token != CODE) {
                        parse_warn (cfile, "expecting \"code\" keyword.");
                        skip_to_semi (cfile);
-                       free_option (option, MDL);
+                       option_dereference(&option, MDL);
                        return;
                }
                if (ip) {
@@ -379,11 +379,11 @@ void parse_client_statement (cfile, ip, config)
                                    "option definitions may only appear in %s",
                                    "the outermost scope.");
                        skip_to_semi (cfile);
-                       free_option (option, MDL);
+                       option_dereference(&option, MDL);
                        return;
                }
-               if (!parse_option_code_definition (cfile, option))
-                       free_option (option, MDL);
+               parse_option_code_definition(cfile, option);
+               option_dereference(&option, MDL);
                return;
 
              case MEDIA:
@@ -610,7 +610,8 @@ void parse_option_list (cfile, list)
        int token;
        const char *val;
        pair p = (pair)0, q = (pair)0, r;
-       struct option *option;
+       struct option *option = NULL;
+       isc_result_t status;
 
        ix = 0;
        do {
@@ -625,8 +626,8 @@ void parse_option_list (cfile, list)
                        skip_to_semi (cfile);
                        return;
                }
-               option = parse_option_name (cfile, 0, NULL);
-               if (!option) {
+               status = parse_option_name(cfile, 0, NULL, &option);
+               if (status != ISC_R_SUCCESS || option == NULL) {
                        parse_warn (cfile, "%s: expected option name.", val);
                        return;
                }
@@ -635,12 +636,14 @@ void parse_option_list (cfile, list)
                                "%s.%s: Only global options allowed.",
                                option -> universe -> name, option->name );
                        skip_to_semi (cfile);
+                       option_dereference(&option, MDL);
                        return;
                }
                r = new_pair (MDL);
                if (!r)
                        log_fatal ("can't allocate pair for option code.");
                r -> car = (caddr_t)(long)option -> code;
+               option_dereference(&option, MDL);
                r -> cdr = (pair)0;
                if (p)
                        q -> cdr = r;
index c58135a7f1b1a5ab7f42ff4d97a50d8dc93f3e1d..b04598c113cf92d695be8f918c50edf78c866b77 100644 (file)
@@ -32,7 +32,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.138 2006/05/15 15:07:49 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.139 2006/06/01 20:23:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1130,13 +1130,22 @@ void dhcpoffer (packet)
                if (!lookup_option
                    (&dhcp_universe, packet -> options,
                     client -> config -> required_options [i])) {
-                   log_info ("%s: no %s option.",
-                             obuf, (dhcp_universe.options
-                                    [client -> config -> required_options [i]]
-                                    -> name));
-                               return;
-                       }
+                   struct option *option = NULL;
+                   unsigned code = client->config->required_options[i];
+
+                   option_code_hash_lookup(&option, dhcp_universe.code_hash,
+                                           &code, 0, MDL);
+
+                   if (option)
+                       log_info("%s: no %s option.", obuf, option->name);
+                   else
+                       log_info("%s: no unknown-%u option.", obuf, code);
+
+                   option_dereference(&option, MDL);
+
+                   return;
                }
+           }
        }
 
        /* If we've already seen this lease, don't record it again. */
@@ -1210,6 +1219,7 @@ struct client_lease *packet_to_lease (packet, client)
        struct client_lease *lease;
        unsigned i;
        struct option_cache *oc;
+       struct option *option = NULL;
        struct data_string data;
 
        lease = (struct client_lease *)new_client_lease (MDL);
@@ -1242,11 +1252,18 @@ struct client_lease *packet_to_lease (packet, client)
                                           packet -> options, lease -> options,
                                           &global_scope, oc, MDL)) {
                        if (data.len) {
+                               if (!option_code_hash_lookup(&option,
+                                               dhcp_universe.code_hash,
+                                               &i, 0, MDL))
+                                       log_fatal("Unable to find VENDOR "
+                                                 "option (%s:%d).", MDL);
                                parse_encapsulated_suboptions
-                                       (packet -> options, &dhcp_options [i],
+                                       (packet -> options, option,
                                         data.data, data.len, &dhcp_universe,
                                         client -> config -> vendor_space_name
                                                );
+
+                               option_dereference(&option, MDL);
                        }
                        data_string_forget (&data, MDL);
                }
@@ -1815,6 +1832,7 @@ void make_client_options (client, lease, type, sid, rip, prl, op)
 {
        unsigned i;
        struct option_cache *oc;
+       struct option *option = NULL;
        struct buffer *bp = (struct buffer *)0;
 
        /* If there are any leftover options, get rid of them. */
@@ -1833,26 +1851,31 @@ void make_client_options (client, lease, type, sid, rip, prl, op)
        /* Send the requested address if provided. */
        if (rip) {
                client -> requested_address = *rip;
-               if (!(make_const_option_cache
-                     (&oc, (struct buffer **)0, rip -> iabuf, rip -> len,
-                      &dhcp_options [DHO_DHCP_REQUESTED_ADDRESS], MDL)))
+               i = DHO_DHCP_REQUESTED_ADDRESS;
+               if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash,
+                                             &i, 0, MDL) &&
+                     make_const_option_cache(&oc, NULL, rip->iabuf, rip->len,
+                                             option, MDL)))
                        log_error ("can't make requested address cache.");
                else {
                        save_option (&dhcp_universe, *op, oc);
                        option_cache_dereference (&oc, MDL);
                }
+               option_dereference(&option, MDL);
        } else {
                client -> requested_address.len = 0;
        }
 
-       if (!(make_const_option_cache
-             (&oc, (struct buffer **)0,
-              type, 1, &dhcp_options [DHO_DHCP_MESSAGE_TYPE], MDL)))
+       i = DHO_DHCP_MESSAGE_TYPE;
+       if (!(option_code_hash_lookup(&option, dhcp_universe.code_hash, &i, 0,
+                                     MDL) &&
+             make_const_option_cache(&oc, NULL, type, 1, option, MDL)))
                log_error ("can't make message type.");
        else {
                save_option (&dhcp_universe, *op, oc);
                option_cache_dereference (&oc, MDL);
        }
+       option_dereference(&option, MDL);
 
        if (prl) {
                /* Figure out how many parameters were requested. */
@@ -1863,15 +1886,18 @@ void make_client_options (client, lease, type, sid, rip, prl, op)
                else {
                        for (i = 0; prl [i]; i++)
                                bp -> data [i] = prl [i];
-                       if (!(make_const_option_cache
-                             (&oc, &bp, (u_int8_t *)0, i,
-                              &dhcp_options [DHO_DHCP_PARAMETER_REQUEST_LIST],
-                              MDL)))
+                       i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+                       if (!(option_code_hash_lookup(&option,
+                                                     dhcp_universe.code_hash,
+                                                     &i, 0, MDL) &&
+                             make_const_option_cache(&oc, &bp, NULL, i,
+                                                     option, MDL)))
                                log_error ("can't make option cache");
                        else {
                                save_option (&dhcp_universe, *op, oc);
                                option_cache_dereference (&oc, MDL);
                        }
+                       option_dereference(&option, MDL);
                }
        }
 
index a3bf741884fc304445e5fa53bab17c1307983192..6204a7f3014402648931f1d134fbbbc3312965ce 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: alloc.c,v 1.56 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: alloc.c,v 1.57 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -313,28 +313,24 @@ void free_name_server (ptr, file, line)
        dfree ((VOIDPTR)ptr, file, line);
 }
 
-struct option *new_option (file, line)
+struct option *new_option (name, file, line)
+       const char *name;
        const char *file;
        int line;
 {
-       struct option *rval =
-               dmalloc (sizeof (struct option), file, line);
-       if (rval)
-               memset (rval, 0, sizeof *rval);
-       return rval;
-}
+       struct option *rval;
+       int len;
 
-void free_option (ptr, file, line)
-       struct option *ptr;
-       const char *file;
-       int line;
-{
-/* XXX have to put all options on heap before this is possible. */
-#if 0
-       if (ptr -> name)
-               dfree ((VOIDPTR)option -> name, file, line);
-       dfree ((VOIDPTR)ptr, file, line);
-#endif
+       len = strlen(name);
+
+       rval = dmalloc(sizeof(struct option) + len + 1, file, line);
+
+       if(rval) {
+               memcpy(rval + 1, name, len);
+               rval->name = (char *)(rval + 1);
+       }
+
+       return rval;
 }
 
 struct universe *new_universe (file, line)
index 2dd8b897c36f0ec763166a81c9a19bee0856835c..5f744998d3a50ee4c670ebd37a0e0659976fec2f 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.97 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.98 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -756,6 +756,8 @@ static enum dhcp_token intern (atom, dfv)
                        return GET_LEASE_HOSTNAMES;
                break;
              case 'h':
+               if (!strcasecmp(atom + 1, "ash"))
+                       return HASH;
                if (!strcasecmp (atom + 1, "ba"))
                        return HBA;
                if (!strcasecmp (atom + 1, "ost"))
@@ -813,6 +815,8 @@ static enum dhcp_token intern (atom, dfv)
                        return LEASED_ADDRESS;
                if (!strcasecmp (atom + 1, "ease-time"))
                        return LEASE_TIME;
+               if (!strcasecmp(atom + 1, "ength"))
+                       return LENGTH;
                if (!strcasecmp (atom + 1, "imit"))
                        return LIMIT;
                if (!strcasecmp (atom + 1, "et"))
@@ -990,71 +994,121 @@ static enum dhcp_token intern (atom, dfv)
                        return REFRESH;
                break;
              case 's':
-               if (!strcasecmp (atom + 1, "tate"))
-                       return STATE;
-               if (!strcasecmp (atom + 1, "ecret"))
-                       return SECRET;
-               if (!strcasecmp (atom + 1, "ervfail"))
-                       return NS_SERVFAIL;
-               if (!strcasecmp (atom + 1, "witch"))
-                       return SWITCH;
-               if (!strcasecmp (atom + 1, "igned"))
-                       return SIGNED;
-               if (!strcasecmp (atom + 1, "tring"))
-                       return STRING_TOKEN;
-               if (!strcasecmp (atom + 1, "uffix"))
-                       return SUFFIX;
-               if (!strcasecmp (atom + 1, "earch"))
-                       return SEARCH;
-               if (!strcasecmp (atom + 1, "tarts"))
-                       return STARTS;
-               if (!strcasecmp (atom + 1, "iaddr"))
-                       return SIADDR;
-               if (!strcasecmp (atom + 1, "hared-network"))
-                       return SHARED_NETWORK;
-               if (!strcasecmp (atom + 1, "econdary"))
-                       return SECONDARY;
-               if (!strcasecmp (atom + 1, "erver-name"))
-                       return SERVER_NAME;
-               if (!strcasecmp (atom + 1, "erver-identifier"))
-                       return SERVER_IDENTIFIER;
-               if (!strcasecmp (atom + 1, "erver"))
-                       return SERVER;
-               if (!strcasecmp (atom + 1, "elect-timeout"))
-                       return SELECT_TIMEOUT;
-               if (!strcasecmp (atom + 1, "elect"))
-                       return SELECT;
-               if (!strcasecmp (atom + 1, "end"))
-                       return SEND;
-               if (!strcasecmp (atom + 1, "cript"))
-                       return SCRIPT;
-               if (!strcasecmp (atom + 1, "upersede"))
-                       return SUPERSEDE;
-               if (!strncasecmp (atom + 1, "ub", 2)) {
-                       if (!strcasecmp (atom + 3, "string"))
-                               return SUBSTRING;
-                       if (!strcasecmp (atom + 3, "net"))
-                               return SUBNET;
-                       if (!strcasecmp (atom + 3, "class"))
-                               return SUBCLASS;
+                if (!strcasecmp(atom + 1, "cript"))
+                        return SCRIPT;
+               if (tolower(atom[1]) == 'e') {
+                        if (!strcasecmp(atom + 2, "arch"))
+                                return SEARCH;
+                       if (tolower(atom[2]) == 'c') {
+                               if (!strcasecmp(atom + 3, "ond")) {
+                                        if (!strcasecmp(atom + 6, "ary"))
+                                                return SECONDARY;
+                                        if (!strcasecmp(atom + 6, "s"))
+                                                return SECONDS;
+                                       break;
+                               }
+                                if (!strcasecmp(atom + 3, "ret"))
+                                        return SECRET;
+                               break;
+                       }
+                       if (!strncasecmp(atom + 2, "lect", 4)) {
+                                if (atom[6] == '\0')
+                                        return SELECT;
+                                if (!strcasecmp(atom + 6, "-timeout"))
+                                        return SELECT_TIMEOUT;
+                               break;
+                       }
+                        if (!strcasecmp(atom + 2, "nd"))
+                                return SEND;
+                       if (!strncasecmp(atom + 2, "rv", 2)) {
+                               if (!strncasecmp(atom + 4, "er", 2)) {
+                                        if (atom[6] == '\0')
+                                                return SERVER;
+                                       if (atom[6] == '-') {
+                                                if (!strcasecmp(atom + 7,
+                                                               "name"))
+                                                        return SERVER_NAME;
+                                                if (!strcasecmp(atom + 7,
+                                                               "identifier"))
+                                                      return SERVER_IDENTIFIER;
+                                               break;
+                                       }
+                                       break;
+                               }
+                                if (!strcasecmp(atom + 4, "fail"))
+                                        return NS_SERVFAIL;
+                               break;
+                       }
+                        if (!strcasecmp(atom + 2, "t"))
+                                return TOKEN_SET;
                        break;
                }
-               if (!strcasecmp (atom + 1, "pawn"))
-                       return SPAWN;
-               if (!strcasecmp (atom + 1, "pace"))
-                       return SPACE;
-               if (!strcasecmp (atom + 1, "tatic"))
-                       return STATIC;
-               if (!strcasecmp (atom + 1, "plit"))
-                       return SPLIT;
-               if (!strcasecmp (atom + 1, "et"))
-                       return TOKEN_SET;
-               if (!strcasecmp (atom + 1, "econds"))
-                       return SECONDS;
-               if (!strcasecmp (atom + 1, "hutdown"))
-                       return SHUTDOWN;
-               if (!strcasecmp (atom + 1, "tartup"))
-                       return STARTUP;
+               if (tolower(atom[1]) == 'h') {
+                        if (!strcasecmp(atom + 2, "ared-network"))
+                                return SHARED_NETWORK;
+                        if (!strcasecmp(atom + 2, "utdown"))
+                                return SHUTDOWN;
+                       break;
+               }
+               if (tolower(atom[1]) == 'i') {
+                        if (!strcasecmp(atom + 2, "addr"))
+                                return SIADDR;
+                        if (!strcasecmp(atom + 2, "gned"))
+                                return SIGNED;
+                        if (!strcasecmp(atom + 2, "ze"))
+                                return SIZE;
+                       break;
+               }
+               if (tolower(atom[1]) == 'p') {
+                       if (tolower(atom[2]) == 'a') {
+                                if (!strcasecmp(atom + 3, "ce"))
+                                        return SPACE;
+                                if (!strcasecmp(atom + 3, "wn"))
+                                        return SPAWN;
+                               break;
+                       }
+                        if (!strcasecmp(atom + 2, "lit"))
+                                return SPLIT;
+                       break;
+               }
+               if (tolower(atom[1]) == 't') {
+                       if (tolower(atom[2]) == 'a') {
+                               if(strncasecmp(atom + 3, "rt", 2)) {
+                                         if (!strcasecmp(atom + 5, "s"))
+                                                 return STARTS;
+                                         if (!strcasecmp(atom + 5, "up"))
+                                                 return STARTUP;
+                                       break;
+                               }
+                               if (tolower(atom[3]) == 't') {
+                                        if (!strcasecmp(atom + 4, "e"))
+                                                return STATE;
+                                        if (!strcasecmp(atom + 4, "ic"))
+                                                return STATIC;
+                                       break;
+                               }
+                       }
+                        if (!strcasecmp(atom + 2, "ring"))
+                                return STRING_TOKEN;
+                       break;
+               }
+                if (!strncasecmp(atom + 1, "ub", 2)) {
+                        if (!strcasecmp(atom + 3, "class"))
+                                return SUBCLASS;
+                        if (!strcasecmp(atom + 3, "net"))
+                                return SUBNET;
+                        if (!strcasecmp(atom + 3, "string"))
+                                return SUBSTRING;
+                        break;
+                }
+               if (tolower(atom[1]) == 'u') {
+                        if (!strcasecmp(atom + 2, "ffix"))
+                                return SUFFIX;
+                        if (!strcasecmp(atom + 2, "persede"))
+                                return SUPERSEDE;
+               }
+                if (!strcasecmp(atom + 1, "witch"))
+                        return SWITCH;
                break;
              case 't':
                if (!strcasecmp (atom + 1, "imestamp"))
@@ -1116,6 +1170,8 @@ static enum dhcp_token intern (atom, dfv)
              case 'w':
                if (!strcasecmp (atom + 1, "ith"))
                        return WITH;
+               if (!strcasecmp(atom + 1, "idth"))
+                       return WIDTH;
                break;
              case 'y':
                if (!strcasecmp (atom + 1, "iaddr"))
index 777874a9486117e344261074ca2e181e93235258..ed2eaf0528368a3952def9b4369210b16c326351 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: dhcp-options.5,v 1.28 2006/05/05 20:32:30 dhankins Exp $
+.\"    $Id: dhcp-options.5,v 1.29 2006/06/01 20:23:17 dhankins Exp $
 .\"
 .\" Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
@@ -1475,13 +1475,37 @@ use the \fRoption space\fP statement:
 .B option
 .B space
 .I name
-.B ;
+.B [ [ code width
+.I number
+.B ] [ length width
+.I number
+.B ] [ hash size
+.I number
+.B ] ] ;
+.PP
+Where the numbers following \fBcode width\fR, \fBlength width\fR,
+and \fBhash size\fR respectively identify the number of bytes used to
+describe option codes, option lengths, and the size in buckets of the
+hash tables to hold options in this space.
+.PP
+The code and length widths are used in DHCP protocol - you must configure
+these numbers to match the applicable option space you are configuring.
+They each default to 1.  Valid values for code widths are 1, 2 or 4.
+Valid values for length widths are 1 or 2.
+.PP
+The hash size defaults depend upon the \fBcode width\fR selected, and
+may be 254 or 1009.  Valid values range between 1 and 65535.  Note
+that the higher you configure this value, the more memory will be used.  It
+is considered good practice to configure a value that is slightly larger
+than the estimated number of options you plan to configure within the
+space.  Due to limitations in previous versions of ISC DHCP (up to and
+including DHCP 3.0.*), this value was fixed at 9973.
 .PP
 The name can then be used in option definitions, as described earlier in
 this document.   For example:
 .nf
 
-option space SUNW;
+option space SUNW code width 1 length width 1 hash size 3;
 option SUNW.server-address code 2 = ip-address;
 option SUNW.server-name code 3 = text;
 option SUNW.root-path code 4 = text;
index fed20889327121cf27ec1773c64c4b2483c23a93..97804ec5ff44ddebb140c259ed30486da4d576f9 100644 (file)
@@ -33,7 +33,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dns.c,v 1.38 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dns.c,v 1.39 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -192,7 +192,7 @@ isc_result_t enter_dns_zone (struct dns_zone *zone)
                        dns_zone_dereference (&tz, MDL);
                }
        } else {
-               if (!dns_zone_new_hash (&dns_zone_hash, 1, MDL))
+               if (!dns_zone_new_hash(&dns_zone_hash, DNS_HASH_SIZE, MDL))
                        return ISC_R_NOMEMORY;
        }
        dns_zone_hash_add (dns_zone_hash, zone -> name, 0, zone, MDL);
@@ -963,4 +963,4 @@ isc_result_t ddns_remove_a (struct data_string *ddns_fwd_name,
 #endif /* NSUPDATE */
 
 HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone, dns_zone_hash_t,
-               dns_zone_reference, dns_zone_dereference)
+               dns_zone_reference, dns_zone_dereference, do_case_hash)
index 0540405d5ec74359fa3e24a6282093d477a7ea59..22a6c0cc3847cb6b18777011531888612f1cf8ba 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: memory.c,v 1.68 2005/03/17 20:14:59 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: memory.c,v 1.69 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -119,7 +119,7 @@ isc_result_t supersede_group (struct group_object *group, int writep)
                        }
                }
        } else {
-               group_new_hash (&group_name_hash, 0, MDL);
+               group_new_hash(&group_name_hash, GROUP_HASH_SIZE, MDL);
                t = (struct group_object *)0;
        }
 
index d69b635ad744fe5874d32f974ab3c7248711aac1..070cf71ca2f00a728f24dc02c705902964cf1131 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: options.c,v 1.90 2006/05/30 19:58:14 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: options.c,v 1.91 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #define DHCP_OPTION_DATA
@@ -136,40 +136,47 @@ int parse_option_buffer (options, buffer, length, universe)
        unsigned char *t;
        const unsigned char *end = buffer + length;
        unsigned len, offset;
-       int code;
+       unsigned code;
        struct option_cache *op = (struct option_cache *)0;
        struct buffer *bp = (struct buffer *)0;
+       struct option *option = NULL;
 
        if (!buffer_allocate (&bp, length, MDL)) {
                log_error ("no memory for option buffer.");
                return 0;
        }
        memcpy (bp -> data, buffer, length);
-       
-       for (offset = 0; buffer [offset] != DHO_END && offset < length; ) {
-               code = buffer [offset];
+
+       for (offset = 0;
+            (offset + universe->tag_size) > length &&
+            (code = universe->get_tag(bp->data + offset)) != universe->end; ) {
+               offset += universe->tag_size;
+
                /* Pad options don't have a length - just skip them. */
-               if (code == DHO_PAD) {
-                       ++offset;
+               if (code == DHO_PAD)
                        continue;
-               }
 
                /* Don't look for length if the buffer isn't that big. */
-               if (offset + 2 > length) {
+               if (offset + universe->length_size > length) {
                        len = 65536;
                        goto bogus;
                }
 
                /* All other fields (except end, see above) have a
                   one-byte length. */
-               len = buffer [offset + 1];
+               len = universe->get_length(bp->data + offset);
+
+               offset += universe->length_size;
+
+               option_code_hash_lookup(&option, universe->code_hash, &code,
+                                       0, MDL);
 
                /* If the length is outrageous, the options are bad. */
-               if (offset + len + 2 > length) {
+               if (offset + len > length) {
                      bogus:
-                       log_error ("parse_option_buffer: option %s (%d) %s.",
-                                  dhcp_options [code].name, len,
-                                  "larger than buffer");
+                       log_error ("parse_option_buffer: option %s (%u:%u) %s.",
+                                  option ? option->name : "<unknown>",
+                                  code, len, "larger than buffer");
                        buffer_dereference (&bp, MDL);
                        return 0;
                }
@@ -178,12 +185,12 @@ int parse_option_buffer (options, buffer, length, universe)
                   the parse fails, or the option isn't an encapsulation (by
                   far the most common case), or the option isn't entirely
                   an encapsulation, keep the raw data as well. */
-               if (universe -> options [code] &&
-                   !((universe -> options [code] -> format [0] == 'e' ||
-                      universe -> options [code] -> format [0] == 'E') &&
+               if (!(option &&
+                     (option->format[0] == 'e' ||
+                      option->format[0] == 'E') &&
                      (parse_encapsulated_suboptions
-                      (options, universe -> options [code],
-                       buffer + offset + 2, len,
+                      (options, option,
+                       bp->data + offset, len,
                        universe, (const char *)0)))) {
                    op = lookup_option (universe, options, code);
                    if (op) {
@@ -194,22 +201,26 @@ int parse_option_buffer (options, buffer, length, universe)
                            log_error ("parse_option_buffer: No memory.");
                            return 0;
                        }
-                       memcpy (new.buffer -> data, op -> data.data,
+                       /* Copy old option to new data object. */
+                       memcpy(new.buffer -> data, op -> data.data,
                                op -> data.len);
-                       memcpy (&new.buffer -> data [op -> data.len],
-                               &bp -> data [offset + 2], len);
+                       /* Concat new option behind old. */
+                       memcpy(new.buffer->data + op->data.len,
+                               bp->data + offset, len);
                        new.len = op -> data.len + len;
                        new.data = new.buffer -> data;
+                       /* Save new concat'd object. */
                        data_string_forget (&op -> data, MDL);
                        data_string_copy (&op -> data, &new, MDL);
                        data_string_forget (&new, MDL);
                    } else {
                        save_option_buffer (universe, options, bp,
-                                           &bp -> data [offset + 2], len,
-                                           universe -> options [code], 1);
+                                           bp->data + offset, len,
+                                           code, 1);
                    }
                }
-               offset += len + 2;
+               option_dereference(&option, MDL);
+               offset += len;
        }
        buffer_dereference (&bp, MDL);
        return 1;
@@ -316,9 +327,8 @@ int fqdn_universe_decode (struct option_state *options,
                bp -> data [0] = 1;
        else
                bp -> data [0] = 0;
-       if (!save_option_buffer (&fqdn_universe, options, bp,
-                                &bp -> data [0], 1,
-                                &fqdn_options [FQDN_ENCODED], 0)) {
+       if (!save_option_buffer(&fqdn_universe, options, bp,
+                               bp->data, 1, FQDN_ENCODED, 0)) {
              bad:
                buffer_dereference (&bp, MDL);
                return 0;
@@ -357,25 +367,24 @@ int fqdn_universe_decode (struct option_state *options,
 
                /* Note: If the client sends a FQDN, the first '.' will
                   be used as a NUL terminator for the hostname. */
-               if (i)
-                       if (!save_option_buffer (&fqdn_universe, options, bp,
-                                                &bp -> data[5], i,
-                                                &fqdn_options [FQDN_HOSTNAME],
-                                                0))
+               if (i && (!save_option_buffer(&fqdn_universe, options, bp,
+                                             &bp->data[5], i,
+                                             FQDN_HOSTNAME, 0)))
                        goto bad;
                /* Note: If the client sends a single label, the
                   FQDN_DOMAINNAME option won't be set. */
                if (length > 4 + i &&
-                   !save_option_buffer (&fqdn_universe, options, bp,
+                   (!save_option_buffer(&fqdn_universe, options, bp,
                                         &bp -> data[6 + i], length - 4 - i,
-                                        &fqdn_options [FQDN_DOMAINNAME], 1))
+                                        FQDN_DOMAINNAME, 1)))
                        goto bad;
                /* Also save the whole name. */
-               if (length > 3)
-                       if (!save_option_buffer (&fqdn_universe, options, bp,
-                                                &bp -> data [5], length - 3,
-                                                &fqdn_options [FQDN_FQDN], 1))
+               if (length > 3) {
+                       if (!save_option_buffer(&fqdn_universe, options, bp,
+                                               &bp -> data [5], length - 3,
+                                               FQDN_FQDN, 1))
                                goto bad;
+               }
        } else {
                unsigned len;
                unsigned total_len = 0;
@@ -421,40 +430,40 @@ int fqdn_universe_decode (struct option_state *options,
                }
 
                if (first_len > 0 &&
-                   !save_option_buffer (&fqdn_universe, options, bp,
-                                        &bp -> data[6], first_len,
-                                        &fqdn_options [FQDN_HOSTNAME], 0))
+                   !save_option_buffer(&fqdn_universe, options, bp,
+                                       &bp -> data[6], first_len,
+                                       FQDN_HOSTNAME, 0))
                        goto bad;
                if (total_len > 0 && first_len != total_len) {
-                       if (!save_option_buffer
-                           (&fqdn_universe, options, bp,
-                            &bp -> data[6 + first_len], total_len - first_len,
-                            &fqdn_options [FQDN_DOMAINNAME], 1))
+                       if (!save_option_buffer(&fqdn_universe, options, bp,
+                                               &bp->data[6 + first_len],
+                                               total_len - first_len,
+                                               FQDN_DOMAINNAME, 1))
                                goto bad;
                }
                if (total_len > 0)
                        if (!save_option_buffer (&fqdn_universe, options, bp,
                                                 &bp -> data [6], total_len,
-                                                &fqdn_options [FQDN_FQDN], 1))
+                                                FQDN_FQDN, 1))
                                goto bad;
        }
 
        if (!save_option_buffer (&fqdn_universe, options, bp,
                                 &bp -> data [1], 1,
-                                &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
+                                FQDN_NO_CLIENT_UPDATE, 0))
            goto bad;
        if (!save_option_buffer (&fqdn_universe, options, bp,
                                 &bp -> data [2], 1,
-                                &fqdn_options [FQDN_SERVER_UPDATE], 0))
+                                FQDN_SERVER_UPDATE, 0))
                goto bad;
 
        if (!save_option_buffer (&fqdn_universe, options, bp,
                                 &bp -> data [3], 1,
-                                &fqdn_options [FQDN_RCODE1], 0))
+                                FQDN_RCODE1, 0))
                goto bad;
        if (!save_option_buffer (&fqdn_universe, options, bp,
                                 &bp -> data [4], 1,
-                                &fqdn_options [FQDN_RCODE2], 0))
+                                FQDN_RCODE2, 0))
                goto bad;
 
        buffer_dereference (&bp, MDL);
@@ -785,6 +794,7 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
        int bufend, sbufend;
        struct data_string od;
        struct option_cache *oc;
+       struct option *option=NULL;
        unsigned code;
 
        if (first_cutoff) {
@@ -835,6 +845,10 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
            int splitup;
 
            memset (&encapsulation, 0, sizeof encapsulation);
+           have_encapsulation = 0;
+
+           if (option != NULL)
+               option_dereference(&option, MDL);
 
            /* Code for next option to try to store. */
            code = priority_list [i];
@@ -848,19 +862,24 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
 
            oc = lookup_option (u, cfg_options, code);
 
+           if (oc && oc->option)
+               option_reference(&option, oc->option, MDL);
+           else
+               option_code_hash_lookup(&option, u->code_hash, &code, 0, MDL);
+
            /* It's an encapsulation, try to find the universe
               to be encapsulated first, except that if it's a straight
               encapsulation and the user has provided a value for the
               encapsulation option, use the user-provided value. */
-           if (u -> options [code] &&
-               ((u -> options [code] -> format [0] == 'E' && !oc) ||
-                u -> options [code] -> format [0] == 'e')) {
+           if ((option != NULL) &&
+               ((option->format[0] == 'E' && oc != NULL) ||
+                (option->format[0] == 'e'))) {
                int uix;
                static char *s, *t;
                struct option_cache *tmp;
                struct data_string name;
 
-               s = strchr (u -> options [code] -> format, 'E');
+               s = strchr (option->format, 'E');
                if (s)
                    t = strchr (++s, '.');
                if (s && t) {
@@ -914,14 +933,23 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
            }
            
            /* Find the value of the option... */
+           od.len = 0;
            if (oc) {
                evaluate_option_cache (&od, packet,
                                       lease, client_state, in_options,
                                       cfg_options, scope, oc, MDL);
+
+               /* If we have encapsulation for this option, and an oc
+                * lookup succeeded, but the evaluation failed, it is
+                * either because this is a complex atom (atoms before
+                * E on format list) and the top half of the option is
+                * not configured, or this is a simple encapsulated
+                * space and the evaluator is giving us a NULL.  Prefer
+                * the evaluator's opinion over the subspace.
+                */
                if (!od.len) {
                    data_string_forget (&encapsulation, MDL);
                    data_string_forget (&od, MDL);
-                   have_encapsulation = 0;
                    continue;
                }
            }
@@ -930,6 +958,11 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
            length = od.len;
            if (have_encapsulation) {
                    length += encapsulation.len;
+
+                   /* od.len can be nonzero if we got here without an
+                    * oc (cache lookup failed), but did have an enapculated
+                    * simple encapsulation space.
+                    */
                    if (!od.len) {
                            data_string_copy (&od, &encapsulation, MDL);
                            data_string_forget (&encapsulation, MDL);
@@ -955,7 +988,7 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
            }
 
            /* Do we add a NUL? */
-           if (terminate && dhcp_options [code].format [0] == 't') {
+           if (terminate && option && format_has_text(option->format)) {
                    length++;
                    tto = 1;
            } else {
@@ -969,7 +1002,6 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
               in any case, if the option data will cross a buffer
               boundary, split it across that boundary. */
 
-
            if (length > 255)
                splitup = 1;
            else
@@ -1056,6 +1088,9 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
            data_string_forget (&od, MDL);
        }
 
+       if (option != NULL)
+           option_dereference(&option, MDL);
+
        /* If we can overload, and we have, then PAD and END those spaces. */
        if (first_cutoff && six) {
            if ((first_cutoff + six + 1) < sbufend)
@@ -1655,18 +1690,67 @@ int save_option_buffer (struct universe *universe,
                        struct option_state *options,
                        struct buffer *bp,
                        unsigned char *buffer, unsigned length,
-                       struct option *option, int tp)
+                       unsigned code, int tp)
 {
        struct buffer *lbp = (struct buffer *)0;
        struct option_cache *op = (struct option_cache *)0;
+       struct option *option = NULL;
+
+       /* Code sizes of 8, 16, and 32 bits are allowed. */
+       switch(universe->tag_size) {
+             case 1:
+               if (code > 0xff)
+                       return 0;
+               break;
+             case 2:
+               if (code > 0xffff)
+                       return 0;
+               break;
+             case 4:
+               if (code > 0xffffffff)
+                       return 0;
+               break;
+
+             default:
+               log_fatal("Inconstent universe tag size at %s:%d.", MDL);
+       }
+
+       option_code_hash_lookup(&option, universe->code_hash, &code, 0, MDL);
+
+       /* If we created an option structure for each option a client
+        * supplied, it's possible we may create > 2^32 option structures.
+        * That's not feasible.  So by failing to enter these option
+        * structures into the code and name hash tables, references will
+        * never be more than 1 - when the option cache is destroyed, this
+        * will be cleaned up.
+        */
+       if (!option) {
+               char nbuf[sizeof("unknown-4294967295")];
+
+               sprintf(nbuf, "unknown-%u", code);
+
+               option = new_option(nbuf, MDL);
+
+               if (!option)
+                       return 0;
+
+               option->format = default_option_format;
+               option->universe = universe;
+               option->code = code;
+
+               /* new_option() doesn't set references, pretend. */
+               option->refcnt = 1;
+       }
 
        if (!option_cache_allocate (&op, MDL)) {
-               log_error ("No memory for option %s.%s.",
-                          universe -> name,
-                          option -> name);
+               log_error("No memory for option code %s.%s.",
+                         universe->name, option->name);
+               option_dereference(&option, MDL);
                return 0;
        }
 
+       option_reference(&op->option, option, MDL);
+
        /* If we weren't passed a buffer in which the data are saved and
           refcounted, allocate one now. */
        if (!bp) {
@@ -1674,6 +1758,7 @@ int save_option_buffer (struct universe *universe,
                        log_error ("no memory for option buffer.");
 
                        option_cache_dereference (&op, MDL);
+                       option_dereference(&option, MDL);
                        return 0;
                }
                memcpy (lbp -> data, buffer, length + tp);
@@ -1684,11 +1769,11 @@ int save_option_buffer (struct universe *universe,
        /* Reference buffer copy to option cache. */
        op -> data.buffer = (struct buffer *)0;
        buffer_reference (&op -> data.buffer, bp, MDL);
-               
+
        /* Point option cache into buffer. */
        op -> data.data = buffer;
        op -> data.len = length;
-                       
+
        if (tp) {
                /* NUL terminate (we can get away with this because we (or
                   the caller!) allocated one more than the buffer size, and
@@ -1699,8 +1784,6 @@ int save_option_buffer (struct universe *universe,
                op -> data.terminated = 1;
        } else
                op -> data.terminated = 0;
-       
-       op -> option = option;
 
        /* If this option is ultimately a text option, null determinate to
         * comply with RFC2132 section 2.  Mark a flag so this can be sensed
@@ -1720,8 +1803,9 @@ int save_option_buffer (struct universe *universe,
        /* Now store the option. */
        save_option (universe, options, op);
 
-       /* And let go of our reference. */
+       /* And let go of our references. */
        option_cache_dereference (&op, MDL);
+       option_dereference(&option, MDL);
 
        return 1;
 }
@@ -1861,6 +1945,8 @@ int option_cache_dereference (ptr, file, line)
        if (!(*ptr) -> refcnt) {
                if ((*ptr) -> data.buffer)
                        data_string_forget (&(*ptr) -> data, file, line);
+               if ((*ptr)->option)
+                       option_dereference(&(*ptr)->option, MDL);
                if ((*ptr) -> expression)
                        expression_dereference (&(*ptr) -> expression,
                                                file, line);
@@ -2073,13 +2159,19 @@ int nwip_option_space_encapsulate (result, packet, lease, client_state,
           a suboption saying there's no data. */
        if (!status) {
                if (!no_nwip) {
+                       unsigned one = 1;
                        static unsigned char nni [] = { 1, 0 };
+
                        memset (&ds, 0, sizeof ds);
                        ds.data = nni;
                        ds.len = 2;
                        if (option_cache_allocate (&no_nwip, MDL))
                                data_string_copy (&no_nwip -> data, &ds, MDL);
-                       no_nwip -> option = nwip_universe.options [1];
+                       if (!option_code_hash_lookup(&no_nwip->option,
+                                                    nwip_universe.code_hash,
+                                                    &one, 0, MDL))
+                               log_fatal("Nwip option hash does not contain "
+                                         "1 (%s:%d).", MDL);
                }
                if (no_nwip) {
                        if (store_option (result, universe, packet, lease,
@@ -2550,4 +2642,3 @@ void do_packet (interface, packet, len, from_port, from, hfrom)
        dump_rc_history (0);
 #endif
 }
-
index 247e39b78cc0d11321b7578c0cb9c00c0bcadbd0..6b0115af049cc59ce217e1dd842af8010a70e21b 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.109 2006/05/15 15:07:49 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.110 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -913,10 +913,12 @@ TIME parse_date (cfile)
                   IDENTIFIER . IDENTIFIER
  */
 
-struct option *parse_option_name (cfile, allocate, known)
+isc_result_t
+parse_option_name (cfile, allocate, known, opt)
        struct parse *cfile;
        int allocate;
        int *known;
+       struct option **opt;
 {
        const char *val;
        enum dhcp_token token;
@@ -924,13 +926,16 @@ struct option *parse_option_name (cfile, allocate, known)
        struct universe *universe;
        struct option *option;
 
+       if (opt == NULL)
+               return ISC_R_INVALIDARG;
+
        token = next_token (&val, (unsigned *)0, cfile);
        if (!is_identifier (token)) {
                parse_warn (cfile,
                            "expecting identifier after option keyword.");
                if (token != SEMI)
                        skip_to_semi (cfile);
-               return (struct option *)0;
+               return ISC_R_BADPARSE;
        }
        uname = dmalloc (strlen (val) + 1, MDL);
        if (!uname)
@@ -947,7 +952,7 @@ struct option *parse_option_name (cfile, allocate, known)
                        parse_warn (cfile, "expecting identifier after '.'");
                        if (token != SEMI)
                                skip_to_semi (cfile);
-                       return (struct option *)0;
+                       return ISC_R_BADPARSE;
                }
 
                /* Look up the option name hash table for the specified
@@ -957,7 +962,7 @@ struct option *parse_option_name (cfile, allocate, known)
                                           uname, 0, MDL)) {
                        parse_warn (cfile, "no option space named %s.", uname);
                        skip_to_semi (cfile);
-                       return (struct option *)0;
+                       return ISC_R_NOTFOUND;
                }
        } else {
                /* Use the default hash table, which contains all the
@@ -968,7 +973,8 @@ struct option *parse_option_name (cfile, allocate, known)
 
        /* Look up the actual option info... */
        option = (struct option *)0;
-       option_hash_lookup (&option, universe -> hash, val, 0, MDL);
+       option_name_hash_lookup(opt, universe->name_hash, val, 0, MDL);
+       option = *opt;
 
        /* If we didn't get an option structure, it's an undefined option. */
        if (option) {
@@ -979,22 +985,12 @@ struct option *parse_option_name (cfile, allocate, known)
                   (might) be an option code definition, so we'll create
                   an option structure just in case. */
                if (allocate) {
-                       option = new_option (MDL);
-                       if (val == uname)
-                               option -> name = val;
-                       else {
-                               char *s;
-                               dfree (uname, MDL);
-                               s = dmalloc (strlen (val) + 1, MDL);
-                               if (!s)
-                                   log_fatal ("no memory for option %s.%s",
-                                              universe -> name, val);
-                               strcpy (s, val);
-                               option -> name = s;
-                       }
+                       option = new_option(val, MDL);
                        option -> universe = universe;
-                       option -> code = 0;
-                       return option;
+                       option_reference(opt, option, MDL);
+
+                       dfree(uname, MDL);
+                       return ISC_R_SUCCESS;
                }
                if (val == uname)
                        parse_warn (cfile, "no option named %s", val);
@@ -1002,15 +998,19 @@ struct option *parse_option_name (cfile, allocate, known)
                        parse_warn (cfile, "no option named %s in space %s",
                                    val, uname);
                skip_to_semi (cfile);
-               return (struct option *)0;
+               dfree(uname, MDL);
+               return ISC_R_NOTFOUND;
        }
 
        /* Free the initial identifier token. */
        dfree (uname, MDL);
-       return option;
+       return ISC_R_SUCCESS;
 }
 
-/* IDENTIFIER SEMI */
+/* IDENTIFIER [WIDTHS] SEMI
+ *   WIDTHS ~= LENGTH WIDTH NUMBER
+ *             CODE WIDTH NUMBER
+ */
 
 void parse_option_space_decl (cfile)
        struct parse *cfile;
@@ -1018,7 +1018,8 @@ void parse_option_space_decl (cfile)
        int token;
        const char *val;
        struct universe **ua, *nu;
-       char *s;
+       char *nu_name;
+       int tsize=1, lsize=1, hsize = 0;
 
        next_token (&val, (unsigned *)0, cfile);  /* Discard the SPACE token,
                                                     which was checked by the
@@ -1034,23 +1035,147 @@ void parse_option_space_decl (cfile)
                log_fatal ("No memory for new option space.");
 
        /* Set up the server option universe... */
-       s = dmalloc (strlen (val) + 1, MDL);
-       if (!s)
+       nu_name = dmalloc (strlen (val) + 1, MDL);
+       if (!nu_name)
                log_fatal ("No memory for new option space name.");
-       strcpy (s, val);
-       nu -> name = s;
+       strcpy (nu_name, val);
+       nu -> name = nu_name;
+
+       do {
+               token = next_token(&val, NULL, cfile);
+               switch(token) {
+                     case SEMI:
+                       break;
+
+                     case CODE:
+                       token = next_token(&val, NULL, cfile);
+                       if (token != WIDTH) {
+                               parse_warn(cfile, "expecting width token.");
+                               goto bad;
+                       }
+
+                       token = next_token(&val, NULL, cfile);
+                       if (token != NUMBER) {
+                               parse_warn(cfile, "expecting number 1, 2, 4.");
+                               goto bad;
+                       }
+
+                       tsize = atoi(val);
+
+
+                       switch (tsize) {
+                             case 1:
+                               if (!hsize)
+                                       hsize = BYTE_NAME_HASH_SIZE;
+                               break;
+                             case 2:
+                               if (!hsize)
+                                       hsize = WORD_NAME_HASH_SIZE;
+                               break;
+                             case 4:
+                               if (!hsize)
+                                       hsize = QUAD_NAME_HASH_SIZE;
+                               break;
+                             default:
+                               parse_warn(cfile, "invalid code width (%d), "
+                                                 "expecting a 1, 2 or 4.",
+                                          val);
+                               goto bad;
+                       }
+                       break;
+
+                     case LENGTH:
+                       token = next_token(&val, NULL, cfile);
+                       if (token != WIDTH) {
+                               parse_warn(cfile, "expecting width token.");
+                               goto bad;
+                       }
+
+                       token = next_token(&val, NULL, cfile);
+                       if (token != NUMBER) {
+                               parse_warn(cfile, "expecting number 1 or 2.");
+                               goto bad;
+                       }
+
+                       lsize = atoi(val);
+                       if (lsize != 1 && lsize != 2) {
+                               parse_warn(cfile, "invalid length width (%d) "
+                                                 "expecting 1 or 2.", val);
+                               goto bad;
+                       }
+
+                       break;
+
+                     case HASH:
+                       token = next_token(&val, NULL, cfile);
+                       if (token != SIZE) {
+                               parse_warn(cfile, "expecting size token.");
+                               goto bad;
+                       }
+
+                       token = next_token(&val, NULL, cfile);
+                       if (token != NUMBER) {
+                               parse_warn(cfile, "expecting a 10base number");
+                               goto bad;
+                       }
+
+                       /* (2^31)-1 is the highest Mersenne prime we should
+                        * probably allow...
+                        */
+                       hsize = atoi(val);
+                       if (hsize < 0 || hsize > 0x7FFFFFFF) {
+                               parse_warn(cfile, "invalid hash length: %d",
+                                          hsize);
+                               goto bad;
+                       }
+
+                       break;
+
+                     default:
+                       parse_warn(cfile, "Unexpected token.");
+               }
+       } while (token != SEMI);
+
+       if (!hsize)
+               hsize = DEFAULT_SPACE_HASH_SIZE;
+
        nu -> lookup_func = lookup_hashed_option;
-       nu -> option_state_dereference =
-               hashed_option_state_dereference;
+       nu -> option_state_dereference = hashed_option_state_dereference;
        nu -> foreach = hashed_option_space_foreach;
        nu -> save_func = save_hashed_option;
        nu -> delete_func = delete_hashed_option;
        nu -> encapsulate = hashed_option_space_encapsulate;
        nu -> decode = parse_option_buffer;
-       nu -> length_size = 1;
-       nu -> tag_size = 1;
-       nu -> store_tag = putUChar;
-       nu -> store_length = putUChar;
+       nu -> length_size = lsize;
+       nu -> tag_size = tsize;
+       switch(tsize) {
+             case 1:
+               nu->get_tag = getUChar;
+               nu->store_tag = putUChar;
+               break;
+             case 2:
+               nu->get_tag = getUShort;
+               nu->store_tag = putUShort;
+               break;
+             case 4:
+               nu->get_tag = getULong;
+               nu->store_tag = putULong;
+               break;
+             default:
+               log_fatal("Impossible condition at %s:%d.", MDL);
+       }
+       switch(lsize) {
+            case 1:
+               nu->get_length = getUChar;
+               nu->store_length = putUChar;
+               break;
+            case 2:
+               nu->get_length = getUShort;
+               nu->store_length = putUShort;
+               break;
+            default:
+               log_fatal("Impossible condition at %s:%d.", MDL);
+       }
        nu -> index = universe_count++;
        if (nu -> index >= universe_max) {
                ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
@@ -1062,11 +1187,15 @@ void parse_option_space_decl (cfile)
                universes = ua;
        }
        universes [nu -> index] = nu;
-       option_new_hash (&nu -> hash, 1, MDL);
-       if (!nu -> hash)
-               log_fatal ("Can't allocate %s option hash table.", nu -> name);
+       if (!option_name_new_hash(&nu->name_hash, hsize, MDL) ||
+           !option_code_new_hash(&nu->code_hash, hsize, MDL))
+               log_fatal("Can't allocate %s option hash table.", nu->name);
        universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
-       parse_semi (cfile);
+       return;
+
+    bad:
+       dfree(nu_name, MDL);
+       dfree(nu, MDL);
 }
 
 /* This is faked up to look good right now.   Ideally, this should do a
@@ -1108,6 +1237,7 @@ int parse_option_code_definition (cfile, option)
 {
        const char *val;
        enum dhcp_token token;
+       struct option *oldopt;
        unsigned arrayp = 0;
        int recordp = 0;
        int no_more_in_record = 0;
@@ -1355,14 +1485,22 @@ int parse_option_code_definition (cfile, option)
                s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
        s [tokix] = 0;
        option -> format = s;
-       if (option -> universe -> options [option -> code]) {
-               /* XXX Free the option, but we can't do that now because they
-                  XXX may start out static. */
+
+       oldopt = NULL;
+       option_code_hash_lookup(&oldopt, option->universe->code_hash,
+                               &option->code, 0, MDL);
+       if (oldopt) {
+               option_name_hash_delete(option->universe->name_hash,
+                                       oldopt->name, 0, MDL);
+               option_code_hash_delete(option->universe->code_hash,
+                                       &oldopt->code, 0, MDL);
+
+               option_dereference(&oldopt, MDL);
        }
-       option -> universe -> options [option -> code] = option;
-       option_hash_add (option -> universe -> hash,
-                        (const char *)option -> name,
-                        0, option, MDL);
+       option_code_hash_add(option->universe->code_hash, &option->code, 0,
+                            option, MDL);
+       option_name_hash_add(option->universe->name_hash, option->name, 0,
+                            option, MDL);
        return 1;
 }
 
@@ -1662,25 +1800,29 @@ int parse_executable_statement (result, cfile, lose, case_context)
              case SEND:
                token = next_token (&val, (unsigned *)0, cfile);
                known = 0;
-               option = parse_option_name (cfile, 0, &known);
-               if (!option) {
+               status = parse_option_name (cfile, 0, &known, &option);
+               if (status != ISC_R_SUCCESS || option == NULL) {
                        *lose = 1;
                        return 0;
                }
-               return parse_option_statement (result, cfile, 1, option,
-                                              send_option_statement);
+               status = parse_option_statement(result, cfile, 1, option,
+                                               send_option_statement);
+               option_dereference(&option, MDL);
+               return status;
 
              case SUPERSEDE:
              case OPTION:
                token = next_token (&val, (unsigned *)0, cfile);
                known = 0;
-               option = parse_option_name (cfile, 0, &known);
-               if (!option) {
+               status = parse_option_name (cfile, 0, &known, &option);
+               if (status != ISC_R_SUCCESS || option == NULL) {
                        *lose = 1;
                        return 0;
                }
-               return parse_option_statement (result, cfile, 1, option,
-                                              supersede_option_statement);
+               status = parse_option_statement(result, cfile, 1, option,
+                                               supersede_option_statement);
+               option_dereference(&option, MDL);
+               return status;
 
              case ALLOW:
                flag = 1;
@@ -1707,35 +1849,41 @@ int parse_executable_statement (result, cfile, lose, case_context)
                if (token == COLON)
                        goto switch_default;
                known = 0;
-               option = parse_option_name (cfile, 0, &known);
-               if (!option) {
+               status = parse_option_name (cfile, 0, &known, &option);
+               if (status != ISC_R_SUCCESS || option == NULL) {
                        *lose = 1;
                        return 0;
                }
-               return parse_option_statement (result, cfile, 1, option,
-                                              default_option_statement);
+               status = parse_option_statement(result, cfile, 1, option,
+                                               default_option_statement);
+               option_dereference(&option, MDL);
+               return status;
 
              case PREPEND:
                token = next_token (&val, (unsigned *)0, cfile);
                known = 0;
-               option = parse_option_name (cfile, 0, &known);
-               if (!option) {
+               status = parse_option_name (cfile, 0, &known, &option);
+               if (status != ISC_R_SUCCESS || option == NULL) {
                        *lose = 1;
                        return 0;
                }
-               return parse_option_statement (result, cfile, 1, option,
-                                              prepend_option_statement);
+               status = parse_option_statement(result, cfile, 1, option,
+                                               prepend_option_statement);
+               option_dereference(&option, MDL);
+               return status;
 
              case APPEND:
                token = next_token (&val, (unsigned *)0, cfile);
                known = 0;
-               option = parse_option_name (cfile, 0, &known);
-               if (!option) {
+               status = parse_option_name (cfile, 0, &known, &option);
+               if (status != ISC_R_SUCCESS || option == NULL) {
                        *lose = 1;
                        return 0;
                }
-               return parse_option_statement (result, cfile, 1, option,
-                                              append_option_statement);
+               status = parse_option_statement(result, cfile, 1, option,
+                                               append_option_statement);
+               option_dereference(&option, MDL);
+               return status;
 
              case ON:
                token = next_token (&val, (unsigned *)0, cfile);
@@ -2095,14 +2243,17 @@ int parse_executable_statement (result, cfile, lose, case_context)
              default:
                if (config_universe && is_identifier (token)) {
                        option = (struct option *)0;
-                       option_hash_lookup (&option, config_universe -> hash,
-                                           val, 0, MDL);
+                       option_name_hash_lookup(&option,
+                                               config_universe->name_hash,
+                                               val, 0, MDL);
                        if (option) {
                                token = next_token (&val,
                                                    (unsigned *)0, cfile);
-                               return parse_option_statement
-                                       (result, cfile, 1, option,
-                                        supersede_option_statement);
+                               status = parse_option_statement
+                                               (result, cfile, 1, option,
+                                                supersede_option_statement);
+                               option_dereference(&option, MDL);
+                               return status;
                        }
                }
 
@@ -2978,8 +3129,11 @@ int parse_non_binary (expr, cfile, lose, context)
                        log_fatal ("can't allocate expression");
                (*expr) -> op = expr_exists;
                known = 0;
-               (*expr) -> data.option = parse_option_name (cfile, 0, &known);
-               if (!(*expr) -> data.option) {
+               /* Pass reference directly to expression structure. */
+               status = parse_option_name(cfile, 0, &known,
+                                          &(*expr)->data.option);
+               if (status != ISC_R_SUCCESS ||
+                   (*expr)->data.option == NULL) {
                        *lose = 1;
                        expression_dereference (expr, MDL);
                        return 0;
@@ -3567,8 +3721,11 @@ int parse_non_binary (expr, cfile, lose, context)
                                 : expr_config_option);
                token = next_token (&val, (unsigned *)0, cfile);
                known = 0;
-               (*expr) -> data.option = parse_option_name (cfile, 0, &known);
-               if (!(*expr) -> data.option) {
+               /* Pass reference directly to expression structure. */
+               status = parse_option_name(cfile, 0, &known,
+                                          &(*expr)->data.option);
+               if (status != ISC_R_SUCCESS ||
+                   (*expr)->data.option == NULL) {
                        *lose = 1;
                        expression_dereference (expr, MDL);
                        return 0;
@@ -4677,9 +4834,10 @@ int parse_option_decl (oc, cfile)
        struct buffer *bp;
        int known = 0;
        struct enumeration_value *e;
+       isc_result_t status;
 
-       option = parse_option_name (cfile, 0, &known);
-       if (!option)
+       status = parse_option_name (cfile, 0, &known, &option);
+       if (status != ISC_R_SUCCESS || option == NULL)
                return 0;
 
        /* Parse the option data... */
@@ -4699,8 +4857,7 @@ int parse_option_decl (oc, cfile)
                                        parse_warn (cfile,
                                                    "malformed %s (bug!)",
                                                    "encapsulation format");
-                                       skip_to_semi (cfile);
-                                       return 0;
+                                       goto parse_exit;
                                }
                              case 'X':
                                len = parse_X (cfile, &hunkbuf [hunkix],
@@ -4714,15 +4871,13 @@ int parse_option_decl (oc, cfile)
                                if (token != STRING) {
                                        parse_warn (cfile,
                                                    "expecting string.");
-                                       skip_to_semi (cfile);
-                                       return 0;
+                                       goto parse_exit;
                                }
                                if (hunkix + len + 1 > sizeof hunkbuf) {
                                        parse_warn (cfile,
                                                    "option data buffer %s",
                                                    "overflow");
-                                       skip_to_semi (cfile);
-                                       return 0;
+                                       goto parse_exit;
                                }
                                memcpy (&hunkbuf [hunkix], val, len + 1);
                                nul_term = 1;
@@ -4736,22 +4891,20 @@ int parse_option_decl (oc, cfile)
                                        parse_warn (cfile,
                                                    "malformed %s (bug!)",
                                                    "enumeration format");
-                                     foo:
-                                       skip_to_semi (cfile);
-                                       return 0;
+                                       goto parse_exit;
                                }
                                token = next_token (&val,
                                                    (unsigned *)0, cfile);
                                if (!is_identifier (token)) {
                                        parse_warn (cfile,
                                                    "identifier expected");
-                                       goto foo;
+                                       goto parse_exit;
                                }
                                e = find_enumeration_value (f, fmt - f, val);
                                if (!e) {
                                        parse_warn (cfile,
                                                    "unknown value");
-                                       goto foo;
+                                       goto parse_exit;
                                }
                                len = 1;
                                dp = &e -> value;
@@ -4759,7 +4912,7 @@ int parse_option_decl (oc, cfile)
 
                              case 'I': /* IP address. */
                                if (!parse_ip_addr (cfile, &ip_addr))
-                                       return 0;
+                                       goto exit;
                                len = ip_addr.len;
                                dp = ip_addr.iabuf;
 
@@ -4768,8 +4921,7 @@ int parse_option_decl (oc, cfile)
                                        parse_warn (cfile,
                                                    "option data buffer %s",
                                                    "overflow");
-                                       skip_to_semi (cfile);
-                                       return 0;
+                                       goto parse_exit;
                                }
                                memcpy (&hunkbuf [hunkix], dp, len);
                                hunkix += len;
@@ -4785,8 +4937,9 @@ int parse_option_decl (oc, cfile)
                                        parse_warn (cfile,
                                                    "expecting number.");
                                        if (token != SEMI)
-                                               skip_to_semi (cfile);
-                                       return 0;
+                                               goto parse_exit;
+                                       else
+                                               goto exit;
                                }
                                convert_num (cfile, buf, val, 0, 32);
                                len = 4;
@@ -4825,8 +4978,9 @@ int parse_option_decl (oc, cfile)
                                                    "expecting identifier.");
                                      bad_flag:
                                        if (token != SEMI)
-                                               skip_to_semi (cfile);
-                                       return 0;
+                                               goto parse_exit;
+                                       else
+                                               goto exit;
                                }
                                if (!strcasecmp (val, "true")
                                    || !strcasecmp (val, "on"))
@@ -4846,8 +5000,7 @@ int parse_option_decl (oc, cfile)
                              default:
                                log_error ("parse_option_param: Bad format %c",
                                      *fmt);
-                               skip_to_semi (cfile);
-                               return 0;
+                               goto parse_exit;
                        }
                }
                token = next_token (&val, (unsigned *)0, cfile);
@@ -4855,8 +5008,7 @@ int parse_option_decl (oc, cfile)
 
        if (token != SEMI) {
                parse_warn (cfile, "semicolon expected.");
-               skip_to_semi (cfile);
-               return 0;
+               goto parse_exit;
        }
 
        bp = (struct buffer *)0;
@@ -4873,8 +5025,16 @@ int parse_option_decl (oc, cfile)
        (*oc) -> data.data = &bp -> data [0];
        (*oc) -> data.terminated = nul_term;
        (*oc) -> data.len = hunkix;
-       (*oc) -> option = option;
+       option_reference(&(*oc)->option, option, MDL);
+       option_dereference(&option, MDL);
        return 1;
+
+parse_exit:
+       skip_to_semi (cfile);
+exit:
+       option_dereference(&option, MDL);
+
+       return 0;
 }
 
 /* Consider merging parse_cshl into this. */
index 6f177b0b54d663eb7f733b5482cdb8e92ff0a3bd..caad763d767a007fb65c32ba60821f1174f6324f 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tables.c,v 1.54 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tables.c,v 1.55 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -42,9 +42,14 @@ static char copyright[] =
 /* XXXDPN: Moved here from hash.c, when it moved to libomapi.  Not sure
    where these really belong. */
 HASH_FUNCTIONS (group, const char *, struct group_object, group_hash_t,
-               group_reference, group_dereference)
-HASH_FUNCTIONS (universe, const char *, struct universe, universe_hash_t, 0, 0)
-HASH_FUNCTIONS (option, const char *, struct option, option_hash_t, 0, 0)
+               group_reference, group_dereference, do_string_hash)
+HASH_FUNCTIONS (universe, const char *, struct universe, universe_hash_t, 0, 0,
+               do_case_hash)
+HASH_FUNCTIONS (option_name, const char *, struct option, option_name_hash_t,
+               option_reference, option_dereference, do_case_hash)
+HASH_FUNCTIONS (option_code, const unsigned *, struct option,
+               option_code_hash_t, option_reference, option_dereference,
+               do_number_hash)
 
 /* DHCP Option names, formats and codes, from RFC1533.
 
@@ -92,523 +97,113 @@ HASH_FUNCTIONS (option, const char *, struct option, option_hash_t, 0, 0)
 */
 
 struct universe dhcp_universe;
-struct option dhcp_options [256] = {
-       { "pad", "",                                    &dhcp_universe, 0 },
-       { "subnet-mask", "I",                           &dhcp_universe, 1 },
-       { "time-offset", "l",                           &dhcp_universe, 2 },
-       { "routers", "IA",                              &dhcp_universe, 3 },
-       { "time-servers", "IA",                         &dhcp_universe, 4 },
-       { "ien116-name-servers", "IA",                  &dhcp_universe, 5 },
-       { "domain-name-servers", "IA",                  &dhcp_universe, 6 },
-       { "log-servers", "IA",                          &dhcp_universe, 7 },
-       { "cookie-servers", "IA",                       &dhcp_universe, 8 },
-       { "lpr-servers", "IA",                          &dhcp_universe, 9 },
-       { "impress-servers", "IA",                      &dhcp_universe, 10 },
-       { "resource-location-servers", "IA",            &dhcp_universe, 11 },
-       { "host-name", "t",                             &dhcp_universe, 12 },
-       { "boot-size", "S",                             &dhcp_universe, 13 },
-       { "merit-dump", "t",                            &dhcp_universe, 14 },
-       { "domain-name", "t",                           &dhcp_universe, 15 },
-       { "swap-server", "I",                           &dhcp_universe, 16 },
-       { "root-path", "t",                             &dhcp_universe, 17 },
-       { "extensions-path", "t",                       &dhcp_universe, 18 },
-       { "ip-forwarding", "f",                         &dhcp_universe, 19 },
-       { "non-local-source-routing", "f",              &dhcp_universe, 20 },
-       { "policy-filter", "IIA",                       &dhcp_universe, 21 },
-       { "max-dgram-reassembly", "S",                  &dhcp_universe, 22 },
-       { "default-ip-ttl", "B",                        &dhcp_universe, 23 },
-       { "path-mtu-aging-timeout", "L",                &dhcp_universe, 24 },
-       { "path-mtu-plateau-table", "SA",               &dhcp_universe, 25 },
-       { "interface-mtu", "S",                         &dhcp_universe, 26 },
-       { "all-subnets-local", "f",                     &dhcp_universe, 27 },
-       { "broadcast-address", "I",                     &dhcp_universe, 28 },
-       { "perform-mask-discovery", "f",                &dhcp_universe, 29 },
-       { "mask-supplier", "f",                         &dhcp_universe, 30 },
-       { "router-discovery", "f",                      &dhcp_universe, 31 },
-       { "router-solicitation-address", "I",           &dhcp_universe, 32 },
-       { "static-routes", "IIA",                       &dhcp_universe, 33 },
-       { "trailer-encapsulation", "f",                 &dhcp_universe, 34 },
-       { "arp-cache-timeout", "L",                     &dhcp_universe, 35 },
-       { "ieee802-3-encapsulation", "f",               &dhcp_universe, 36 },
-       { "default-tcp-ttl", "B",                       &dhcp_universe, 37 },
-       { "tcp-keepalive-interval", "L",                &dhcp_universe, 38 },
-       { "tcp-keepalive-garbage", "f",                 &dhcp_universe, 39 },
-       { "nis-domain", "t",                            &dhcp_universe, 40 },
-       { "nis-servers", "IA",                          &dhcp_universe, 41 },
-       { "ntp-servers", "IA",                          &dhcp_universe, 42 },
-       { "vendor-encapsulated-options", "E.",          &dhcp_universe, 43 },
-       { "netbios-name-servers", "IA",                 &dhcp_universe, 44 },
-       { "netbios-dd-server", "IA",                    &dhcp_universe, 45 },
-       { "netbios-node-type", "B",                     &dhcp_universe, 46 },
-       { "netbios-scope", "t",                         &dhcp_universe, 47 },
-       { "font-servers", "IA",                         &dhcp_universe, 48 },
-       { "x-display-manager", "IA",                    &dhcp_universe, 49 },
-       { "dhcp-requested-address", "I",                &dhcp_universe, 50 },
-       { "dhcp-lease-time", "L",                       &dhcp_universe, 51 },
-       { "dhcp-option-overload", "B",                  &dhcp_universe, 52 },
-       { "dhcp-message-type", "B",                     &dhcp_universe, 53 },
-       { "dhcp-server-identifier", "I",                &dhcp_universe, 54 },
-       { "dhcp-parameter-request-list", "BA",          &dhcp_universe, 55 },
-       { "dhcp-message", "t",                          &dhcp_universe, 56 },
-       { "dhcp-max-message-size", "S",                 &dhcp_universe, 57 },
-       { "dhcp-renewal-time", "L",                     &dhcp_universe, 58 },
-       { "dhcp-rebinding-time", "L",                   &dhcp_universe, 59 },
-       { "vendor-class-identifier", "X",               &dhcp_universe, 60 },
-       { "dhcp-client-identifier", "X",                &dhcp_universe, 61 },
-       { "nwip-domain", "t",                           &dhcp_universe, 62 },
-       { "nwip-suboptions", "Enwip.",                  &dhcp_universe, 63 },
-       { "nisplus-domain", "t",                        &dhcp_universe, 64 },
-       { "nisplus-servers", "IA",                      &dhcp_universe, 65 },
-       { "tftp-server-name", "t",                      &dhcp_universe, 66 },
-       { "bootfile-name", "t",                         &dhcp_universe, 67 },
-       { "mobile-ip-home-agent", "IA",                 &dhcp_universe, 68 },
-       { "smtp-server", "IA",                          &dhcp_universe, 69 },
-       { "pop-server", "IA",                           &dhcp_universe, 70 },
-       { "nntp-server", "IA",                          &dhcp_universe, 71 },
-       { "www-server", "IA",                           &dhcp_universe, 72 },
-       { "finger-server", "IA",                        &dhcp_universe, 73 },
-       { "irc-server", "IA",                           &dhcp_universe, 74 },
-       { "streettalk-server", "IA",                    &dhcp_universe, 75 },
-       { "streettalk-directory-assistance-server", "IA", &dhcp_universe, 76 },
-       { "user-class", "t",                            &dhcp_universe, 77 },
-       { "slp-directory-agent", "fIa",                 &dhcp_universe, 78 },
-       { "slp-service-scope", "fto",                   &dhcp_universe, 79 },
-       { "unknown-80", "X",                            &dhcp_universe, 80 },
-       { "fqdn", "Efqdn.",                             &dhcp_universe, 81 },
-       { "relay-agent-information", "Eagent.",         &dhcp_universe, 82 },
-       { "unknown-83", "X",                            &dhcp_universe, 83 },
-       { "unknown-84", "X",                            &dhcp_universe, 84 },
-       { "nds-servers", "IA",                          &dhcp_universe, 85 },
-       { "nds-tree-name", "t",                         &dhcp_universe, 86 },
-       { "nds-context", "t",                           &dhcp_universe, 87 },
-       { "unknown-88", "X",                            &dhcp_universe, 88 },
-       { "unknown-89", "X",                            &dhcp_universe, 89 },
-       { "unknown-90", "X",                            &dhcp_universe, 90 },
-       { "unknown-91", "X",                            &dhcp_universe, 91 },
-       { "unknown-92", "X",                            &dhcp_universe, 92 },
-       { "unknown-93", "X",                            &dhcp_universe, 93 },
-       { "unknown-94", "X",                            &dhcp_universe, 94 },
-       { "unknown-95", "X",                            &dhcp_universe, 95 },
-       { "unknown-96", "X",                            &dhcp_universe, 96 },
-       { "unknown-97", "X",                            &dhcp_universe, 97 },
-       { "uap-servers", "t",                           &dhcp_universe, 98 },
-       { "unknown-99", "X",                            &dhcp_universe, 99 },
-       { "unknown-100", "X",                           &dhcp_universe, 100 },
-       { "unknown-101", "X",                           &dhcp_universe, 101 },
-       { "unknown-102", "X",                           &dhcp_universe, 102 },
-       { "unknown-103", "X",                           &dhcp_universe, 103 },
-       { "unknown-104", "X",                           &dhcp_universe, 104 },
-       { "unknown-105", "X",                           &dhcp_universe, 105 },
-       { "unknown-106", "X",                           &dhcp_universe, 106 },
-       { "unknown-107", "X",                           &dhcp_universe, 107 },
-       { "unknown-108", "X",                           &dhcp_universe, 108 },
-       { "unknown-109", "X",                           &dhcp_universe, 109 },
-       { "unknown-110", "X",                           &dhcp_universe, 110 },
-       { "unknown-111", "X",                           &dhcp_universe, 111 },
-       { "unknown-112", "X",                           &dhcp_universe, 112 },
-       { "unknown-113", "X",                           &dhcp_universe, 113 },
-       { "unknown-114", "X",                           &dhcp_universe, 114 },
-       { "unknown-115", "X",                           &dhcp_universe, 115 },
-       { "unknown-116", "X",                           &dhcp_universe, 116 },
-       { "unknown-117", "X",                           &dhcp_universe, 117 },
-       { "subnet-selection", "I",                      &dhcp_universe, 118 },
-       { "unknown-119", "X",                           &dhcp_universe, 119 },
-       { "unknown-120", "X",                           &dhcp_universe, 120 },
-       { "unknown-121", "X",                           &dhcp_universe, 121 },
-       { "unknown-122", "X",                           &dhcp_universe, 122 },
-       { "unknown-123", "X",                           &dhcp_universe, 123 },
-       { "unknown-124", "X",                           &dhcp_universe, 124 },
-       { "unknown-125", "X",                           &dhcp_universe, 125 },
-       { "unknown-126", "X",                           &dhcp_universe, 126 },
-       { "unknown-127", "X",                           &dhcp_universe, 127 },
-       { "unknown-128", "X",                           &dhcp_universe, 128 },
-       { "unknown-129", "X",                           &dhcp_universe, 129 },
-       { "unknown-130", "X",                           &dhcp_universe, 130 },
-       { "unknown-131", "X",                           &dhcp_universe, 131 },
-       { "unknown-132", "X",                           &dhcp_universe, 132 },
-       { "unknown-133", "X",                           &dhcp_universe, 133 },
-       { "unknown-134", "X",                           &dhcp_universe, 134 },
-       { "unknown-135", "X",                           &dhcp_universe, 135 },
-       { "unknown-136", "X",                           &dhcp_universe, 136 },
-       { "unknown-137", "X",                           &dhcp_universe, 137 },
-       { "unknown-138", "X",                           &dhcp_universe, 138 },
-       { "unknown-139", "X",                           &dhcp_universe, 139 },
-       { "unknown-140", "X",                           &dhcp_universe, 140 },
-       { "unknown-141", "X",                           &dhcp_universe, 141 },
-       { "unknown-142", "X",                           &dhcp_universe, 142 },
-       { "unknown-143", "X",                           &dhcp_universe, 143 },
-       { "unknown-144", "X",                           &dhcp_universe, 144 },
-       { "unknown-145", "X",                           &dhcp_universe, 145 },
-       { "unknown-146", "X",                           &dhcp_universe, 146 },
-       { "unknown-147", "X",                           &dhcp_universe, 147 },
-       { "unknown-148", "X",                           &dhcp_universe, 148 },
-       { "unknown-149", "X",                           &dhcp_universe, 149 },
-       { "unknown-150", "X",                           &dhcp_universe, 150 },
-       { "unknown-151", "X",                           &dhcp_universe, 151 },
-       { "unknown-152", "X",                           &dhcp_universe, 152 },
-       { "unknown-153", "X",                           &dhcp_universe, 153 },
-       { "unknown-154", "X",                           &dhcp_universe, 154 },
-       { "unknown-155", "X",                           &dhcp_universe, 155 },
-       { "unknown-156", "X",                           &dhcp_universe, 156 },
-       { "unknown-157", "X",                           &dhcp_universe, 157 },
-       { "unknown-158", "X",                           &dhcp_universe, 158 },
-       { "unknown-159", "X",                           &dhcp_universe, 159 },
-       { "unknown-160", "X",                           &dhcp_universe, 160 },
-       { "unknown-161", "X",                           &dhcp_universe, 161 },
-       { "unknown-162", "X",                           &dhcp_universe, 162 },
-       { "unknown-163", "X",                           &dhcp_universe, 163 },
-       { "unknown-164", "X",                           &dhcp_universe, 164 },
-       { "unknown-165", "X",                           &dhcp_universe, 165 },
-       { "unknown-166", "X",                           &dhcp_universe, 166 },
-       { "unknown-167", "X",                           &dhcp_universe, 167 },
-       { "unknown-168", "X",                           &dhcp_universe, 168 },
-       { "unknown-169", "X",                           &dhcp_universe, 169 },
-       { "unknown-170", "X",                           &dhcp_universe, 170 },
-       { "unknown-171", "X",                           &dhcp_universe, 171 },
-       { "unknown-172", "X",                           &dhcp_universe, 172 },
-       { "unknown-173", "X",                           &dhcp_universe, 173 },
-       { "unknown-174", "X",                           &dhcp_universe, 174 },
-       { "unknown-175", "X",                           &dhcp_universe, 175 },
-       { "unknown-176", "X",                           &dhcp_universe, 176 },
-       { "unknown-177", "X",                           &dhcp_universe, 177 },
-       { "unknown-178", "X",                           &dhcp_universe, 178 },
-       { "unknown-179", "X",                           &dhcp_universe, 179 },
-       { "unknown-180", "X",                           &dhcp_universe, 180 },
-       { "unknown-181", "X",                           &dhcp_universe, 181 },
-       { "unknown-182", "X",                           &dhcp_universe, 182 },
-       { "unknown-183", "X",                           &dhcp_universe, 183 },
-       { "unknown-184", "X",                           &dhcp_universe, 184 },
-       { "unknown-185", "X",                           &dhcp_universe, 185 },
-       { "unknown-186", "X",                           &dhcp_universe, 186 },
-       { "unknown-187", "X",                           &dhcp_universe, 187 },
-       { "unknown-188", "X",                           &dhcp_universe, 188 },
-       { "unknown-189", "X",                           &dhcp_universe, 189 },
-       { "unknown-190", "X",                           &dhcp_universe, 190 },
-       { "unknown-191", "X",                           &dhcp_universe, 191 },
-       { "unknown-192", "X",                           &dhcp_universe, 192 },
-       { "unknown-193", "X",                           &dhcp_universe, 193 },
-       { "unknown-194", "X",                           &dhcp_universe, 194 },
-       { "unknown-195", "X",                           &dhcp_universe, 195 },
-       { "unknown-196", "X",                           &dhcp_universe, 196 },
-       { "unknown-197", "X",                           &dhcp_universe, 197 },
-       { "unknown-198", "X",                           &dhcp_universe, 198 },
-       { "unknown-199", "X",                           &dhcp_universe, 199 },
-       { "unknown-200", "X",                           &dhcp_universe, 200 },
-       { "unknown-201", "X",                           &dhcp_universe, 201 },
-       { "unknown-202", "X",                           &dhcp_universe, 202 },
-       { "unknown-203", "X",                           &dhcp_universe, 203 },
-       { "unknown-204", "X",                           &dhcp_universe, 204 },
-       { "unknown-205", "X",                           &dhcp_universe, 205 },
-       { "unknown-206", "X",                           &dhcp_universe, 206 },
-       { "unknown-207", "X",                           &dhcp_universe, 207 },
-       { "unknown-208", "X",                           &dhcp_universe, 208 },
-       { "unknown-209", "X",                           &dhcp_universe, 209 },
-       { "authenticate", "X",                          &dhcp_universe, 210 },
-       { "unknown-211", "X",                           &dhcp_universe, 211 },
-       { "unknown-212", "X",                           &dhcp_universe, 212 },
-       { "unknown-213", "X",                           &dhcp_universe, 213 },
-       { "unknown-214", "X",                           &dhcp_universe, 214 },
-       { "unknown-215", "X",                           &dhcp_universe, 215 },
-       { "unknown-216", "X",                           &dhcp_universe, 216 },
-       { "unknown-217", "X",                           &dhcp_universe, 217 },
-       { "unknown-218", "X",                           &dhcp_universe, 218 },
-       { "unknown-219", "X",                           &dhcp_universe, 219 },
-       { "unknown-220", "X",                           &dhcp_universe, 220 },
-       { "unknown-221", "X",                           &dhcp_universe, 221 },
-       { "unknown-222", "X",                           &dhcp_universe, 222 },
-       { "unknown-223", "X",                           &dhcp_universe, 223 },
-       { "unknown-224", "X",                           &dhcp_universe, 224 },
-       { "unknown-225", "X",                           &dhcp_universe, 225 },
-       { "unknown-226", "X",                           &dhcp_universe, 226 },
-       { "unknown-227", "X",                           &dhcp_universe, 227 },
-       { "unknown-228", "X",                           &dhcp_universe, 228 },
-       { "unknown-229", "X",                           &dhcp_universe, 229 },
-       { "unknown-230", "X",                           &dhcp_universe, 230 },
-       { "unknown-231", "X",                           &dhcp_universe, 231 },
-       { "unknown-232", "X",                           &dhcp_universe, 232 },
-       { "unknown-233", "X",                           &dhcp_universe, 233 },
-       { "unknown-234", "X",                           &dhcp_universe, 234 },
-       { "unknown-235", "X",                           &dhcp_universe, 235 },
-       { "unknown-236", "X",                           &dhcp_universe, 236 },
-       { "unknown-237", "X",                           &dhcp_universe, 237 },
-       { "unknown-238", "X",                           &dhcp_universe, 238 },
-       { "unknown-239", "X",                           &dhcp_universe, 239 },
-       { "unknown-240", "X",                           &dhcp_universe, 240 },
-       { "unknown-241", "X",                           &dhcp_universe, 241 },
-       { "unknown-242", "X",                           &dhcp_universe, 242 },
-       { "unknown-243", "X",                           &dhcp_universe, 243 },
-       { "unknown-244", "X",                           &dhcp_universe, 244 },
-       { "unknown-245", "X",                           &dhcp_universe, 245 },
-       { "unknown-246", "X",                           &dhcp_universe, 246 },
-       { "unknown-247", "X",                           &dhcp_universe, 247 },
-       { "unknown-248", "X",                           &dhcp_universe, 248 },
-       { "unknown-249", "X",                           &dhcp_universe, 249 },
-       { "unknown-250", "X",                           &dhcp_universe, 250 },
-       { "unknown-251", "X",                           &dhcp_universe, 251 },
-       { "unknown-252", "X",                           &dhcp_universe, 252 },
-       { "unknown-253", "X",                           &dhcp_universe, 253 },
-       { "unknown-254", "X",                           &dhcp_universe, 254 },
-       { "option-end", "e",                            &dhcp_universe, 255 },
+static struct option dhcp_options[] = {
+       { "subnet-mask", "I",                   &dhcp_universe,   1, 1 },
+       { "time-offset", "l",                   &dhcp_universe,   2, 1 },
+       { "routers", "IA",                      &dhcp_universe,   3, 1 },
+       { "time-servers", "IA",                 &dhcp_universe,   4, 1 },
+       { "ien116-name-servers", "IA",          &dhcp_universe,   5, 1 },
+       { "domain-name-servers", "IA",          &dhcp_universe,   6, 1 },
+       { "log-servers", "IA",                  &dhcp_universe,   7, 1 },
+       { "cookie-servers", "IA",               &dhcp_universe,   8, 1 },
+       { "lpr-servers", "IA",                  &dhcp_universe,   9, 1 },
+       { "impress-servers", "IA",              &dhcp_universe,  10, 1 },
+       { "resource-location-servers", "IA",    &dhcp_universe,  11, 1 },
+       { "host-name", "t",                     &dhcp_universe,  12, 1 },
+       { "boot-size", "S",                     &dhcp_universe,  13, 1 },
+       { "merit-dump", "t",                    &dhcp_universe,  14, 1 },
+       { "domain-name", "t",                   &dhcp_universe,  15, 1 },
+       { "swap-server", "I",                   &dhcp_universe,  16, 1 },
+       { "root-path", "t",                     &dhcp_universe,  17, 1 },
+       { "extensions-path", "t",               &dhcp_universe,  18, 1 },
+       { "ip-forwarding", "f",                 &dhcp_universe,  19, 1 },
+       { "non-local-source-routing", "f",      &dhcp_universe,  20, 1 },
+       { "policy-filter", "IIA",               &dhcp_universe,  21, 1 },
+       { "max-dgram-reassembly", "S",          &dhcp_universe,  22, 1 },
+       { "default-ip-ttl", "B",                &dhcp_universe,  23, 1 },
+       { "path-mtu-aging-timeout", "L",        &dhcp_universe,  24, 1 },
+       { "path-mtu-plateau-table", "SA",       &dhcp_universe,  25, 1 },
+       { "interface-mtu", "S",                 &dhcp_universe,  26, 1 },
+       { "all-subnets-local", "f",             &dhcp_universe,  27, 1 },
+       { "broadcast-address", "I",             &dhcp_universe,  28, 1 },
+       { "perform-mask-discovery", "f",        &dhcp_universe,  29, 1 },
+       { "mask-supplier", "f",                 &dhcp_universe,  30, 1 },
+       { "router-discovery", "f",              &dhcp_universe,  31, 1 },
+       { "router-solicitation-address", "I",   &dhcp_universe,  32, 1 },
+       { "static-routes", "IIA",               &dhcp_universe,  33, 1 },
+       { "trailer-encapsulation", "f",         &dhcp_universe,  34, 1 },
+       { "arp-cache-timeout", "L",             &dhcp_universe,  35, 1 },
+       { "ieee802-3-encapsulation", "f",       &dhcp_universe,  36, 1 },
+       { "default-tcp-ttl", "B",               &dhcp_universe,  37, 1 },
+       { "tcp-keepalive-interval", "L",        &dhcp_universe,  38, 1 },
+       { "tcp-keepalive-garbage", "f",         &dhcp_universe,  39, 1 },
+       { "nis-domain", "t",                    &dhcp_universe,  40, 1 },
+       { "nis-servers", "IA",                  &dhcp_universe,  41, 1 },
+       { "ntp-servers", "IA",                  &dhcp_universe,  42, 1 },
+       { "vendor-encapsulated-options", "E.",  &dhcp_universe,  43, 1 },
+       { "netbios-name-servers", "IA",         &dhcp_universe,  44, 1 },
+       { "netbios-dd-server", "IA",            &dhcp_universe,  45, 1 },
+       { "netbios-node-type", "B",             &dhcp_universe,  46, 1 },
+       { "netbios-scope", "t",                 &dhcp_universe,  47, 1 },
+       { "font-servers", "IA",                 &dhcp_universe,  48, 1 },
+       { "x-display-manager", "IA",            &dhcp_universe,  49, 1 },
+       { "dhcp-requested-address", "I",        &dhcp_universe,  50, 1 },
+       { "dhcp-lease-time", "L",               &dhcp_universe,  51, 1 },
+       { "dhcp-option-overload", "B",          &dhcp_universe,  52, 1 },
+       { "dhcp-message-type", "B",             &dhcp_universe,  53, 1 },
+       { "dhcp-server-identifier", "I",        &dhcp_universe,  54, 1 },
+       { "dhcp-parameter-request-list", "BA",  &dhcp_universe,  55, 1 },
+       { "dhcp-message", "t",                  &dhcp_universe,  56, 1 },
+       { "dhcp-max-message-size", "S",         &dhcp_universe,  57, 1 },
+       { "dhcp-renewal-time", "L",             &dhcp_universe,  58, 1 },
+       { "dhcp-rebinding-time", "L",           &dhcp_universe,  59, 1 },
+       { "vendor-class-identifier", "X",       &dhcp_universe,  60, 1 },
+       { "dhcp-client-identifier", "X",        &dhcp_universe,  61, 1 },
+       { "nwip-domain", "t",                   &dhcp_universe,  62, 1 },
+       { "nwip-suboptions", "Enwip.",          &dhcp_universe,  63, 1 },
+       { "nisplus-domain", "t",                &dhcp_universe,  64, 1 },
+       { "nisplus-servers", "IA",              &dhcp_universe,  65, 1 },
+       { "tftp-server-name", "t",              &dhcp_universe,  66, 1 },
+       { "bootfile-name", "t",                 &dhcp_universe,  67, 1 },
+       { "mobile-ip-home-agent", "IA",         &dhcp_universe,  68, 1 },
+       { "smtp-server", "IA",                  &dhcp_universe,  69, 1 },
+       { "pop-server", "IA",                   &dhcp_universe,  70, 1 },
+       { "nntp-server", "IA",                  &dhcp_universe,  71, 1 },
+       { "www-server", "IA",                   &dhcp_universe,  72, 1 },
+       { "finger-server", "IA",                &dhcp_universe,  73, 1 },
+       { "irc-server", "IA",                   &dhcp_universe,  74, 1 },
+       { "streettalk-server", "IA",            &dhcp_universe,  75, 1 },
+       { "streettalk-directory-assistance-server", "IA",
+                                               &dhcp_universe,  76, 1 },
+       { "user-class", "t",                    &dhcp_universe,  77, 1 },
+       { "slp-directory-agent", "fIa",         &dhcp_universe,  78, 1 },
+       { "slp-service-scope", "fto",           &dhcp_universe,  79, 1 },
+       { "fqdn", "Efqdn.",                     &dhcp_universe,  81, 1 },
+       { "relay-agent-information", "Eagent.", &dhcp_universe,  82, 1 },
+       { "nds-servers", "IA",                  &dhcp_universe,  85, 1 },
+       { "nds-tree-name", "t",                 &dhcp_universe,  86, 1 },
+       { "nds-context", "t",                   &dhcp_universe,  87, 1 },
+       { "uap-servers", "t",                   &dhcp_universe,  98, 1 },
+       { "subnet-selection", "I",              &dhcp_universe, 118, 1 },
+       { "vivco", "Evendor-class.",            &dhcp_universe, 124, 1 },
+       { "vivso", "Evendor.",                  &dhcp_universe, 125, 1 },
+       { NULL, NULL, NULL, 0, 0 }
 };
 
 struct universe nwip_universe;
-struct option nwip_options [256] = {
-       { "pad", "",                                    &nwip_universe, 0 },
-       { "illegal-1", "",                              &nwip_universe, 1 },
-       { "illegal-2", "",                              &nwip_universe, 2 },
-       { "illegal-3", "",                              &nwip_universe, 3 },
-       { "illegal-4", "",                              &nwip_universe, 4 },
-       { "nsq-broadcast", "f",                         &nwip_universe, 5 },
-       { "preferred-dss", "IA",                        &nwip_universe, 6 },
-       { "nearest-nwip-server", "IA",                  &nwip_universe, 7 },
-       { "autoretries", "B",                           &nwip_universe, 8 },
-       { "autoretry-secs", "B",                        &nwip_universe, 9 },
-       { "nwip-1-1", "f",                              &nwip_universe, 10 },
-       { "primary-dss", "I",                           &nwip_universe, 11 },
-       { "unknown-12", "X",                            &nwip_universe, 12 },
-       { "unknown-13", "X",                            &nwip_universe, 13 },
-       { "unknown-14", "X",                            &nwip_universe, 14 },
-       { "unknown-15", "X",                            &nwip_universe, 15 },
-       { "unknown-16", "X",                            &nwip_universe, 16 },
-       { "unknown-17", "X",                            &nwip_universe, 17 },
-       { "unknown-18", "X",                            &nwip_universe, 18 },
-       { "unknown-19", "X",                            &nwip_universe, 19 },
-       { "unknown-20", "X",                            &nwip_universe, 20 },
-       { "unknown-21", "X",                            &nwip_universe, 21 },
-       { "unknown-22", "X",                            &nwip_universe, 22 },
-       { "unknown-23", "X",                            &nwip_universe, 23 },
-       { "unknown-24", "X",                            &nwip_universe, 24 },
-       { "unknown-25", "X",                            &nwip_universe, 25 },
-       { "unknown-26", "X",                            &nwip_universe, 26 },
-       { "unknown-27", "X",                            &nwip_universe, 27 },
-       { "unknown-28", "X",                            &nwip_universe, 28 },
-       { "unknown-29", "X",                            &nwip_universe, 29 },
-       { "unknown-30", "X",                            &nwip_universe, 30 },
-       { "unknown-31", "X",                            &nwip_universe, 31 },
-       { "unknown-32", "X",                            &nwip_universe, 32 },
-       { "unknown-33", "X",                            &nwip_universe, 33 },
-       { "unknown-34", "X",                            &nwip_universe, 34 },
-       { "unknown-35", "X",                            &nwip_universe, 35 },
-       { "unknown-36", "X",                            &nwip_universe, 36 },
-       { "unknown-37", "X",                            &nwip_universe, 37 },
-       { "unknown-38", "X",                            &nwip_universe, 38 },
-       { "unknown-39", "X",                            &nwip_universe, 39 },
-       { "unknown-40", "X",                            &nwip_universe, 40 },
-       { "unknown-41", "X",                            &nwip_universe, 41 },
-       { "unknown-42", "X",                            &nwip_universe, 42 },
-       { "unknown-43", "X",                            &nwip_universe, 43 },
-       { "unknown-44", "X",                            &nwip_universe, 44 },
-       { "unknown-45", "X",                            &nwip_universe, 45 },
-       { "unknown-46", "X",                            &nwip_universe, 46 },
-       { "unknown-47", "X",                            &nwip_universe, 47 },
-       { "unknown-48", "X",                            &nwip_universe, 48 },
-       { "unknown-49", "X",                            &nwip_universe, 49 },
-       { "unknown-50", "X",                            &nwip_universe, 50 },
-       { "unknown-51", "X",                            &nwip_universe, 51 },
-       { "unknown-52", "X",                            &nwip_universe, 52 },
-       { "unknown-53", "X",                            &nwip_universe, 53 },
-       { "unknown-54", "X",                            &nwip_universe, 54 },
-       { "unknown-55", "X",                            &nwip_universe, 55 },
-       { "unknown-56", "X",                            &nwip_universe, 56 },
-       { "unknown-57", "X",                            &nwip_universe, 57 },
-       { "unknown-58", "X",                            &nwip_universe, 58 },
-       { "unknown-59", "X",                            &nwip_universe, 59 },
-       { "unknown-60", "X",                            &nwip_universe, 60 },
-       { "unknown-61", "X",                            &nwip_universe, 61 },
-       { "unknown-62", "X",                            &nwip_universe, 62 },
-       { "unknown-63", "X",                            &nwip_universe, 63 },
-       { "unknown-64", "X",                            &nwip_universe, 64 },
-       { "unknown-65", "X",                            &nwip_universe, 65 },
-       { "unknown-66", "X",                            &nwip_universe, 66 },
-       { "unknown-67", "X",                            &nwip_universe, 67 },
-       { "unknown-68", "X",                            &nwip_universe, 68 },
-       { "unknown-69", "X",                            &nwip_universe, 69 },
-       { "unknown-70", "X",                            &nwip_universe, 70 },
-       { "unknown-71", "X",                            &nwip_universe, 71 },
-       { "unknown-72", "X",                            &nwip_universe, 72 },
-       { "unknown-73", "X",                            &nwip_universe, 73 },
-       { "unknown-74", "X",                            &nwip_universe, 74 },
-       { "unknown-75", "X",                            &nwip_universe, 75 },
-       { "unknown-76", "X",                            &nwip_universe, 76 },
-       { "unknown-77", "X",                            &nwip_universe, 77 },
-       { "unknown-78", "X",                            &nwip_universe, 78 },
-       { "unknown-79", "X",                            &nwip_universe, 79 },
-       { "unknown-80", "X",                            &nwip_universe, 80 },
-       { "unknown-81", "X",                            &nwip_universe, 81 },
-       { "unknown-82", "X",                            &nwip_universe, 82 },
-       { "unknown-83", "X",                            &nwip_universe, 83 },
-       { "unknown-84", "X",                            &nwip_universe, 84 },
-       { "unknown-85", "X",                            &nwip_universe, 85 },
-       { "unknown-86", "X",                            &nwip_universe, 86 },
-       { "unknown-87", "X",                            &nwip_universe, 87 },
-       { "unknown-88", "X",                            &nwip_universe, 88 },
-       { "unknown-89", "X",                            &nwip_universe, 89 },
-       { "unknown-90", "X",                            &nwip_universe, 90 },
-       { "unknown-91", "X",                            &nwip_universe, 91 },
-       { "unknown-92", "X",                            &nwip_universe, 92 },
-       { "unknown-93", "X",                            &nwip_universe, 93 },
-       { "unknown-94", "X",                            &nwip_universe, 94 },
-       { "unknown-95", "X",                            &nwip_universe, 95 },
-       { "unknown-96", "X",                            &nwip_universe, 96 },
-       { "unknown-97", "X",                            &nwip_universe, 97 },
-       { "unknown-98", "X",                            &nwip_universe, 98 },
-       { "unknown-99", "X",                            &nwip_universe, 99 },
-       { "unknown-100", "X",                           &nwip_universe, 100 },
-       { "unknown-101", "X",                           &nwip_universe, 101 },
-       { "unknown-102", "X",                           &nwip_universe, 102 },
-       { "unknown-103", "X",                           &nwip_universe, 103 },
-       { "unknown-104", "X",                           &nwip_universe, 104 },
-       { "unknown-105", "X",                           &nwip_universe, 105 },
-       { "unknown-106", "X",                           &nwip_universe, 106 },
-       { "unknown-107", "X",                           &nwip_universe, 107 },
-       { "unknown-108", "X",                           &nwip_universe, 108 },
-       { "unknown-109", "X",                           &nwip_universe, 109 },
-       { "unknown-110", "X",                           &nwip_universe, 110 },
-       { "unknown-111", "X",                           &nwip_universe, 111 },
-       { "unknown-112", "X",                           &nwip_universe, 112 },
-       { "unknown-113", "X",                           &nwip_universe, 113 },
-       { "unknown-114", "X",                           &nwip_universe, 114 },
-       { "unknown-115", "X",                           &nwip_universe, 115 },
-       { "unknown-116", "X",                           &nwip_universe, 116 },
-       { "unknown-117", "X",                           &nwip_universe, 117 },
-       { "unknown-118", "X",                           &nwip_universe, 118 },
-       { "unknown-119", "X",                           &nwip_universe, 119 },
-       { "unknown-120", "X",                           &nwip_universe, 120 },
-       { "unknown-121", "X",                           &nwip_universe, 121 },
-       { "unknown-122", "X",                           &nwip_universe, 122 },
-       { "unknown-123", "X",                           &nwip_universe, 123 },
-       { "unknown-124", "X",                           &nwip_universe, 124 },
-       { "unknown-125", "X",                           &nwip_universe, 125 },
-       { "unknown-126", "X",                           &nwip_universe, 126 },
-       { "unknown-127", "X",                           &nwip_universe, 127 },
-       { "unknown-128", "X",                           &nwip_universe, 128 },
-       { "unknown-129", "X",                           &nwip_universe, 129 },
-       { "unknown-130", "X",                           &nwip_universe, 130 },
-       { "unknown-131", "X",                           &nwip_universe, 131 },
-       { "unknown-132", "X",                           &nwip_universe, 132 },
-       { "unknown-133", "X",                           &nwip_universe, 133 },
-       { "unknown-134", "X",                           &nwip_universe, 134 },
-       { "unknown-135", "X",                           &nwip_universe, 135 },
-       { "unknown-136", "X",                           &nwip_universe, 136 },
-       { "unknown-137", "X",                           &nwip_universe, 137 },
-       { "unknown-138", "X",                           &nwip_universe, 138 },
-       { "unknown-139", "X",                           &nwip_universe, 139 },
-       { "unknown-140", "X",                           &nwip_universe, 140 },
-       { "unknown-141", "X",                           &nwip_universe, 141 },
-       { "unknown-142", "X",                           &nwip_universe, 142 },
-       { "unknown-143", "X",                           &nwip_universe, 143 },
-       { "unknown-144", "X",                           &nwip_universe, 144 },
-       { "unknown-145", "X",                           &nwip_universe, 145 },
-       { "unknown-146", "X",                           &nwip_universe, 146 },
-       { "unknown-147", "X",                           &nwip_universe, 147 },
-       { "unknown-148", "X",                           &nwip_universe, 148 },
-       { "unknown-149", "X",                           &nwip_universe, 149 },
-       { "unknown-150", "X",                           &nwip_universe, 150 },
-       { "unknown-151", "X",                           &nwip_universe, 151 },
-       { "unknown-152", "X",                           &nwip_universe, 152 },
-       { "unknown-153", "X",                           &nwip_universe, 153 },
-       { "unknown-154", "X",                           &nwip_universe, 154 },
-       { "unknown-155", "X",                           &nwip_universe, 155 },
-       { "unknown-156", "X",                           &nwip_universe, 156 },
-       { "unknown-157", "X",                           &nwip_universe, 157 },
-       { "unknown-158", "X",                           &nwip_universe, 158 },
-       { "unknown-159", "X",                           &nwip_universe, 159 },
-       { "unknown-160", "X",                           &nwip_universe, 160 },
-       { "unknown-161", "X",                           &nwip_universe, 161 },
-       { "unknown-162", "X",                           &nwip_universe, 162 },
-       { "unknown-163", "X",                           &nwip_universe, 163 },
-       { "unknown-164", "X",                           &nwip_universe, 164 },
-       { "unknown-165", "X",                           &nwip_universe, 165 },
-       { "unknown-166", "X",                           &nwip_universe, 166 },
-       { "unknown-167", "X",                           &nwip_universe, 167 },
-       { "unknown-168", "X",                           &nwip_universe, 168 },
-       { "unknown-169", "X",                           &nwip_universe, 169 },
-       { "unknown-170", "X",                           &nwip_universe, 170 },
-       { "unknown-171", "X",                           &nwip_universe, 171 },
-       { "unknown-172", "X",                           &nwip_universe, 172 },
-       { "unknown-173", "X",                           &nwip_universe, 173 },
-       { "unknown-174", "X",                           &nwip_universe, 174 },
-       { "unknown-175", "X",                           &nwip_universe, 175 },
-       { "unknown-176", "X",                           &nwip_universe, 176 },
-       { "unknown-177", "X",                           &nwip_universe, 177 },
-       { "unknown-178", "X",                           &nwip_universe, 178 },
-       { "unknown-179", "X",                           &nwip_universe, 179 },
-       { "unknown-180", "X",                           &nwip_universe, 180 },
-       { "unknown-181", "X",                           &nwip_universe, 181 },
-       { "unknown-182", "X",                           &nwip_universe, 182 },
-       { "unknown-183", "X",                           &nwip_universe, 183 },
-       { "unknown-184", "X",                           &nwip_universe, 184 },
-       { "unknown-185", "X",                           &nwip_universe, 185 },
-       { "unknown-186", "X",                           &nwip_universe, 186 },
-       { "unknown-187", "X",                           &nwip_universe, 187 },
-       { "unknown-188", "X",                           &nwip_universe, 188 },
-       { "unknown-189", "X",                           &nwip_universe, 189 },
-       { "unknown-190", "X",                           &nwip_universe, 190 },
-       { "unknown-191", "X",                           &nwip_universe, 191 },
-       { "unknown-192", "X",                           &nwip_universe, 192 },
-       { "unknown-193", "X",                           &nwip_universe, 193 },
-       { "unknown-194", "X",                           &nwip_universe, 194 },
-       { "unknown-195", "X",                           &nwip_universe, 195 },
-       { "unknown-196", "X",                           &nwip_universe, 196 },
-       { "unknown-197", "X",                           &nwip_universe, 197 },
-       { "unknown-198", "X",                           &nwip_universe, 198 },
-       { "unknown-199", "X",                           &nwip_universe, 199 },
-       { "unknown-200", "X",                           &nwip_universe, 200 },
-       { "unknown-201", "X",                           &nwip_universe, 201 },
-       { "unknown-202", "X",                           &nwip_universe, 202 },
-       { "unknown-203", "X",                           &nwip_universe, 203 },
-       { "unknown-204", "X",                           &nwip_universe, 204 },
-       { "unknown-205", "X",                           &nwip_universe, 205 },
-       { "unknown-206", "X",                           &nwip_universe, 206 },
-       { "unknown-207", "X",                           &nwip_universe, 207 },
-       { "unknown-208", "X",                           &nwip_universe, 208 },
-       { "unknown-209", "X",                           &nwip_universe, 209 },
-       { "unknown-210", "X",                           &nwip_universe, 210 },
-       { "unknown-211", "X",                           &nwip_universe, 211 },
-       { "unknown-212", "X",                           &nwip_universe, 212 },
-       { "unknown-213", "X",                           &nwip_universe, 213 },
-       { "unknown-214", "X",                           &nwip_universe, 214 },
-       { "unknown-215", "X",                           &nwip_universe, 215 },
-       { "unknown-216", "X",                           &nwip_universe, 216 },
-       { "unknown-217", "X",                           &nwip_universe, 217 },
-       { "unknown-218", "X",                           &nwip_universe, 218 },
-       { "unknown-219", "X",                           &nwip_universe, 219 },
-       { "unknown-220", "X",                           &nwip_universe, 220 },
-       { "unknown-221", "X",                           &nwip_universe, 221 },
-       { "unknown-222", "X",                           &nwip_universe, 222 },
-       { "unknown-223", "X",                           &nwip_universe, 223 },
-       { "unknown-224", "X",                           &nwip_universe, 224 },
-       { "unknown-225", "X",                           &nwip_universe, 225 },
-       { "unknown-226", "X",                           &nwip_universe, 226 },
-       { "unknown-227", "X",                           &nwip_universe, 227 },
-       { "unknown-228", "X",                           &nwip_universe, 228 },
-       { "unknown-229", "X",                           &nwip_universe, 229 },
-       { "unknown-230", "X",                           &nwip_universe, 230 },
-       { "unknown-231", "X",                           &nwip_universe, 231 },
-       { "unknown-232", "X",                           &nwip_universe, 232 },
-       { "unknown-233", "X",                           &nwip_universe, 233 },
-       { "unknown-234", "X",                           &nwip_universe, 234 },
-       { "unknown-235", "X",                           &nwip_universe, 235 },
-       { "unknown-236", "X",                           &nwip_universe, 236 },
-       { "unknown-237", "X",                           &nwip_universe, 237 },
-       { "unknown-238", "X",                           &nwip_universe, 238 },
-       { "unknown-239", "X",                           &nwip_universe, 239 },
-       { "unknown-240", "X",                           &nwip_universe, 240 },
-       { "unknown-241", "X",                           &nwip_universe, 241 },
-       { "unknown-242", "X",                           &nwip_universe, 242 },
-       { "unknown-243", "X",                           &nwip_universe, 243 },
-       { "unknown-244", "X",                           &nwip_universe, 244 },
-       { "unknown-245", "X",                           &nwip_universe, 245 },
-       { "unknown-246", "X",                           &nwip_universe, 246 },
-       { "unknown-247", "X",                           &nwip_universe, 247 },
-       { "unknown-248", "X",                           &nwip_universe, 248 },
-       { "unknown-249", "X",                           &nwip_universe, 249 },
-       { "unknown-250", "X",                           &nwip_universe, 250 },
-       { "unknown-251", "X",                           &nwip_universe, 251 },
-       { "unknown-252", "X",                           &nwip_universe, 252 },
-       { "unknown-253", "X",                           &nwip_universe, 253 },
-       { "unknown-254", "X",                           &nwip_universe, 254 },
-       { "unknown-end", "e",                           &nwip_universe, 255 },
+static struct option nwip_options[] = {
+       { "illegal-1", "",                      &nwip_universe,   1, 1 },
+       { "illegal-2", "",                      &nwip_universe,   2, 1 },
+       { "illegal-3", "",                      &nwip_universe,   3, 1 },
+       { "illegal-4", "",                      &nwip_universe,   4, 1 },
+       { "nsq-broadcast", "f",                 &nwip_universe,   5, 1 },
+       { "preferred-dss", "IA",                &nwip_universe,   6, 1 },
+       { "nearest-nwip-server", "IA",          &nwip_universe,   7, 1 },
+       { "autoretries", "B",                   &nwip_universe,   8, 1 },
+       { "autoretry-secs", "B",                &nwip_universe,   9, 1 },
+       { "nwip-1-1", "f",                      &nwip_universe,  10, 1 },
+       { "primary-dss", "I",                   &nwip_universe,  11, 1 },
+       { NULL, NULL, NULL, 0, 0 }
 };
 
 /* Note that the "FQDN suboption space" does not reflect the FQDN option
@@ -621,263 +216,35 @@ struct option nwip_options [256] = {
  */
 
 struct universe fqdn_universe;
-struct option fqdn_options [256] = {
-       { "pad", "",                                    &fqdn_universe, 0 },
-       { "no-client-update", "f",                      &fqdn_universe, 1 },
-       { "server-update", "f",                         &fqdn_universe, 2 },
-       { "encoded", "f",                               &fqdn_universe, 3 },
-       { "rcode1", "B",                                &fqdn_universe, 4 },
-       { "rcode2", "B",                                &fqdn_universe, 5 },
-       { "hostname", "t",                              &fqdn_universe, 6 },
-       { "domainname", "t",                            &fqdn_universe, 7 },
-       { "fqdn", "t",                                  &fqdn_universe, 8 },
-       { "unknown-9", "X",                             &fqdn_universe, 9 },
-       { "unknown-10", "X",                            &fqdn_universe, 10 },
-       { "unknown-11", "X",                            &fqdn_universe, 11 },
-       { "unknown-12", "X",                            &fqdn_universe, 12 },
-       { "unknown-13", "X",                            &fqdn_universe, 13 },
-       { "unknown-14", "X",                            &fqdn_universe, 14 },
-       { "unknown-15", "X",                            &fqdn_universe, 15 },
-       { "unknown-16", "X",                            &fqdn_universe, 16 },
-       { "unknown-17", "X",                            &fqdn_universe, 17 },
-       { "unknown-18", "X",                            &fqdn_universe, 18 },
-       { "unknown-19", "X",                            &fqdn_universe, 19 },
-       { "unknown-20", "X",                            &fqdn_universe, 20 },
-       { "unknown-21", "X",                            &fqdn_universe, 21 },
-       { "unknown-22", "X",                            &fqdn_universe, 22 },
-       { "unknown-23", "X",                            &fqdn_universe, 23 },
-       { "unknown-24", "X",                            &fqdn_universe, 24 },
-       { "unknown-25", "X",                            &fqdn_universe, 25 },
-       { "unknown-26", "X",                            &fqdn_universe, 26 },
-       { "unknown-27", "X",                            &fqdn_universe, 27 },
-       { "unknown-28", "X",                            &fqdn_universe, 28 },
-       { "unknown-29", "X",                            &fqdn_universe, 29 },
-       { "unknown-30", "X",                            &fqdn_universe, 30 },
-       { "unknown-31", "X",                            &fqdn_universe, 31 },
-       { "unknown-32", "X",                            &fqdn_universe, 32 },
-       { "unknown-33", "X",                            &fqdn_universe, 33 },
-       { "unknown-34", "X",                            &fqdn_universe, 34 },
-       { "unknown-35", "X",                            &fqdn_universe, 35 },
-       { "unknown-36", "X",                            &fqdn_universe, 36 },
-       { "unknown-37", "X",                            &fqdn_universe, 37 },
-       { "unknown-38", "X",                            &fqdn_universe, 38 },
-       { "unknown-39", "X",                            &fqdn_universe, 39 },
-       { "unknown-40", "X",                            &fqdn_universe, 40 },
-       { "unknown-41", "X",                            &fqdn_universe, 41 },
-       { "unknown-42", "X",                            &fqdn_universe, 42 },
-       { "unknown-43", "X",                            &fqdn_universe, 43 },
-       { "unknown-44", "X",                            &fqdn_universe, 44 },
-       { "unknown-45", "X",                            &fqdn_universe, 45 },
-       { "unknown-46", "X",                            &fqdn_universe, 46 },
-       { "unknown-47", "X",                            &fqdn_universe, 47 },
-       { "unknown-48", "X",                            &fqdn_universe, 48 },
-       { "unknown-49", "X",                            &fqdn_universe, 49 },
-       { "unknown-50", "X",                            &fqdn_universe, 50 },
-       { "unknown-51", "X",                            &fqdn_universe, 51 },
-       { "unknown-52", "X",                            &fqdn_universe, 52 },
-       { "unknown-53", "X",                            &fqdn_universe, 53 },
-       { "unknown-54", "X",                            &fqdn_universe, 54 },
-       { "unknown-55", "X",                            &fqdn_universe, 55 },
-       { "unknown-56", "X",                            &fqdn_universe, 56 },
-       { "unknown-57", "X",                            &fqdn_universe, 57 },
-       { "unknown-58", "X",                            &fqdn_universe, 58 },
-       { "unknown-59", "X",                            &fqdn_universe, 59 },
-       { "unknown-60", "X",                            &fqdn_universe, 60 },
-       { "unknown-61", "X",                            &fqdn_universe, 61 },
-       { "unknown-62", "X",                            &fqdn_universe, 62 },
-       { "unknown-63", "X",                            &fqdn_universe, 63 },
-       { "unknown-64", "X",                            &fqdn_universe, 64 },
-       { "unknown-65", "X",                            &fqdn_universe, 65 },
-       { "unknown-66", "X",                            &fqdn_universe, 66 },
-       { "unknown-67", "X",                            &fqdn_universe, 67 },
-       { "unknown-68", "X",                            &fqdn_universe, 68 },
-       { "unknown-69", "X",                            &fqdn_universe, 69 },
-       { "unknown-70", "X",                            &fqdn_universe, 70 },
-       { "unknown-71", "X",                            &fqdn_universe, 71 },
-       { "unknown-72", "X",                            &fqdn_universe, 72 },
-       { "unknown-73", "X",                            &fqdn_universe, 73 },
-       { "unknown-74", "X",                            &fqdn_universe, 74 },
-       { "unknown-75", "X",                            &fqdn_universe, 75 },
-       { "unknown-76", "X",                            &fqdn_universe, 76 },
-       { "unknown-77", "X",                            &fqdn_universe, 77 },
-       { "unknown-78", "X",                            &fqdn_universe, 78 },
-       { "unknown-79", "X",                            &fqdn_universe, 79 },
-       { "unknown-80", "X",                            &fqdn_universe, 80 },
-       { "unknown-81", "X",                            &fqdn_universe, 81 },
-       { "unknown-82", "X",                            &fqdn_universe, 82 },
-       { "unknown-83", "X",                            &fqdn_universe, 83 },
-       { "unknown-84", "X",                            &fqdn_universe, 84 },
-       { "unknown-85", "X",                            &fqdn_universe, 85 },
-       { "unknown-86", "X",                            &fqdn_universe, 86 },
-       { "unknown-87", "X",                            &fqdn_universe, 87 },
-       { "unknown-88", "X",                            &fqdn_universe, 88 },
-       { "unknown-89", "X",                            &fqdn_universe, 89 },
-       { "unknown-90", "X",                            &fqdn_universe, 90 },
-       { "unknown-91", "X",                            &fqdn_universe, 91 },
-       { "unknown-92", "X",                            &fqdn_universe, 92 },
-       { "unknown-93", "X",                            &fqdn_universe, 93 },
-       { "unknown-94", "X",                            &fqdn_universe, 94 },
-       { "unknown-95", "X",                            &fqdn_universe, 95 },
-       { "unknown-96", "X",                            &fqdn_universe, 96 },
-       { "unknown-97", "X",                            &fqdn_universe, 97 },
-       { "unknown-98", "X",                            &fqdn_universe, 98 },
-       { "unknown-99", "X",                            &fqdn_universe, 99 },
-       { "unknown-100", "X",                           &fqdn_universe, 100 },
-       { "unknown-101", "X",                           &fqdn_universe, 101 },
-       { "unknown-102", "X",                           &fqdn_universe, 102 },
-       { "unknown-103", "X",                           &fqdn_universe, 103 },
-       { "unknown-104", "X",                           &fqdn_universe, 104 },
-       { "unknown-105", "X",                           &fqdn_universe, 105 },
-       { "unknown-106", "X",                           &fqdn_universe, 106 },
-       { "unknown-107", "X",                           &fqdn_universe, 107 },
-       { "unknown-108", "X",                           &fqdn_universe, 108 },
-       { "unknown-109", "X",                           &fqdn_universe, 109 },
-       { "unknown-110", "X",                           &fqdn_universe, 110 },
-       { "unknown-111", "X",                           &fqdn_universe, 111 },
-       { "unknown-112", "X",                           &fqdn_universe, 112 },
-       { "unknown-113", "X",                           &fqdn_universe, 113 },
-       { "unknown-114", "X",                           &fqdn_universe, 114 },
-       { "unknown-115", "X",                           &fqdn_universe, 115 },
-       { "unknown-116", "X",                           &fqdn_universe, 116 },
-       { "unknown-117", "X",                           &fqdn_universe, 117 },
-       { "unknown-118", "X",                           &fqdn_universe, 118 },
-       { "unknown-119", "X",                           &fqdn_universe, 119 },
-       { "unknown-120", "X",                           &fqdn_universe, 120 },
-       { "unknown-121", "X",                           &fqdn_universe, 121 },
-       { "unknown-122", "X",                           &fqdn_universe, 122 },
-       { "unknown-123", "X",                           &fqdn_universe, 123 },
-       { "unknown-124", "X",                           &fqdn_universe, 124 },
-       { "unknown-125", "X",                           &fqdn_universe, 125 },
-       { "unknown-126", "X",                           &fqdn_universe, 126 },
-       { "unknown-127", "X",                           &fqdn_universe, 127 },
-       { "unknown-128", "X",                           &fqdn_universe, 128 },
-       { "unknown-129", "X",                           &fqdn_universe, 129 },
-       { "unknown-130", "X",                           &fqdn_universe, 130 },
-       { "unknown-131", "X",                           &fqdn_universe, 131 },
-       { "unknown-132", "X",                           &fqdn_universe, 132 },
-       { "unknown-133", "X",                           &fqdn_universe, 133 },
-       { "unknown-134", "X",                           &fqdn_universe, 134 },
-       { "unknown-135", "X",                           &fqdn_universe, 135 },
-       { "unknown-136", "X",                           &fqdn_universe, 136 },
-       { "unknown-137", "X",                           &fqdn_universe, 137 },
-       { "unknown-138", "X",                           &fqdn_universe, 138 },
-       { "unknown-139", "X",                           &fqdn_universe, 139 },
-       { "unknown-140", "X",                           &fqdn_universe, 140 },
-       { "unknown-141", "X",                           &fqdn_universe, 141 },
-       { "unknown-142", "X",                           &fqdn_universe, 142 },
-       { "unknown-143", "X",                           &fqdn_universe, 143 },
-       { "unknown-144", "X",                           &fqdn_universe, 144 },
-       { "unknown-145", "X",                           &fqdn_universe, 145 },
-       { "unknown-146", "X",                           &fqdn_universe, 146 },
-       { "unknown-147", "X",                           &fqdn_universe, 147 },
-       { "unknown-148", "X",                           &fqdn_universe, 148 },
-       { "unknown-149", "X",                           &fqdn_universe, 149 },
-       { "unknown-150", "X",                           &fqdn_universe, 150 },
-       { "unknown-151", "X",                           &fqdn_universe, 151 },
-       { "unknown-152", "X",                           &fqdn_universe, 152 },
-       { "unknown-153", "X",                           &fqdn_universe, 153 },
-       { "unknown-154", "X",                           &fqdn_universe, 154 },
-       { "unknown-155", "X",                           &fqdn_universe, 155 },
-       { "unknown-156", "X",                           &fqdn_universe, 156 },
-       { "unknown-157", "X",                           &fqdn_universe, 157 },
-       { "unknown-158", "X",                           &fqdn_universe, 158 },
-       { "unknown-159", "X",                           &fqdn_universe, 159 },
-       { "unknown-160", "X",                           &fqdn_universe, 160 },
-       { "unknown-161", "X",                           &fqdn_universe, 161 },
-       { "unknown-162", "X",                           &fqdn_universe, 162 },
-       { "unknown-163", "X",                           &fqdn_universe, 163 },
-       { "unknown-164", "X",                           &fqdn_universe, 164 },
-       { "unknown-165", "X",                           &fqdn_universe, 165 },
-       { "unknown-166", "X",                           &fqdn_universe, 166 },
-       { "unknown-167", "X",                           &fqdn_universe, 167 },
-       { "unknown-168", "X",                           &fqdn_universe, 168 },
-       { "unknown-169", "X",                           &fqdn_universe, 169 },
-       { "unknown-170", "X",                           &fqdn_universe, 170 },
-       { "unknown-171", "X",                           &fqdn_universe, 171 },
-       { "unknown-172", "X",                           &fqdn_universe, 172 },
-       { "unknown-173", "X",                           &fqdn_universe, 173 },
-       { "unknown-174", "X",                           &fqdn_universe, 174 },
-       { "unknown-175", "X",                           &fqdn_universe, 175 },
-       { "unknown-176", "X",                           &fqdn_universe, 176 },
-       { "unknown-177", "X",                           &fqdn_universe, 177 },
-       { "unknown-178", "X",                           &fqdn_universe, 178 },
-       { "unknown-179", "X",                           &fqdn_universe, 179 },
-       { "unknown-180", "X",                           &fqdn_universe, 180 },
-       { "unknown-181", "X",                           &fqdn_universe, 181 },
-       { "unknown-182", "X",                           &fqdn_universe, 182 },
-       { "unknown-183", "X",                           &fqdn_universe, 183 },
-       { "unknown-184", "X",                           &fqdn_universe, 184 },
-       { "unknown-185", "X",                           &fqdn_universe, 185 },
-       { "unknown-186", "X",                           &fqdn_universe, 186 },
-       { "unknown-187", "X",                           &fqdn_universe, 187 },
-       { "unknown-188", "X",                           &fqdn_universe, 188 },
-       { "unknown-189", "X",                           &fqdn_universe, 189 },
-       { "unknown-190", "X",                           &fqdn_universe, 190 },
-       { "unknown-191", "X",                           &fqdn_universe, 191 },
-       { "unknown-192", "X",                           &fqdn_universe, 192 },
-       { "unknown-193", "X",                           &fqdn_universe, 193 },
-       { "unknown-194", "X",                           &fqdn_universe, 194 },
-       { "unknown-195", "X",                           &fqdn_universe, 195 },
-       { "unknown-196", "X",                           &fqdn_universe, 196 },
-       { "unknown-197", "X",                           &fqdn_universe, 197 },
-       { "unknown-198", "X",                           &fqdn_universe, 198 },
-       { "unknown-199", "X",                           &fqdn_universe, 199 },
-       { "unknown-200", "X",                           &fqdn_universe, 200 },
-       { "unknown-201", "X",                           &fqdn_universe, 201 },
-       { "unknown-202", "X",                           &fqdn_universe, 202 },
-       { "unknown-203", "X",                           &fqdn_universe, 203 },
-       { "unknown-204", "X",                           &fqdn_universe, 204 },
-       { "unknown-205", "X",                           &fqdn_universe, 205 },
-       { "unknown-206", "X",                           &fqdn_universe, 206 },
-       { "unknown-207", "X",                           &fqdn_universe, 207 },
-       { "unknown-208", "X",                           &fqdn_universe, 208 },
-       { "unknown-209", "X",                           &fqdn_universe, 209 },
-       { "unknown-210", "X",                           &fqdn_universe, 210 },
-       { "unknown-211", "X",                           &fqdn_universe, 211 },
-       { "unknown-212", "X",                           &fqdn_universe, 212 },
-       { "unknown-213", "X",                           &fqdn_universe, 213 },
-       { "unknown-214", "X",                           &fqdn_universe, 214 },
-       { "unknown-215", "X",                           &fqdn_universe, 215 },
-       { "unknown-216", "X",                           &fqdn_universe, 216 },
-       { "unknown-217", "X",                           &fqdn_universe, 217 },
-       { "unknown-218", "X",                           &fqdn_universe, 218 },
-       { "unknown-219", "X",                           &fqdn_universe, 219 },
-       { "unknown-220", "X",                           &fqdn_universe, 220 },
-       { "unknown-221", "X",                           &fqdn_universe, 221 },
-       { "unknown-222", "X",                           &fqdn_universe, 222 },
-       { "unknown-223", "X",                           &fqdn_universe, 223 },
-       { "unknown-224", "X",                           &fqdn_universe, 224 },
-       { "unknown-225", "X",                           &fqdn_universe, 225 },
-       { "unknown-226", "X",                           &fqdn_universe, 226 },
-       { "unknown-227", "X",                           &fqdn_universe, 227 },
-       { "unknown-228", "X",                           &fqdn_universe, 228 },
-       { "unknown-229", "X",                           &fqdn_universe, 229 },
-       { "unknown-230", "X",                           &fqdn_universe, 230 },
-       { "unknown-231", "X",                           &fqdn_universe, 231 },
-       { "unknown-232", "X",                           &fqdn_universe, 232 },
-       { "unknown-233", "X",                           &fqdn_universe, 233 },
-       { "unknown-234", "X",                           &fqdn_universe, 234 },
-       { "unknown-235", "X",                           &fqdn_universe, 235 },
-       { "unknown-236", "X",                           &fqdn_universe, 236 },
-       { "unknown-237", "X",                           &fqdn_universe, 237 },
-       { "unknown-238", "X",                           &fqdn_universe, 238 },
-       { "unknown-239", "X",                           &fqdn_universe, 239 },
-       { "unknown-240", "X",                           &fqdn_universe, 240 },
-       { "unknown-241", "X",                           &fqdn_universe, 241 },
-       { "unknown-242", "X",                           &fqdn_universe, 242 },
-       { "unknown-243", "X",                           &fqdn_universe, 243 },
-       { "unknown-244", "X",                           &fqdn_universe, 244 },
-       { "unknown-245", "X",                           &fqdn_universe, 245 },
-       { "unknown-246", "X",                           &fqdn_universe, 246 },
-       { "unknown-247", "X",                           &fqdn_universe, 247 },
-       { "unknown-248", "X",                           &fqdn_universe, 248 },
-       { "unknown-249", "X",                           &fqdn_universe, 249 },
-       { "unknown-250", "X",                           &fqdn_universe, 250 },
-       { "unknown-251", "X",                           &fqdn_universe, 251 },
-       { "unknown-252", "X",                           &fqdn_universe, 252 },
-       { "unknown-253", "X",                           &fqdn_universe, 253 },
-       { "unknown-254", "X",                           &fqdn_universe, 254 },
-       { "unknown-end", "e",                           &fqdn_universe, 255 },
+static struct option fqdn_options[] = {
+       { "no-client-update", "f",              &fqdn_universe,   1, 1 },
+       { "server-update", "f",                 &fqdn_universe,   2, 1 },
+       { "encoded", "f",                       &fqdn_universe,   3, 1 },
+       { "rcode1", "B",                        &fqdn_universe,   4, 1 },
+       { "rcode2", "B",                        &fqdn_universe,   5, 1 },
+       { "hostname", "t",                      &fqdn_universe,   6, 1 },
+       { "domainname", "t",                    &fqdn_universe,   7, 1 },
+       { "fqdn", "t",                          &fqdn_universe,   8, 1 },
+       { NULL, NULL, NULL, 0, 0 }
+};
+
+struct universe vendor_class_universe;
+static struct option vendor_class_options[] =  {
+       { "isc", "X",                   &vendor_class_universe,      2495, 1 },
+       { NULL, NULL, NULL, 0, 0 }
+};
+
+struct universe vendor_universe;
+static struct option vendor_options[] = {
+       { "isc", "Eisc.",               &vendor_universe,            2495, 1 },
+       { NULL, NULL, NULL, 0, 0 }
+};
+
+struct universe isc_universe;
+static struct option isc_options [] = {
+       { "media", "t",                         &isc_universe,   1, 1 },
+       { "update-assist", "X",                 &isc_universe,   2, 1 },
+       { NULL, NULL, NULL, 0, 0 }
 };
 
 const char *hardware_types [] = {
@@ -1148,8 +515,84 @@ int universe_count, universe_max;
 
 struct universe *config_universe;
 
+/* XXX: omapi must die...all the below keeps us from having to make the
+ * option structures omapi typed objects, which is a bigger headache.
+ */
+
+char *default_option_format = "X";
+
+/* Must match hash_reference/dereference types in omapip/hash.h. */
+int
+option_reference(struct option **dest, struct option *src,
+                const char * file, int line)
+{
+       if (!dest || !src)
+               return ISC_R_INVALIDARG;
+
+       if (*dest) {
+#if defined(POINTER_DEBUG)
+               log_fatal("%s(%d): reference store into non-null pointer!",
+                         file, line);
+#else
+               return ISC_R_INVALIDARG;
+#endif
+       }
+
+       *dest = src;
+       src->refcnt++;
+       rc_register(file, line, dest, src, src->refcnt, 0, RC_MISC);
+       return(ISC_R_SUCCESS);
+}
+
+int
+option_dereference(struct option **dest, const char *file, int line)
+{
+       if (!dest)
+               return ISC_R_INVALIDARG;
+
+       if (!*dest) {
+#if defined (POINTER_DEBUG)
+               log_fatal("%s(%d): dereference of null pointer!", file, line);
+#else
+               return ISC_R_INVALIDARG;
+#endif
+       }
+
+       if ((*dest)->refcnt <= 0) {
+#if defined (POINTER_DEBUG)
+               log_fatal("%s(%d): dereference of <= 0 refcnt!", file, line);
+#else
+               return ISC_R_INVALIDARG;
+#endif
+       }
+
+       (*dest)->refcnt--;
+
+       rc_register(file, line, dest, (*dest), (*dest)->refcnt, 1, RC_MISC);
+
+       if ((*dest)->refcnt == 0) {
+               /* The option name may be packed in the same alloc as the
+                * option structure.
+                */
+               if ((*dest)->name != (char *)((*dest) + 1))
+                       dfree((*dest)->name, file, line);
+
+               /* It's either a user-configured format (allocated), or the
+                * default static format.
+                */
+               if ((*dest)->format != default_option_format)
+                       dfree((*dest)->format, file, line);
+
+               dfree(*dest, file, line);
+       }
+
+       *dest = NULL;
+       return ISC_R_SUCCESS;
+}
+
 void initialize_common_option_spaces()
 {
+       unsigned code;
        int i;
 
        universe_max = 10;
@@ -1171,17 +614,25 @@ void initialize_common_option_spaces()
        dhcp_universe.decode = parse_option_buffer;
        dhcp_universe.length_size = 1;
        dhcp_universe.tag_size = 1;
+       dhcp_universe.get_tag = getUChar;
        dhcp_universe.store_tag = putUChar;
+       dhcp_universe.get_length = getUChar;
        dhcp_universe.store_length = putUChar;
+       dhcp_universe.end = DHO_END;
        dhcp_universe.index = universe_count++;
        universes [dhcp_universe.index] = &dhcp_universe;
-       if (!option_new_hash (&dhcp_universe.hash, 1, MDL))
+       if (!option_name_new_hash(&dhcp_universe.name_hash,
+                                 BYTE_NAME_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&dhcp_universe.code_hash,
+                                 BYTE_CODE_HASH_SIZE, MDL))
                log_fatal ("Can't allocate dhcp option hash table.");
-       for (i = 0; i < 256; i++) {
-               dhcp_universe.options [i] = &dhcp_options [i];
-               option_hash_add (dhcp_universe.hash,
-                                dhcp_options [i].name, 0,
-                                &dhcp_options [i], MDL);
+       for (i = 0 ; dhcp_options[i].name ; i++) {
+               option_code_hash_add(dhcp_universe.code_hash,
+                                    &dhcp_options[i].code, 0,
+                                    &dhcp_options[i], MDL);
+               option_name_hash_add(dhcp_universe.name_hash,
+                                    dhcp_options [i].name, 0,
+                                    &dhcp_options [i], MDL);
        }
 
        /* Set up the Novell option universe (for option 63)... */
@@ -1196,19 +647,30 @@ void initialize_common_option_spaces()
        nwip_universe.decode = parse_option_buffer;
        nwip_universe.length_size = 1;
        nwip_universe.tag_size = 1;
+       nwip_universe.get_tag = getUChar;
        nwip_universe.store_tag = putUChar;
+       nwip_universe.get_length = getUChar;
        nwip_universe.store_length = putUChar;
-       nwip_universe.enc_opt = &dhcp_options [DHO_NWIP_SUBOPTIONS];
+       nwip_universe.end = 0;
+       code = DHO_NWIP_SUBOPTIONS;
+       nwip_universe.enc_opt = NULL;
+       if (!option_code_hash_lookup(&nwip_universe.enc_opt,
+                                    dhcp_universe.code_hash, &code, 0, MDL))
+               log_fatal("Unable to find NWIP parent option (%s:%d).", MDL);
        nwip_universe.index = universe_count++;
        universes [nwip_universe.index] = &nwip_universe;
-       option_new_hash (&nwip_universe.hash, 1, MDL);
-       if (!nwip_universe.hash)
+       if (!option_name_new_hash(&nwip_universe.name_hash,
+                                 NWIP_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&nwip_universe.code_hash,
+                                 NWIP_HASH_SIZE, MDL))
                log_fatal ("Can't allocate nwip option hash table.");
-       for (i = 0; i < 256; i++) {
-               nwip_universe.options [i] = &nwip_options [i];
-               option_hash_add (nwip_universe.hash,
-                                nwip_options [i].name, 0,
-                                &nwip_options [i], MDL);
+       for (i = 0 ; nwip_options[i].name ; i++) {
+               option_code_hash_add(nwip_universe.code_hash,
+                                    &nwip_options[i].code, 0,
+                                    &nwip_options[i], MDL);
+               option_name_hash_add(nwip_universe.name_hash,
+                                    nwip_options[i].name, 0,
+                                    &nwip_options[i], MDL);
        }
 
        /* Set up the FQDN option universe... */
@@ -1223,30 +685,162 @@ void initialize_common_option_spaces()
        fqdn_universe.decode = fqdn_universe_decode;
        fqdn_universe.length_size = 1;
        fqdn_universe.tag_size = 1;
+       fqdn_universe.get_tag = getUChar;
        fqdn_universe.store_tag = putUChar;
+       fqdn_universe.get_length = getUChar;
        fqdn_universe.store_length = putUChar;
+       fqdn_universe.end = 0;
        fqdn_universe.index = universe_count++;
-       fqdn_universe.enc_opt = &dhcp_options [DHO_FQDN];
+       code = DHO_FQDN;
+       fqdn_universe.enc_opt = NULL;
+       if (!option_code_hash_lookup(&fqdn_universe.enc_opt,
+                                    dhcp_universe.code_hash, &code, 0, MDL))
+               log_fatal("Unable to find FQDN parent option (%s:%d).", MDL);
        universes [fqdn_universe.index] = &fqdn_universe;
-       option_new_hash (&fqdn_universe.hash, 1, MDL);
-       if (!fqdn_universe.hash)
+       if (!option_name_new_hash(&fqdn_universe.name_hash,
+                                 FQDN_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&fqdn_universe.code_hash,
+                                 FQDN_HASH_SIZE, MDL))
                log_fatal ("Can't allocate fqdn option hash table.");
-       for (i = 0; i < 256; i++) {
-               fqdn_universe.options [i] = &fqdn_options [i];
-               option_hash_add (fqdn_universe.hash,
-                                fqdn_options [i].name, 0,
-                                &fqdn_options [i], MDL);
+       for (i = 0 ; fqdn_options[i].name ; i++) {
+               option_code_hash_add(nwip_universe.code_hash,
+                                    &fqdn_options[i].code, 0,
+                                    &fqdn_options[i], MDL);
+               option_name_hash_add(fqdn_universe.name_hash,
+                                    fqdn_options[i].name, 0,
+                                    &fqdn_options[i], MDL);
        }
 
+        /* Set up the Vendor Identified Vendor Class options (for option
+        * 125)...
+        */
+        vendor_class_universe.name = "vendor-class";
+        vendor_class_universe.lookup_func = lookup_hashed_option;
+        vendor_class_universe.option_state_dereference =
+                hashed_option_state_dereference;
+        vendor_class_universe.save_func = save_hashed_option;
+        vendor_class_universe.delete_func = delete_hashed_option;
+        vendor_class_universe.encapsulate = hashed_option_space_encapsulate;
+        vendor_class_universe.foreach = hashed_option_space_foreach;
+        vendor_class_universe.decode = parse_option_buffer;
+        vendor_class_universe.length_size = 1;
+        vendor_class_universe.tag_size = 4;
+       vendor_class_universe.get_tag = getULong;
+        vendor_class_universe.store_tag = putULong;
+       vendor_class_universe.get_length = getUChar;
+        vendor_class_universe.store_length = putUChar;
+       vendor_class_universe.end = 0;
+       code = DHO_VIVCO_SUBOPTIONS;
+       vendor_class_universe.enc_opt = NULL;
+       if (!option_code_hash_lookup(&vendor_class_universe.enc_opt,
+                                    dhcp_universe.code_hash, &code, 0, MDL))
+               log_fatal("Unable to find VIVCO parent option (%s:%d).", MDL);
+        vendor_class_universe.index = universe_count++;
+        universes[vendor_class_universe.index] = &vendor_class_universe;
+        if (!option_name_new_hash(&vendor_class_universe.name_hash,
+                                 VIVCO_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&vendor_class_universe.code_hash,
+                                 VIVCO_HASH_SIZE, MDL))
+                log_fatal("Can't allocate Vendor Identified Vendor Class "
+                         "option hash table.");
+        for (i = 0 ; vendor_class_options[i].name ; i++) {
+               option_code_hash_add(vendor_class_universe.code_hash,
+                                    &vendor_class_options[i].code, 0,
+                                    &vendor_class_options[i], MDL);
+                option_name_hash_add(vendor_class_universe.name_hash,
+                                     vendor_class_options[i].name, 0,
+                                     &vendor_class_options[i], MDL);
+        }
+
+        /* Set up the Vendor Identified Vendor Sub-options (option 126)... */
+        vendor_universe.name = "vendor";
+        vendor_universe.lookup_func = lookup_hashed_option;
+        vendor_universe.option_state_dereference =
+                hashed_option_state_dereference;
+        vendor_universe.save_func = save_hashed_option;
+        vendor_universe.delete_func = delete_hashed_option;
+        vendor_universe.encapsulate = hashed_option_space_encapsulate;
+        vendor_universe.foreach = hashed_option_space_foreach;
+        vendor_universe.decode = parse_option_buffer;
+        vendor_universe.length_size = 1;
+        vendor_universe.tag_size = 4;
+       vendor_universe.get_tag = getULong;
+        vendor_universe.store_tag = putULong;
+       vendor_universe.get_length = getUChar;
+        vendor_universe.store_length = putUChar;
+       vendor_universe.end = 0;
+       code = DHO_VIVSO_SUBOPTIONS;
+       vendor_universe.enc_opt = NULL;
+       if (!option_code_hash_lookup(&vendor_universe.enc_opt,
+                                    dhcp_universe.code_hash, &code, 0, MDL))
+               log_fatal("Unable to find VIVSO parent option (%s:%d).", MDL);
+        vendor_universe.index = universe_count++;
+        universes[vendor_universe.index] = &vendor_universe;
+        if (!option_name_new_hash(&vendor_universe.name_hash,
+                                 VIVSO_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&vendor_universe.code_hash,
+                                 VIVSO_HASH_SIZE, MDL))
+                log_fatal("Can't allocate Vendor Identified Vendor Sub-"
+                         "options hash table.");
+        for (i = 0 ; vendor_options[i].name ; i++) {
+                option_code_hash_add(vendor_universe.code_hash,
+                                    &vendor_options[i].code, 0,
+                                    &vendor_options[i], MDL);
+                option_name_hash_add(vendor_universe.name_hash,
+                                    vendor_options[i].name, 0,
+                                    &vendor_options[i], MDL);
+        }
+
+        /* Set up the ISC Vendor-option universe (for option 125.2495)... */
+        isc_universe.name = "isc";
+        isc_universe.lookup_func = lookup_linked_option;
+        isc_universe.option_state_dereference =
+                linked_option_state_dereference;
+        isc_universe.save_func = save_linked_option;
+        isc_universe.delete_func = delete_linked_option;
+        isc_universe.encapsulate = linked_option_space_encapsulate;
+        isc_universe.foreach = linked_option_space_foreach;
+        isc_universe.decode = parse_option_buffer;
+        isc_universe.length_size = 2;
+        isc_universe.tag_size = 2;
+       isc_universe.get_tag = getUShort;
+        isc_universe.store_tag = putUShort;
+       isc_universe.get_length = getUShort;
+        isc_universe.store_length = putUShort;
+       isc_universe.end = 0;
+       code = VENDOR_ISC_SUBOPTIONS;
+       isc_universe.enc_opt = NULL;
+       if (!option_code_hash_lookup(&isc_universe.enc_opt,
+                                    vendor_universe.code_hash, &code, 0, MDL))
+               log_fatal("Unable to find ISC parent option (%s:%d).", MDL);
+        isc_universe.index = universe_count++;
+        universes[isc_universe.index] = &isc_universe;
+        if (!option_name_new_hash(&isc_universe.name_hash,
+                                 VIV_ISC_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&isc_universe.code_hash,
+                                 VIV_ISC_HASH_SIZE, MDL))
+                log_fatal("Can't allocate ISC Vendor options hash table.");
+        for (i = 0 ; vendor_options[i].name ; i++) {
+               option_code_hash_add(vendor_universe.code_hash,
+                                    &vendor_options[i].code, 0,
+                                    &vendor_options[i], MDL);
+                option_name_hash_add(vendor_universe.name_hash,
+                                     vendor_options[i].name, 0,
+                                     &vendor_options[i], MDL);
+        }
+
        /* Set up the hash of universes. */
-       universe_new_hash (&universe_hash, 1, MDL);
-       universe_hash_add (universe_hash,
-                          dhcp_universe.name, 0,
-                          &dhcp_universe, MDL);
-       universe_hash_add (universe_hash,
-                          nwip_universe.name, 0,
-                          &nwip_universe, MDL);
-       universe_hash_add (universe_hash,
-                          fqdn_universe.name, 0,
-                          &fqdn_universe, MDL);
+       universe_new_hash(&universe_hash, UNIVERSE_HASH_SIZE, MDL);
+       universe_hash_add(universe_hash, dhcp_universe.name, 0,
+                         &dhcp_universe, MDL);
+       universe_hash_add(universe_hash, nwip_universe.name, 0,
+                         &nwip_universe, MDL);
+       universe_hash_add(universe_hash, fqdn_universe.name, 0,
+                         &fqdn_universe, MDL);
+       universe_hash_add(universe_hash, vendor_class_universe.name, 0,
+                         &vendor_class_universe, MDL);
+       universe_hash_add(universe_hash, vendor_universe.name, 0,
+                         &vendor_universe, MDL);
+       universe_hash_add(universe_hash, isc_universe.name, 0,
+                         &isc_universe, MDL);
 }
index a572b8d9a8feb173d2b35226e7c00ad5d57834f5..bfabf3e132ebdf3e2fd20125242ddf89717517c2 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tree.c,v 1.105 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tree.c,v 1.106 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -289,7 +289,7 @@ int option_cache (struct option_cache **oc, struct data_string *dp,
                data_string_copy (&(*oc) -> data, dp, file, line);
        if (expr)
                expression_reference (&(*oc) -> expression, expr, file, line);
-       (*oc) -> option = option;
+       option_reference(&(*oc)->option, option, MDL);
        return 1;
 }
 
index 38a594ead76f7c5cb4c02bfcbcdcb5dad2fdb8bb..cb4ac5abe04d5b9de53c234ff700ac9d99c47bce 100644 (file)
@@ -149,6 +149,8 @@ struct dhcp_packet {
 #define DHO_FQDN                       81
 #define DHO_DHCP_AGENT_OPTIONS         82
 #define DHO_SUBNET_SELECTION           118 /* RFC3011! */
+#define DHO_VIVCO_SUBOPTIONS           124
+#define DHO_VIVSO_SUBOPTIONS           125
 /* The DHO_AUTHENTICATE option is not a standard yet, so I've
    allocated an option out of the "local" option space for it on a
    temporary basis.  Once an option code number is assigned, I will
@@ -183,3 +185,6 @@ struct dhcp_packet {
 #define FQDN_DOMAINNAME                        7
 #define FQDN_FQDN                      8
 #define FQDN_SUBOPTION_COUNT           8
+
+/* Enterprise Suboptions: */
+#define VENDOR_ISC_SUBOPTIONS          2495
index dc6582cd3f7839abaf11ed9fbea47a9b275e046b..a1c36a393f10f024aa0f89c61619776ea6863e80 100644 (file)
@@ -64,7 +64,8 @@
 struct hash_table;
 typedef struct hash_table group_hash_t;
 typedef struct hash_table universe_hash_t;
-typedef struct hash_table option_hash_t;
+typedef struct hash_table option_name_hash_t;
+typedef struct hash_table option_code_hash_t;
 typedef struct hash_table dns_zone_hash_t;
 typedef struct hash_table lease_hash_t;
 typedef struct hash_table host_hash_t;
@@ -79,6 +80,86 @@ typedef struct hash_table class_hash_t;
 #include <isc-dhcp/result.h>
 #include <omapip/omapip_p.h>
 
+#if !defined (BYTE_NAME_HASH_SIZE)
+# define BYTE_NAME_HASH_SIZE   401     /* Default would be rediculous. */
+#endif
+#if !defined (BYTE_CODE_HASH_SIZE)
+# define BYTE_CODE_HASH_SIZE   254     /* Default would be rediculous. */
+#endif
+
+#if !defined (WORD_NAME_HASH_SIZE)
+# define WORD_NAME_HASH_SIZE   0       /* Default. */
+#endif
+#if !defined (WORD_CODE_HASH_SIZE)
+# define WORD_CODE_HASH_SIZE   0       /* Default. */
+#endif
+
+#if !defined (QUAD_NAME_HASH_SIZE)
+# define QUAD_NAME_HASH_SIZE   WORD_NAME_HASH_SIZE
+#endif
+#if !defined (QUAD_CODE_HASH_SIZE)
+# define QUAD_CODE_HASH_SIZE   WORD_CODE_HASH_SIZE
+#endif
+
+#if !defined (DNS_HASH_SIZE)
+# define DNS_HASH_SIZE         0       /* Default. */
+#endif
+
+/* Default size to use for name/code hashes on user-defined option spaces. */
+#if !defined (DEFAULT_SPACE_HASH_SIZE)
+# define DEFAULT_SPACE_HASH_SIZE       11
+#endif
+
+#if !defined (NWIP_HASH_SIZE)
+# define NWIP_HASH_SIZE                11      /* A really small table. */
+#endif
+
+#if !defined (FQDN_HASH_SIZE)
+# define FQDN_HASH_SIZE                7       /* A rediculously small table. */
+#endif
+
+#if !defined (VIVCO_HASH_SIZE)
+# define VIVCO_HASH_SIZE       QUAD_CODE_HASH_SIZE
+#endif
+
+#if !defined (VIVSO_HASH_SIZE)
+# define VIVSO_HASH_SIZE       VIVCO_HASH_SIZE
+#endif
+
+#if !defined (VIV_ISC_HASH_SIZE)
+# define VIV_ISC_HASH_SIZE     3       /* An incredulously small table. */
+#endif
+
+#if !defined (UNIVERSE_HASH_SIZE)
+# define UNIVERSE_HASH_SIZE    11      /* A really small table. */
+#endif
+
+#if !defined (GROUP_HASH_SIZE)
+# define GROUP_HASH_SIZE       0       /* Default. */
+#endif
+
+#if !defined (HOST_HASH_SIZE)
+# define HOST_HASH_SIZE                0       /* Default. */
+#endif
+
+#if !defined (LEASE_HASH_SIZE)
+# define LEASE_HASH_SIZE       0       /* Default. */
+#endif
+
+#if !defined (SCLASS_HASH_SIZE)
+# define SCLASS_HASH_SIZE      1009    /* A less than gigantic sized table. */
+#endif
+
+#if !defined (AGENT_HASH_SIZE)
+# define AGENT_HASH_SIZE       11      /* A really small table. */
+#endif
+
+#if !defined (SERVER_HASH_SIZE)
+# define SERVER_HASH_SIZE      (sizeof(server_options) / sizeof(struct option))
+#endif
+
+
+
 #if !defined (OPTION_HASH_SIZE)
 # define OPTION_HASH_SIZE 17
 # define OPTION_HASH_PTWO 32   /* Next power of two above option hash. */
@@ -997,7 +1078,10 @@ typedef unsigned char option_mask [16];
 
 HASH_FUNCTIONS_DECL (group, const char *, struct group_object, group_hash_t)
 HASH_FUNCTIONS_DECL (universe, const char *, struct universe, universe_hash_t)
-HASH_FUNCTIONS_DECL (option, const char *, struct option, option_hash_t)
+HASH_FUNCTIONS_DECL (option_name, const char *, struct option,
+                    option_name_hash_t)
+HASH_FUNCTIONS_DECL (option_code, const unsigned *, struct option,
+                    option_code_hash_t)
 HASH_FUNCTIONS_DECL (dns_zone, const char *, struct dns_zone, dns_zone_hash_t)
 HASH_FUNCTIONS_DECL (lease, const unsigned char *, struct lease, lease_hash_t)
 HASH_FUNCTIONS_DECL (host, const unsigned char *, struct host_decl, host_hash_t)
@@ -1044,7 +1128,7 @@ struct option_cache *lookup_hashed_option PROTO ((struct universe *,
                                                  unsigned));
 int save_option_buffer (struct universe *, struct option_state *,
                        struct buffer *, unsigned char *, unsigned,
-                       struct option *, int);
+                       unsigned, int);
 void save_option PROTO ((struct universe *,
                         struct option_state *, struct option_cache *));
 void save_hashed_option PROTO ((struct universe *,
@@ -1255,7 +1339,8 @@ unsigned char *parse_numeric_aggregate PROTO ((struct parse *,
 void convert_num PROTO ((struct parse *, unsigned char *, const char *,
                         int, unsigned));
 TIME parse_date PROTO ((struct parse *));
-struct option *parse_option_name PROTO ((struct parse *, int, int *));
+isc_result_t parse_option_name PROTO ((struct parse *, int, int *,
+                                      struct option **));
 void parse_option_space_decl PROTO ((struct parse *));
 int parse_option_code_definition PROTO ((struct parse *, struct option *));
 int parse_base64 (struct data_string *, struct parse *);
@@ -1494,11 +1579,13 @@ struct lease_state *new_lease_state PROTO ((const char *, int));
 struct domain_search_list *new_domain_search_list PROTO ((const char *, int));
 struct name_server *new_name_server PROTO ((const char *, int));
 void free_name_server PROTO ((struct name_server *, const char *, int));
-struct option *new_option PROTO ((const char *, int));
+struct option *new_option PROTO ((const char *, const char *, int));
+int option_reference(struct option **dest, struct option *src,
+                    const char * file, int line);
+int option_dereference(struct option **dest, const char *file, int line);
 int group_allocate (struct group **, const char *, int);
 int group_reference (struct group **, struct group *, const char *, int);
 int group_dereference (struct group **, const char *, int);
-void free_option PROTO ((struct option *, const char *, int));
 struct universe *new_universe PROTO ((const char *, int));
 void free_universe PROTO ((struct universe *, const char *, int));
 void free_domain_search_list PROTO ((struct domain_search_list *,
@@ -1835,12 +1922,10 @@ OMAPI_OBJECT_ALLOC_DECL (interface,
                         struct interface_info, dhcp_type_interface)
 
 /* tables.c */
+extern char *default_option_format;
 extern struct universe dhcp_universe;
-extern struct option dhcp_options [256];
 extern struct universe nwip_universe;
-extern struct option nwip_options [256];
 extern struct universe fqdn_universe;
-extern struct option fqdn_options [256];
 extern int dhcp_option_default_priority_list [];
 extern int dhcp_option_default_priority_list_count;
 extern const char *hardware_types [256];
@@ -1862,9 +1947,7 @@ extern const char *dhcp_flink_state_names [];
 extern const char *binding_state_names [];
 
 extern struct universe agent_universe;
-extern struct option agent_options [256];
 extern struct universe server_universe;
-extern struct option server_options [256];
 
 extern struct enumeration ddns_styles;
 extern struct enumeration syslog_enum;
@@ -1959,8 +2042,7 @@ int write_failover_state (dhcp_failover_state_t *);
 #endif
 int db_printable PROTO ((const char *));
 int db_printable_len PROTO ((const unsigned char *, unsigned));
-isc_result_t write_named_billing_class(const unsigned char *, unsigned,
-                                      void *);
+isc_result_t write_named_billing_class(const void *, unsigned, void *);
 void write_billing_classes (void);
 int write_billing_class PROTO ((struct class *));
 void commit_leases_timeout PROTO ((void *));
@@ -2504,7 +2586,7 @@ void hw_hash_add PROTO ((struct lease *));
 void hw_hash_delete PROTO ((struct lease *));
 int write_leases PROTO ((void));
 int lease_enqueue (struct lease *);
-isc_result_t lease_instantiate(const unsigned char *, unsigned, void *);
+isc_result_t lease_instantiate(const void *, unsigned, void *);
 void expire_all_pools PROTO ((void));
 void dump_subnets PROTO ((void));
 #if defined (DEBUG_MEMORY_LEAKAGE) || \
index 88bf0264f0cfadd06b389c7ee223d05b12333985..73a7ff0d7008ad9c3f9e1a88923544a2d59f4e03 100644 (file)
@@ -312,6 +312,10 @@ enum dhcp_token {
        ATSFP = 616,
        LCASE = 617,
        UCASE = 618
+       WIDTH = 619,
+       LENGTH = 620,
+       HASH = 621,
+       SIZE = 622
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index a194acccef327433d8de87d60ffa85770cf5d92a..5bda95fab7eb1cde98f82aab560fef0891c8a2a8 100644 (file)
 #ifndef OMAPI_HASH_H
 #define OMAPI_HASH_H
 
-#define DEFAULT_HASH_SIZE      9973
+#if !defined (DEFAULT_HASH_SIZE)
+# define DEFAULT_HASH_SIZE     9973
+#endif
+
+#if !defined (KEY_HASH_SIZE)
+# define KEY_HASH_SIZE         1009
+#endif
 
 /* The purpose of the hashed_object_t struct is to not match anything else. */
 typedef struct {
        int foo;
 } hashed_object_t;
 
-typedef isc_result_t (*hash_foreach_func)(const unsigned char *, unsigned,
-                                         void *);
+typedef isc_result_t (*hash_foreach_func)(const void *, unsigned, void *);
 typedef int (*hash_reference) (hashed_object_t **, hashed_object_t *,
                               const char *, int);
 typedef int (*hash_dereference) (hashed_object_t **, const char *, int);
@@ -63,7 +68,7 @@ struct hash_table {
        hash_reference referencer;
        hash_dereference dereferencer;
        hash_comparator_t cmp;
-       int (*do_hash) (const unsigned char *, unsigned, unsigned);
+       unsigned (*do_hash)(const void *, unsigned, unsigned);
 };
 
 struct named_hash {
@@ -80,26 +85,24 @@ void name##_hash_delete (hashtype *, bufarg, unsigned,                            \
 int name##_hash_lookup (type **, hashtype *, bufarg, unsigned,               \
                        const char *, int);                                   \
 int name##_hash_foreach (hashtype *, hash_foreach_func);                     \
-int name##_new_hash (hashtype **, int, const char *, int);                   \
+int name##_new_hash (hashtype **, unsigned, const char *, int);                      \
 void name##_free_hash_table (hashtype **, const char *, int);
 
 
-#define HASH_FUNCTIONS(name, bufarg, type, hashtype, ref, deref)             \
+#define HASH_FUNCTIONS(name, bufarg, type, hashtype, ref, deref, hasher)      \
 void name##_hash_add (hashtype *table,                                       \
                      bufarg buf, unsigned len, type *ptr,                    \
                      const char *file, int line)                             \
 {                                                                            \
-       add_hash ((struct hash_table *)table,                                 \
-                 (const unsigned char *)buf,                                 \
+       add_hash ((struct hash_table *)table, buf,                            \
                  len, (hashed_object_t *)ptr, file, line);                   \
 }                                                                            \
                                                                              \
-void name##_hash_delete (hashtype *table,                                    \
-                        bufarg buf, unsigned len, const char *file, int line)\
+void name##_hash_delete (hashtype *table, bufarg buf, unsigned len,          \
+                        const char *file, int line)                          \
 {                                                                            \
-       delete_hash_entry ((struct hash_table *)table,                        \
-                          (const unsigned char *)buf,                        \
-                          len, file, line);                                  \
+       delete_hash_entry ((struct hash_table *)table, buf, len,              \
+                          file, line);                                       \
 }                                                                            \
                                                                              \
 int name##_hash_lookup (type **ptr, hashtype *table,                         \
@@ -107,7 +110,7 @@ int name##_hash_lookup (type **ptr, hashtype *table,                              \
 {                                                                            \
        return hash_lookup ((hashed_object_t **)ptr,                          \
                            (struct hash_table *)table,                       \
-                           (const unsigned char *)buf, len, file, line);     \
+                           buf, len, file, line);                            \
 }                                                                            \
                                                                              \
 int name##_hash_foreach (hashtype *table, hash_foreach_func func)            \
@@ -116,11 +119,11 @@ int name##_hash_foreach (hashtype *table, hash_foreach_func func)       \
                             func);                                           \
 }                                                                            \
                                                                              \
-int name##_new_hash (hashtype **tp, int c, const char *file, int line)       \
+int name##_new_hash (hashtype **tp, unsigned c, const char *file, int line)   \
 {                                                                            \
        return new_hash ((struct hash_table **)tp,                            \
                         (hash_reference)ref, (hash_dereference)deref, c,     \
-                        file, line);                                         \
+                        hasher, file, line);                                 \
 }                                                                            \
                                                                              \
 void name##_free_hash_table (hashtype **table, const char *file, int line)    \
@@ -129,19 +132,25 @@ void name##_free_hash_table (hashtype **table, const char *file, int line)    \
 }
 
 void relinquish_hash_bucket_hunks (void);
-int new_hash_table (struct hash_table **, int, const char *, int);
+int new_hash_table (struct hash_table **, unsigned, const char *, int);
 void free_hash_table (struct hash_table **, const char *, int);
 struct hash_bucket *new_hash_bucket (const char *, int);
 void free_hash_bucket (struct hash_bucket *, const char *, int);
-int new_hash (struct hash_table **,
-             hash_reference, hash_dereference, int, const char *, int);
+int new_hash(struct hash_table **,
+            hash_reference, hash_dereference, unsigned,
+            unsigned (*do_hash)(const void *, unsigned, unsigned),
+            const char *, int);
+unsigned do_string_hash(const void *, unsigned, unsigned);
+unsigned do_case_hash(const void *, unsigned, unsigned);
+unsigned do_number_hash(const void *, unsigned, unsigned);
+unsigned do_ip4_hash(const void *, unsigned, unsigned);
 void add_hash (struct hash_table *,
-                     const unsigned char *, unsigned, hashed_object_t *,
+                     const void *, unsigned, hashed_object_t *,
                      const char *, int);
-void delete_hash_entry (struct hash_table *, const unsigned char *,
+void delete_hash_entry (struct hash_table *, const void *,
                               unsigned, const char *, int);
 int hash_lookup (hashed_object_t **, struct hash_table *,
-                       const unsigned char *, unsigned, const char *, int);
+                       const void *, unsigned, const char *, int);
 int hash_foreach (struct hash_table *, hash_foreach_func);
 int casecmp (const void *s, const void *t, unsigned long len);
 
index b12bc9ec93788f556b16ce6108b050a176633940..e70a612309f5d229c4c796aa2205afc3349e9b6c 100644 (file)
@@ -324,18 +324,22 @@ struct universe {
                            struct option_state *, struct option_state *,
                            struct binding_scope **,
                            struct universe *);
+       u_int32_t (*get_tag) (const unsigned char *);
        void (*store_tag) PROTO ((unsigned char *, u_int32_t));
+       u_int32_t (*get_length) (const unsigned char *);
        void (*store_length) PROTO ((unsigned char *, u_int32_t));
        int tag_size, length_size;
-       option_hash_t *hash;
-       struct option *options [256];
+       unsigned end;
+       option_name_hash_t *name_hash;
+       option_code_hash_t *code_hash;
        struct option *enc_opt;
        int index;
 };
 
 struct option {
-       const char *name;
-       const char *format;
+       char *name;
+       char *format;
        struct universe *universe;
        unsigned code;
+       int refcnt;
 };
index 48a7089d96085a94da6ed634486ea311c1df54c8..29fbde1638d3a75add0ffb96e11345df8c60a684 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: auth.c,v 1.5 2005/03/17 20:15:20 dhankins Exp $ Copyright 2004 Internet Systems Consortium.";
+"$Id: auth.c,v 1.6 2006/06/01 20:23:17 dhankins Exp $ Copyright 2004 Internet Systems Consortium.";
 #endif
 
 #include <omapip/omapip_p.h>
@@ -46,7 +46,8 @@ HASH_FUNCTIONS_DECL (omapi_auth_key, const char *,
 omapi_auth_hash_t *auth_key_hash;
 HASH_FUNCTIONS (omapi_auth_key, const char *, omapi_auth_key_t,
                omapi_auth_hash_t,
-               omapi_auth_key_reference, omapi_auth_key_dereference)
+               omapi_auth_key_reference, omapi_auth_key_dereference,
+               do_case_hash)
 
 isc_result_t omapi_auth_key_new (omapi_auth_key_t **o, const char *file,
                                 int line)
@@ -97,7 +98,8 @@ isc_result_t omapi_auth_key_enter (omapi_auth_key_t *a)
                        omapi_auth_key_dereference (&tk, MDL);
                }
        } else {
-               if (!omapi_auth_key_new_hash (&auth_key_hash, 1, MDL))
+               if (!omapi_auth_key_new_hash(&auth_key_hash,
+                                            KEY_HASH_SIZE, MDL))
                        return ISC_R_NOMEMORY;
        }
        omapi_auth_key_hash_add (auth_key_hash, a -> name, 0, a, MDL);
index 4b1833b9c17c0b1717248903ff682119a15d6fd8..e44aa71173503ce7e67be78d959e58bd3ddcc231 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: hash.c,v 1.7 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: hash.c,v 1.8 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include <omapip/omapip_p.h>
 #include <ctype.h>
 
-static int do_hash (const unsigned char *, unsigned, unsigned);
-static int do_case_hash (const unsigned char *, unsigned, unsigned);
+static inline unsigned
+find_length(const void *key,
+           unsigned (*do_hash)(const void *, unsigned, unsigned))
+{
+       if (do_hash == do_case_hash || do_hash == do_string_hash)
+               return strlen((const char *)key);
+       if (do_hash == do_number_hash)
+               return sizeof(unsigned);
+       if (do_hash == do_ip4_hash)
+               return 4;
+
+       log_fatal("Impossible condition at %s:%d.", MDL);
+}
 
 int new_hash_table (tp, count, file, line)
        struct hash_table **tp;
-       int count;
+       unsigned count;
        const char *file;
        int line;
 {
@@ -188,42 +199,46 @@ void free_hash_bucket (ptr, file, line)
        free_hash_buckets = ptr;
 }
 
-int new_hash (struct hash_table **rp,
-             hash_reference referencer,
-             hash_dereference dereferencer,
-             int casep, const char *file, int line)
+int new_hash(struct hash_table **rp,
+            hash_reference referencer,
+            hash_dereference dereferencer,
+            unsigned hsize,
+            unsigned (*hasher)(const void *, unsigned, unsigned),
+            const char *file, int line)
 {
-       if (!new_hash_table (rp, DEFAULT_HASH_SIZE, file, line))
+       if (hsize == 0)
+               hsize = DEFAULT_HASH_SIZE;
+
+       if (!new_hash_table (rp, hsize, file, line))
                return 0;
-       memset (&(*rp) -> buckets [0], 0,
-               DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
-       (*rp) -> referencer = referencer;
-       (*rp) -> dereferencer = dereferencer;
-       if (casep) {
-               (*rp) -> cmp = casecmp;
-               (*rp) -> do_hash = do_case_hash;
-       } else {
-               (*rp) -> cmp = (hash_comparator_t)memcmp;
-               (*rp) -> do_hash = do_hash;
-       }
+
+       memset ((*rp)->buckets, 0, hsize * sizeof(struct hash_bucket *));
+
+       (*rp)->referencer = referencer;
+       (*rp)->dereferencer = dereferencer;
+       (*rp)->do_hash = hasher;
+
+       if (hasher == do_case_hash)
+               (*rp)->cmp = casecmp;
+       else
+               (*rp)->cmp = memcmp;
+
        return 1;
 }
 
-static int do_case_hash (name, len, size)
-       const unsigned char *name;
-       unsigned len;
-       unsigned size;
+unsigned
+do_case_hash(const void *name, unsigned len, unsigned size)
 {
-       register int accum = 0;
-       register const unsigned char *s = (const unsigned char *)name;
+       register unsigned accum = 0;
+       register const unsigned char *s = name;
        int i = len;
        register unsigned c;
 
        while (i--) {
                /* Make the hash case-insensitive. */
                c = *s++;
-               if (isascii (c) && isupper (c))
-                       c = tolower (c);
+               if (isascii(c))
+                       c = tolower(c);
 
                /* Add the character in... */
                accum = (accum << 1) + c;
@@ -232,16 +247,15 @@ static int do_case_hash (name, len, size)
                while (accum > 65535) {
                        accum = (accum & 65535) + (accum >> 16);
                }
+
        }
        return accum % size;
 }
 
-static int do_hash (name, len, size)
-       const unsigned char *name;
-       unsigned len;
-       unsigned size;
+unsigned
+do_string_hash(const void *name, unsigned len, unsigned size)
 {
-       register int accum = 0;
+       register unsigned accum = 0;
        register const unsigned char *s = (const unsigned char *)name;
        int i = len;
 
@@ -257,10 +271,30 @@ static int do_hash (name, len, size)
        return accum % size;
 }
 
-void add_hash (table, name, len, pointer, file, line)
+unsigned
+do_number_hash(const void *key, unsigned len, unsigned size)
+{
+       register unsigned number = *((const unsigned *)key);
+
+       return number % size;
+}
+
+unsigned
+do_ip4_hash(const void *key, unsigned len, unsigned size)
+{
+       u_int32_t number;
+
+       memcpy(&number, key, 4);
+
+       number = ntohl(number);
+
+       return number % size;
+}
+
+void add_hash (table, key, len, pointer, file, line)
        struct hash_table *table;
        unsigned len;
-       const unsigned char *name;
+       const void *key;
        hashed_object_t *pointer;
        const char *file;
        int line;
@@ -273,16 +307,16 @@ void add_hash (table, name, len, pointer, file, line)
                return;
 
        if (!len)
-               len = strlen ((const char *)name);
+               len = find_length(key, table->do_hash);
 
-       hashno = (*table -> do_hash) (name, len, table -> hash_count);
+       hashno = (*table->do_hash)(key, len, table->hash_count);
        bp = new_hash_bucket (file, line);
 
        if (!bp) {
-               log_error ("Can't add %s to hash table.", name);
+               log_error ("Can't add entry to hash table: no memory.");
                return;
        }
-       bp -> name = name;
+       bp -> name = key;
        if (table -> referencer) {
                foo = &bp -> value;
                (*(table -> referencer)) (foo, pointer, file, line);
@@ -293,10 +327,10 @@ void add_hash (table, name, len, pointer, file, line)
        table -> buckets [hashno] = bp;
 }
 
-void delete_hash_entry (table, name, len, file, line)
+void delete_hash_entry (table, key, len, file, line)
        struct hash_table *table;
        unsigned len;
-       const unsigned char *name;
+       const void *key;
        const char *file;
        int line;
 {
@@ -308,17 +342,17 @@ void delete_hash_entry (table, name, len, file, line)
                return;
 
        if (!len)
-               len = strlen ((const char *)name);
+               len = find_length(key, table->do_hash);
 
-       hashno = (*table -> do_hash) (name, len, table -> hash_count);
+       hashno = (*table->do_hash)(key, len, table->hash_count);
 
        /* Go through the list looking for an entry that matches;
           if we find it, delete it. */
        for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
                if ((!bp -> len &&
-                    !strcmp ((const char *)bp -> name, (const char *)name)) ||
+                    !strcmp ((const char *)bp->name, key)) ||
                    (bp -> len == len &&
-                    !(*table -> cmp) (bp -> name, name, len))) {
+                    !(table -> cmp)(bp->name, key, len))) {
                        if (pbp) {
                                pbp -> next = bp -> next;
                        } else {
@@ -335,10 +369,10 @@ void delete_hash_entry (table, name, len, file, line)
        }
 }
 
-int hash_lookup (vp, table, name, len, file, line)
+int hash_lookup (vp, table, key, len, file, line)
        hashed_object_t **vp;
        struct hash_table *table;
-       const unsigned char *name;
+       const void *key;
        unsigned len;
        const char *file;
        int line;
@@ -349,13 +383,13 @@ int hash_lookup (vp, table, name, len, file, line)
        if (!table)
                return 0;
        if (!len)
-               len = strlen ((const char *)name);
+               len = find_length(key, table->do_hash);
 
-       hashno = (*table -> do_hash) (name, len, table -> hash_count);
+       hashno = (*table->do_hash)(key, len, table->hash_count);
 
        for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
                if (len == bp -> len
-                   && !(*table -> cmp) (bp -> name, name, len)) {
+                   && !(*table->cmp)(bp->name, key, len)) {
                        if (table -> referencer)
                                (*table -> referencer) (vp, bp -> value,
                                                        file, line);
index 6600fc40839a9fdc89ceb7347bee6d43cb2d9e4c..7bf2afe324a5f57521cbfdbf7affe9f8f0e456fb 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: bootp.c,v 1.74 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: bootp.c,v 1.75 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -210,8 +210,9 @@ void bootp (packet)
                                     lease -> subnet -> netmask.iabuf,
                                     lease -> subnet -> netmask.len,
                                     0, 0, MDL)) {
-                                       oc -> option =
-                                               dhcp_universe.options [i];
+                                       option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                               &i, 0, MDL);
                                        save_option (&dhcp_universe,
                                                     options, oc);
                                }
index 09f8926c75e34925863ab2a72ca9c9ba02b7ef52..367a8be0f3af1e0d48e1435b2c3a5ab1d911192d 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: class.c,v 1.32 2005/03/17 20:15:26 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: class.c,v 1.33 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
 
 #endif /* not lint */
 
@@ -190,7 +190,8 @@ int check_collection (packet, lease, collection)
                                                  MDL);
                                data_string_forget (&data, MDL);
                                if (!class -> hash)
-                                   class_new_hash (&class -> hash, 0, MDL);
+                                   class_new_hash(&class->hash,
+                                                  SCLASS_HASH_SIZE, MDL);
                                class_hash_add (class -> hash,
                                                (const char *)
                                                nc -> hash_string.data,
index 0338b896eae43e899840a3e4037812bfa013e610..8eea3f0fb4ee581b3bff0c71932bdb49c01361b2 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.153 2006/05/11 16:35:56 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.154 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -340,12 +340,13 @@ int parse_statement (cfile, group, type, host_decl, declaration)
        struct data_string data;
        struct hardware hardware;
        struct executable_statement *et, *ep;
-       struct option *option;
+       struct option *option = NULL;
        struct option_cache *cache;
        int lose;
        struct data_string key_id;
        int known;
        isc_result_t status;
+       unsigned code;
 
        token = peek_token (&val, (unsigned *)0, cfile);
 
@@ -592,7 +593,11 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                /* "server-identifier" is a special hack, equivalent to
                   "option dhcp-server-identifier". */
              case SERVER_IDENTIFIER:
-               option = dhcp_universe.options [DHO_DHCP_SERVER_IDENTIFIER];
+               code = DHO_DHCP_SERVER_IDENTIFIER;
+               if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
+                                            &code, 0, MDL))
+                       log_fatal("Server identifier not in hash (%s:%d).",
+                                 MDL);
                token = next_token (&val, (unsigned *)0, cfile);
                goto finish_option;
 
@@ -612,8 +617,8 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                }
 
                known = 0;
-               option = parse_option_name (cfile, 1, &known);
-               if (option) {
+               status = parse_option_name(cfile, 1, &known, &option);
+               if (status == ISC_R_SUCCESS) {
                        token = peek_token (&val, (unsigned *)0, cfile);
                        if (token == CODE) {
                                if (type != ROOT_GROUP) {
@@ -621,13 +626,12 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                                                    "option definitions%s",
                                                    " may not be scoped.");
                                        skip_to_semi (cfile);
-                                       free_option (option, MDL);
+                                       option_dereference(&option, MDL);
                                        break;
                                }
                                next_token (&val, (unsigned *)0, cfile);
-                               if (!parse_option_code_definition (cfile,
-                                                                  option))
-                                       free_option (option, MDL);
+                               parse_option_code_definition(cfile, option);
+                               option_dereference(&option, MDL);
                                return declaration;
                        }
 
@@ -638,7 +642,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                                            option -> universe -> name,
                                            option -> name);
                                skip_to_semi (cfile);
-                               free_option (option, MDL);
+                               option_dereference(&option, MDL);
                                return declaration;
                        }
 
@@ -648,6 +652,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                                (&et, cfile, 1, option,
                                 supersede_option_statement))
                                return declaration;
+                       option_dereference(&option, MDL);
                        goto insert_statement;
                } else
                        return declaration;
@@ -1841,6 +1846,7 @@ int parse_class_declaration (cp, cfile, group, type)
        isc_result_t status = ISC_R_FAILURE;
        int matchedonce = 0;
        int submatchedonce = 0;
+       unsigned code;
 
        token = next_token (&val, (unsigned *)0, cfile);
        if (token != STRING) {
@@ -1954,7 +1960,7 @@ int parse_class_declaration (cp, cfile, group, type)
                        }
                        data_string_copy (&class -> hash_string, &data, MDL);
                        if (!pc -> hash &&
-                           !class_new_hash (&pc -> hash, 0, MDL))
+                           !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
                                log_fatal ("No memory for subclass hash.");
                        class_hash_add (pc -> hash,
                                        (const char *)class -> hash_string.data,
@@ -1978,11 +1984,13 @@ int parse_class_declaration (cp, cfile, group, type)
                        if (option_cache_allocate (&stmt -> data.option,
                                                   MDL)) {
                                stmt -> data.option -> data = data;
-                               stmt -> data.option -> option =
-                                       dhcp_universe.options
-                                       [(type == CLASS_TYPE_VENDOR)
+                               code = (type == CLASS_TYPE_VENDOR)
                                        ? DHO_VENDOR_CLASS_IDENTIFIER
-                                       : DHO_USER_CLASS];
+                                       : DHO_USER_CLASS;
+                               option_code_hash_lookup(
+                                               &stmt->data.option->option,
+                                                       dhcp_universe.code_hash,
+                                                       &code, 0, MDL);
                        }
                        class -> statements = stmt;
                }
@@ -3340,6 +3348,8 @@ int parse_allow_deny (oc, cfile, flag)
        enum dhcp_token token;
        const char *val;
        unsigned char rf = flag;
+       unsigned code;
+       struct option *option = NULL;
        struct expression *data = (struct expression *)0;
        int status;
 
@@ -3349,42 +3359,31 @@ int parse_allow_deny (oc, cfile, flag)
        token = next_token (&val, (unsigned *)0, cfile);
        switch (token) {
              case TOKEN_BOOTP:
-               status = option_cache (oc, (struct data_string *)0, data,
-                                      &server_options [SV_ALLOW_BOOTP], MDL);
+               code = SV_ALLOW_BOOTP;
                break;
 
              case BOOTING:
-               status = option_cache (oc, (struct data_string *)0, data,
-                                      &server_options [SV_ALLOW_BOOTING],
-                                      MDL);
+               code = SV_ALLOW_BOOTING;
                break;
 
              case DYNAMIC_BOOTP:
-               status = option_cache (oc, (struct data_string *)0, data,
-                                      &server_options [SV_DYNAMIC_BOOTP],
-                                      MDL);
+               code = SV_DYNAMIC_BOOTP;
                break;
 
              case UNKNOWN_CLIENTS:
-               status = (option_cache
-                         (oc, (struct data_string *)0, data,
-                          &server_options [SV_BOOT_UNKNOWN_CLIENTS], MDL));
+               code = SV_BOOT_UNKNOWN_CLIENTS;
                break;
 
              case DUPLICATES:
-               status = option_cache (oc, (struct data_string *)0, data,
-                                      &server_options [SV_DUPLICATES], MDL);
+               code = SV_DUPLICATES;
                break;
 
              case DECLINES:
-               status = option_cache (oc, (struct data_string *)0, data,
-                                      &server_options [SV_DECLINES], MDL);
+               code= SV_DECLINES;
                break;
 
              case CLIENT_UPDATES:
-               status = option_cache (oc, (struct data_string *)0, data,
-                                      &server_options [SV_CLIENT_UPDATES],
-                                      MDL);
+               code = SV_CLIENT_UPDATES;
                break;
 
              case INFINITE:
@@ -3410,6 +3409,12 @@ int parse_allow_deny (oc, cfile, flag)
                skip_to_semi (cfile);
                return 0;
        }
+       /* Reference on option is passed to option cache. */
+       if (!option_code_hash_lookup(&option, server_universe.code_hash,
+                                    &code, 0, MDL))
+               log_fatal("Unable to find server option %u (%s:%d).",
+                         code, MDL);
+       status = option_cache(oc, NULL, data, option, MDL);
        expression_dereference (&data, MDL);
        parse_semi (cfile);
        return status;
index 6b739ee726df3c36cde2e98507832be49d7dee9b..fe8303526ee0be9bb2ea676485fc6eacaf90909e 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: db.c,v 1.71 2006/04/27 17:26:42 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: db.c,v 1.72 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -644,9 +644,9 @@ static int print_hash_string(FILE *fp, struct class *class)
 
 
 isc_result_t
-write_named_billing_class(const unsigned char *name, unsigned len,
-                         void *object)
+write_named_billing_class(const void *key, unsigned len, void *object)
 {
+       const unsigned char *name = key;
        struct class *class = object;
 
        if (class->flags & CLASS_DECL_DYNAMIC) {
index 1b10f867150f3700b346ca87efe2484cf2630353..b28113245c50b21ec2e8f6cc132b8152774afa69 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: ddns.c,v 1.18 2005/03/17 20:15:26 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: ddns.c,v 1.19 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -586,14 +586,12 @@ int ddns_updates (struct packet *packet,
                bp -> data [0] = server_updates_a;
                if (!save_option_buffer (&fqdn_universe, state -> options,
                                         bp, &bp -> data [0], 1,
-                                        &fqdn_options [FQDN_SERVER_UPDATE],
-                                        0))
+                                        FQDN_SERVER_UPDATE, 0))
                        goto badfqdn;
                bp -> data [1] = server_updates_a;
                if (!save_option_buffer (&fqdn_universe, state -> options,
                                         bp, &bp -> data [1], 1,
-                                        &fqdn_options [FQDN_NO_CLIENT_UPDATE],
-                                        0))
+                                        FQDN_NO_CLIENT_UPDATE, 0))
                        goto badfqdn;
                /* Do the same encoding the client did. */
                oc = lookup_option (&fqdn_universe, packet -> options,
@@ -609,20 +607,17 @@ int ddns_updates (struct packet *packet,
                        bp -> data [2] = 0;
                if (!save_option_buffer (&fqdn_universe, state -> options,
                                         bp, &bp -> data [2], 1,
-                                        &fqdn_options [FQDN_ENCODED],
-                                        0))
+                                        FQDN_ENCODED, 0))
                        goto badfqdn;
                bp -> data [3] = isc_rcode_to_ns (rcode1);
                if (!save_option_buffer (&fqdn_universe, state -> options,
                                         bp, &bp -> data [3], 1,
-                                        &fqdn_options [FQDN_RCODE1],
-                                        0))
+                                        FQDN_RCODE1, 0))
                        goto badfqdn;
                bp -> data [4] = isc_rcode_to_ns (rcode2);
                if (!save_option_buffer (&fqdn_universe, state -> options,
                                         bp, &bp -> data [4], 1,
-                                        &fqdn_options [FQDN_RCODE2],
-                                        0))
+                                        FQDN_RCODE2, 0))
                        goto badfqdn;
                if (ddns_fwd_name.len) {
                    memcpy (&bp -> data [5],
@@ -630,8 +625,7 @@ int ddns_updates (struct packet *packet,
                    if (!save_option_buffer (&fqdn_universe, state -> options,
                                             bp, &bp -> data [5],
                                             ddns_fwd_name.len,
-                                            &fqdn_options [FQDN_FQDN],
-                                            0))
+                                            FQDN_FQDN, 0))
                        goto badfqdn;
                }
        }
index e0b2f2e9acc3d2735dca36c91c0fcbbe64e5aa1f..354eb86643688a1ea461efcbae2536d425c26e88 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dhcp.c,v 1.203 2006/05/17 20:15:32 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhcp.c,v 1.204 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1082,7 +1082,9 @@ void dhcpinform (packet, ms_nulltp)
        if (option_cache_allocate (&oc, MDL)) {
                if (make_const_data (&oc -> expression,
                                     &dhcpack, 1, 0, 0, MDL)) {
-                       oc -> option = dhcp_universe.options [i];
+                       option_code_hash_lookup(&oc->option,
+                                               dhcp_universe.code_hash,
+                                               &i, 0, MDL);
                        save_option (&dhcp_universe, options, oc);
                }
                option_cache_dereference (&oc, MDL);
@@ -1100,7 +1102,9 @@ void dhcpinform (packet, ms_nulltp)
                              &packet -> interface -> addresses [0]),
                             sizeof packet -> interface -> addresses [0],
                             0, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe, options, oc);
                        }
                        option_cache_dereference (&oc, MDL);
@@ -1132,7 +1136,9 @@ void dhcpinform (packet, ms_nulltp)
                                             subnet -> netmask.iabuf,
                                             subnet -> netmask.len,
                                             0, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe, options, oc);
                        }
                        option_cache_dereference (&oc, MDL);
@@ -1335,7 +1341,9 @@ void nak_lease (packet, cip)
                option_state_dereference (&options, MDL);
                return;
        }
-       oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE];
+       i = DHO_DHCP_MESSAGE_TYPE;
+       option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
+                               &i, 0, MDL);
        save_option (&dhcp_universe, options, oc);
        option_cache_dereference (&oc, MDL);
                     
@@ -1353,7 +1361,9 @@ void nak_lease (packet, cip)
                option_state_dereference (&options, MDL);
                return;
        }
-       oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE];
+       i = DHO_DHCP_MESSAGE;
+       option_code_hash_lookup(&oc->option, dhcp_universe.code_hash,
+                               &i, 0, MDL);
        save_option (&dhcp_universe, options, oc);
        option_cache_dereference (&oc, MDL);
                     
@@ -1369,8 +1379,9 @@ void nak_lease (packet, cip)
                              &packet -> interface -> addresses [0]),
                             sizeof packet -> interface -> addresses [0],
                             0, 0, MDL)) {
-                               oc -> option =
-                                       dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe, options, oc);
                        }
                        option_cache_dereference (&oc, MDL);
@@ -2437,8 +2448,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                if (option_cache_allocate (&oc, MDL)) {
                        if (make_const_data (&oc -> expression,
                                             &state -> offer, 1, 0, 0, MDL)) {
-                               oc -> option =
-                                       dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe,
                                             state -> options, oc);
                        }
@@ -2457,8 +2469,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                                      &state -> ip -> addresses [0]),
                                     sizeof state -> ip -> addresses [0],
                                     0, 0, MDL)) {
-                                       oc -> option =
-                                               dhcp_universe.options [i];
+                                       option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                        save_option (&dhcp_universe,
                                                     state -> options, oc);
                                }
@@ -2500,7 +2513,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                if (option_cache_allocate (&oc, MDL)) {
                        if (make_const_data(&oc->expression, state->expiry,
                                            4, 0, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe,
                                             state -> options, oc);
                        }
@@ -2518,7 +2533,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                if (option_cache_allocate (&oc, MDL)) {
                        if (make_const_data(&oc->expression, state->renewal,
                                            4, 0, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe,
                                             state -> options, oc);
                        }
@@ -2537,7 +2554,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                if (option_cache_allocate (&oc, MDL)) {
                        if (make_const_data(&oc->expression, state->rebind,
                                            4, 0, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe,
                                             state -> options, oc);
                        }
@@ -2580,7 +2599,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                                             lease -> subnet -> netmask.iabuf,
                                             lease -> subnet -> netmask.len,
                                             0, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe,
                                             state -> options, oc);
                        }
@@ -2606,7 +2627,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                                              lease -> host -> name),
                                             strlen (lease -> host -> name),
                                             1, 0, MDL)) {
-                               oc -> option = dhcp_universe.options [i];
+                               option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                       &i, 0, MDL);
                                save_option (&dhcp_universe,
                                             state -> options, oc);
                        }
@@ -2638,8 +2661,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                                                      h -> h_name),
                                                     strlen (h -> h_name) + 1,
                                                     1, 1, MDL)) {
-                                       oc -> option =
-                                               dhcp_universe.options [i];
+                                       option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                               &i, 0, MDL);
                                        save_option (&dhcp_universe,
                                                     state -> options, oc);
                                }
@@ -2666,8 +2690,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
                                                     lease -> ip_addr.iabuf,
                                                     lease -> ip_addr.len,
                                                     0, 0, MDL)) {
-                                       oc -> option =
-                                               dhcp_universe.options [i];
+                                       option_code_hash_lookup(&oc->option,
+                                                       dhcp_universe.code_hash,
+                                                               &i, 0, MDL);
                                        save_option (&dhcp_universe,
                                                     state -> options, oc);
                                }
index 20ad847bcb2e5ddcba57ff7f7e165328846154fd..959fb4695bbe66b7330a46849d955e0f0f9abdc9 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: mdb.c,v 1.78 2006/05/30 19:46:37 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: mdb.c,v 1.79 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -130,7 +130,7 @@ isc_result_t enter_host (hd, dynamicp, commit)
        struct executable_statement *esp;
 
        if (!host_name_hash) {
-               if (!host_new_hash (&host_name_hash, 0, MDL))
+               if (!host_new_hash(&host_name_hash, HOST_HASH_SIZE, MDL))
                        log_fatal ("Can't allocate host name hash");
                host_hash_add (host_name_hash,
                               (unsigned char *)hd -> name,
@@ -185,7 +185,8 @@ isc_result_t enter_host (hd, dynamicp, commit)
 
        if (hd -> interface.hlen) {
                if (!host_hw_addr_hash) {
-                       if (!host_new_hash (&host_hw_addr_hash, 0, MDL))
+                       if (!host_new_hash(&host_hw_addr_hash,
+                                          HOST_HASH_SIZE, MDL))
                                log_fatal ("Can't allocate host/hw hash");
                } else {
                        /* If there isn't already a host decl matching this
@@ -229,7 +230,8 @@ isc_result_t enter_host (hd, dynamicp, commit)
                /* If there's no uid hash, make one; otherwise, see if
                   there's already an entry in the hash for this host. */
                if (!host_uid_hash) {
-                       if (!host_new_hash (&host_uid_hash, 0, MDL))
+                       if (!host_new_hash(&host_uid_hash,
+                                          HOST_HASH_SIZE, MDL))
                                log_fatal ("Can't allocate host/uid hash");
 
                        host_hash_add (host_uid_hash,
@@ -538,15 +540,15 @@ void new_address_range (cfile, low, high, subnet, pool, lpchain)
 
        /* Initialize the hash table if it hasn't been done yet. */
        if (!lease_uid_hash) {
-               if (!lease_new_hash (&lease_uid_hash, 0, MDL))
+               if (!lease_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL))
                        log_fatal ("Can't allocate lease/uid hash");
        }
        if (!lease_ip_addr_hash) {
-               if (!lease_new_hash (&lease_ip_addr_hash, 0, MDL))
+               if (!lease_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE, MDL))
                        log_fatal ("Can't allocate lease/ip hash");
        }
        if (!lease_hw_addr_hash) {
-               if (!lease_new_hash (&lease_hw_addr_hash, 0, MDL))
+               if (!lease_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE, MDL))
                        log_fatal ("Can't allocate lease/hw hash");
        }
 
@@ -2055,7 +2057,7 @@ int lease_enqueue (struct lease *comp)
    in lease_ip_addr_hash. */
 
 isc_result_t
-lease_instantiate(const unsigned char *val, unsigned len, void *object)
+lease_instantiate(const void *key, unsigned len, void *object)
 {
        struct lease *lease = object;
        struct class *class;
@@ -2208,11 +2210,11 @@ void dump_subnets ()
 }
 
 HASH_FUNCTIONS (lease, const unsigned char *, struct lease, lease_hash_t,
-               lease_reference, lease_dereference)
+               lease_reference, lease_dereference, do_ip4_hash)
 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
-               host_reference, host_dereference)
+               host_reference, host_dereference, do_string_hash)
 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
-               class_reference, class_dereference)
+               class_reference, class_dereference, do_string_hash)
 
 #if defined (DEBUG_MEMORY_LEAKAGE) && \
                defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
index 9704a03ca69302a170c0312bc0d5521d62ad3c08..3cd6628479a850fad94368127c01ffc01343be22 100644 (file)
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: omapi.c,v 1.57 2006/04/27 17:26:42 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: omapi.c,v 1.58 2006/06/01 20:23:17 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -2029,7 +2029,7 @@ class_signal_handler(omapi_object_t *h,
                if (issubclass) {
                        if (!class -> superclass -> hash)
                                class_new_hash(&class->superclass->hash,
-                                               0, MDL);
+                                              SCLASS_HASH_SIZE, MDL);
 
                        add_hash (class -> superclass -> hash,
                                  class -> hash_string.data,
index 57ee6f29e9ad197d408d28f3c35618b0b4d3d927..88567f690381d83b23756a4a22bcb2e566be18e4 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: stables.c,v 1.28 2006/04/27 17:26:42 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: stables.c,v 1.29 2006/06/01 20:23:18 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -173,523 +173,65 @@ const char *binding_state_names [] = {
        "reset", "backup" };
 
 struct universe agent_universe;
-struct option agent_options [256] = {
-       { "pad", "",                                    &agent_universe, 0 },
-       { "circuit-id", "X",                            &agent_universe, 1 },
-       { "remote-id", "X",                             &agent_universe, 2 },
-       { "agent-id", "I",                              &agent_universe, 3 },
-       { "DOCSIS-device-class", "L",                   &agent_universe, 4 },
-       { "unknown-5", "X",                             &agent_universe, 5 },
-       { "unknown-6", "X",                             &agent_universe, 6 },
-       { "unknown-7", "X",                             &agent_universe, 7 },
-       { "unknown-8", "X",                             &agent_universe, 8 },
-       { "unknown-9", "X",                             &agent_universe, 9 },
-       { "unknown-10", "X",                            &agent_universe, 10 },
-       { "unknown-11", "X",                            &agent_universe, 11 },
-       { "unknown-12", "X",                            &agent_universe, 12 },
-       { "unknown-13", "X",                            &agent_universe, 13 },
-       { "unknown-14", "X",                            &agent_universe, 14 },
-       { "unknown-15", "X",                            &agent_universe, 15 },
-       { "unknown-16", "X",                            &agent_universe, 16 },
-       { "unknown-17", "X",                            &agent_universe, 17 },
-       { "unknown-18", "X",                            &agent_universe, 18 },
-       { "unknown-19", "X",                            &agent_universe, 19 },
-       { "unknown-20", "X",                            &agent_universe, 20 },
-       { "unknown-21", "X",                            &agent_universe, 21 },
-       { "unknown-22", "X",                            &agent_universe, 22 },
-       { "unknown-23", "X",                            &agent_universe, 23 },
-       { "unknown-24", "X",                            &agent_universe, 24 },
-       { "unknown-25", "X",                            &agent_universe, 25 },
-       { "unknown-26", "X",                            &agent_universe, 26 },
-       { "unknown-27", "X",                            &agent_universe, 27 },
-       { "unknown-28", "X",                            &agent_universe, 28 },
-       { "unknown-29", "X",                            &agent_universe, 29 },
-       { "unknown-30", "X",                            &agent_universe, 30 },
-       { "unknown-31", "X",                            &agent_universe, 31 },
-       { "unknown-32", "X",                            &agent_universe, 32 },
-       { "unknown-33", "X",                            &agent_universe, 33 },
-       { "unknown-34", "X",                            &agent_universe, 34 },
-       { "unknown-35", "X",                            &agent_universe, 35 },
-       { "unknown-36", "X",                            &agent_universe, 36 },
-       { "unknown-37", "X",                            &agent_universe, 37 },
-       { "unknown-38", "X",                            &agent_universe, 38 },
-       { "unknown-39", "X",                            &agent_universe, 39 },
-       { "unknown-40", "X",                            &agent_universe, 40 },
-       { "unknown-41", "X",                            &agent_universe, 41 },
-       { "unknown-42", "X",                            &agent_universe, 42 },
-       { "unknown-43", "X",                            &agent_universe, 43 },
-       { "unknown-44", "X",                            &agent_universe, 44 },
-       { "unknown-45", "X",                            &agent_universe, 45 },
-       { "unknown-46", "X",                            &agent_universe, 46 },
-       { "unknown-47", "X",                            &agent_universe, 47 },
-       { "unknown-48", "X",                            &agent_universe, 48 },
-       { "unknown-49", "X",                            &agent_universe, 49 },
-       { "unknown-50", "X",                            &agent_universe, 50 },
-       { "unknown-51", "X",                            &agent_universe, 51 },
-       { "unknown-52", "X",                            &agent_universe, 52 },
-       { "unknown-53", "X",                            &agent_universe, 53 },
-       { "unknown-54", "X",                            &agent_universe, 54 },
-       { "unknown-55", "X",                            &agent_universe, 55 },
-       { "unknown-56", "X",                            &agent_universe, 56 },
-       { "unknown-57", "X",                            &agent_universe, 57 },
-       { "unknown-58", "X",                            &agent_universe, 58 },
-       { "unknown-59", "X",                            &agent_universe, 59 },
-       { "unknown-60", "X",                            &agent_universe, 60 },
-       { "unknown-61", "X",                            &agent_universe, 61 },
-       { "unknown-62", "X",                            &agent_universe, 62 },
-       { "unknown-63", "X",                            &agent_universe, 63 },
-       { "unknown-64", "X",                            &agent_universe, 64 },
-       { "unknown-65", "X",                            &agent_universe, 65 },
-       { "unknown-66", "X",                            &agent_universe, 66 },
-       { "unknown-67", "X",                            &agent_universe, 67 },
-       { "unknown-68", "X",                            &agent_universe, 68 },
-       { "unknown-69", "X",                            &agent_universe, 69 },
-       { "unknown-70", "X",                            &agent_universe, 70 },
-       { "unknown-71", "X",                            &agent_universe, 71 },
-       { "unknown-72", "X",                            &agent_universe, 72 },
-       { "unknown-73", "X",                            &agent_universe, 73 },
-       { "unknown-74", "X",                            &agent_universe, 74 },
-       { "unknown-75", "X",                            &agent_universe, 75 },
-       { "unknown-76", "X",                            &agent_universe, 76 },
-       { "unknown-77", "X",                            &agent_universe, 77 },
-       { "unknown-78", "X",                            &agent_universe, 78 },
-       { "unknown-79", "X",                            &agent_universe, 79 },
-       { "unknown-80", "X",                            &agent_universe, 80 },
-       { "unknown-81", "X",                            &agent_universe, 81 },
-       { "unknown-82", "X",                            &agent_universe, 82 },
-       { "unknown-83", "X",                            &agent_universe, 83 },
-       { "unknown-84", "X",                            &agent_universe, 84 },
-       { "unknown-85", "X",                            &agent_universe, 85 },
-       { "unknown-86", "X",                            &agent_universe, 86 },
-       { "unknown-87", "X",                            &agent_universe, 87 },
-       { "unknown-88", "X",                            &agent_universe, 88 },
-       { "unknown-89", "X",                            &agent_universe, 89 },
-       { "unknown-90", "X",                            &agent_universe, 90 },
-       { "unknown-91", "X",                            &agent_universe, 91 },
-       { "unknown-92", "X",                            &agent_universe, 92 },
-       { "unknown-93", "X",                            &agent_universe, 93 },
-       { "unknown-94", "X",                            &agent_universe, 94 },
-       { "unknown-95", "X",                            &agent_universe, 95 },
-       { "unknown-96", "X",                            &agent_universe, 96 },
-       { "unknown-97", "X",                            &agent_universe, 97 },
-       { "unknown-98", "X",                            &agent_universe, 98 },
-       { "unknown-99", "X",                            &agent_universe, 99 },
-       { "unknown-100", "X",                           &agent_universe, 100 },
-       { "unknown-101", "X",                           &agent_universe, 101 },
-       { "unknown-102", "X",                           &agent_universe, 102 },
-       { "unknown-103", "X",                           &agent_universe, 103 },
-       { "unknown-104", "X",                           &agent_universe, 104 },
-       { "unknown-105", "X",                           &agent_universe, 105 },
-       { "unknown-106", "X",                           &agent_universe, 106 },
-       { "unknown-107", "X",                           &agent_universe, 107 },
-       { "unknown-108", "X",                           &agent_universe, 108 },
-       { "unknown-109", "X",                           &agent_universe, 109 },
-       { "unknown-110", "X",                           &agent_universe, 110 },
-       { "unknown-111", "X",                           &agent_universe, 111 },
-       { "unknown-112", "X",                           &agent_universe, 112 },
-       { "unknown-113", "X",                           &agent_universe, 113 },
-       { "unknown-114", "X",                           &agent_universe, 114 },
-       { "unknown-115", "X",                           &agent_universe, 115 },
-       { "unknown-116", "X",                           &agent_universe, 116 },
-       { "unknown-117", "X",                           &agent_universe, 117 },
-       { "unknown-118", "X",                           &agent_universe, 118 },
-       { "unknown-119", "X",                           &agent_universe, 119 },
-       { "unknown-120", "X",                           &agent_universe, 120 },
-       { "unknown-121", "X",                           &agent_universe, 121 },
-       { "unknown-122", "X",                           &agent_universe, 122 },
-       { "unknown-123", "X",                           &agent_universe, 123 },
-       { "unknown-124", "X",                           &agent_universe, 124 },
-       { "unknown-125", "X",                           &agent_universe, 125 },
-       { "unknown-126", "X",                           &agent_universe, 126 },
-       { "unknown-127", "X",                           &agent_universe, 127 },
-       { "unknown-128", "X",                           &agent_universe, 128 },
-       { "unknown-129", "X",                           &agent_universe, 129 },
-       { "unknown-130", "X",                           &agent_universe, 130 },
-       { "unknown-131", "X",                           &agent_universe, 131 },
-       { "unknown-132", "X",                           &agent_universe, 132 },
-       { "unknown-133", "X",                           &agent_universe, 133 },
-       { "unknown-134", "X",                           &agent_universe, 134 },
-       { "unknown-135", "X",                           &agent_universe, 135 },
-       { "unknown-136", "X",                           &agent_universe, 136 },
-       { "unknown-137", "X",                           &agent_universe, 137 },
-       { "unknown-138", "X",                           &agent_universe, 138 },
-       { "unknown-139", "X",                           &agent_universe, 139 },
-       { "unknown-140", "X",                           &agent_universe, 140 },
-       { "unknown-141", "X",                           &agent_universe, 141 },
-       { "unknown-142", "X",                           &agent_universe, 142 },
-       { "unknown-143", "X",                           &agent_universe, 143 },
-       { "unknown-144", "X",                           &agent_universe, 144 },
-       { "unknown-145", "X",                           &agent_universe, 145 },
-       { "unknown-146", "X",                           &agent_universe, 146 },
-       { "unknown-147", "X",                           &agent_universe, 147 },
-       { "unknown-148", "X",                           &agent_universe, 148 },
-       { "unknown-149", "X",                           &agent_universe, 149 },
-       { "unknown-150", "X",                           &agent_universe, 150 },
-       { "unknown-151", "X",                           &agent_universe, 151 },
-       { "unknown-152", "X",                           &agent_universe, 152 },
-       { "unknown-153", "X",                           &agent_universe, 153 },
-       { "unknown-154", "X",                           &agent_universe, 154 },
-       { "unknown-155", "X",                           &agent_universe, 155 },
-       { "unknown-156", "X",                           &agent_universe, 156 },
-       { "unknown-157", "X",                           &agent_universe, 157 },
-       { "unknown-158", "X",                           &agent_universe, 158 },
-       { "unknown-159", "X",                           &agent_universe, 159 },
-       { "unknown-160", "X",                           &agent_universe, 160 },
-       { "unknown-161", "X",                           &agent_universe, 161 },
-       { "unknown-162", "X",                           &agent_universe, 162 },
-       { "unknown-163", "X",                           &agent_universe, 163 },
-       { "unknown-164", "X",                           &agent_universe, 164 },
-       { "unknown-165", "X",                           &agent_universe, 165 },
-       { "unknown-166", "X",                           &agent_universe, 166 },
-       { "unknown-167", "X",                           &agent_universe, 167 },
-       { "unknown-168", "X",                           &agent_universe, 168 },
-       { "unknown-169", "X",                           &agent_universe, 169 },
-       { "unknown-170", "X",                           &agent_universe, 170 },
-       { "unknown-171", "X",                           &agent_universe, 171 },
-       { "unknown-172", "X",                           &agent_universe, 172 },
-       { "unknown-173", "X",                           &agent_universe, 173 },
-       { "unknown-174", "X",                           &agent_universe, 174 },
-       { "unknown-175", "X",                           &agent_universe, 175 },
-       { "unknown-176", "X",                           &agent_universe, 176 },
-       { "unknown-177", "X",                           &agent_universe, 177 },
-       { "unknown-178", "X",                           &agent_universe, 178 },
-       { "unknown-179", "X",                           &agent_universe, 179 },
-       { "unknown-180", "X",                           &agent_universe, 180 },
-       { "unknown-181", "X",                           &agent_universe, 181 },
-       { "unknown-182", "X",                           &agent_universe, 182 },
-       { "unknown-183", "X",                           &agent_universe, 183 },
-       { "unknown-184", "X",                           &agent_universe, 184 },
-       { "unknown-185", "X",                           &agent_universe, 185 },
-       { "unknown-186", "X",                           &agent_universe, 186 },
-       { "unknown-187", "X",                           &agent_universe, 187 },
-       { "unknown-188", "X",                           &agent_universe, 188 },
-       { "unknown-189", "X",                           &agent_universe, 189 },
-       { "unknown-190", "X",                           &agent_universe, 190 },
-       { "unknown-191", "X",                           &agent_universe, 191 },
-       { "unknown-192", "X",                           &agent_universe, 192 },
-       { "unknown-193", "X",                           &agent_universe, 193 },
-       { "unknown-194", "X",                           &agent_universe, 194 },
-       { "unknown-195", "X",                           &agent_universe, 195 },
-       { "unknown-196", "X",                           &agent_universe, 196 },
-       { "unknown-197", "X",                           &agent_universe, 197 },
-       { "unknown-198", "X",                           &agent_universe, 198 },
-       { "unknown-199", "X",                           &agent_universe, 199 },
-       { "unknown-200", "X",                           &agent_universe, 200 },
-       { "unknown-201", "X",                           &agent_universe, 201 },
-       { "unknown-202", "X",                           &agent_universe, 202 },
-       { "unknown-203", "X",                           &agent_universe, 203 },
-       { "unknown-204", "X",                           &agent_universe, 204 },
-       { "unknown-205", "X",                           &agent_universe, 205 },
-       { "unknown-206", "X",                           &agent_universe, 206 },
-       { "unknown-207", "X",                           &agent_universe, 207 },
-       { "unknown-208", "X",                           &agent_universe, 208 },
-       { "unknown-209", "X",                           &agent_universe, 209 },
-       { "unknown-210", "X",                           &agent_universe, 210 },
-       { "unknown-211", "X",                           &agent_universe, 211 },
-       { "unknown-212", "X",                           &agent_universe, 212 },
-       { "unknown-213", "X",                           &agent_universe, 213 },
-       { "unknown-214", "X",                           &agent_universe, 214 },
-       { "unknown-215", "X",                           &agent_universe, 215 },
-       { "unknown-216", "X",                           &agent_universe, 216 },
-       { "unknown-217", "X",                           &agent_universe, 217 },
-       { "unknown-218", "X",                           &agent_universe, 218 },
-       { "unknown-219", "X",                           &agent_universe, 219 },
-       { "unknown-220", "X",                           &agent_universe, 220 },
-       { "unknown-221", "X",                           &agent_universe, 221 },
-       { "unknown-222", "X",                           &agent_universe, 222 },
-       { "unknown-223", "X",                           &agent_universe, 223 },
-       { "unknown-224", "X",                           &agent_universe, 224 },
-       { "unknown-225", "X",                           &agent_universe, 225 },
-       { "unknown-226", "X",                           &agent_universe, 226 },
-       { "unknown-227", "X",                           &agent_universe, 227 },
-       { "unknown-228", "X",                           &agent_universe, 228 },
-       { "unknown-229", "X",                           &agent_universe, 229 },
-       { "unknown-230", "X",                           &agent_universe, 230 },
-       { "unknown-231", "X",                           &agent_universe, 231 },
-       { "unknown-232", "X",                           &agent_universe, 232 },
-       { "unknown-233", "X",                           &agent_universe, 233 },
-       { "unknown-234", "X",                           &agent_universe, 234 },
-       { "unknown-235", "X",                           &agent_universe, 235 },
-       { "unknown-236", "X",                           &agent_universe, 236 },
-       { "unknown-237", "X",                           &agent_universe, 237 },
-       { "unknown-238", "X",                           &agent_universe, 238 },
-       { "unknown-239", "X",                           &agent_universe, 239 },
-       { "unknown-240", "X",                           &agent_universe, 240 },
-       { "unknown-241", "X",                           &agent_universe, 241 },
-       { "unknown-242", "X",                           &agent_universe, 242 },
-       { "unknown-243", "X",                           &agent_universe, 243 },
-       { "unknown-244", "X",                           &agent_universe, 244 },
-       { "unknown-245", "X",                           &agent_universe, 245 },
-       { "unknown-246", "X",                           &agent_universe, 246 },
-       { "unknown-247", "X",                           &agent_universe, 247 },
-       { "unknown-248", "X",                           &agent_universe, 248 },
-       { "unknown-249", "X",                           &agent_universe, 249 },
-       { "unknown-250", "X",                           &agent_universe, 250 },
-       { "unknown-251", "X",                           &agent_universe, 251 },
-       { "unknown-252", "X",                           &agent_universe, 252 },
-       { "unknown-253", "X",                           &agent_universe, 253 },
-       { "unknown-254", "X",                           &agent_universe, 254 },
-       { "option-end", "e",                            &agent_universe, 255 },
+static struct option agent_options[] = {
+       { "circuit-id", "X",                    &agent_universe,   1, 1 },
+       { "remote-id", "X",                     &agent_universe,   2, 1 },
+       { "agent-id", "I",                      &agent_universe,   3, 1 },
+       { "DOCSIS-device-class", "L",           &agent_universe,   4, 1 },
+       { NULL, NULL, NULL, 0, 0 }
 };
 
 struct universe server_universe;
-struct option server_options [256] = {
-       { "pad", "",                                    &server_universe, 0 },
-       { "default-lease-time", "T",                    &server_universe, 1 },
-       { "max-lease-time", "T",                        &server_universe, 2 },
-       { "min-lease-time", "T",                        &server_universe, 3 },
-       { "dynamic-bootp-lease-cutoff", "T",            &server_universe, 4 },
-       { "dynamic-bootp-lease-length", "L",            &server_universe, 5 },
-       { "boot-unknown-clients", "f",                  &server_universe, 6 },
-       { "dynamic-bootp", "f",                         &server_universe, 7 },
-       { "allow-bootp", "f",                           &server_universe, 8 },
-       { "allow-booting", "f",                         &server_universe, 9 },
-       { "one-lease-per-client", "f",                  &server_universe, 10 },
-       { "get-lease-hostnames", "f",                   &server_universe, 11 },
-       { "use-host-decl-names", "f",                   &server_universe, 12 },
-       { "use-lease-addr-for-default-route", "f",      &server_universe, 13 },
-       { "min-secs", "B",                              &server_universe, 14 },
-       { "filename", "t",                              &server_universe, 15 },
-       { "server-name", "t",                           &server_universe, 16 },
-       { "next-server", "I",                           &server_universe, 17 },
-       { "authoritative", "f",                         &server_universe, 18 },
-       { "vendor-option-space", "U",                   &server_universe, 19 },
-       { "always-reply-rfc1048", "f",                  &server_universe, 20 },
-       { "site-option-space", "X",                     &server_universe, 21 },
-       { "always-broadcast", "f",                      &server_universe, 22 },
-       { "ddns-domainname", "t",                       &server_universe, 23 },
-       { "ddns-hostname", "t",                         &server_universe, 24 },
-       { "ddns-rev-domainname", "t",                   &server_universe, 25 },
-       { "lease-file-name", "t",                       &server_universe, 26 },
-       { "pid-file-name", "t",                         &server_universe, 27 },
-       { "duplicates", "f",                            &server_universe, 28 },
-       { "declines", "f",                              &server_universe, 29 },
-       { "ddns-updates", "f",                          &server_universe, 30 },
-       { "omapi-port", "S",                            &server_universe, 31 },
-       { "local-port", "S",                            &server_universe, 32 },
-       { "limited-broadcast-address", "I",             &server_universe, 33 },
-       { "remote-port", "S",                           &server_universe, 34 },
-       { "local-address", "I",                         &server_universe, 35 },
-       { "omapi-key", "d",                             &server_universe, 36 },
-       { "stash-agent-options", "f",                   &server_universe, 37 },
-       { "ddns-ttl", "T",                              &server_universe, 38 },
-       { "ddns-update-style", "Nddns-styles.",         &server_universe, 39 },
-       { "client-updates", "f",                        &server_universe, 40 },
-       { "update-optimization", "f",                   &server_universe, 41 },
-       { "ping-check", "f",                            &server_universe, 42 },
-       { "update-static-leases", "f",                  &server_universe, 43 },
-       { "log-facility", "Nsyslog-facilities.",        &server_universe, 44 },
-       { "do-forward-updates", "f",                    &server_universe, 45 },
-       { "ping-timeout", "T",                          &server_universe, 46 },
-       { "unknown-47", "X",                            &server_universe, 47 },
-       { "unknown-48", "X",                            &server_universe, 48 },
-       { "unknown-49", "X",                            &server_universe, 49 },
-       { "unknown-50", "X",                            &server_universe, 50 },
-       { "unknown-51", "X",                            &server_universe, 51 },
-       { "unknown-52", "X",                            &server_universe, 52 },
-       { "unknown-53", "X",                            &server_universe, 53 },
-       { "unknown-54", "X",                            &server_universe, 54 },
-       { "unknown-55", "X",                            &server_universe, 55 },
-       { "unknown-56", "X",                            &server_universe, 56 },
-       { "unknown-57", "X",                            &server_universe, 57 },
-       { "unknown-58", "X",                            &server_universe, 58 },
-       { "unknown-59", "X",                            &server_universe, 59 },
-       { "unknown-60", "X",                            &server_universe, 60 },
-       { "unknown-61", "X",                            &server_universe, 61 },
-       { "unknown-62", "X",                            &server_universe, 62 },
-       { "unknown-63", "X",                            &server_universe, 63 },
-       { "unknown-64", "X",                            &server_universe, 64 },
-       { "unknown-65", "X",                            &server_universe, 65 },
-       { "unknown-66", "X",                            &server_universe, 66 },
-       { "unknown-67", "X",                            &server_universe, 67 },
-       { "unknown-68", "X",                            &server_universe, 68 },
-       { "unknown-69", "X",                            &server_universe, 69 },
-       { "unknown-70", "X",                            &server_universe, 70 },
-       { "unknown-71", "X",                            &server_universe, 71 },
-       { "unknown-72", "X",                            &server_universe, 72 },
-       { "unknown-73", "X",                            &server_universe, 73 },
-       { "unknown-74", "X",                            &server_universe, 74 },
-       { "unknown-75", "X",                            &server_universe, 75 },
-       { "unknown-76", "X",                            &server_universe, 76 },
-       { "unknown-77", "X",                            &server_universe, 77 },
-       { "unknown-78", "X",                            &server_universe, 78 },
-       { "unknown-79", "X",                            &server_universe, 79 },
-       { "unknown-80", "X",                            &server_universe, 80 },
-       { "unknown-81", "X",                            &server_universe, 81 },
-       { "unknown-82", "X",                            &server_universe, 82 },
-       { "unknown-83", "X",                            &server_universe, 83 },
-       { "unknown-84", "X",                            &server_universe, 84 },
-       { "unknown-85", "X",                            &server_universe, 85 },
-       { "unknown-86", "X",                            &server_universe, 86 },
-       { "unknown-87", "X",                            &server_universe, 87 },
-       { "unknown-88", "X",                            &server_universe, 88 },
-       { "unknown-89", "X",                            &server_universe, 89 },
-       { "unknown-90", "X",                            &server_universe, 90 },
-       { "unknown-91", "X",                            &server_universe, 91 },
-       { "unknown-92", "X",                            &server_universe, 92 },
-       { "unknown-93", "X",                            &server_universe, 93 },
-       { "unknown-94", "X",                            &server_universe, 94 },
-       { "unknown-95", "X",                            &server_universe, 95 },
-       { "unknown-96", "X",                            &server_universe, 96 },
-       { "unknown-97", "X",                            &server_universe, 97 },
-       { "unknown-98", "X",                            &server_universe, 98 },
-       { "unknown-99", "X",                            &server_universe, 99 },
-       { "unknown-100", "X",                           &server_universe, 100 },
-       { "unknown-101", "X",                           &server_universe, 101 },
-       { "unknown-102", "X",                           &server_universe, 102 },
-       { "unknown-103", "X",                           &server_universe, 103 },
-       { "unknown-104", "X",                           &server_universe, 104 },
-       { "unknown-105", "X",                           &server_universe, 105 },
-       { "unknown-106", "X",                           &server_universe, 106 },
-       { "unknown-107", "X",                           &server_universe, 107 },
-       { "unknown-108", "X",                           &server_universe, 108 },
-       { "unknown-109", "X",                           &server_universe, 109 },
-       { "unknown-110", "X",                           &server_universe, 110 },
-       { "unknown-111", "X",                           &server_universe, 111 },
-       { "unknown-112", "X",                           &server_universe, 112 },
-       { "unknown-113", "X",                           &server_universe, 113 },
-       { "unknown-114", "X",                           &server_universe, 114 },
-       { "unknown-115", "X",                           &server_universe, 115 },
-       { "unknown-116", "X",                           &server_universe, 116 },
-       { "unknown-117", "X",                           &server_universe, 117 },
-       { "unknown-118", "X",                           &server_universe, 118 },
-       { "unknown-119", "X",                           &server_universe, 119 },
-       { "unknown-120", "X",                           &server_universe, 120 },
-       { "unknown-121", "X",                           &server_universe, 121 },
-       { "unknown-122", "X",                           &server_universe, 122 },
-       { "unknown-123", "X",                           &server_universe, 123 },
-       { "unknown-124", "X",                           &server_universe, 124 },
-       { "unknown-125", "X",                           &server_universe, 125 },
-       { "unknown-126", "X",                           &server_universe, 126 },
-       { "unknown-127", "X",                           &server_universe, 127 },
-       { "unknown-128", "X",                           &server_universe, 128 },
-       { "unknown-129", "X",                           &server_universe, 129 },
-       { "unknown-130", "X",                           &server_universe, 130 },
-       { "unknown-131", "X",                           &server_universe, 131 },
-       { "unknown-132", "X",                           &server_universe, 132 },
-       { "unknown-133", "X",                           &server_universe, 133 },
-       { "unknown-134", "X",                           &server_universe, 134 },
-       { "unknown-135", "X",                           &server_universe, 135 },
-       { "unknown-136", "X",                           &server_universe, 136 },
-       { "unknown-137", "X",                           &server_universe, 137 },
-       { "unknown-138", "X",                           &server_universe, 138 },
-       { "unknown-139", "X",                           &server_universe, 139 },
-       { "unknown-140", "X",                           &server_universe, 140 },
-       { "unknown-141", "X",                           &server_universe, 141 },
-       { "unknown-142", "X",                           &server_universe, 142 },
-       { "unknown-143", "X",                           &server_universe, 143 },
-       { "unknown-144", "X",                           &server_universe, 144 },
-       { "unknown-145", "X",                           &server_universe, 145 },
-       { "unknown-146", "X",                           &server_universe, 146 },
-       { "unknown-147", "X",                           &server_universe, 147 },
-       { "unknown-148", "X",                           &server_universe, 148 },
-       { "unknown-149", "X",                           &server_universe, 149 },
-       { "unknown-150", "X",                           &server_universe, 150 },
-       { "unknown-151", "X",                           &server_universe, 151 },
-       { "unknown-152", "X",                           &server_universe, 152 },
-       { "unknown-153", "X",                           &server_universe, 153 },
-       { "unknown-154", "X",                           &server_universe, 154 },
-       { "unknown-155", "X",                           &server_universe, 155 },
-       { "unknown-156", "X",                           &server_universe, 156 },
-       { "unknown-157", "X",                           &server_universe, 157 },
-       { "unknown-158", "X",                           &server_universe, 158 },
-       { "unknown-159", "X",                           &server_universe, 159 },
-       { "unknown-160", "X",                           &server_universe, 160 },
-       { "unknown-161", "X",                           &server_universe, 161 },
-       { "unknown-162", "X",                           &server_universe, 162 },
-       { "unknown-163", "X",                           &server_universe, 163 },
-       { "unknown-164", "X",                           &server_universe, 164 },
-       { "unknown-165", "X",                           &server_universe, 165 },
-       { "unknown-166", "X",                           &server_universe, 166 },
-       { "unknown-167", "X",                           &server_universe, 167 },
-       { "unknown-168", "X",                           &server_universe, 168 },
-       { "unknown-169", "X",                           &server_universe, 169 },
-       { "unknown-170", "X",                           &server_universe, 170 },
-       { "unknown-171", "X",                           &server_universe, 171 },
-       { "unknown-172", "X",                           &server_universe, 172 },
-       { "unknown-173", "X",                           &server_universe, 173 },
-       { "unknown-174", "X",                           &server_universe, 174 },
-       { "unknown-175", "X",                           &server_universe, 175 },
-       { "unknown-176", "X",                           &server_universe, 176 },
-       { "unknown-177", "X",                           &server_universe, 177 },
-       { "unknown-178", "X",                           &server_universe, 178 },
-       { "unknown-179", "X",                           &server_universe, 179 },
-       { "unknown-180", "X",                           &server_universe, 180 },
-       { "unknown-181", "X",                           &server_universe, 181 },
-       { "unknown-182", "X",                           &server_universe, 182 },
-       { "unknown-183", "X",                           &server_universe, 183 },
-       { "unknown-184", "X",                           &server_universe, 184 },
-       { "unknown-185", "X",                           &server_universe, 185 },
-       { "unknown-186", "X",                           &server_universe, 186 },
-       { "unknown-187", "X",                           &server_universe, 187 },
-       { "unknown-188", "X",                           &server_universe, 188 },
-       { "unknown-189", "X",                           &server_universe, 189 },
-       { "unknown-190", "X",                           &server_universe, 190 },
-       { "unknown-191", "X",                           &server_universe, 191 },
-       { "unknown-192", "X",                           &server_universe, 192 },
-       { "unknown-193", "X",                           &server_universe, 193 },
-       { "unknown-194", "X",                           &server_universe, 194 },
-       { "unknown-195", "X",                           &server_universe, 195 },
-       { "unknown-196", "X",                           &server_universe, 196 },
-       { "unknown-197", "X",                           &server_universe, 197 },
-       { "unknown-198", "X",                           &server_universe, 198 },
-       { "unknown-199", "X",                           &server_universe, 199 },
-       { "unknown-200", "X",                           &server_universe, 200 },
-       { "unknown-201", "X",                           &server_universe, 201 },
-       { "unknown-202", "X",                           &server_universe, 202 },
-       { "unknown-203", "X",                           &server_universe, 203 },
-       { "unknown-204", "X",                           &server_universe, 204 },
-       { "unknown-205", "X",                           &server_universe, 205 },
-       { "unknown-206", "X",                           &server_universe, 206 },
-       { "unknown-207", "X",                           &server_universe, 207 },
-       { "unknown-208", "X",                           &server_universe, 208 },
-       { "unknown-209", "X",                           &server_universe, 209 },
-       { "unknown-210", "X",                           &server_universe, 210 },
-       { "unknown-211", "X",                           &server_universe, 211 },
-       { "unknown-212", "X",                           &server_universe, 212 },
-       { "unknown-213", "X",                           &server_universe, 213 },
-       { "unknown-214", "X",                           &server_universe, 214 },
-       { "unknown-215", "X",                           &server_universe, 215 },
-       { "unknown-216", "X",                           &server_universe, 216 },
-       { "unknown-217", "X",                           &server_universe, 217 },
-       { "unknown-218", "X",                           &server_universe, 218 },
-       { "unknown-219", "X",                           &server_universe, 219 },
-       { "unknown-220", "X",                           &server_universe, 220 },
-       { "unknown-221", "X",                           &server_universe, 221 },
-       { "unknown-222", "X",                           &server_universe, 222 },
-       { "unknown-223", "X",                           &server_universe, 223 },
-       { "unknown-224", "X",                           &server_universe, 224 },
-       { "unknown-225", "X",                           &server_universe, 225 },
-       { "unknown-226", "X",                           &server_universe, 226 },
-       { "unknown-227", "X",                           &server_universe, 227 },
-       { "unknown-228", "X",                           &server_universe, 228 },
-       { "unknown-229", "X",                           &server_universe, 229 },
-       { "unknown-230", "X",                           &server_universe, 230 },
-       { "unknown-231", "X",                           &server_universe, 231 },
-       { "unknown-232", "X",                           &server_universe, 232 },
-       { "unknown-233", "X",                           &server_universe, 233 },
-       { "unknown-234", "X",                           &server_universe, 234 },
-       { "unknown-235", "X",                           &server_universe, 235 },
-       { "unknown-236", "X",                           &server_universe, 236 },
-       { "unknown-237", "X",                           &server_universe, 237 },
-       { "unknown-238", "X",                           &server_universe, 238 },
-       { "unknown-239", "X",                           &server_universe, 239 },
-       { "unknown-240", "X",                           &server_universe, 240 },
-       { "unknown-241", "X",                           &server_universe, 241 },
-       { "unknown-242", "X",                           &server_universe, 242 },
-       { "unknown-243", "X",                           &server_universe, 243 },
-       { "unknown-244", "X",                           &server_universe, 244 },
-       { "unknown-245", "X",                           &server_universe, 245 },
-       { "unknown-246", "X",                           &server_universe, 246 },
-       { "unknown-247", "X",                           &server_universe, 247 },
-       { "unknown-248", "X",                           &server_universe, 248 },
-       { "unknown-249", "X",                           &server_universe, 249 },
-       { "unknown-250", "X",                           &server_universe, 250 },
-       { "unknown-251", "X",                           &server_universe, 251 },
-       { "unknown-252", "X",                           &server_universe, 252 },
-       { "unknown-253", "X",                           &server_universe, 253 },
-       { "unknown-254", "X",                           &server_universe, 254 },
-       { "option-end", "e",                            &server_universe, 255 },
+static struct option server_options[] = {
+       { "default-lease-time", "T",            &server_universe,   1, 1 },
+       { "max-lease-time", "T",                &server_universe,   2, 1 },
+       { "min-lease-time", "T",                &server_universe,   3, 1 },
+       { "dynamic-bootp-lease-cutoff", "T",    &server_universe,   4, 1 },
+       { "dynamic-bootp-lease-length", "L",    &server_universe,   5, 1 },
+       { "boot-unknown-clients", "f",          &server_universe,   6, 1 },
+       { "dynamic-bootp", "f",                 &server_universe,   7, 1 },
+       { "allow-bootp", "f",                   &server_universe,   8, 1 },
+       { "allow-booting", "f",                 &server_universe,   9, 1 },
+       { "one-lease-per-client", "f",          &server_universe,  10, 1 },
+       { "get-lease-hostnames", "f",           &server_universe,  11, 1 },
+       { "use-host-decl-names", "f",           &server_universe,  12, 1 },
+       { "use-lease-addr-for-default-route", "f",
+                                               &server_universe,  13, 1 },
+       { "min-secs", "B",                      &server_universe,  14, 1 },
+       { "filename", "t",                      &server_universe,  15, 1 },
+       { "server-name", "t",                   &server_universe,  16, 1 },
+       { "next-server", "I",                   &server_universe,  17, 1 },
+       { "authoritative", "f",                 &server_universe,  18, 1 },
+       { "vendor-option-space", "U",           &server_universe,  19, 1 },
+       { "always-reply-rfc1048", "f",          &server_universe,  20, 1 },
+       { "site-option-space", "X",             &server_universe,  21, 1 },
+       { "always-broadcast", "f",              &server_universe,  22, 1 },
+       { "ddns-domainname", "t",               &server_universe,  23, 1 },
+       { "ddns-hostname", "t",                 &server_universe,  24, 1 },
+       { "ddns-rev-domainname", "t",           &server_universe,  25, 1 },
+       { "lease-file-name", "t",               &server_universe,  26, 1 },
+       { "pid-file-name", "t",                 &server_universe,  27, 1 },
+       { "duplicates", "f",                    &server_universe,  28, 1 },
+       { "declines", "f",                      &server_universe,  29, 1 },
+       { "ddns-updates", "f",                  &server_universe,  30, 1 },
+       { "omapi-port", "S",                    &server_universe,  31, 1 },
+       { "local-port", "S",                    &server_universe,  32, 1 },
+       { "limited-broadcast-address", "I",     &server_universe,  33, 1 },
+       { "remote-port", "S",                   &server_universe,  34, 1 },
+       { "local-address", "I",                 &server_universe,  35, 1 },
+       { "omapi-key", "d",                     &server_universe,  36, 1 },
+       { "stash-agent-options", "f",           &server_universe,  37, 1 },
+       { "ddns-ttl", "T",                      &server_universe,  38, 1 },
+       { "ddns-update-style", "Nddns-styles.", &server_universe,  39, 1 },
+       { "client-updates", "f",                &server_universe,  40, 1 },
+       { "update-optimization", "f",           &server_universe,  41, 1 },
+       { "ping-check", "f",                    &server_universe,  42, 1 },
+       { "update-static-leases", "f",          &server_universe,  43, 1 },
+       { "log-facility", "Nsyslog-facilities.",
+                                               &server_universe,  44, 1 },
+       { "do-forward-updates", "f",            &server_universe,  45, 1 },
+       { "ping-timeout", "T",                  &server_universe,  46, 1 },
+       { NULL, NULL, NULL, 0, 0 }
 };
 
 struct enumeration_value ddns_styles_values [] = {
@@ -778,6 +320,7 @@ struct enumeration syslog_enum = {
 void initialize_server_option_spaces()
 {
        int i;
+       unsigned code;
 
        /* Set up the Relay Agent Information Option suboption space... */
        agent_universe.name = "agent";
@@ -792,20 +335,27 @@ void initialize_server_option_spaces()
        agent_universe.index = universe_count++;
        agent_universe.length_size = 1;
        agent_universe.tag_size = 1;
+       agent_universe.get_tag = getUChar;
        agent_universe.store_tag = putUChar;
+       agent_universe.get_length = getUChar;
        agent_universe.store_length = putUChar;
        universes [agent_universe.index] = &agent_universe;
-       option_new_hash (&agent_universe.hash, 1, MDL);
-       if (!agent_universe.hash)
+       if (!option_name_new_hash(&agent_universe.name_hash,
+                                 AGENT_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&agent_universe.code_hash,
+                                 AGENT_HASH_SIZE, MDL))
                log_fatal ("Can't allocate agent option hash table.");
-       for (i = 0; i < 256; i++) {
-               agent_universe.options [i] = &agent_options [i];
-               option_hash_add (agent_universe.hash,
-                                agent_options [i].name, 0,
-                                &agent_options [i], MDL);
+       for (i = 0 ; agent_options[i].name ; i++) {
+               option_code_hash_add(agent_universe.code_hash,
+                                    &agent_options[i].code, 0,
+                                    &agent_options[i], MDL);
+               option_name_hash_add(agent_universe.name_hash,
+                                    agent_options[i].name, 0,
+                                    &agent_options[i], MDL);
        }
-       agent_universe.enc_opt = &dhcp_options [DHO_DHCP_AGENT_OPTIONS];
-
+       code = DHO_DHCP_AGENT_OPTIONS;
+       option_code_hash_lookup(&agent_universe.enc_opt,
+                               dhcp_universe.code_hash, &code, 0, MDL);
 
        /* Set up the server option universe... */
        server_universe.name = "server";
@@ -816,20 +366,24 @@ void initialize_server_option_spaces()
        server_universe.delete_func = delete_hashed_option;
        server_universe.encapsulate = hashed_option_space_encapsulate;
        server_universe.foreach = hashed_option_space_foreach;
-       server_universe.length_size = 1;
-       server_universe.tag_size = 1;
+       server_universe.length_size = 1; /* Never used ... */
+       server_universe.tag_size = 4;
        server_universe.store_tag = putUChar;
        server_universe.store_length = putUChar;
        server_universe.index = universe_count++;
        universes [server_universe.index] = &server_universe;
-       option_new_hash (&server_universe.hash, 1, MDL);
-       if (!server_universe.hash)
+       if (!option_name_new_hash(&server_universe.name_hash,
+                                 SERVER_HASH_SIZE, MDL) ||
+           !option_code_new_hash(&server_universe.code_hash,
+                                 SERVER_HASH_SIZE, MDL))
                log_fatal ("Can't allocate server option hash table.");
-       for (i = 0; i < 256; i++) {
-               server_universe.options [i] = &server_options [i];
-               option_hash_add (server_universe.hash,
-                                server_options [i].name, 0,
-                                &server_options [i], MDL);
+       for (i = 0 ; server_options[i].name ; i++) {
+               option_code_hash_add(server_universe.code_hash,
+                                    &server_options[i].code, 0,
+                                    &server_options[i], MDL);
+               option_name_hash_add(server_universe.name_hash,
+                                    server_options[i].name, 0,
+                                    &server_options[i], MDL);
        }
 
        /* Add the server and agent option spaces to the option space hash. */
@@ -840,5 +394,8 @@ void initialize_server_option_spaces()
 
        /* Make the server universe the configuration option universe. */
        config_universe = &server_universe;
-       vendor_cfg_option = &server_options [SV_VENDOR_OPTION_SPACE];
+
+       code = SV_VENDOR_OPTION_SPACE;
+       option_code_hash_lookup(&vendor_cfg_option, server_universe.code_hash,
+                               &code, 0, MDL);
 }