Fold tables.c into options.c and stop exporting the one
authorkrw <krw@openbsd.org>
Sat, 8 Jul 2017 20:38:31 +0000 (20:38 +0000)
committerkrw <krw@openbsd.org>
Sat, 8 Jul 2017 20:38:31 +0000 (20:38 +0000)
table (dhcp_options) involved. Provide functions
code_to_name(), name_to_code(), code_to_format() and
replace direct access to dhcp_options with them. Eliminate
unneeded 'struct option'.

Unhook tables.c from Makefile.

sbin/dhclient/Makefile
sbin/dhclient/clparse.c
sbin/dhclient/dhclient.c
sbin/dhclient/dhcpd.h
sbin/dhclient/options.c

index 685425f..b011385 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.19 2017/04/09 20:44:13 krw Exp $
+# $OpenBSD: Makefile,v 1.20 2017/07/08 20:38:31 krw Exp $
 #
 # Copyright (c) 1996, 1997 The Internet Software Consortium.
 # All rights reserved.
@@ -33,7 +33,7 @@
 .include <bsd.own.mk>
 
 SRCS=  dhclient.c clparse.c dispatch.c bpf.c options.c \
-       conflex.c log.c packet.c tables.c \
+       conflex.c log.c packet.c  \
        parse.c privsep.c kroute.c
 
 PROG=  dhclient
index 1cb8246..afe5db7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: clparse.c,v 1.118 2017/07/08 15:26:27 krw Exp $       */
+/*     $OpenBSD: clparse.c,v 1.119 2017/07/08 20:38:31 krw Exp $       */
 
 /* Parser for dhclient config and lease files. */
 
@@ -409,10 +409,8 @@ parse_option_list(FILE *cfile, uint8_t *list, size_t sz)
                 * lists.  They are not really options and it makes no sense
                 * to request, require or ignore them.
                 */
-               for (i = 1; i < DHO_END; i++)
-                       if (!strcasecmp(dhcp_options[i].name, val))
-                               break;
 
+               i = name_to_code(val);
                if (i == DHO_END) {
                        parse_warn("expecting option name.");
                        goto syntaxerror;
@@ -637,12 +635,8 @@ parse_option_decl(FILE *cfile, struct option_data *options)
        }
 
        /* Look up the actual option info. */
-       fmt = NULL;
-       for (code = 0; code < DHO_COUNT; code++)
-               if (strcasecmp(dhcp_options[code].name, val) == 0)
-                       break;
-
-       if (code > 255) {
+       code = name_to_code(val);
+       if (code == DHO_END) {
                parse_warn("unknown option name.");
                skip_to_semi(cfile);
                return (-1);
@@ -650,7 +644,7 @@ parse_option_decl(FILE *cfile, struct option_data *options)
 
        /* Parse the option data. */
        do {
-               for (fmt = dhcp_options[code].format; *fmt; fmt++) {
+               for (fmt = code_to_format(code); *fmt; fmt++) {
                        if (*fmt == 'A')
                                break;
                        switch (*fmt) {
index 84e5007..579be48 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dhclient.c,v 1.460 2017/07/08 00:36:10 krw Exp $      */
+/*     $OpenBSD: dhclient.c,v 1.461 2017/07/08 20:38:31 krw Exp $      */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -1187,7 +1187,7 @@ packet_to_lease(struct interface_info *ifi, struct option_data *options)
        struct dhcp_packet *packet = &ifi->recv_packet;
        char ifname[IF_NAMESIZE];
        struct client_lease *lease;
-       char *pretty, *buf;
+       char *pretty, *buf, *name;
        int i;
 
        lease = calloc(1, sizeof(struct client_lease));
@@ -1200,8 +1200,8 @@ packet_to_lease(struct interface_info *ifi, struct option_data *options)
        for (i = 0; i < DHO_COUNT; i++) {
                if (options[i].len == 0)
                        continue;
-               if (!unknown_ok && strncmp("option-",
-                   dhcp_options[i].name, 7) != 0) {
+               name = code_to_name(i);
+               if (!unknown_ok && strncmp("option-", name, 7) != 0) {
                        log_warnx("lease declined: unknown option %d", i);
                        goto decline;
                }
@@ -1215,7 +1215,7 @@ packet_to_lease(struct interface_info *ifi, struct option_data *options)
                            options[i].len);
                        if (buf == NULL || !res_hnok_list(buf)) {
                                log_warnx("Ignoring %s in offer: invalid host "
-                                   "name(s)", dhcp_options[i].name);
+                                   "name(s)", name);
                                continue;
                        }
                        break;
@@ -1228,7 +1228,7 @@ packet_to_lease(struct interface_info *ifi, struct option_data *options)
                         */
                        if (!res_hnok_list(pretty)) {
                                log_warnx("Ignoring %s in offer: invalid host "
-                                   "name(s)", dhcp_options[i].name);
+                                   "name(s)", name);
                                continue;
                        }
                        break;
@@ -1236,7 +1236,7 @@ packet_to_lease(struct interface_info *ifi, struct option_data *options)
                case DHO_NIS_DOMAIN:
                        if (!res_hnok(pretty)) {
                                log_warnx("Ignoring %s in offer: invalid host "
-                                   "name", dhcp_options[i].name);
+                                   "name", name);
                                continue;
                        }
                        break;
@@ -1253,8 +1253,9 @@ packet_to_lease(struct interface_info *ifi, struct option_data *options)
         */
        for (i = 0; i < config->required_option_count; i++) {
                if (!lease->options[config->required_options[i]].len) {
+                       name = code_to_name(i);
                        log_warnx("lease declined: %s required but missing",
-                           dhcp_options[i].name);
+                           name);
                        goto decline;
                }
        }
@@ -1829,12 +1830,12 @@ append_statement(char *string, size_t sz, char *s1, char *s2)
 }
 
 char *
-lease_as_string(char *name, char *type, struct client_lease *lease)
+lease_as_string(char *ifname, char *type, struct client_lease *lease)
 {
        static char string[8192];
        char timebuf[27];       /* to hold "6 2017/04/08 05:47:50 UTC;" */
        struct option_data *opt;
-       char *buf;
+       char *buf, *name;
        size_t rslt;
        int i;
 
@@ -1844,7 +1845,7 @@ lease_as_string(char *name, char *type, struct client_lease *lease)
        strlcat(string, " {\n", sizeof(string));
        strlcat(string, BOOTP_LEASE(lease) ? "  bootp;\n" : "", sizeof(string));
 
-       buf = pretty_print_string(name, strlen(name), 1);
+       buf = pretty_print_string(ifname, strlen(ifname), 1);
        if (buf == NULL)
                return (NULL);
        append_statement(string, sizeof(string), "  interface ", buf);
@@ -1880,12 +1881,13 @@ lease_as_string(char *name, char *type, struct client_lease *lease)
                opt = &lease->options[i];
                if (opt->len == 0)
                        continue;
+               name = code_to_name(i);
 
                buf = pretty_print_option(i, opt, 1);
                if (buf == NULL)
                        return (NULL);
                strlcat(string, "  option ", sizeof(string));
-               strlcat(string, dhcp_options[i].name, sizeof(string));
+               strlcat(string, name, sizeof(string));
                append_statement(string, sizeof(string), " ", buf);
        }
 
@@ -2367,10 +2369,7 @@ apply_ignore_list(char *ignore_list)
                if (*p == '\0')
                        continue;
 
-               for (i = 1; i < DHO_END; i++)
-                       if (!strcasecmp(dhcp_options[i].name, p))
-                               break;
-
+               i = name_to_code(p);
                if (i == DHO_END) {
                        log_info("Invalid option name: '%s'", p);
                        return;
index dbdee34..45d504b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dhcpd.h,v 1.208 2017/07/08 00:36:10 krw Exp $ */
+/*     $OpenBSD: dhcpd.h,v 1.209 2017/07/08 20:38:31 krw Exp $ */
 
 /*
  * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
 #define        INTERNALSIG     INT_MAX
 #define DB_TIMEFMT     "%w %Y/%m/%d %T UTC"
 
-struct option {
-       char *name;
-       char *format;
-};
-
 struct option_data {
        unsigned int     len;
        uint8_t         *data;
@@ -176,6 +171,9 @@ char *pretty_print_domain_search(unsigned char *, size_t);
 char *pretty_print_string(unsigned char *, size_t, int);
 char *pretty_print_classless_routes(unsigned char *, size_t);
 struct option_data *unpack_options(struct dhcp_packet *);
+char *code_to_name(int);
+char *code_to_format(int);
+int name_to_code(char *);
 
 /* conflex.c */
 extern int lexline, lexchar;
@@ -213,9 +211,6 @@ int interface_status(char *);
 void get_hw_address(struct interface_info *);
 void sendhup(void);
 
-/* tables.c */
-extern const struct option dhcp_options[DHO_COUNT];
-
 /* dhclient.c */
 extern char *path_dhclient_conf;
 extern char *path_dhclient_db;
index 1a2c572..c0309e9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.c,v 1.96 2017/07/08 00:36:10 krw Exp $        */
+/*     $OpenBSD: options.c,v 1.97 2017/07/08 20:38:31 krw Exp $        */
 
 /* DHCP options parsing and reassembly. */
 
 int parse_option_buffer(struct option_data *, unsigned char *, int);
 int expand_search_domain_name(unsigned char *, size_t, int *, unsigned char *);
 
+/*
+ * DHCP Option names, formats and codes, from RFC1533.
+ *
+ * Format codes:
+ *
+ * e - end of data
+ * I - IP address
+ * l - 32-bit signed integer
+ * L - 32-bit unsigned integer
+ * S - 16-bit unsigned integer
+ * B - 8-bit unsigned integer
+ * t - ASCII text
+ * f - flag (true or false)
+ * A - array of whatever precedes (e.g., IA means array of IP addresses)
+ * C - CIDR description
+ */
+
+static const struct {
+       char *name;
+       char *format;
+} dhcp_options[DHO_COUNT] = {
+       /*   0 */ { "pad", "" },
+       /*   1 */ { "subnet-mask", "I" },
+       /*   2 */ { "time-offset", "l" },
+       /*   3 */ { "routers", "IA" },
+       /*   4 */ { "time-servers", "IA" },
+       /*   5 */ { "ien116-name-servers", "IA" },
+       /*   6 */ { "domain-name-servers", "IA" },
+       /*   7 */ { "log-servers", "IA" },
+       /*   8 */ { "cookie-servers", "IA" },
+       /*   9 */ { "lpr-servers", "IA" },
+       /*  10 */ { "impress-servers", "IA" },
+       /*  11 */ { "resource-location-servers", "IA" },
+       /*  12 */ { "host-name", "t" },
+       /*  13 */ { "boot-size", "S" },
+       /*  14 */ { "merit-dump", "t" },
+       /*  15 */ { "domain-name", "t" },
+       /*  16 */ { "swap-server", "I" },
+       /*  17 */ { "root-path", "t" },
+       /*  18 */ { "extensions-path", "t" },
+       /*  19 */ { "ip-forwarding", "f" },
+       /*  20 */ { "non-local-source-routing", "f" },
+       /*  21 */ { "policy-filter", "IIA" },
+       /*  22 */ { "max-dgram-reassembly", "S" },
+       /*  23 */ { "default-ip-ttl", "B" },
+       /*  24 */ { "path-mtu-aging-timeout", "L" },
+       /*  25 */ { "path-mtu-plateau-table", "SA" },
+       /*  26 */ { "interface-mtu", "S" },
+       /*  27 */ { "all-subnets-local", "f" },
+       /*  28 */ { "broadcast-address", "I" },
+       /*  29 */ { "perform-mask-discovery", "f" },
+       /*  30 */ { "mask-supplier", "f" },
+       /*  31 */ { "router-discovery", "f" },
+       /*  32 */ { "router-solicitation-address", "I" },
+       /*  33 */ { "static-routes", "IIA" },
+       /*  34 */ { "trailer-encapsulation", "f" },
+       /*  35 */ { "arp-cache-timeout", "L" },
+       /*  36 */ { "ieee802-3-encapsulation", "f" },
+       /*  37 */ { "default-tcp-ttl", "B" },
+       /*  38 */ { "tcp-keepalive-interval", "L" },
+       /*  39 */ { "tcp-keepalive-garbage", "f" },
+       /*  40 */ { "nis-domain", "t" },
+       /*  41 */ { "nis-servers", "IA" },
+       /*  42 */ { "ntp-servers", "IA" },
+       /*  43 */ { "vendor-encapsulated-options", "X" },
+       /*  44 */ { "netbios-name-servers", "IA" },
+       /*  45 */ { "netbios-dd-server", "IA" },
+       /*  46 */ { "netbios-node-type", "B" },
+       /*  47 */ { "netbios-scope", "t" },
+       /*  48 */ { "font-servers", "IA" },
+       /*  49 */ { "x-display-manager", "IA" },
+       /*  50 */ { "dhcp-requested-address", "I" },
+       /*  51 */ { "dhcp-lease-time", "L" },
+       /*  52 */ { "dhcp-option-overload", "B" },
+       /*  53 */ { "dhcp-message-type", "B" },
+       /*  54 */ { "dhcp-server-identifier", "I" },
+       /*  55 */ { "dhcp-parameter-request-list", "BA" },
+       /*  56 */ { "dhcp-message", "t" },
+       /*  57 */ { "dhcp-max-message-size", "S" },
+       /*  58 */ { "dhcp-renewal-time", "L" },
+       /*  59 */ { "dhcp-rebinding-time", "L" },
+       /*  60 */ { "dhcp-class-identifier", "t" },
+       /*  61 */ { "dhcp-client-identifier", "X" },
+       /*  62 */ { NULL, NULL },
+       /*  63 */ { NULL, NULL },
+       /*  64 */ { "nisplus-domain", "t" },
+       /*  65 */ { "nisplus-servers", "IA" },
+       /*  66 */ { "tftp-server-name", "t" },
+       /*  67 */ { "bootfile-name", "t" },
+       /*  68 */ { "mobile-ip-home-agent", "IA" },
+       /*  69 */ { "smtp-server", "IA" },
+       /*  70 */ { "pop-server", "IA" },
+       /*  71 */ { "nntp-server", "IA" },
+       /*  72 */ { "www-server", "IA" },
+       /*  73 */ { "finger-server", "IA" },
+       /*  74 */ { "irc-server", "IA" },
+       /*  75 */ { "streettalk-server", "IA" },
+       /*  76 */ { "streettalk-directory-assistance-server", "IA" },
+       /*  77 */ { "user-class", "t" },
+       /*  78 */ { NULL, NULL },
+       /*  79 */ { NULL, NULL },
+       /*  80 */ { NULL, NULL },
+       /*  81 */ { NULL, NULL },
+       /*  82 */ { "relay-agent-information", "X" },
+       /*  83 */ { NULL, NULL },
+       /*  84 */ { NULL, NULL },
+       /*  85 */ { "nds-servers", "IA" },
+       /*  86 */ { "nds-tree-name", "X" },
+       /*  87 */ { "nds-context", "X" },
+       /*  88 */ { NULL, NULL },
+       /*  89 */ { NULL, NULL },
+       /*  90 */ { NULL, NULL },
+       /*  91 */ { NULL, NULL },
+       /*  92 */ { NULL, NULL },
+       /*  93 */ { NULL, NULL },
+       /*  94 */ { NULL, NULL },
+       /*  95 */ { NULL, NULL },
+       /*  96 */ { NULL, NULL },
+       /*  97 */ { NULL, NULL },
+       /*  98 */ { NULL, NULL },
+       /*  99 */ { NULL, NULL },
+       /* 100 */ { NULL, NULL },
+       /* 101 */ { NULL, NULL },
+       /* 102 */ { NULL, NULL },
+       /* 103 */ { NULL, NULL },
+       /* 104 */ { NULL, NULL },
+       /* 105 */ { NULL, NULL },
+       /* 106 */ { NULL, NULL },
+       /* 107 */ { NULL, NULL },
+       /* 108 */ { NULL, NULL },
+       /* 109 */ { NULL, NULL },
+       /* 110 */ { NULL, NULL },
+       /* 111 */ { NULL, NULL },
+       /* 112 */ { NULL, NULL },
+       /* 113 */ { NULL, NULL },
+       /* 114 */ { NULL, NULL },
+       /* 115 */ { NULL, NULL },
+       /* 116 */ { NULL, NULL },
+       /* 117 */ { NULL, NULL },
+       /* 118 */ { NULL, NULL },
+       /* 119 */ { "domain-search", "X" },
+       /* 120 */ { NULL, NULL },
+       /* 121 */ { "classless-static-routes", "CIA" },
+       /* 122 */ { NULL, NULL },
+       /* 123 */ { NULL, NULL },
+       /* 124 */ { NULL, NULL },
+       /* 125 */ { NULL, NULL },
+       /* 126 */ { NULL, NULL },
+       /* 127 */ { NULL, NULL },
+       /* 128 */ { NULL, NULL },
+       /* 129 */ { NULL, NULL },
+       /* 130 */ { NULL, NULL },
+       /* 131 */ { NULL, NULL },
+       /* 132 */ { NULL, NULL },
+       /* 133 */ { NULL, NULL },
+       /* 134 */ { NULL, NULL },
+       /* 135 */ { NULL, NULL },
+       /* 136 */ { NULL, NULL },
+       /* 137 */ { NULL, NULL },
+       /* 138 */ { NULL, NULL },
+       /* 139 */ { NULL, NULL },
+       /* 140 */ { NULL, NULL },
+       /* 141 */ { NULL, NULL },
+       /* 142 */ { NULL, NULL },
+       /* 143 */ { NULL, NULL },
+       /* 144 */ { "tftp-config-file", "t" },
+       /* 145 */ { NULL, NULL },
+       /* 146 */ { NULL, NULL },
+       /* 147 */ { NULL, NULL },
+       /* 148 */ { NULL, NULL },
+       /* 149 */ { NULL, NULL },
+       /* 150 */ { "voip-configuration-server", "IA" },
+       /* 151 */ { NULL, NULL },
+       /* 152 */ { NULL, NULL },
+       /* 153 */ { NULL, NULL },
+       /* 154 */ { NULL, NULL },
+       /* 155 */ { NULL, NULL },
+       /* 156 */ { NULL, NULL },
+       /* 157 */ { NULL, NULL },
+       /* 158 */ { NULL, NULL },
+       /* 159 */ { NULL, NULL },
+       /* 160 */ { NULL, NULL },
+       /* 161 */ { NULL, NULL },
+       /* 162 */ { NULL, NULL },
+       /* 163 */ { NULL, NULL },
+       /* 164 */ { NULL, NULL },
+       /* 165 */ { NULL, NULL },
+       /* 166 */ { NULL, NULL },
+       /* 167 */ { NULL, NULL },
+       /* 168 */ { NULL, NULL },
+       /* 169 */ { NULL, NULL },
+       /* 170 */ { NULL, NULL },
+       /* 171 */ { NULL, NULL },
+       /* 172 */ { NULL, NULL },
+       /* 173 */ { NULL, NULL },
+       /* 174 */ { NULL, NULL },
+       /* 175 */ { NULL, NULL },
+       /* 176 */ { NULL, NULL },
+       /* 177 */ { NULL, NULL },
+       /* 178 */ { NULL, NULL },
+       /* 179 */ { NULL, NULL },
+       /* 180 */ { NULL, NULL },
+       /* 181 */ { NULL, NULL },
+       /* 182 */ { NULL, NULL },
+       /* 183 */ { NULL, NULL },
+       /* 184 */ { NULL, NULL },
+       /* 185 */ { NULL, NULL },
+       /* 186 */ { NULL, NULL },
+       /* 187 */ { NULL, NULL },
+       /* 188 */ { NULL, NULL },
+       /* 189 */ { NULL, NULL },
+       /* 190 */ { NULL, NULL },
+       /* 191 */ { NULL, NULL },
+       /* 192 */ { NULL, NULL },
+       /* 193 */ { NULL, NULL },
+       /* 194 */ { NULL, NULL },
+       /* 195 */ { NULL, NULL },
+       /* 196 */ { NULL, NULL },
+       /* 197 */ { NULL, NULL },
+       /* 198 */ { NULL, NULL },
+       /* 199 */ { NULL, NULL },
+       /* 200 */ { NULL, NULL },
+       /* 201 */ { NULL, NULL },
+       /* 202 */ { NULL, NULL },
+       /* 203 */ { NULL, NULL },
+       /* 204 */ { NULL, NULL },
+       /* 205 */ { NULL, NULL },
+       /* 206 */ { NULL, NULL },
+       /* 207 */ { NULL, NULL },
+       /* 208 */ { NULL, NULL },
+       /* 209 */ { NULL, NULL },
+       /* 210 */ { NULL, NULL },
+       /* 211 */ { NULL, NULL },
+       /* 212 */ { NULL, NULL },
+       /* 213 */ { NULL, NULL },
+       /* 214 */ { NULL, NULL },
+       /* 215 */ { NULL, NULL },
+       /* 216 */ { NULL, NULL },
+       /* 217 */ { NULL, NULL },
+       /* 218 */ { NULL, NULL },
+       /* 219 */ { NULL, NULL },
+       /* 220 */ { NULL, NULL },
+       /* 221 */ { NULL, NULL },
+       /* 222 */ { NULL, NULL },
+       /* 223 */ { NULL, NULL },
+       /* 224 */ { NULL, NULL },
+       /* 225 */ { NULL, NULL },
+       /* 226 */ { NULL, NULL },
+       /* 227 */ { NULL, NULL },
+       /* 228 */ { NULL, NULL },
+       /* 229 */ { NULL, NULL },
+       /* 230 */ { NULL, NULL },
+       /* 231 */ { NULL, NULL },
+       /* 232 */ { NULL, NULL },
+       /* 233 */ { NULL, NULL },
+       /* 234 */ { NULL, NULL },
+       /* 235 */ { NULL, NULL },
+       /* 236 */ { NULL, NULL },
+       /* 237 */ { NULL, NULL },
+       /* 238 */ { NULL, NULL },
+       /* 239 */ { NULL, NULL },
+       /* 240 */ { NULL, NULL },
+       /* 241 */ { NULL, NULL },
+       /* 242 */ { NULL, NULL },
+       /* 243 */ { NULL, NULL },
+       /* 244 */ { NULL, NULL },
+       /* 245 */ { NULL, NULL },
+       /* 246 */ { NULL, NULL },
+       /* 247 */ { NULL, NULL },
+       /* 248 */ { NULL, NULL },
+       /* 249 */ { "classless-ms-static-routes", "CIA" },
+       /* 250 */ { NULL, NULL },
+       /* 251 */ { NULL, NULL },
+       /* 252 */ { "autoproxy-script", "t" },
+       /* 253 */ { NULL, NULL },
+       /* 254 */ { NULL, NULL },
+       /* 255 */ { "option-end", "e" },
+};
+
+char *
+code_to_name(int code)
+{
+       static char      unknown[11];   /* "option-NNN" */
+       int              ret;
+
+       if (code < 0 || code >= DHO_COUNT)
+               return "";
+
+       if (dhcp_options[code].name != NULL)
+               return dhcp_options[code].name;
+
+       ret = snprintf(unknown, sizeof(unknown), "option-%d", code);
+       if (ret == -1 || ret >= (int)sizeof(unknown))
+               return "";
+
+       return unknown;
+}
+
+int
+name_to_code(char *name)
+{
+       char    unknown[11];    /* "option-NNN" */
+       int     code, ret;
+
+       for (code = 1; code < DHO_END; code++) {
+               if (dhcp_options[code].name == NULL) {
+                       ret = snprintf(unknown, sizeof(unknown), "option-%d",
+                           code);
+                       if (ret == -1 || ret >= (int)sizeof(unknown))
+                               return DHO_END;
+                       if (strcasecmp(unknown, name) == 0)
+                               return code;
+               } else if (strcasecmp(dhcp_options[code].name, name) == 0) {
+                       return code;
+               }
+       }
+
+       return DHO_END;
+}
+
+char *
+code_to_format(int code)
+{
+       if (code < 0 || code >= DHO_COUNT)
+               return "";
+
+       if (dhcp_options[code].format == NULL)
+               return "X";
+
+       return dhcp_options[code].format;
+}
+
 /*
  * Parse options out of the specified buffer, storing addresses of
  * option values in options. Return 0 if errors, 1 if not.
@@ -72,8 +404,9 @@ int
 parse_option_buffer(struct option_data *options, unsigned char *buffer,
     int length)
 {
-       unsigned char *s, *t, *end = buffer + length;
-       int len, code;
+       unsigned char   *s, *t, *end = buffer + length;
+       char            *name, *fmt;
+       int              len, code;
 
        for (s = buffer; *s != DHO_END && s < end; ) {
                code = s[0];
@@ -84,6 +417,9 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                        continue;
                }
 
+               name = code_to_name(code);
+               fmt = code_to_format(code);
+
                /*
                 * All options other than DHO_PAD and DHO_END have a one-byte
                 * length field. It could be 0! Make sure that the length byte
@@ -95,12 +431,11 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                                ; /* option data is all there. */
                        } else {
                                log_warnx("option %s (%d) larger than buffer.",
-                                   dhcp_options[code].name, len);
+                                   name, len);
                                return (0);
                        }
                } else {
-                       log_warnx("option %s has no length field.",
-                           dhcp_options[code].name);
+                       log_warnx("option %s has no length field.", name);
                        return (0);
                }
 
@@ -111,7 +446,7 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                 * a trailing NULL; however, the receiver of such options
                 * MUST be prepared to delete trailing nulls if they exist."
                 */
-               if (dhcp_options[code].format[0] == 't') {
+               if (fmt[0] == 't') {
                        while (len > 0 && s[len + 1] == '\0')
                                len--;
                }
@@ -123,7 +458,7 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                if (!options[code].data) {
                        if (!(t = calloc(1, len + 1)))
                                fatalx("Can't allocate storage for option %s.",
-                                   dhcp_options[code].name);
+                                   name);
                        /*
                         * Copy and NUL-terminate the option (in case
                         * it's an ASCII string).
@@ -140,7 +475,7 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
                        t = calloc(1, len + options[code].len + 1);
                        if (!t)
                                fatalx("Can't expand storage for option %s.",
-                                   dhcp_options[code].name);
+                                   name);
                        memcpy(t, options[code].data, options[code].len);
                        memcpy(t + options[code].len, &s[2], len);
                        options[code].len += len;
@@ -419,7 +754,7 @@ pretty_print_option(unsigned int code, struct option_data *option,
        struct in_addr   foo;
        unsigned char   *data = option->data;
        unsigned char   *dp = data;
-       char            *op = optbuf, *buf;
+       char            *op = optbuf, *buf, *name, *fmt;
        int              hunksize = 0, numhunk = -1, numelem = 0;
        int              i, j, k, opleft = sizeof(optbuf);
        int              len = option->len;
@@ -455,26 +790,26 @@ pretty_print_option(unsigned int code, struct option_data *option,
                break;
        }
 
+       name = code_to_name(code);
+       fmt = code_to_format(code);
+
        /* Figure out the size of the data. */
-       for (i = 0; dhcp_options[code].format[i]; i++) {
+       for (i = 0; fmt[i]; i++) {
                if (!numhunk) {
                        log_warnx("%s: Excess information in format string: "
-                           "%s", dhcp_options[code].name,
-                           &(dhcp_options[code].format[i]));
+                           "%s", name, &fmt[i]);
                        goto done;
                }
                numelem++;
-               fmtbuf[i] = dhcp_options[code].format[i];
-               switch (dhcp_options[code].format[i]) {
+               fmtbuf[i] = fmt[i];
+               switch (fmt[i]) {
                case 'A':
                        --numelem;
                        fmtbuf[i] = 0;
                        numhunk = 0;
                        if (hunksize == 0) {
                                log_warnx("%s: no size indicator before A"
-                                   " in format string: %s",
-                                   dhcp_options[code].name,
-                                   dhcp_options[code].format);
+                                   " in format string: %s", name, fmt);
                                goto done;
                        }
                        break;
@@ -512,23 +847,22 @@ pretty_print_option(unsigned int code, struct option_data *option,
                case 'e':
                        break;
                default:
-                       log_warnx("%s: garbage in format string: %s",
-                           dhcp_options[code].name,
-                           &(dhcp_options[code].format[i]));
+                       log_warnx("%s: garbage in format string: %s", name,
+                           &fmt[i]);
                        goto done;
                }
        }
 
        /* Check for too few bytes. */
        if (hunksize > len) {
-               log_warnx("%s: expecting at least %d bytes; got %d",
-                   dhcp_options[code].name, hunksize, len);
+               log_warnx("%s: expecting at least %d bytes; got %d", name,
+                   hunksize, len);
                goto done;
        }
        /* Check for too many bytes. */
        if (numhunk == -1 && hunksize < len) {
-               log_warnx("%s: expecting only %d bytes: got %d",
-                   dhcp_options[code].name, hunksize, len);
+               log_warnx("%s: expecting only %d bytes: got %d", name,
+                   hunksize, len);
                goto done;
        }
 
@@ -537,8 +871,8 @@ pretty_print_option(unsigned int code, struct option_data *option,
                numhunk = len / hunksize;
        /* See if we got an exact number of hunks. */
        if (numhunk > 0 && numhunk * hunksize != len) {
-               log_warnx("%s: expecting %d bytes: got %d",
-                   dhcp_options[code].name, numhunk * hunksize, len);
+               log_warnx("%s: expecting %d bytes: got %d", name,
+                   numhunk * hunksize, len);
                goto done;
        }