17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5d04ccbb3Scarlsonj * Common Development and Distribution License (the "License").
6d04ccbb3Scarlsonj * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
224b56a003SDaniel Anderson * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <string.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <stdarg.h>
327c478bd9Sstevel@tonic-gate #include <limits.h>
337c478bd9Sstevel@tonic-gate #include <ctype.h>
347c478bd9Sstevel@tonic-gate #include <libgen.h>
357c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
367c478bd9Sstevel@tonic-gate #include <sys/socket.h>
37d04ccbb3Scarlsonj #include <net/if_arp.h>
387c478bd9Sstevel@tonic-gate #include <netinet/in.h>
397c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate #include <libinetutil.h>
42d04ccbb3Scarlsonj #include <libdlpi.h>
43d04ccbb3Scarlsonj #include <netinet/dhcp6.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #include "dhcp_symbol.h"
467c478bd9Sstevel@tonic-gate #include "dhcp_inittab.h"
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate static void inittab_msg(const char *, ...);
497c478bd9Sstevel@tonic-gate static uchar_t category_to_code(const char *);
507c478bd9Sstevel@tonic-gate static boolean_t encode_number(uint8_t, uint8_t, boolean_t, uint8_t,
517c478bd9Sstevel@tonic-gate const char *, uint8_t *, int *);
527c478bd9Sstevel@tonic-gate static boolean_t decode_number(uint8_t, uint8_t, boolean_t, uint8_t,
537c478bd9Sstevel@tonic-gate const uint8_t *, char *, int *);
547c478bd9Sstevel@tonic-gate static dhcp_symbol_t *inittab_lookup(uchar_t, char, const char *, int32_t,
557c478bd9Sstevel@tonic-gate size_t *);
567c478bd9Sstevel@tonic-gate static dsym_category_t itabcode_to_dsymcode(uchar_t);
577c478bd9Sstevel@tonic-gate static boolean_t parse_entry(char *, char **);
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate * forward declaration of our internal inittab_table[]. too bulky to put
617c478bd9Sstevel@tonic-gate * up front -- check the end of this file for its definition.
62d04ccbb3Scarlsonj *
63d04ccbb3Scarlsonj * Note: we have only an IPv4 version here. The inittab_verify() function is
64d04ccbb3Scarlsonj * used by the DHCP server and manager. We'll need a new function if the
65d04ccbb3Scarlsonj * server is extended to DHCPv6.
667c478bd9Sstevel@tonic-gate */
677c478bd9Sstevel@tonic-gate static dhcp_symbol_t inittab_table[];
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate * the number of fields in the inittab and names for the fields. note that
717c478bd9Sstevel@tonic-gate * this order is meaningful to parse_entry(); other functions should just
727c478bd9Sstevel@tonic-gate * use them as indexes into the array returned from parse_entry().
737c478bd9Sstevel@tonic-gate */
747c478bd9Sstevel@tonic-gate #define ITAB_FIELDS 7
757c478bd9Sstevel@tonic-gate enum { ITAB_NAME, ITAB_CODE, ITAB_TYPE, ITAB_GRAN, ITAB_MAX, ITAB_CONS,
767c478bd9Sstevel@tonic-gate ITAB_CAT };
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate * the category_map_entry_t is used to map the inittab category codes to
807c478bd9Sstevel@tonic-gate * the dsym codes. the reason the codes are different is that the inittab
817c478bd9Sstevel@tonic-gate * needs to have the codes be ORable such that queries can retrieve more
827c478bd9Sstevel@tonic-gate * than one category at a time. this map is also used to map the inittab
837c478bd9Sstevel@tonic-gate * string representation of a category to its numerical code.
847c478bd9Sstevel@tonic-gate */
857c478bd9Sstevel@tonic-gate typedef struct category_map_entry {
867c478bd9Sstevel@tonic-gate dsym_category_t cme_dsymcode;
877c478bd9Sstevel@tonic-gate char *cme_name;
887c478bd9Sstevel@tonic-gate uchar_t cme_itabcode;
897c478bd9Sstevel@tonic-gate } category_map_entry_t;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate static category_map_entry_t category_map[] = {
927c478bd9Sstevel@tonic-gate { DSYM_STANDARD, "STANDARD", ITAB_CAT_STANDARD },
937c478bd9Sstevel@tonic-gate { DSYM_FIELD, "FIELD", ITAB_CAT_FIELD },
947c478bd9Sstevel@tonic-gate { DSYM_INTERNAL, "INTERNAL", ITAB_CAT_INTERNAL },
957c478bd9Sstevel@tonic-gate { DSYM_VENDOR, "VENDOR", ITAB_CAT_VENDOR },
967c478bd9Sstevel@tonic-gate { DSYM_SITE, "SITE", ITAB_CAT_SITE }
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate * inittab_load(): returns all inittab entries with the specified criteria
1017c478bd9Sstevel@tonic-gate *
1027c478bd9Sstevel@tonic-gate * input: uchar_t: the categories the consumer is interested in
1037c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1047c478bd9Sstevel@tonic-gate * size_t *: set to the number of entries returned
1057c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: an array of dynamically allocated entries
1067c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1077c478bd9Sstevel@tonic-gate */
108d04ccbb3Scarlsonj
1097c478bd9Sstevel@tonic-gate dhcp_symbol_t *
inittab_load(uchar_t categories,char consumer,size_t * n_entries)1107c478bd9Sstevel@tonic-gate inittab_load(uchar_t categories, char consumer, size_t *n_entries)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate return (inittab_lookup(categories, consumer, NULL, -1, n_entries));
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate * inittab_getbyname(): returns an inittab entry with the specified criteria
1177c478bd9Sstevel@tonic-gate *
1187c478bd9Sstevel@tonic-gate * input: int: the categories the consumer is interested in
1197c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1207c478bd9Sstevel@tonic-gate * char *: the name of the inittab entry the consumer wants
1217c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure
1227c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1237c478bd9Sstevel@tonic-gate */
124d04ccbb3Scarlsonj
1257c478bd9Sstevel@tonic-gate dhcp_symbol_t *
inittab_getbyname(uchar_t categories,char consumer,const char * name)1267c478bd9Sstevel@tonic-gate inittab_getbyname(uchar_t categories, char consumer, const char *name)
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate return (inittab_lookup(categories, consumer, name, -1, NULL));
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * inittab_getbycode(): returns an inittab entry with the specified criteria
1337c478bd9Sstevel@tonic-gate *
1347c478bd9Sstevel@tonic-gate * input: uchar_t: the categories the consumer is interested in
1357c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1367c478bd9Sstevel@tonic-gate * uint16_t: the code of the inittab entry the consumer wants
1377c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure
1387c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1397c478bd9Sstevel@tonic-gate */
140d04ccbb3Scarlsonj
1417c478bd9Sstevel@tonic-gate dhcp_symbol_t *
inittab_getbycode(uchar_t categories,char consumer,uint16_t code)1427c478bd9Sstevel@tonic-gate inittab_getbycode(uchar_t categories, char consumer, uint16_t code)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate return (inittab_lookup(categories, consumer, NULL, code, NULL));
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate /*
1487c478bd9Sstevel@tonic-gate * inittab_lookup(): returns inittab entries with the specified criteria
1497c478bd9Sstevel@tonic-gate *
1507c478bd9Sstevel@tonic-gate * input: uchar_t: the categories the consumer is interested in
1517c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1527c478bd9Sstevel@tonic-gate * const char *: the name of the entry the caller is interested
1537c478bd9Sstevel@tonic-gate * in, or NULL if the caller doesn't care
1547c478bd9Sstevel@tonic-gate * int32_t: the code the caller is interested in, or -1 if the
1557c478bd9Sstevel@tonic-gate * caller doesn't care
1567c478bd9Sstevel@tonic-gate * size_t *: set to the number of entries returned
1577c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: dynamically allocated dhcp_symbol structures
1587c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1597c478bd9Sstevel@tonic-gate */
160d04ccbb3Scarlsonj
1617c478bd9Sstevel@tonic-gate static dhcp_symbol_t *
inittab_lookup(uchar_t categories,char consumer,const char * name,int32_t code,size_t * n_entriesp)1627c478bd9Sstevel@tonic-gate inittab_lookup(uchar_t categories, char consumer, const char *name,
1637c478bd9Sstevel@tonic-gate int32_t code, size_t *n_entriesp)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate FILE *inittab_fp;
1667c478bd9Sstevel@tonic-gate dhcp_symbol_t *new_entries, *entries = NULL;
1677c478bd9Sstevel@tonic-gate dhcp_symbol_t entry;
1687c478bd9Sstevel@tonic-gate char buffer[ITAB_MAX_LINE_LEN];
1697c478bd9Sstevel@tonic-gate char *fields[ITAB_FIELDS];
1707c478bd9Sstevel@tonic-gate unsigned long line = 0;
1717c478bd9Sstevel@tonic-gate size_t i, n_entries = 0;
172d04ccbb3Scarlsonj const char *inittab_path;
1737c478bd9Sstevel@tonic-gate uchar_t category_code;
1747c478bd9Sstevel@tonic-gate dsym_cdtype_t type;
1757c478bd9Sstevel@tonic-gate
176d04ccbb3Scarlsonj if (categories & ITAB_CAT_V6) {
177d04ccbb3Scarlsonj inittab_path = getenv("DHCP_INITTAB6_PATH");
178d04ccbb3Scarlsonj if (inittab_path == NULL)
179d04ccbb3Scarlsonj inittab_path = ITAB_INITTAB6_PATH;
180d04ccbb3Scarlsonj } else {
1817c478bd9Sstevel@tonic-gate inittab_path = getenv("DHCP_INITTAB_PATH");
1827c478bd9Sstevel@tonic-gate if (inittab_path == NULL)
1837c478bd9Sstevel@tonic-gate inittab_path = ITAB_INITTAB_PATH;
184d04ccbb3Scarlsonj }
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate inittab_fp = fopen(inittab_path, "r");
1877c478bd9Sstevel@tonic-gate if (inittab_fp == NULL) {
1887c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: fopen: %s: %s",
189d04ccbb3Scarlsonj inittab_path, strerror(errno));
1907c478bd9Sstevel@tonic-gate return (NULL);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate (void) bufsplit(",\n", 0, NULL);
1947c478bd9Sstevel@tonic-gate while (fgets(buffer, sizeof (buffer), inittab_fp) != NULL) {
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate line++;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate /*
1997c478bd9Sstevel@tonic-gate * make sure the string didn't overflow our buffer
2007c478bd9Sstevel@tonic-gate */
2017c478bd9Sstevel@tonic-gate if (strchr(buffer, '\n') == NULL) {
2027c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: too long, "
2037c478bd9Sstevel@tonic-gate "skipping", line);
2047c478bd9Sstevel@tonic-gate continue;
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate * skip `pure comment' lines
2097c478bd9Sstevel@tonic-gate */
2107c478bd9Sstevel@tonic-gate for (i = 0; buffer[i] != '\0'; i++)
2117c478bd9Sstevel@tonic-gate if (isspace(buffer[i]) == 0)
2127c478bd9Sstevel@tonic-gate break;
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate if (buffer[i] == ITAB_COMMENT_CHAR || buffer[i] == '\0')
2157c478bd9Sstevel@tonic-gate continue;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate /*
2187c478bd9Sstevel@tonic-gate * parse the entry out into fields.
2197c478bd9Sstevel@tonic-gate */
2207c478bd9Sstevel@tonic-gate if (parse_entry(buffer, fields) == B_FALSE) {
2217c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: syntax error, "
2227c478bd9Sstevel@tonic-gate "skipping", line);
2237c478bd9Sstevel@tonic-gate continue;
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /*
2277c478bd9Sstevel@tonic-gate * validate the values in the entries; skip if invalid.
2287c478bd9Sstevel@tonic-gate */
2297c478bd9Sstevel@tonic-gate if (atoi(fields[ITAB_GRAN]) > ITAB_GRAN_MAX) {
2307c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: granularity `%s'"
2317c478bd9Sstevel@tonic-gate " out of range, skipping", line, fields[ITAB_GRAN]);
2327c478bd9Sstevel@tonic-gate continue;
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate if (atoi(fields[ITAB_MAX]) > ITAB_MAX_MAX) {
2367c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: maximum `%s' "
2377c478bd9Sstevel@tonic-gate "out of range, skipping", line, fields[ITAB_MAX]);
2387c478bd9Sstevel@tonic-gate continue;
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate if (dsym_get_type_id(fields[ITAB_TYPE], &type, B_FALSE) !=
2427c478bd9Sstevel@tonic-gate DSYM_SUCCESS) {
2437c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: type `%s' "
2447c478bd9Sstevel@tonic-gate "is invalid, skipping", line, fields[ITAB_TYPE]);
2457c478bd9Sstevel@tonic-gate continue;
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * find out whether this entry of interest to our consumer,
2507c478bd9Sstevel@tonic-gate * and if so, throw it onto the set of entries we'll return.
2517c478bd9Sstevel@tonic-gate * check categories last since it's the most expensive check.
2527c478bd9Sstevel@tonic-gate */
2537c478bd9Sstevel@tonic-gate if (strchr(fields[ITAB_CONS], consumer) == NULL)
2547c478bd9Sstevel@tonic-gate continue;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate if (code != -1 && atoi(fields[ITAB_CODE]) != code)
2577c478bd9Sstevel@tonic-gate continue;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate if (name != NULL && strcasecmp(fields[ITAB_NAME], name) != 0)
2607c478bd9Sstevel@tonic-gate continue;
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate category_code = category_to_code(fields[ITAB_CAT]);
2637c478bd9Sstevel@tonic-gate if ((category_code & categories) == 0)
2647c478bd9Sstevel@tonic-gate continue;
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * looks like a match. allocate an entry and fill it in
2687c478bd9Sstevel@tonic-gate */
2697c478bd9Sstevel@tonic-gate new_entries = realloc(entries, (n_entries + 1) *
2707c478bd9Sstevel@tonic-gate sizeof (dhcp_symbol_t));
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate * if we run out of memory, might as well return what we can
2747c478bd9Sstevel@tonic-gate */
2757c478bd9Sstevel@tonic-gate if (new_entries == NULL) {
2767c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: ran out of memory "
2777c478bd9Sstevel@tonic-gate "allocating dhcp_symbol_t's");
2787c478bd9Sstevel@tonic-gate break;
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate entry.ds_max = atoi(fields[ITAB_MAX]);
2827c478bd9Sstevel@tonic-gate entry.ds_code = atoi(fields[ITAB_CODE]);
2837c478bd9Sstevel@tonic-gate entry.ds_type = type;
2847c478bd9Sstevel@tonic-gate entry.ds_gran = atoi(fields[ITAB_GRAN]);
2857c478bd9Sstevel@tonic-gate entry.ds_category = itabcode_to_dsymcode(category_code);
2867c478bd9Sstevel@tonic-gate entry.ds_classes.dc_cnt = 0;
2877c478bd9Sstevel@tonic-gate entry.ds_classes.dc_names = NULL;
2887c478bd9Sstevel@tonic-gate (void) strlcpy(entry.ds_name, fields[ITAB_NAME],
2897c478bd9Sstevel@tonic-gate sizeof (entry.ds_name));
290d04ccbb3Scarlsonj entry.ds_dhcpv6 = (categories & ITAB_CAT_V6) ? 1 : 0;
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate entries = new_entries;
2937c478bd9Sstevel@tonic-gate entries[n_entries++] = entry;
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate if (ferror(inittab_fp) != 0) {
2977c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: error on inittab stream");
2987c478bd9Sstevel@tonic-gate clearerr(inittab_fp);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate (void) fclose(inittab_fp);
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate if (n_entriesp != NULL)
3047c478bd9Sstevel@tonic-gate *n_entriesp = n_entries;
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate return (entries);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate /*
3107c478bd9Sstevel@tonic-gate * parse_entry(): parses an entry out into its constituent fields
3117c478bd9Sstevel@tonic-gate *
3127c478bd9Sstevel@tonic-gate * input: char *: the entry
3137c478bd9Sstevel@tonic-gate * char **: an array of ITAB_FIELDS length which contains
3147c478bd9Sstevel@tonic-gate * pointers into the entry on upon return
3157c478bd9Sstevel@tonic-gate * output: boolean_t: B_TRUE on success, B_FALSE on failure
3167c478bd9Sstevel@tonic-gate */
317d04ccbb3Scarlsonj
3187c478bd9Sstevel@tonic-gate static boolean_t
parse_entry(char * entry,char ** fields)3197c478bd9Sstevel@tonic-gate parse_entry(char *entry, char **fields)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate char *category, *spacep;
3227c478bd9Sstevel@tonic-gate size_t n_fields, i;
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate * due to a mistake made long ago, the first and second fields of
3267c478bd9Sstevel@tonic-gate * each entry are not separated by a comma, but rather by
3277c478bd9Sstevel@tonic-gate * whitespace -- have bufsplit() treat the two fields as one, then
3287c478bd9Sstevel@tonic-gate * pull them apart afterwards.
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate n_fields = bufsplit(entry, ITAB_FIELDS - 1, fields);
3317c478bd9Sstevel@tonic-gate if (n_fields != (ITAB_FIELDS - 1))
3327c478bd9Sstevel@tonic-gate return (B_FALSE);
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate * pull the first and second fields apart. this is complicated
3367c478bd9Sstevel@tonic-gate * since the first field can contain embedded whitespace (so we
3377c478bd9Sstevel@tonic-gate * must separate the two fields by the last span of whitespace).
3387c478bd9Sstevel@tonic-gate *
3397c478bd9Sstevel@tonic-gate * first, find the initial span of whitespace. if there isn't one,
3407c478bd9Sstevel@tonic-gate * then the entry is malformed.
3417c478bd9Sstevel@tonic-gate */
3427c478bd9Sstevel@tonic-gate category = strpbrk(fields[ITAB_NAME], " \t");
3437c478bd9Sstevel@tonic-gate if (category == NULL)
3447c478bd9Sstevel@tonic-gate return (B_FALSE);
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate /*
3477c478bd9Sstevel@tonic-gate * find the last span of whitespace.
3487c478bd9Sstevel@tonic-gate */
3497c478bd9Sstevel@tonic-gate do {
3507c478bd9Sstevel@tonic-gate while (isspace(*category))
3517c478bd9Sstevel@tonic-gate category++;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate spacep = strpbrk(category, " \t");
3547c478bd9Sstevel@tonic-gate if (spacep != NULL)
3557c478bd9Sstevel@tonic-gate category = spacep;
3567c478bd9Sstevel@tonic-gate } while (spacep != NULL);
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate * NUL-terminate the first byte of the last span of whitespace, so
3607c478bd9Sstevel@tonic-gate * that the first field doesn't have any residual trailing
3617c478bd9Sstevel@tonic-gate * whitespace.
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate spacep = category - 1;
3647c478bd9Sstevel@tonic-gate while (isspace(*spacep))
3657c478bd9Sstevel@tonic-gate spacep--;
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate if (spacep <= fields[0])
3687c478bd9Sstevel@tonic-gate return (B_FALSE);
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate *++spacep = '\0';
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate * remove any whitespace from the fields.
3747c478bd9Sstevel@tonic-gate */
3757c478bd9Sstevel@tonic-gate for (i = 0; i < n_fields; i++) {
3767c478bd9Sstevel@tonic-gate while (isspace(*fields[i]))
3777c478bd9Sstevel@tonic-gate fields[i]++;
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate fields[ITAB_CAT] = category;
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate return (B_TRUE);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate * inittab_verify(): verifies that a given inittab entry matches an internal
3867c478bd9Sstevel@tonic-gate * definition
3877c478bd9Sstevel@tonic-gate *
3887c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the inittab entry to verify
3897c478bd9Sstevel@tonic-gate * dhcp_symbol_t *: if non-NULL, a place to store the internal
3907c478bd9Sstevel@tonic-gate * inittab entry upon return
3917c478bd9Sstevel@tonic-gate * output: int: ITAB_FAILURE, ITAB_SUCCESS, or ITAB_UNKNOWN
392d04ccbb3Scarlsonj *
393d04ccbb3Scarlsonj * notes: IPv4 only
3947c478bd9Sstevel@tonic-gate */
395d04ccbb3Scarlsonj
3967c478bd9Sstevel@tonic-gate int
inittab_verify(const dhcp_symbol_t * inittab_ent,dhcp_symbol_t * internal_ent)397d04ccbb3Scarlsonj inittab_verify(const dhcp_symbol_t *inittab_ent, dhcp_symbol_t *internal_ent)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate unsigned int i;
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate for (i = 0; inittab_table[i].ds_name[0] != '\0'; i++) {
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate if (inittab_ent->ds_category != inittab_table[i].ds_category)
4047c478bd9Sstevel@tonic-gate continue;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate if (inittab_ent->ds_code == inittab_table[i].ds_code) {
4077c478bd9Sstevel@tonic-gate if (internal_ent != NULL)
4087c478bd9Sstevel@tonic-gate *internal_ent = inittab_table[i];
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate if (inittab_table[i].ds_type != inittab_ent->ds_type ||
4117c478bd9Sstevel@tonic-gate inittab_table[i].ds_gran != inittab_ent->ds_gran ||
4127c478bd9Sstevel@tonic-gate inittab_table[i].ds_max != inittab_ent->ds_max)
4137c478bd9Sstevel@tonic-gate return (ITAB_FAILURE);
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate return (ITAB_SUCCESS);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate return (ITAB_UNKNOWN);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /*
423d04ccbb3Scarlsonj * get_hw_type(): interpret ",hwtype" in the input string, as part of a DUID.
424d04ccbb3Scarlsonj * The hwtype string is optional, and must be 0-65535 if
425d04ccbb3Scarlsonj * present.
426d04ccbb3Scarlsonj *
427d04ccbb3Scarlsonj * input: char **: pointer to string pointer
428d04ccbb3Scarlsonj * int *: error return value
429d04ccbb3Scarlsonj * output: int: hardware type, or -1 for empty, or -2 for error.
430d04ccbb3Scarlsonj */
431d04ccbb3Scarlsonj
432d04ccbb3Scarlsonj static int
get_hw_type(char ** strp,int * ierrnop)433d04ccbb3Scarlsonj get_hw_type(char **strp, int *ierrnop)
434d04ccbb3Scarlsonj {
435d04ccbb3Scarlsonj char *str = *strp;
436d04ccbb3Scarlsonj ulong_t hwtype;
437d04ccbb3Scarlsonj
438d04ccbb3Scarlsonj if (*str++ != ',') {
439d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
440d04ccbb3Scarlsonj return (-2);
441d04ccbb3Scarlsonj }
442d04ccbb3Scarlsonj if (*str == ',' || *str == '\0') {
443d04ccbb3Scarlsonj *strp = str;
444d04ccbb3Scarlsonj return (-1);
445d04ccbb3Scarlsonj }
446d04ccbb3Scarlsonj hwtype = strtoul(str, strp, 0);
447d04ccbb3Scarlsonj if (errno != 0 || *strp == str || hwtype > 65535) {
448d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
449d04ccbb3Scarlsonj return (-2);
450d04ccbb3Scarlsonj } else {
451d04ccbb3Scarlsonj return ((int)hwtype);
452d04ccbb3Scarlsonj }
453d04ccbb3Scarlsonj }
454d04ccbb3Scarlsonj
455d04ccbb3Scarlsonj /*
456d04ccbb3Scarlsonj * get_mac_addr(): interpret ",macaddr" in the input string, as part of a DUID.
457d04ccbb3Scarlsonj * The 'macaddr' may be a hex string (in any standard format),
458d04ccbb3Scarlsonj * or the name of a physical interface. If an interface name
459d04ccbb3Scarlsonj * is given, then the interface type is extracted as well.
460d04ccbb3Scarlsonj *
461d04ccbb3Scarlsonj * input: const char *: input string
462d04ccbb3Scarlsonj * int *: error return value
463d04ccbb3Scarlsonj * uint16_t *: hardware type output (network byte order)
464d04ccbb3Scarlsonj * int: hardware type input; -1 for empty
465d04ccbb3Scarlsonj * uchar_t *: output buffer for MAC address
466d04ccbb3Scarlsonj * output: int: length of MAC address, or -1 for error
467d04ccbb3Scarlsonj */
468d04ccbb3Scarlsonj
469d04ccbb3Scarlsonj static int
get_mac_addr(const char * str,int * ierrnop,uint16_t * hwret,int hwtype,uchar_t * outbuf)470d04ccbb3Scarlsonj get_mac_addr(const char *str, int *ierrnop, uint16_t *hwret, int hwtype,
471d04ccbb3Scarlsonj uchar_t *outbuf)
472d04ccbb3Scarlsonj {
473d04ccbb3Scarlsonj int maclen;
474d04ccbb3Scarlsonj int dig, val;
475c7e4935fSss150715 dlpi_handle_t dh;
476c7e4935fSss150715 dlpi_info_t dlinfo;
477d04ccbb3Scarlsonj char chr;
478d04ccbb3Scarlsonj
479d04ccbb3Scarlsonj if (*str != '\0') {
480d04ccbb3Scarlsonj if (*str++ != ',')
481d04ccbb3Scarlsonj goto failed;
482c7e4935fSss150715 if (dlpi_open(str, &dh, 0) != DLPI_SUCCESS) {
483d04ccbb3Scarlsonj maclen = 0;
484d04ccbb3Scarlsonj dig = val = 0;
485d04ccbb3Scarlsonj /*
486d04ccbb3Scarlsonj * Allow MAC addresses with separators matching regexp
487d04ccbb3Scarlsonj * (:|-| *).
488d04ccbb3Scarlsonj */
489d04ccbb3Scarlsonj while ((chr = *str++) != '\0') {
490d04ccbb3Scarlsonj if (isdigit(chr)) {
491d04ccbb3Scarlsonj val = (val << 4) + chr - '0';
492d04ccbb3Scarlsonj } else if (isxdigit(chr)) {
493d04ccbb3Scarlsonj val = (val << 4) + chr -
494d04ccbb3Scarlsonj (isupper(chr) ? 'A' : 'a') + 10;
495d04ccbb3Scarlsonj } else if (isspace(chr) && dig == 0) {
496d04ccbb3Scarlsonj continue;
497d04ccbb3Scarlsonj } else if (chr == ':' || chr == '-' ||
498d04ccbb3Scarlsonj isspace(chr)) {
499d04ccbb3Scarlsonj dig = 1;
500d04ccbb3Scarlsonj } else {
501d04ccbb3Scarlsonj goto failed;
502d04ccbb3Scarlsonj }
503d04ccbb3Scarlsonj if (++dig == 2) {
504d04ccbb3Scarlsonj *outbuf++ = val;
505d04ccbb3Scarlsonj maclen++;
506d04ccbb3Scarlsonj dig = val = 0;
507d04ccbb3Scarlsonj }
508d04ccbb3Scarlsonj }
509d04ccbb3Scarlsonj } else {
510*35b6f047SDavid Höppner if (dlpi_bind(dh, DLPI_ANY_SAP, NULL) !=
511*35b6f047SDavid Höppner DLPI_SUCCESS || dlpi_info(dh, &dlinfo, 0) !=
512*35b6f047SDavid Höppner DLPI_SUCCESS) {
513c7e4935fSss150715 dlpi_close(dh);
514d04ccbb3Scarlsonj goto failed;
515c7e4935fSss150715 }
516c7e4935fSss150715 maclen = dlinfo.di_physaddrlen;
517c7e4935fSss150715 (void) memcpy(outbuf, dlinfo.di_physaddr, maclen);
518c7e4935fSss150715 dlpi_close(dh);
519d04ccbb3Scarlsonj if (hwtype == -1)
520948f2876Sss150715 hwtype = dlpi_arptype(dlinfo.di_mactype);
521d04ccbb3Scarlsonj }
522d04ccbb3Scarlsonj }
523d04ccbb3Scarlsonj if (hwtype == -1)
524d04ccbb3Scarlsonj goto failed;
525d04ccbb3Scarlsonj *hwret = htons(hwtype);
526d04ccbb3Scarlsonj return (maclen);
527d04ccbb3Scarlsonj
528d04ccbb3Scarlsonj failed:
529d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
530d04ccbb3Scarlsonj return (-1);
531d04ccbb3Scarlsonj }
532d04ccbb3Scarlsonj
533d04ccbb3Scarlsonj /*
5347c478bd9Sstevel@tonic-gate * inittab_encode_e(): converts a string representation of a given datatype into
5357c478bd9Sstevel@tonic-gate * binary; used for encoding ascii values into a form that
5367c478bd9Sstevel@tonic-gate * can be put in DHCP packets to be sent on the wire.
5377c478bd9Sstevel@tonic-gate *
538d04ccbb3Scarlsonj * input: const dhcp_symbol_t *: the entry describing the value option
5397c478bd9Sstevel@tonic-gate * const char *: the value to convert
5407c478bd9Sstevel@tonic-gate * uint16_t *: set to the length of the binary data returned
5417c478bd9Sstevel@tonic-gate * boolean_t: if false, return a full DHCP option
542d04ccbb3Scarlsonj * int *: error return value
5437c478bd9Sstevel@tonic-gate * output: uchar_t *: a dynamically allocated byte array with converted data
5447c478bd9Sstevel@tonic-gate */
545d04ccbb3Scarlsonj
5467c478bd9Sstevel@tonic-gate uchar_t *
inittab_encode_e(const dhcp_symbol_t * ie,const char * value,uint16_t * lengthp,boolean_t just_payload,int * ierrnop)547d04ccbb3Scarlsonj inittab_encode_e(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp,
5487c478bd9Sstevel@tonic-gate boolean_t just_payload, int *ierrnop)
5497c478bd9Sstevel@tonic-gate {
550d04ccbb3Scarlsonj int hlen = 0;
551d04ccbb3Scarlsonj uint16_t length;
5527c478bd9Sstevel@tonic-gate uchar_t n_entries = 0;
5537c478bd9Sstevel@tonic-gate const char *valuep;
5547c478bd9Sstevel@tonic-gate char *currp;
5557c478bd9Sstevel@tonic-gate uchar_t *result = NULL;
556d04ccbb3Scarlsonj uchar_t *optstart;
5577c478bd9Sstevel@tonic-gate unsigned int i;
5587c478bd9Sstevel@tonic-gate uint8_t type_size = inittab_type_to_size(ie);
5597c478bd9Sstevel@tonic-gate boolean_t is_signed;
5607c478bd9Sstevel@tonic-gate uint_t vallen, reslen;
561d04ccbb3Scarlsonj dhcpv6_option_t *d6o;
562d04ccbb3Scarlsonj int type;
563d04ccbb3Scarlsonj char *cp2;
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate *ierrnop = 0;
5667c478bd9Sstevel@tonic-gate if (type_size == 0) {
5677c478bd9Sstevel@tonic-gate *ierrnop = ITAB_SYNTAX_ERROR;
5687c478bd9Sstevel@tonic-gate return (NULL);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate
571d04ccbb3Scarlsonj switch (ie->ds_type) {
572d04ccbb3Scarlsonj case DSYM_ASCII:
5737c478bd9Sstevel@tonic-gate n_entries = strlen(value); /* no NUL */
574d04ccbb3Scarlsonj break;
575d04ccbb3Scarlsonj
576d04ccbb3Scarlsonj case DSYM_OCTET:
5777c478bd9Sstevel@tonic-gate vallen = strlen(value);
5787c478bd9Sstevel@tonic-gate n_entries = vallen / 2;
5797c478bd9Sstevel@tonic-gate n_entries += vallen % 2;
580d04ccbb3Scarlsonj break;
581d04ccbb3Scarlsonj
582d04ccbb3Scarlsonj case DSYM_DOMAIN:
583d04ccbb3Scarlsonj /*
584d04ccbb3Scarlsonj * Maximum (worst-case) encoded length is one byte more than
585d04ccbb3Scarlsonj * the number of characters on input.
586d04ccbb3Scarlsonj */
587d04ccbb3Scarlsonj n_entries = strlen(value) + 1;
588d04ccbb3Scarlsonj break;
589d04ccbb3Scarlsonj
590d04ccbb3Scarlsonj case DSYM_DUID:
591d04ccbb3Scarlsonj /* Worst case is ":::::" */
592d04ccbb3Scarlsonj n_entries = strlen(value);
593c7e4935fSss150715 if (n_entries < DLPI_PHYSADDR_MAX)
594c7e4935fSss150715 n_entries = DLPI_PHYSADDR_MAX;
595d04ccbb3Scarlsonj n_entries += sizeof (duid_llt_t);
596d04ccbb3Scarlsonj break;
597d04ccbb3Scarlsonj
598d04ccbb3Scarlsonj default:
5997c478bd9Sstevel@tonic-gate /*
6007c478bd9Sstevel@tonic-gate * figure out the number of entries by counting the spaces
6017c478bd9Sstevel@tonic-gate * in the value string
6027c478bd9Sstevel@tonic-gate */
6037c478bd9Sstevel@tonic-gate for (valuep = value; valuep++ != NULL; n_entries++)
6047c478bd9Sstevel@tonic-gate valuep = strchr(valuep, ' ');
605d04ccbb3Scarlsonj break;
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate /*
6097c478bd9Sstevel@tonic-gate * if we're gonna return a complete option, then include the
6107c478bd9Sstevel@tonic-gate * option length and code in the size of the packet we allocate
6117c478bd9Sstevel@tonic-gate */
612d04ccbb3Scarlsonj if (!just_payload)
613d04ccbb3Scarlsonj hlen = ie->ds_dhcpv6 ? sizeof (*d6o) : 2;
6147c478bd9Sstevel@tonic-gate
615d04ccbb3Scarlsonj length = n_entries * type_size;
616d04ccbb3Scarlsonj if (hlen + length > 0)
617d04ccbb3Scarlsonj result = malloc(hlen + length);
618d04ccbb3Scarlsonj
619d04ccbb3Scarlsonj if ((optstart = result) != NULL && !just_payload)
620d04ccbb3Scarlsonj optstart += hlen;
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate switch (ie->ds_type) {
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate case DSYM_ASCII:
6257c478bd9Sstevel@tonic-gate
626d04ccbb3Scarlsonj if (optstart == NULL) {
6277c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
6287c478bd9Sstevel@tonic-gate return (NULL);
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate
631d04ccbb3Scarlsonj (void) memcpy(optstart, value, length);
632d04ccbb3Scarlsonj break;
633d04ccbb3Scarlsonj
634d04ccbb3Scarlsonj case DSYM_DOMAIN:
635d04ccbb3Scarlsonj if (optstart == NULL) {
636d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
6377c478bd9Sstevel@tonic-gate return (NULL);
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate
640d04ccbb3Scarlsonj /*
641d04ccbb3Scarlsonj * Note that this encoder always presents the trailing 0-octet
642d04ccbb3Scarlsonj * when dealing with a list. This means that you can't have
643d04ccbb3Scarlsonj * non-fully-qualified members anywhere but at the end of a
644d04ccbb3Scarlsonj * list (or as the only member of the list).
645d04ccbb3Scarlsonj */
646d04ccbb3Scarlsonj valuep = value;
647d04ccbb3Scarlsonj while (*valuep != '\0') {
648d04ccbb3Scarlsonj int dig, val, inchr;
649d04ccbb3Scarlsonj boolean_t escape;
650d04ccbb3Scarlsonj uchar_t *flen;
651d04ccbb3Scarlsonj
652d04ccbb3Scarlsonj /*
653d04ccbb3Scarlsonj * Skip over whitespace that delimits list members.
654d04ccbb3Scarlsonj */
655d04ccbb3Scarlsonj if (isascii(*valuep) && isspace(*valuep)) {
656d04ccbb3Scarlsonj valuep++;
657d04ccbb3Scarlsonj continue;
658d04ccbb3Scarlsonj }
659d04ccbb3Scarlsonj dig = val = 0;
660d04ccbb3Scarlsonj escape = B_FALSE;
661d04ccbb3Scarlsonj flen = optstart++;
662d04ccbb3Scarlsonj while ((inchr = *valuep) != '\0') {
663d04ccbb3Scarlsonj valuep++;
664d04ccbb3Scarlsonj /*
665d04ccbb3Scarlsonj * Just copy non-ASCII text directly to the
666d04ccbb3Scarlsonj * output string. This simplifies the use of
667d04ccbb3Scarlsonj * other ctype macros below, as, unlike the
668d04ccbb3Scarlsonj * special isascii function, they don't handle
669d04ccbb3Scarlsonj * non-ASCII.
670d04ccbb3Scarlsonj */
671d04ccbb3Scarlsonj if (!isascii(inchr)) {
672d04ccbb3Scarlsonj escape = B_FALSE;
673d04ccbb3Scarlsonj *optstart++ = inchr;
674d04ccbb3Scarlsonj continue;
675d04ccbb3Scarlsonj }
676d04ccbb3Scarlsonj if (escape) {
677d04ccbb3Scarlsonj /*
678d04ccbb3Scarlsonj * Handle any of \D, \DD, or \DDD for
679d04ccbb3Scarlsonj * a digit escape.
680d04ccbb3Scarlsonj */
681d04ccbb3Scarlsonj if (isdigit(inchr)) {
682d04ccbb3Scarlsonj val = val * 10 + inchr - '0';
683d04ccbb3Scarlsonj if (++dig == 3) {
684d04ccbb3Scarlsonj *optstart++ = val;
685d04ccbb3Scarlsonj dig = val = 0;
686d04ccbb3Scarlsonj escape = B_FALSE;
687d04ccbb3Scarlsonj }
688d04ccbb3Scarlsonj continue;
689d04ccbb3Scarlsonj } else if (dig > 0) {
690d04ccbb3Scarlsonj /*
691d04ccbb3Scarlsonj * User terminated \D or \DD
692d04ccbb3Scarlsonj * with non-digit. An error,
693d04ccbb3Scarlsonj * but we can assume he means
694d04ccbb3Scarlsonj * to treat as \00D or \0DD.
695d04ccbb3Scarlsonj */
696d04ccbb3Scarlsonj *optstart++ = val;
697d04ccbb3Scarlsonj dig = val = 0;
698d04ccbb3Scarlsonj }
699d04ccbb3Scarlsonj /* Fall through and copy character */
700d04ccbb3Scarlsonj escape = B_FALSE;
701d04ccbb3Scarlsonj } else if (inchr == '\\') {
702d04ccbb3Scarlsonj escape = B_TRUE;
703d04ccbb3Scarlsonj continue;
704d04ccbb3Scarlsonj } else if (inchr == '.') {
705d04ccbb3Scarlsonj /*
706d04ccbb3Scarlsonj * End of component. Write the length
707d04ccbb3Scarlsonj * prefix. If the component is zero
708d04ccbb3Scarlsonj * length (i.e., ".."), the just omit
709d04ccbb3Scarlsonj * it.
710d04ccbb3Scarlsonj */
711d04ccbb3Scarlsonj *flen = (optstart - flen) - 1;
712d04ccbb3Scarlsonj if (*flen > 0)
713d04ccbb3Scarlsonj flen = optstart++;
714d04ccbb3Scarlsonj continue;
715d04ccbb3Scarlsonj } else if (isspace(inchr)) {
716d04ccbb3Scarlsonj /*
717d04ccbb3Scarlsonj * Unescaped space; end of domain name
718d04ccbb3Scarlsonj * in list.
719d04ccbb3Scarlsonj */
720d04ccbb3Scarlsonj break;
721d04ccbb3Scarlsonj }
722d04ccbb3Scarlsonj *optstart++ = inchr;
723d04ccbb3Scarlsonj }
724d04ccbb3Scarlsonj /*
725d04ccbb3Scarlsonj * Handle trailing escape sequence. If string ends
726d04ccbb3Scarlsonj * with \, then assume user wants \ at end of encoded
727d04ccbb3Scarlsonj * string. If it ends with \D or \DD, assume \00D or
728d04ccbb3Scarlsonj * \0DD.
729d04ccbb3Scarlsonj */
730d04ccbb3Scarlsonj if (escape)
731d04ccbb3Scarlsonj *optstart++ = dig > 0 ? val : '\\';
732d04ccbb3Scarlsonj *flen = (optstart - flen) - 1;
733d04ccbb3Scarlsonj /*
734d04ccbb3Scarlsonj * If user specified FQDN with trailing '.', then above
735d04ccbb3Scarlsonj * will result in zero for the last component length.
736d04ccbb3Scarlsonj * We're done, and optstart already points to the start
737d04ccbb3Scarlsonj * of the next in list. Otherwise, we need to write a
738d04ccbb3Scarlsonj * single zero byte to end the entry, if there are more
739d04ccbb3Scarlsonj * entries that will be decoded.
740d04ccbb3Scarlsonj */
741d04ccbb3Scarlsonj while (isascii(*valuep) && isspace(*valuep))
742d04ccbb3Scarlsonj valuep++;
743d04ccbb3Scarlsonj if (*flen > 0 && *valuep != '\0')
744d04ccbb3Scarlsonj *optstart++ = '\0';
745d04ccbb3Scarlsonj }
746d04ccbb3Scarlsonj length = (optstart - result) - hlen;
747d04ccbb3Scarlsonj break;
748d04ccbb3Scarlsonj
749d04ccbb3Scarlsonj case DSYM_DUID:
750d04ccbb3Scarlsonj if (optstart == NULL) {
751d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
752d04ccbb3Scarlsonj return (NULL);
753d04ccbb3Scarlsonj }
754d04ccbb3Scarlsonj
755d04ccbb3Scarlsonj errno = 0;
756d04ccbb3Scarlsonj type = strtoul(value, &currp, 0);
757d04ccbb3Scarlsonj if (errno != 0 || value == currp || type > 65535 ||
758d04ccbb3Scarlsonj (*currp != ',' && *currp != '\0')) {
759d04ccbb3Scarlsonj free(result);
760d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
761d04ccbb3Scarlsonj return (NULL);
762d04ccbb3Scarlsonj }
763d04ccbb3Scarlsonj switch (type) {
764d04ccbb3Scarlsonj case DHCPV6_DUID_LLT: {
765d04ccbb3Scarlsonj duid_llt_t dllt;
766d04ccbb3Scarlsonj int hwtype;
767d04ccbb3Scarlsonj ulong_t tstamp;
768d04ccbb3Scarlsonj int maclen;
769d04ccbb3Scarlsonj
770d04ccbb3Scarlsonj if ((hwtype = get_hw_type(&currp, ierrnop)) == -2) {
771d04ccbb3Scarlsonj free(result);
772d04ccbb3Scarlsonj return (NULL);
773d04ccbb3Scarlsonj }
774d04ccbb3Scarlsonj if (*currp++ != ',') {
775d04ccbb3Scarlsonj free(result);
776d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
777d04ccbb3Scarlsonj return (NULL);
778d04ccbb3Scarlsonj }
779d04ccbb3Scarlsonj if (*currp == ',' || *currp == '\0') {
780d04ccbb3Scarlsonj tstamp = time(NULL) - DUID_TIME_BASE;
781d04ccbb3Scarlsonj } else {
782d04ccbb3Scarlsonj tstamp = strtoul(currp, &cp2, 0);
783d04ccbb3Scarlsonj if (errno != 0 || currp == cp2) {
784d04ccbb3Scarlsonj free(result);
785d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
786d04ccbb3Scarlsonj return (NULL);
787d04ccbb3Scarlsonj }
788d04ccbb3Scarlsonj currp = cp2;
789d04ccbb3Scarlsonj }
790d04ccbb3Scarlsonj maclen = get_mac_addr(currp, ierrnop,
791d04ccbb3Scarlsonj &dllt.dllt_hwtype, hwtype,
792d04ccbb3Scarlsonj optstart + sizeof (dllt));
793d04ccbb3Scarlsonj if (maclen == -1) {
794d04ccbb3Scarlsonj free(result);
795d04ccbb3Scarlsonj return (NULL);
796d04ccbb3Scarlsonj }
797d04ccbb3Scarlsonj dllt.dllt_dutype = htons(type);
798d04ccbb3Scarlsonj dllt.dllt_time = htonl(tstamp);
799d04ccbb3Scarlsonj (void) memcpy(optstart, &dllt, sizeof (dllt));
800d04ccbb3Scarlsonj length = maclen + sizeof (dllt);
801d04ccbb3Scarlsonj break;
802d04ccbb3Scarlsonj }
803d04ccbb3Scarlsonj case DHCPV6_DUID_EN: {
804d04ccbb3Scarlsonj duid_en_t den;
805d04ccbb3Scarlsonj ulong_t enterp;
806d04ccbb3Scarlsonj
807d04ccbb3Scarlsonj if (*currp++ != ',') {
808d04ccbb3Scarlsonj free(result);
809d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
810d04ccbb3Scarlsonj return (NULL);
811d04ccbb3Scarlsonj }
812d04ccbb3Scarlsonj enterp = strtoul(currp, &cp2, 0);
813d04ccbb3Scarlsonj DHCPV6_SET_ENTNUM(&den, enterp);
814d04ccbb3Scarlsonj if (errno != 0 || currp == cp2 ||
815d04ccbb3Scarlsonj enterp != DHCPV6_GET_ENTNUM(&den) ||
816d04ccbb3Scarlsonj (*cp2 != ',' && *cp2 != '\0')) {
817d04ccbb3Scarlsonj free(result);
818d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
819d04ccbb3Scarlsonj return (NULL);
820d04ccbb3Scarlsonj }
821d04ccbb3Scarlsonj if (*cp2 == ',')
822d04ccbb3Scarlsonj cp2++;
823d04ccbb3Scarlsonj vallen = strlen(cp2);
824d04ccbb3Scarlsonj reslen = (vallen + 1) / 2;
825d04ccbb3Scarlsonj if (hexascii_to_octet(cp2, vallen,
826d04ccbb3Scarlsonj optstart + sizeof (den), &reslen) != 0) {
827d04ccbb3Scarlsonj free(result);
828d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
829d04ccbb3Scarlsonj return (NULL);
830d04ccbb3Scarlsonj }
831d04ccbb3Scarlsonj den.den_dutype = htons(type);
832d04ccbb3Scarlsonj (void) memcpy(optstart, &den, sizeof (den));
833d04ccbb3Scarlsonj length = reslen + sizeof (den);
834d04ccbb3Scarlsonj break;
835d04ccbb3Scarlsonj }
836d04ccbb3Scarlsonj case DHCPV6_DUID_LL: {
837d04ccbb3Scarlsonj duid_ll_t dll;
838d04ccbb3Scarlsonj int hwtype;
839d04ccbb3Scarlsonj int maclen;
840d04ccbb3Scarlsonj
841d04ccbb3Scarlsonj if ((hwtype = get_hw_type(&currp, ierrnop)) == -2) {
842d04ccbb3Scarlsonj free(result);
843d04ccbb3Scarlsonj return (NULL);
844d04ccbb3Scarlsonj }
845d04ccbb3Scarlsonj maclen = get_mac_addr(currp, ierrnop, &dll.dll_hwtype,
846d04ccbb3Scarlsonj hwtype, optstart + sizeof (dll));
847d04ccbb3Scarlsonj if (maclen == -1) {
848d04ccbb3Scarlsonj free(result);
849d04ccbb3Scarlsonj return (NULL);
850d04ccbb3Scarlsonj }
851d04ccbb3Scarlsonj dll.dll_dutype = htons(type);
852d04ccbb3Scarlsonj (void) memcpy(optstart, &dll, sizeof (dll));
853d04ccbb3Scarlsonj length = maclen + sizeof (dll);
854d04ccbb3Scarlsonj break;
855d04ccbb3Scarlsonj }
856d04ccbb3Scarlsonj default:
857d04ccbb3Scarlsonj if (*currp == ',')
858d04ccbb3Scarlsonj currp++;
859d04ccbb3Scarlsonj vallen = strlen(currp);
860d04ccbb3Scarlsonj reslen = (vallen + 1) / 2;
861d04ccbb3Scarlsonj if (hexascii_to_octet(currp, vallen, optstart + 2,
862d04ccbb3Scarlsonj &reslen) != 0) {
863d04ccbb3Scarlsonj free(result);
864d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
865d04ccbb3Scarlsonj return (NULL);
866d04ccbb3Scarlsonj }
867d04ccbb3Scarlsonj optstart[0] = type >> 8;
868d04ccbb3Scarlsonj optstart[1] = type;
869d04ccbb3Scarlsonj length = reslen + 2;
870d04ccbb3Scarlsonj break;
871d04ccbb3Scarlsonj }
8727c478bd9Sstevel@tonic-gate break;
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate case DSYM_OCTET:
8757c478bd9Sstevel@tonic-gate
876d04ccbb3Scarlsonj if (optstart == NULL) {
8777c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_OCTET;
8787c478bd9Sstevel@tonic-gate return (NULL);
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate reslen = length;
8827c478bd9Sstevel@tonic-gate /* Call libinetutil function to decode */
883d04ccbb3Scarlsonj if (hexascii_to_octet(value, vallen, optstart, &reslen) != 0) {
8847c478bd9Sstevel@tonic-gate free(result);
8857c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_OCTET;
8867c478bd9Sstevel@tonic-gate return (NULL);
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate break;
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate case DSYM_IP:
891d04ccbb3Scarlsonj case DSYM_IPV6:
8927c478bd9Sstevel@tonic-gate
893d04ccbb3Scarlsonj if (optstart == NULL) {
8947c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_IPADDR;
8957c478bd9Sstevel@tonic-gate return (NULL);
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate if (n_entries % ie->ds_gran != 0) {
8987c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_GRAN;
8997c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: number of entries "
9007c478bd9Sstevel@tonic-gate "not compatible with option granularity");
9017c478bd9Sstevel@tonic-gate free(result);
9027c478bd9Sstevel@tonic-gate return (NULL);
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate for (valuep = value, i = 0; i < n_entries; i++, valuep++) {
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate currp = strchr(valuep, ' ');
9087c478bd9Sstevel@tonic-gate if (currp != NULL)
9097c478bd9Sstevel@tonic-gate *currp = '\0';
910d04ccbb3Scarlsonj if (inet_pton(ie->ds_type == DSYM_IP ? AF_INET :
911d04ccbb3Scarlsonj AF_INET6, valuep, optstart) != 1) {
9127c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_IPADDR;
9137c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: bogus ip address");
9147c478bd9Sstevel@tonic-gate free(result);
9157c478bd9Sstevel@tonic-gate return (NULL);
9167c478bd9Sstevel@tonic-gate }
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate valuep = currp;
9197c478bd9Sstevel@tonic-gate if (valuep == NULL) {
9207c478bd9Sstevel@tonic-gate if (i < (n_entries - 1)) {
9217c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOT_ENOUGH_IP;
9227c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: too few "
9237c478bd9Sstevel@tonic-gate "ip addresses");
9247c478bd9Sstevel@tonic-gate free(result);
9257c478bd9Sstevel@tonic-gate return (NULL);
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate break;
9287c478bd9Sstevel@tonic-gate }
929d04ccbb3Scarlsonj optstart += type_size;
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate break;
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate case DSYM_NUMBER: /* FALLTHRU */
9347c478bd9Sstevel@tonic-gate case DSYM_UNUMBER8: /* FALLTHRU */
9357c478bd9Sstevel@tonic-gate case DSYM_SNUMBER8: /* FALLTHRU */
9367c478bd9Sstevel@tonic-gate case DSYM_UNUMBER16: /* FALLTHRU */
9377c478bd9Sstevel@tonic-gate case DSYM_SNUMBER16: /* FALLTHRU */
938d04ccbb3Scarlsonj case DSYM_UNUMBER24: /* FALLTHRU */
9397c478bd9Sstevel@tonic-gate case DSYM_UNUMBER32: /* FALLTHRU */
9407c478bd9Sstevel@tonic-gate case DSYM_SNUMBER32: /* FALLTHRU */
9417c478bd9Sstevel@tonic-gate case DSYM_UNUMBER64: /* FALLTHRU */
9427c478bd9Sstevel@tonic-gate case DSYM_SNUMBER64:
9437c478bd9Sstevel@tonic-gate
944d04ccbb3Scarlsonj if (optstart == NULL) {
9457c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_NUMBER;
9467c478bd9Sstevel@tonic-gate return (NULL);
9477c478bd9Sstevel@tonic-gate }
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate is_signed = (ie->ds_type == DSYM_SNUMBER64 ||
9507c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER32 ||
9517c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER16 ||
9527c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER8);
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate if (encode_number(n_entries, type_size, is_signed, 0, value,
955d04ccbb3Scarlsonj optstart, ierrnop) == B_FALSE) {
9567c478bd9Sstevel@tonic-gate free(result);
9577c478bd9Sstevel@tonic-gate return (NULL);
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate break;
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate default:
9627c478bd9Sstevel@tonic-gate if (ie->ds_type == DSYM_BOOL)
9637c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_BOOLEAN;
9647c478bd9Sstevel@tonic-gate else
9657c478bd9Sstevel@tonic-gate *ierrnop = ITAB_SYNTAX_ERROR;
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: unsupported type `%d'",
9687c478bd9Sstevel@tonic-gate ie->ds_type);
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate free(result);
9717c478bd9Sstevel@tonic-gate return (NULL);
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate /*
975d04ccbb3Scarlsonj * if just_payload is false, then we need to add the option
976d04ccbb3Scarlsonj * code and length fields in.
9777c478bd9Sstevel@tonic-gate */
978d04ccbb3Scarlsonj if (!just_payload) {
979d04ccbb3Scarlsonj if (ie->ds_dhcpv6) {
980d04ccbb3Scarlsonj /* LINTED: alignment */
981d04ccbb3Scarlsonj d6o = (dhcpv6_option_t *)result;
982d04ccbb3Scarlsonj d6o->d6o_code = htons(ie->ds_code);
983d04ccbb3Scarlsonj d6o->d6o_len = htons(length);
984d04ccbb3Scarlsonj } else {
9857c478bd9Sstevel@tonic-gate result[0] = ie->ds_code;
986d04ccbb3Scarlsonj result[1] = length;
987d04ccbb3Scarlsonj }
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate if (lengthp != NULL)
991d04ccbb3Scarlsonj *lengthp = length + hlen;
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate return (result);
9947c478bd9Sstevel@tonic-gate }
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate /*
9977c478bd9Sstevel@tonic-gate * inittab_decode_e(): converts a binary representation of a given datatype into
9987c478bd9Sstevel@tonic-gate * a string; used for decoding DHCP options in a packet off
9997c478bd9Sstevel@tonic-gate * the wire into ascii
10007c478bd9Sstevel@tonic-gate *
10017c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the entry describing the payload option
10027c478bd9Sstevel@tonic-gate * uchar_t *: the payload to convert
10037c478bd9Sstevel@tonic-gate * uint16_t: the payload length (only used if just_payload is true)
10047c478bd9Sstevel@tonic-gate * boolean_t: if false, payload is assumed to be a DHCP option
10057c478bd9Sstevel@tonic-gate * int *: set to extended error code if error occurs.
10067c478bd9Sstevel@tonic-gate * output: char *: a dynamically allocated string containing the converted data
10077c478bd9Sstevel@tonic-gate */
1008d04ccbb3Scarlsonj
10097c478bd9Sstevel@tonic-gate char *
inittab_decode_e(const dhcp_symbol_t * ie,const uchar_t * payload,uint16_t length,boolean_t just_payload,int * ierrnop)1010d04ccbb3Scarlsonj inittab_decode_e(const dhcp_symbol_t *ie, const uchar_t *payload,
1011d04ccbb3Scarlsonj uint16_t length, boolean_t just_payload, int *ierrnop)
10127c478bd9Sstevel@tonic-gate {
1013d04ccbb3Scarlsonj char *resultp, *result = NULL;
1014d04ccbb3Scarlsonj uint_t n_entries;
10157c478bd9Sstevel@tonic-gate struct in_addr in_addr;
1016d04ccbb3Scarlsonj in6_addr_t in6_addr;
10177c478bd9Sstevel@tonic-gate uint8_t type_size = inittab_type_to_size(ie);
10187c478bd9Sstevel@tonic-gate boolean_t is_signed;
1019d04ccbb3Scarlsonj int type;
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate *ierrnop = 0;
10227c478bd9Sstevel@tonic-gate if (type_size == 0) {
10237c478bd9Sstevel@tonic-gate *ierrnop = ITAB_SYNTAX_ERROR;
10247c478bd9Sstevel@tonic-gate return (NULL);
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate
1027d04ccbb3Scarlsonj if (!just_payload) {
1028d04ccbb3Scarlsonj if (ie->ds_dhcpv6) {
1029d04ccbb3Scarlsonj dhcpv6_option_t d6o;
1030d04ccbb3Scarlsonj
1031d04ccbb3Scarlsonj (void) memcpy(&d6o, payload, sizeof (d6o));
1032d04ccbb3Scarlsonj length = ntohs(d6o.d6o_len);
1033d04ccbb3Scarlsonj payload += sizeof (d6o);
1034d04ccbb3Scarlsonj } else {
10357c478bd9Sstevel@tonic-gate length = payload[1];
10367c478bd9Sstevel@tonic-gate payload += 2;
10377c478bd9Sstevel@tonic-gate }
1038d04ccbb3Scarlsonj }
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate * figure out the number of elements to convert. note that
10427c478bd9Sstevel@tonic-gate * for ds_type NUMBER, the granularity is really 1 since the
10437c478bd9Sstevel@tonic-gate * value of ds_gran is the number of bytes in the number.
10447c478bd9Sstevel@tonic-gate */
10457c478bd9Sstevel@tonic-gate if (ie->ds_type == DSYM_NUMBER)
10467c478bd9Sstevel@tonic-gate n_entries = MIN(ie->ds_max, length / type_size);
10477c478bd9Sstevel@tonic-gate else
10487c478bd9Sstevel@tonic-gate n_entries = MIN(ie->ds_max * ie->ds_gran, length / type_size);
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate if (n_entries == 0)
10517c478bd9Sstevel@tonic-gate n_entries = length / type_size;
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate if ((length % type_size) != 0) {
10547c478bd9Sstevel@tonic-gate inittab_msg("inittab_decode: length of string not compatible "
10557c478bd9Sstevel@tonic-gate "with option type `%i'", ie->ds_type);
10567c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_STRING;
10577c478bd9Sstevel@tonic-gate return (NULL);
10587c478bd9Sstevel@tonic-gate }
10597c478bd9Sstevel@tonic-gate
10607c478bd9Sstevel@tonic-gate switch (ie->ds_type) {
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate case DSYM_ASCII:
10637c478bd9Sstevel@tonic-gate
10647c478bd9Sstevel@tonic-gate result = malloc(n_entries + 1);
10657c478bd9Sstevel@tonic-gate if (result == NULL) {
10667c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
10677c478bd9Sstevel@tonic-gate return (NULL);
10687c478bd9Sstevel@tonic-gate }
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate (void) memcpy(result, payload, n_entries);
10717c478bd9Sstevel@tonic-gate result[n_entries] = '\0';
10727c478bd9Sstevel@tonic-gate break;
10737c478bd9Sstevel@tonic-gate
1074d04ccbb3Scarlsonj case DSYM_DOMAIN:
1075d04ccbb3Scarlsonj
1076d04ccbb3Scarlsonj /*
1077d04ccbb3Scarlsonj * A valid, decoded RFC 1035 domain string or sequence of
1078d04ccbb3Scarlsonj * strings is always the same size as the encoded form, but we
1079d04ccbb3Scarlsonj * allow for RFC 1035 \DDD and \\ and \. escaping.
1080d04ccbb3Scarlsonj *
1081d04ccbb3Scarlsonj * Decoding stops at the end of the input or the first coding
1082d04ccbb3Scarlsonj * violation. Coding violations result in discarding the
1083d04ccbb3Scarlsonj * offending list entry entirely. Note that we ignore the 255
1084d04ccbb3Scarlsonj * character overall limit on domain names.
1085d04ccbb3Scarlsonj */
1086d04ccbb3Scarlsonj if ((result = malloc(4 * length + 1)) == NULL) {
1087d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1088d04ccbb3Scarlsonj return (NULL);
1089d04ccbb3Scarlsonj }
1090d04ccbb3Scarlsonj resultp = result;
1091d04ccbb3Scarlsonj while (length > 0) {
1092d04ccbb3Scarlsonj char *dstart;
1093d04ccbb3Scarlsonj int slen;
1094d04ccbb3Scarlsonj
1095d04ccbb3Scarlsonj dstart = resultp;
1096d04ccbb3Scarlsonj while (length > 0) {
1097d04ccbb3Scarlsonj slen = *payload++;
1098d04ccbb3Scarlsonj length--;
1099d04ccbb3Scarlsonj /* Upper two bits of length must be zero */
1100d04ccbb3Scarlsonj if ((slen & 0xc0) != 0 || slen > length) {
1101d04ccbb3Scarlsonj length = 0;
1102d04ccbb3Scarlsonj resultp = dstart;
1103d04ccbb3Scarlsonj break;
1104d04ccbb3Scarlsonj }
1105d04ccbb3Scarlsonj if (resultp != dstart)
1106d04ccbb3Scarlsonj *resultp++ = '.';
1107d04ccbb3Scarlsonj if (slen == 0)
1108d04ccbb3Scarlsonj break;
1109d04ccbb3Scarlsonj length -= slen;
1110d04ccbb3Scarlsonj while (slen > 0) {
1111d04ccbb3Scarlsonj if (!isascii(*payload) ||
1112d04ccbb3Scarlsonj !isgraph(*payload)) {
1113d04ccbb3Scarlsonj (void) snprintf(resultp, 5,
1114d04ccbb3Scarlsonj "\\%03d",
1115d04ccbb3Scarlsonj *(unsigned char *)payload);
1116d04ccbb3Scarlsonj resultp += 4;
1117d04ccbb3Scarlsonj payload++;
1118d04ccbb3Scarlsonj } else {
1119d04ccbb3Scarlsonj if (*payload == '.' ||
1120d04ccbb3Scarlsonj *payload == '\\')
1121d04ccbb3Scarlsonj *resultp++ = '\\';
1122d04ccbb3Scarlsonj *resultp++ = *payload++;
1123d04ccbb3Scarlsonj }
1124d04ccbb3Scarlsonj slen--;
1125d04ccbb3Scarlsonj }
1126d04ccbb3Scarlsonj }
1127d04ccbb3Scarlsonj if (resultp != dstart && length > 0)
1128d04ccbb3Scarlsonj *resultp++ = ' ';
1129d04ccbb3Scarlsonj }
1130d04ccbb3Scarlsonj *resultp = '\0';
1131d04ccbb3Scarlsonj break;
1132d04ccbb3Scarlsonj
1133d04ccbb3Scarlsonj case DSYM_DUID:
1134d04ccbb3Scarlsonj
1135d04ccbb3Scarlsonj /*
1136d04ccbb3Scarlsonj * First, determine the type of DUID. We need at least two
1137d04ccbb3Scarlsonj * octets worth of data to grab the type code. Once we have
1138d04ccbb3Scarlsonj * that, the number of octets required for representation
1139d04ccbb3Scarlsonj * depends on the type.
1140d04ccbb3Scarlsonj */
1141d04ccbb3Scarlsonj
1142d04ccbb3Scarlsonj if (length < 2) {
1143d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1144d04ccbb3Scarlsonj return (NULL);
1145d04ccbb3Scarlsonj }
1146d04ccbb3Scarlsonj type = (payload[0] << 8) + payload[1];
1147d04ccbb3Scarlsonj switch (type) {
1148d04ccbb3Scarlsonj case DHCPV6_DUID_LLT: {
1149d04ccbb3Scarlsonj duid_llt_t dllt;
1150d04ccbb3Scarlsonj
1151d04ccbb3Scarlsonj if (length < sizeof (dllt)) {
1152d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1153d04ccbb3Scarlsonj return (NULL);
1154d04ccbb3Scarlsonj }
1155d04ccbb3Scarlsonj (void) memcpy(&dllt, payload, sizeof (dllt));
1156d04ccbb3Scarlsonj payload += sizeof (dllt);
1157d04ccbb3Scarlsonj length -= sizeof (dllt);
1158d04ccbb3Scarlsonj n_entries = sizeof ("1,65535,4294967295,") +
1159d04ccbb3Scarlsonj length * 3;
1160d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1161d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1162d04ccbb3Scarlsonj return (NULL);
1163d04ccbb3Scarlsonj }
1164d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,%u,%u,", type,
1165d04ccbb3Scarlsonj ntohs(dllt.dllt_hwtype), ntohl(dllt.dllt_time));
1166d04ccbb3Scarlsonj break;
1167d04ccbb3Scarlsonj }
1168d04ccbb3Scarlsonj case DHCPV6_DUID_EN: {
1169d04ccbb3Scarlsonj duid_en_t den;
1170d04ccbb3Scarlsonj
1171d04ccbb3Scarlsonj if (length < sizeof (den)) {
1172d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1173d04ccbb3Scarlsonj return (NULL);
1174d04ccbb3Scarlsonj }
1175d04ccbb3Scarlsonj (void) memcpy(&den, payload, sizeof (den));
1176d04ccbb3Scarlsonj payload += sizeof (den);
1177d04ccbb3Scarlsonj length -= sizeof (den);
1178d04ccbb3Scarlsonj n_entries = sizeof ("2,4294967295,") + length * 2;
1179d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1180d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1181d04ccbb3Scarlsonj return (NULL);
1182d04ccbb3Scarlsonj }
1183d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,%u,", type,
1184d04ccbb3Scarlsonj DHCPV6_GET_ENTNUM(&den));
1185d04ccbb3Scarlsonj break;
1186d04ccbb3Scarlsonj }
1187d04ccbb3Scarlsonj case DHCPV6_DUID_LL: {
1188d04ccbb3Scarlsonj duid_ll_t dll;
1189d04ccbb3Scarlsonj
1190d04ccbb3Scarlsonj if (length < sizeof (dll)) {
1191d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1192d04ccbb3Scarlsonj return (NULL);
1193d04ccbb3Scarlsonj }
1194d04ccbb3Scarlsonj (void) memcpy(&dll, payload, sizeof (dll));
1195d04ccbb3Scarlsonj payload += sizeof (dll);
1196d04ccbb3Scarlsonj length -= sizeof (dll);
1197d04ccbb3Scarlsonj n_entries = sizeof ("3,65535,") + length * 3;
1198d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1199d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1200d04ccbb3Scarlsonj return (NULL);
1201d04ccbb3Scarlsonj }
1202d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,%u,", type,
1203d04ccbb3Scarlsonj ntohs(dll.dll_hwtype));
1204d04ccbb3Scarlsonj break;
1205d04ccbb3Scarlsonj }
1206d04ccbb3Scarlsonj default:
1207d04ccbb3Scarlsonj n_entries = sizeof ("0,") + length * 2;
1208d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1209d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1210d04ccbb3Scarlsonj return (NULL);
1211d04ccbb3Scarlsonj }
1212d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,", type);
1213d04ccbb3Scarlsonj break;
1214d04ccbb3Scarlsonj }
1215d04ccbb3Scarlsonj resultp = result + strlen(result);
1216d04ccbb3Scarlsonj n_entries -= strlen(result);
1217d04ccbb3Scarlsonj if (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) {
1218d04ccbb3Scarlsonj if (length > 0) {
1219d04ccbb3Scarlsonj resultp += snprintf(resultp, 3, "%02X",
1220d04ccbb3Scarlsonj *payload++);
1221d04ccbb3Scarlsonj length--;
1222d04ccbb3Scarlsonj }
1223d04ccbb3Scarlsonj while (length-- > 0) {
1224d04ccbb3Scarlsonj resultp += snprintf(resultp, 4, ":%02X",
1225d04ccbb3Scarlsonj *payload++);
1226d04ccbb3Scarlsonj }
1227d04ccbb3Scarlsonj } else {
1228d04ccbb3Scarlsonj while (length-- > 0) {
1229d04ccbb3Scarlsonj resultp += snprintf(resultp, 3, "%02X",
1230d04ccbb3Scarlsonj *payload++);
1231d04ccbb3Scarlsonj }
1232d04ccbb3Scarlsonj }
1233d04ccbb3Scarlsonj break;
1234d04ccbb3Scarlsonj
12357c478bd9Sstevel@tonic-gate case DSYM_OCTET:
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate result = malloc(n_entries * (sizeof ("0xNN") + 1));
12387c478bd9Sstevel@tonic-gate if (result == NULL) {
12397c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
12407c478bd9Sstevel@tonic-gate return (NULL);
12417c478bd9Sstevel@tonic-gate }
12427c478bd9Sstevel@tonic-gate
1243d04ccbb3Scarlsonj result[0] = '\0';
1244d04ccbb3Scarlsonj resultp = result;
1245d04ccbb3Scarlsonj if (n_entries > 0) {
12467c478bd9Sstevel@tonic-gate resultp += sprintf(resultp, "0x%02X", *payload++);
1247d04ccbb3Scarlsonj n_entries--;
12487c478bd9Sstevel@tonic-gate }
1249d04ccbb3Scarlsonj while (n_entries-- > 0)
1250d04ccbb3Scarlsonj resultp += sprintf(resultp, " 0x%02X", *payload++);
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate break;
12537c478bd9Sstevel@tonic-gate
12547c478bd9Sstevel@tonic-gate case DSYM_IP:
1255d04ccbb3Scarlsonj case DSYM_IPV6:
1256d04ccbb3Scarlsonj if ((length / type_size) % ie->ds_gran != 0) {
12577c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_GRAN;
12587c478bd9Sstevel@tonic-gate inittab_msg("inittab_decode: number of entries "
12597c478bd9Sstevel@tonic-gate "not compatible with option granularity");
12607c478bd9Sstevel@tonic-gate return (NULL);
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate
1263d04ccbb3Scarlsonj result = malloc(n_entries * (ie->ds_type == DSYM_IP ?
1264d04ccbb3Scarlsonj INET_ADDRSTRLEN : INET6_ADDRSTRLEN));
12657c478bd9Sstevel@tonic-gate if (result == NULL) {
12667c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
12677c478bd9Sstevel@tonic-gate return (NULL);
12687c478bd9Sstevel@tonic-gate }
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate for (resultp = result; n_entries != 0; n_entries--) {
1271d04ccbb3Scarlsonj if (ie->ds_type == DSYM_IP) {
12727c478bd9Sstevel@tonic-gate (void) memcpy(&in_addr.s_addr, payload,
12737c478bd9Sstevel@tonic-gate sizeof (ipaddr_t));
1274d04ccbb3Scarlsonj (void) strcpy(resultp, inet_ntoa(in_addr));
1275d04ccbb3Scarlsonj } else {
1276d04ccbb3Scarlsonj (void) memcpy(&in6_addr, payload,
1277d04ccbb3Scarlsonj sizeof (in6_addr));
1278d04ccbb3Scarlsonj (void) inet_ntop(AF_INET6, &in6_addr, resultp,
1279d04ccbb3Scarlsonj INET6_ADDRSTRLEN);
12807c478bd9Sstevel@tonic-gate }
1281d04ccbb3Scarlsonj resultp += strlen(resultp);
1282d04ccbb3Scarlsonj if (n_entries > 1)
1283d04ccbb3Scarlsonj *resultp++ = ' ';
1284d04ccbb3Scarlsonj payload += type_size;
12857c478bd9Sstevel@tonic-gate }
1286d04ccbb3Scarlsonj *resultp = '\0';
12877c478bd9Sstevel@tonic-gate break;
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate case DSYM_NUMBER: /* FALLTHRU */
12907c478bd9Sstevel@tonic-gate case DSYM_UNUMBER8: /* FALLTHRU */
12917c478bd9Sstevel@tonic-gate case DSYM_SNUMBER8: /* FALLTHRU */
12927c478bd9Sstevel@tonic-gate case DSYM_UNUMBER16: /* FALLTHRU */
12937c478bd9Sstevel@tonic-gate case DSYM_SNUMBER16: /* FALLTHRU */
12947c478bd9Sstevel@tonic-gate case DSYM_UNUMBER32: /* FALLTHRU */
12957c478bd9Sstevel@tonic-gate case DSYM_SNUMBER32: /* FALLTHRU */
12967c478bd9Sstevel@tonic-gate case DSYM_UNUMBER64: /* FALLTHRU */
12977c478bd9Sstevel@tonic-gate case DSYM_SNUMBER64:
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate is_signed = (ie->ds_type == DSYM_SNUMBER64 ||
13007c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER32 ||
13017c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER16 ||
13027c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER8);
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate result = malloc(n_entries * ITAB_MAX_NUMBER_LEN);
13057c478bd9Sstevel@tonic-gate if (result == NULL) {
13067c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
13077c478bd9Sstevel@tonic-gate return (NULL);
13087c478bd9Sstevel@tonic-gate }
13097c478bd9Sstevel@tonic-gate
13107c478bd9Sstevel@tonic-gate if (decode_number(n_entries, type_size, is_signed, ie->ds_gran,
13117c478bd9Sstevel@tonic-gate payload, result, ierrnop) == B_FALSE) {
13127c478bd9Sstevel@tonic-gate free(result);
13137c478bd9Sstevel@tonic-gate return (NULL);
13147c478bd9Sstevel@tonic-gate }
13157c478bd9Sstevel@tonic-gate break;
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate default:
13187c478bd9Sstevel@tonic-gate inittab_msg("inittab_decode: unsupported type `%d'",
13197c478bd9Sstevel@tonic-gate ie->ds_type);
13207c478bd9Sstevel@tonic-gate break;
13217c478bd9Sstevel@tonic-gate }
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate return (result);
13247c478bd9Sstevel@tonic-gate }
13257c478bd9Sstevel@tonic-gate
13267c478bd9Sstevel@tonic-gate /*
13277c478bd9Sstevel@tonic-gate * inittab_encode(): converts a string representation of a given datatype into
13287c478bd9Sstevel@tonic-gate * binary; used for encoding ascii values into a form that
13297c478bd9Sstevel@tonic-gate * can be put in DHCP packets to be sent on the wire.
13307c478bd9Sstevel@tonic-gate *
13317c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the entry describing the value option
13327c478bd9Sstevel@tonic-gate * const char *: the value to convert
13337c478bd9Sstevel@tonic-gate * uint16_t *: set to the length of the binary data returned
13347c478bd9Sstevel@tonic-gate * boolean_t: if false, return a full DHCP option
13357c478bd9Sstevel@tonic-gate * output: uchar_t *: a dynamically allocated byte array with converted data
13367c478bd9Sstevel@tonic-gate */
1337d04ccbb3Scarlsonj
13387c478bd9Sstevel@tonic-gate uchar_t *
inittab_encode(const dhcp_symbol_t * ie,const char * value,uint16_t * lengthp,boolean_t just_payload)1339d04ccbb3Scarlsonj inittab_encode(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp,
13407c478bd9Sstevel@tonic-gate boolean_t just_payload)
13417c478bd9Sstevel@tonic-gate {
13427c478bd9Sstevel@tonic-gate int ierrno;
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate return (inittab_encode_e(ie, value, lengthp, just_payload, &ierrno));
13457c478bd9Sstevel@tonic-gate }
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate /*
13487c478bd9Sstevel@tonic-gate * inittab_decode(): converts a binary representation of a given datatype into
13497c478bd9Sstevel@tonic-gate * a string; used for decoding DHCP options in a packet off
13507c478bd9Sstevel@tonic-gate * the wire into ascii
13517c478bd9Sstevel@tonic-gate *
13527c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the entry describing the payload option
13537c478bd9Sstevel@tonic-gate * uchar_t *: the payload to convert
13547c478bd9Sstevel@tonic-gate * uint16_t: the payload length (only used if just_payload is true)
13557c478bd9Sstevel@tonic-gate * boolean_t: if false, payload is assumed to be a DHCP option
13567c478bd9Sstevel@tonic-gate * output: char *: a dynamically allocated string containing the converted data
13577c478bd9Sstevel@tonic-gate */
1358d04ccbb3Scarlsonj
13597c478bd9Sstevel@tonic-gate char *
inittab_decode(const dhcp_symbol_t * ie,const uchar_t * payload,uint16_t length,boolean_t just_payload)1360d04ccbb3Scarlsonj inittab_decode(const dhcp_symbol_t *ie, const uchar_t *payload, uint16_t length,
13617c478bd9Sstevel@tonic-gate boolean_t just_payload)
13627c478bd9Sstevel@tonic-gate {
13637c478bd9Sstevel@tonic-gate int ierrno;
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate return (inittab_decode_e(ie, payload, length, just_payload, &ierrno));
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate
13687c478bd9Sstevel@tonic-gate /*
13697c478bd9Sstevel@tonic-gate * inittab_msg(): prints diagnostic messages if INITTAB_DEBUG is set
13707c478bd9Sstevel@tonic-gate *
13717c478bd9Sstevel@tonic-gate * const char *: a printf-like format string
13727c478bd9Sstevel@tonic-gate * ...: arguments to the format string
13737c478bd9Sstevel@tonic-gate * output: void
13747c478bd9Sstevel@tonic-gate */
1375d04ccbb3Scarlsonj
13767c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
13777c478bd9Sstevel@tonic-gate static void
inittab_msg(const char * fmt,...)13787c478bd9Sstevel@tonic-gate inittab_msg(const char *fmt, ...)
13797c478bd9Sstevel@tonic-gate {
13807c478bd9Sstevel@tonic-gate enum { INITTAB_MSG_CHECK, INITTAB_MSG_RETURN, INITTAB_MSG_OUTPUT };
13817c478bd9Sstevel@tonic-gate
13827c478bd9Sstevel@tonic-gate va_list ap;
13837c478bd9Sstevel@tonic-gate char buf[512];
13847c478bd9Sstevel@tonic-gate static int action = INITTAB_MSG_CHECK;
13857c478bd9Sstevel@tonic-gate
13867c478bd9Sstevel@tonic-gate /*
13877c478bd9Sstevel@tonic-gate * check DHCP_INITTAB_DEBUG the first time in; thereafter, use
13887c478bd9Sstevel@tonic-gate * the the cached result (stored in `action').
13897c478bd9Sstevel@tonic-gate */
13907c478bd9Sstevel@tonic-gate switch (action) {
13917c478bd9Sstevel@tonic-gate
13927c478bd9Sstevel@tonic-gate case INITTAB_MSG_CHECK:
13937c478bd9Sstevel@tonic-gate
13947c478bd9Sstevel@tonic-gate if (getenv("DHCP_INITTAB_DEBUG") == NULL) {
13957c478bd9Sstevel@tonic-gate action = INITTAB_MSG_RETURN;
13967c478bd9Sstevel@tonic-gate return;
13977c478bd9Sstevel@tonic-gate }
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate action = INITTAB_MSG_OUTPUT;
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate /* FALLTHRU into INITTAB_MSG_OUTPUT */
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate case INITTAB_MSG_OUTPUT:
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate va_start(ap, fmt);
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "inittab: %s\n", fmt);
14087c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, buf, ap);
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate va_end(ap);
14117c478bd9Sstevel@tonic-gate break;
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate case INITTAB_MSG_RETURN:
14147c478bd9Sstevel@tonic-gate
14157c478bd9Sstevel@tonic-gate return;
14167c478bd9Sstevel@tonic-gate }
14177c478bd9Sstevel@tonic-gate }
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate /*
14207c478bd9Sstevel@tonic-gate * decode_number(): decodes a sequence of numbers from binary into ascii;
14217c478bd9Sstevel@tonic-gate * binary is coming off of the network, so it is in nbo
14227c478bd9Sstevel@tonic-gate *
14237c478bd9Sstevel@tonic-gate * input: uint8_t: the number of "granularity" numbers to decode
14247c478bd9Sstevel@tonic-gate * uint8_t: the length of each number
14257c478bd9Sstevel@tonic-gate * boolean_t: whether the numbers should be considered signed
14267c478bd9Sstevel@tonic-gate * uint8_t: the number of numbers per granularity
14277c478bd9Sstevel@tonic-gate * const uint8_t *: where to decode the numbers from
14287c478bd9Sstevel@tonic-gate * char *: where to decode the numbers to
14297c478bd9Sstevel@tonic-gate * output: boolean_t: true on successful conversion, false on failure
14307c478bd9Sstevel@tonic-gate */
1431d04ccbb3Scarlsonj
14327c478bd9Sstevel@tonic-gate static boolean_t
decode_number(uint8_t n_entries,uint8_t size,boolean_t is_signed,uint8_t granularity,const uint8_t * from,char * to,int * ierrnop)14337c478bd9Sstevel@tonic-gate decode_number(uint8_t n_entries, uint8_t size, boolean_t is_signed,
14347c478bd9Sstevel@tonic-gate uint8_t granularity, const uint8_t *from, char *to, int *ierrnop)
14357c478bd9Sstevel@tonic-gate {
14367c478bd9Sstevel@tonic-gate uint16_t uint16;
14377c478bd9Sstevel@tonic-gate uint32_t uint32;
14387c478bd9Sstevel@tonic-gate uint64_t uint64;
14397c478bd9Sstevel@tonic-gate
14407c478bd9Sstevel@tonic-gate if (granularity != 0) {
14417c478bd9Sstevel@tonic-gate if ((granularity % n_entries) != 0) {
14427c478bd9Sstevel@tonic-gate inittab_msg("decode_number: number of entries "
14437c478bd9Sstevel@tonic-gate "not compatible with option granularity");
14447c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_GRAN;
14457c478bd9Sstevel@tonic-gate return (B_FALSE);
14467c478bd9Sstevel@tonic-gate }
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate for (; n_entries != 0; n_entries--, from += size) {
14507c478bd9Sstevel@tonic-gate
14517c478bd9Sstevel@tonic-gate switch (size) {
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate case 1:
14547c478bd9Sstevel@tonic-gate to += sprintf(to, is_signed ? "%d" : "%u", *from);
14557c478bd9Sstevel@tonic-gate break;
14567c478bd9Sstevel@tonic-gate
14577c478bd9Sstevel@tonic-gate case 2:
14587c478bd9Sstevel@tonic-gate (void) memcpy(&uint16, from, 2);
14597c478bd9Sstevel@tonic-gate to += sprintf(to, is_signed ? "%hd" : "%hu",
14607c478bd9Sstevel@tonic-gate ntohs(uint16));
14617c478bd9Sstevel@tonic-gate break;
14627c478bd9Sstevel@tonic-gate
1463d04ccbb3Scarlsonj case 3:
1464d04ccbb3Scarlsonj uint32 = 0;
1465d04ccbb3Scarlsonj (void) memcpy((uchar_t *)&uint32 + 1, from, 3);
1466d04ccbb3Scarlsonj to += sprintf(to, is_signed ? "%ld" : "%lu",
1467d04ccbb3Scarlsonj ntohl(uint32));
1468d04ccbb3Scarlsonj break;
1469d04ccbb3Scarlsonj
14707c478bd9Sstevel@tonic-gate case 4:
14717c478bd9Sstevel@tonic-gate (void) memcpy(&uint32, from, 4);
14727c478bd9Sstevel@tonic-gate to += sprintf(to, is_signed ? "%ld" : "%lu",
14737c478bd9Sstevel@tonic-gate ntohl(uint32));
14747c478bd9Sstevel@tonic-gate break;
14757c478bd9Sstevel@tonic-gate
14767c478bd9Sstevel@tonic-gate case 8:
14777c478bd9Sstevel@tonic-gate (void) memcpy(&uint64, from, 8);
14787c478bd9Sstevel@tonic-gate to += sprintf(to, is_signed ? "%lld" : "%llu",
14794b56a003SDaniel Anderson ntohll(uint64));
14807c478bd9Sstevel@tonic-gate break;
14817c478bd9Sstevel@tonic-gate
14827c478bd9Sstevel@tonic-gate default:
14837c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_NUMBER;
14847c478bd9Sstevel@tonic-gate inittab_msg("decode_number: unknown integer size `%d'",
14857c478bd9Sstevel@tonic-gate size);
14867c478bd9Sstevel@tonic-gate return (B_FALSE);
14877c478bd9Sstevel@tonic-gate }
1488d04ccbb3Scarlsonj if (n_entries > 0)
1489d04ccbb3Scarlsonj *to++ = ' ';
14907c478bd9Sstevel@tonic-gate }
14917c478bd9Sstevel@tonic-gate
1492d04ccbb3Scarlsonj *to = '\0';
14937c478bd9Sstevel@tonic-gate return (B_TRUE);
14947c478bd9Sstevel@tonic-gate }
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate /*
14977c478bd9Sstevel@tonic-gate * encode_number(): encodes a sequence of numbers from ascii into binary;
14987c478bd9Sstevel@tonic-gate * number will end up on the wire so it needs to be in nbo
14997c478bd9Sstevel@tonic-gate *
15007c478bd9Sstevel@tonic-gate * input: uint8_t: the number of "granularity" numbers to encode
15017c478bd9Sstevel@tonic-gate * uint8_t: the length of each number
15027c478bd9Sstevel@tonic-gate * boolean_t: whether the numbers should be considered signed
15037c478bd9Sstevel@tonic-gate * uint8_t: the number of numbers per granularity
15047c478bd9Sstevel@tonic-gate * const uint8_t *: where to encode the numbers from
15057c478bd9Sstevel@tonic-gate * char *: where to encode the numbers to
15067c478bd9Sstevel@tonic-gate * int *: set to extended error code if error occurs.
15077c478bd9Sstevel@tonic-gate * output: boolean_t: true on successful conversion, false on failure
15087c478bd9Sstevel@tonic-gate */
1509d04ccbb3Scarlsonj
15107c478bd9Sstevel@tonic-gate static boolean_t /* ARGSUSED */
encode_number(uint8_t n_entries,uint8_t size,boolean_t is_signed,uint8_t granularity,const char * from,uint8_t * to,int * ierrnop)15117c478bd9Sstevel@tonic-gate encode_number(uint8_t n_entries, uint8_t size, boolean_t is_signed,
15127c478bd9Sstevel@tonic-gate uint8_t granularity, const char *from, uint8_t *to, int *ierrnop)
15137c478bd9Sstevel@tonic-gate {
15147c478bd9Sstevel@tonic-gate uint8_t i;
15157c478bd9Sstevel@tonic-gate uint16_t uint16;
15167c478bd9Sstevel@tonic-gate uint32_t uint32;
15177c478bd9Sstevel@tonic-gate uint64_t uint64;
15187c478bd9Sstevel@tonic-gate char *endptr;
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate if (granularity != 0) {
15217c478bd9Sstevel@tonic-gate if ((granularity % n_entries) != 0) {
15227c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_GRAN;
15237c478bd9Sstevel@tonic-gate inittab_msg("encode_number: number of entries "
15247c478bd9Sstevel@tonic-gate "not compatible with option granularity");
15257c478bd9Sstevel@tonic-gate return (B_FALSE);
15267c478bd9Sstevel@tonic-gate }
15277c478bd9Sstevel@tonic-gate }
15287c478bd9Sstevel@tonic-gate
1529d04ccbb3Scarlsonj for (i = 0; i < n_entries; i++, from++, to += size) {
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate /*
15327c478bd9Sstevel@tonic-gate * totally obscure c factoid: it is legal to pass a
15337c478bd9Sstevel@tonic-gate * string representing a negative number to strtoul().
15347c478bd9Sstevel@tonic-gate * in this case, strtoul() will return an unsigned
15357c478bd9Sstevel@tonic-gate * long that if cast to a long, would represent the
15367c478bd9Sstevel@tonic-gate * negative number. we take advantage of this to
15377c478bd9Sstevel@tonic-gate * cut down on code here.
15387c478bd9Sstevel@tonic-gate */
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate errno = 0;
15417c478bd9Sstevel@tonic-gate switch (size) {
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate case 1:
1544d04ccbb3Scarlsonj *to = strtoul(from, &endptr, 0);
15457c478bd9Sstevel@tonic-gate if (errno != 0 || from == endptr) {
15467c478bd9Sstevel@tonic-gate goto error;
15477c478bd9Sstevel@tonic-gate }
15487c478bd9Sstevel@tonic-gate break;
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate case 2:
15517c478bd9Sstevel@tonic-gate uint16 = htons(strtoul(from, &endptr, 0));
15527c478bd9Sstevel@tonic-gate if (errno != 0 || from == endptr) {
15537c478bd9Sstevel@tonic-gate goto error;
15547c478bd9Sstevel@tonic-gate }
1555d04ccbb3Scarlsonj (void) memcpy(to, &uint16, 2);
1556d04ccbb3Scarlsonj break;
1557d04ccbb3Scarlsonj
1558d04ccbb3Scarlsonj case 3:
1559d04ccbb3Scarlsonj uint32 = htonl(strtoul(from, &endptr, 0));
1560d04ccbb3Scarlsonj if (errno != 0 || from == endptr) {
1561d04ccbb3Scarlsonj goto error;
1562d04ccbb3Scarlsonj }
1563d04ccbb3Scarlsonj (void) memcpy(to, (uchar_t *)&uint32 + 1, 3);
15647c478bd9Sstevel@tonic-gate break;
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate case 4:
15677c478bd9Sstevel@tonic-gate uint32 = htonl(strtoul(from, &endptr, 0));
15687c478bd9Sstevel@tonic-gate if (errno != 0 || from == endptr) {
15697c478bd9Sstevel@tonic-gate goto error;
15707c478bd9Sstevel@tonic-gate }
1571d04ccbb3Scarlsonj (void) memcpy(to, &uint32, 4);
15727c478bd9Sstevel@tonic-gate break;
15737c478bd9Sstevel@tonic-gate
15747c478bd9Sstevel@tonic-gate case 8:
15754b56a003SDaniel Anderson uint64 = htonll(strtoull(from, &endptr, 0));
15767c478bd9Sstevel@tonic-gate if (errno != 0 || from == endptr) {
15777c478bd9Sstevel@tonic-gate goto error;
15787c478bd9Sstevel@tonic-gate }
1579d04ccbb3Scarlsonj (void) memcpy(to, &uint64, 8);
15807c478bd9Sstevel@tonic-gate break;
15817c478bd9Sstevel@tonic-gate
15827c478bd9Sstevel@tonic-gate default:
15837c478bd9Sstevel@tonic-gate inittab_msg("encode_number: unsupported integer "
15847c478bd9Sstevel@tonic-gate "size `%d'", size);
15857c478bd9Sstevel@tonic-gate return (B_FALSE);
15867c478bd9Sstevel@tonic-gate }
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate from = strchr(from, ' ');
15897c478bd9Sstevel@tonic-gate if (from == NULL)
15907c478bd9Sstevel@tonic-gate break;
15917c478bd9Sstevel@tonic-gate }
15927c478bd9Sstevel@tonic-gate
15937c478bd9Sstevel@tonic-gate return (B_TRUE);
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate error:
15967c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_NUMBER;
15977c478bd9Sstevel@tonic-gate inittab_msg("encode_number: cannot convert to integer");
15987c478bd9Sstevel@tonic-gate return (B_FALSE);
15997c478bd9Sstevel@tonic-gate }
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate /*
16027c478bd9Sstevel@tonic-gate * inittab_type_to_size(): given an inittab entry, returns size of one entry of
16037c478bd9Sstevel@tonic-gate * its type
16047c478bd9Sstevel@tonic-gate *
16057c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: an entry of the given type
16067c478bd9Sstevel@tonic-gate * output: uint8_t: the size in bytes of an entry of that type
16077c478bd9Sstevel@tonic-gate */
1608d04ccbb3Scarlsonj
16097c478bd9Sstevel@tonic-gate uint8_t
inittab_type_to_size(const dhcp_symbol_t * ie)1610d04ccbb3Scarlsonj inittab_type_to_size(const dhcp_symbol_t *ie)
16117c478bd9Sstevel@tonic-gate {
16127c478bd9Sstevel@tonic-gate switch (ie->ds_type) {
16137c478bd9Sstevel@tonic-gate
1614d04ccbb3Scarlsonj case DSYM_DUID:
1615d04ccbb3Scarlsonj case DSYM_DOMAIN:
16167c478bd9Sstevel@tonic-gate case DSYM_ASCII:
16177c478bd9Sstevel@tonic-gate case DSYM_OCTET:
16187c478bd9Sstevel@tonic-gate case DSYM_SNUMBER8:
16197c478bd9Sstevel@tonic-gate case DSYM_UNUMBER8:
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate return (1);
16227c478bd9Sstevel@tonic-gate
16237c478bd9Sstevel@tonic-gate case DSYM_SNUMBER16:
16247c478bd9Sstevel@tonic-gate case DSYM_UNUMBER16:
16257c478bd9Sstevel@tonic-gate
16267c478bd9Sstevel@tonic-gate return (2);
16277c478bd9Sstevel@tonic-gate
1628d04ccbb3Scarlsonj case DSYM_UNUMBER24:
1629d04ccbb3Scarlsonj
1630d04ccbb3Scarlsonj return (3);
1631d04ccbb3Scarlsonj
16327c478bd9Sstevel@tonic-gate case DSYM_SNUMBER32:
16337c478bd9Sstevel@tonic-gate case DSYM_UNUMBER32:
16347c478bd9Sstevel@tonic-gate case DSYM_IP:
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate return (4);
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate case DSYM_SNUMBER64:
16397c478bd9Sstevel@tonic-gate case DSYM_UNUMBER64:
16407c478bd9Sstevel@tonic-gate
16417c478bd9Sstevel@tonic-gate return (8);
16427c478bd9Sstevel@tonic-gate
16437c478bd9Sstevel@tonic-gate case DSYM_NUMBER:
16447c478bd9Sstevel@tonic-gate
16457c478bd9Sstevel@tonic-gate return (ie->ds_gran);
1646d04ccbb3Scarlsonj
1647d04ccbb3Scarlsonj case DSYM_IPV6:
1648d04ccbb3Scarlsonj
1649d04ccbb3Scarlsonj return (sizeof (in6_addr_t));
16507c478bd9Sstevel@tonic-gate }
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate return (0);
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate /*
16567c478bd9Sstevel@tonic-gate * itabcode_to_dsymcode(): maps an inittab category code to its dsym
16577c478bd9Sstevel@tonic-gate * representation
16587c478bd9Sstevel@tonic-gate *
16597c478bd9Sstevel@tonic-gate * input: uchar_t: the inittab category code
16607c478bd9Sstevel@tonic-gate * output: dsym_category_t: the dsym category code
16617c478bd9Sstevel@tonic-gate */
1662d04ccbb3Scarlsonj
16637c478bd9Sstevel@tonic-gate static dsym_category_t
itabcode_to_dsymcode(uchar_t itabcode)16647c478bd9Sstevel@tonic-gate itabcode_to_dsymcode(uchar_t itabcode)
16657c478bd9Sstevel@tonic-gate {
16667c478bd9Sstevel@tonic-gate
16677c478bd9Sstevel@tonic-gate unsigned int i;
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate for (i = 0; i < ITAB_CAT_COUNT; i++)
16707c478bd9Sstevel@tonic-gate if (category_map[i].cme_itabcode == itabcode)
16717c478bd9Sstevel@tonic-gate return (category_map[i].cme_dsymcode);
16727c478bd9Sstevel@tonic-gate
16737c478bd9Sstevel@tonic-gate return (DSYM_BAD_CAT);
16747c478bd9Sstevel@tonic-gate }
16757c478bd9Sstevel@tonic-gate
16767c478bd9Sstevel@tonic-gate /*
16777c478bd9Sstevel@tonic-gate * category_to_code(): maps a category name to its numeric representation
16787c478bd9Sstevel@tonic-gate *
16797c478bd9Sstevel@tonic-gate * input: const char *: the category name
16807c478bd9Sstevel@tonic-gate * output: uchar_t: its internal code (numeric representation)
16817c478bd9Sstevel@tonic-gate */
1682d04ccbb3Scarlsonj
16837c478bd9Sstevel@tonic-gate static uchar_t
category_to_code(const char * category)16847c478bd9Sstevel@tonic-gate category_to_code(const char *category)
16857c478bd9Sstevel@tonic-gate {
16867c478bd9Sstevel@tonic-gate unsigned int i;
16877c478bd9Sstevel@tonic-gate
16887c478bd9Sstevel@tonic-gate for (i = 0; i < ITAB_CAT_COUNT; i++)
16897c478bd9Sstevel@tonic-gate if (strcasecmp(category_map[i].cme_name, category) == 0)
16907c478bd9Sstevel@tonic-gate return (category_map[i].cme_itabcode);
16917c478bd9Sstevel@tonic-gate
16927c478bd9Sstevel@tonic-gate return (0);
16937c478bd9Sstevel@tonic-gate }
16947c478bd9Sstevel@tonic-gate
16957c478bd9Sstevel@tonic-gate /*
16967c478bd9Sstevel@tonic-gate * our internal table of DHCP option values, used by inittab_verify()
16977c478bd9Sstevel@tonic-gate */
16987c478bd9Sstevel@tonic-gate static dhcp_symbol_t inittab_table[] =
16997c478bd9Sstevel@tonic-gate {
17007c478bd9Sstevel@tonic-gate { DSYM_INTERNAL, 1024, "Hostname", DSYM_BOOL, 0, 0 },
17017c478bd9Sstevel@tonic-gate { DSYM_INTERNAL, 1025, "LeaseNeg", DSYM_BOOL, 0, 0 },
17027c478bd9Sstevel@tonic-gate { DSYM_INTERNAL, 1026, "EchoVC", DSYM_BOOL, 0, 0 },
17037c478bd9Sstevel@tonic-gate { DSYM_INTERNAL, 1027, "BootPath", DSYM_ASCII, 1, 128 },
17047c478bd9Sstevel@tonic-gate { DSYM_FIELD, 0, "Opcode", DSYM_UNUMBER8, 1, 1 },
17057c478bd9Sstevel@tonic-gate { DSYM_FIELD, 1, "Htype", DSYM_UNUMBER8, 1, 1 },
17067c478bd9Sstevel@tonic-gate { DSYM_FIELD, 2, "HLen", DSYM_UNUMBER8, 1, 1 },
17077c478bd9Sstevel@tonic-gate { DSYM_FIELD, 3, "Hops", DSYM_UNUMBER8, 1, 1 },
17087c478bd9Sstevel@tonic-gate { DSYM_FIELD, 4, "Xid", DSYM_UNUMBER32, 1, 1 },
17097c478bd9Sstevel@tonic-gate { DSYM_FIELD, 8, "Secs", DSYM_UNUMBER16, 1, 1 },
17107c478bd9Sstevel@tonic-gate { DSYM_FIELD, 10, "Flags", DSYM_OCTET, 1, 2 },
17117c478bd9Sstevel@tonic-gate { DSYM_FIELD, 12, "Ciaddr", DSYM_IP, 1, 1 },
17127c478bd9Sstevel@tonic-gate { DSYM_FIELD, 16, "Yiaddr", DSYM_IP, 1, 1 },
17137c478bd9Sstevel@tonic-gate { DSYM_FIELD, 20, "BootSrvA", DSYM_IP, 1, 1 },
17147c478bd9Sstevel@tonic-gate { DSYM_FIELD, 24, "Giaddr", DSYM_IP, 1, 1 },
17157c478bd9Sstevel@tonic-gate { DSYM_FIELD, 28, "Chaddr", DSYM_OCTET, 1, 16 },
17167c478bd9Sstevel@tonic-gate { DSYM_FIELD, 44, "BootSrvN", DSYM_ASCII, 1, 64 },
17177c478bd9Sstevel@tonic-gate { DSYM_FIELD, 108, "BootFile", DSYM_ASCII, 1, 128 },
17187c478bd9Sstevel@tonic-gate { DSYM_FIELD, 236, "Magic", DSYM_OCTET, 1, 4 },
17197c478bd9Sstevel@tonic-gate { DSYM_FIELD, 240, "Options", DSYM_OCTET, 1, 60 },
17207c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 1, "Subnet", DSYM_IP, 1, 1 },
17217c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 2, "UTCoffst", DSYM_SNUMBER32, 1, 1 },
17227c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 3, "Router", DSYM_IP, 1, 0 },
17237c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 4, "Timeserv", DSYM_IP, 1, 0 },
17247c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 5, "IEN116ns", DSYM_IP, 1, 0 },
17257c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 6, "DNSserv", DSYM_IP, 1, 0 },
17267c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 7, "Logserv", DSYM_IP, 1, 0 },
17277c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 8, "Cookie", DSYM_IP, 1, 0 },
17287c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 9, "Lprserv", DSYM_IP, 1, 0 },
17297c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 10, "Impress", DSYM_IP, 1, 0 },
17307c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 11, "Resource", DSYM_IP, 1, 0 },
17317c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 12, "Hostname", DSYM_ASCII, 1, 0 },
17327c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 13, "Bootsize", DSYM_UNUMBER16, 1, 1 },
17337c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 14, "Dumpfile", DSYM_ASCII, 1, 0 },
17347c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 15, "DNSdmain", DSYM_ASCII, 1, 0 },
17357c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 16, "Swapserv", DSYM_IP, 1, 1 },
17367c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 17, "Rootpath", DSYM_ASCII, 1, 0 },
17377c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 18, "ExtendP", DSYM_ASCII, 1, 0 },
17387c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 19, "IpFwdF", DSYM_UNUMBER8, 1, 1 },
17397c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 20, "NLrouteF", DSYM_UNUMBER8, 1, 1 },
17407c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 21, "PFilter", DSYM_IP, 2, 0 },
17417c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 22, "MaxIpSiz", DSYM_UNUMBER16, 1, 1 },
17427c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 23, "IpTTL", DSYM_UNUMBER8, 1, 1 },
17437c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 24, "PathTO", DSYM_UNUMBER32, 1, 1 },
17447c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 25, "PathTbl", DSYM_UNUMBER16, 1, 0 },
17457c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 26, "MTU", DSYM_UNUMBER16, 1, 1 },
17467c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 27, "SameMtuF", DSYM_UNUMBER8, 1, 1 },
17477c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 28, "Broadcst", DSYM_IP, 1, 1 },
17487c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 29, "MaskDscF", DSYM_UNUMBER8, 1, 1 },
17497c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 30, "MaskSupF", DSYM_UNUMBER8, 1, 1 },
17507c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 31, "RDiscvyF", DSYM_UNUMBER8, 1, 1 },
17517c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 32, "RSolictS", DSYM_IP, 1, 1 },
17527c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 33, "StaticRt", DSYM_IP, 2, 0 },
17537c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 34, "TrailerF", DSYM_UNUMBER8, 1, 1 },
17547c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 35, "ArpTimeO", DSYM_UNUMBER32, 1, 1 },
17557c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 36, "EthEncap", DSYM_UNUMBER8, 1, 1 },
17567c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 37, "TcpTTL", DSYM_UNUMBER8, 1, 1 },
17577c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 38, "TcpKaInt", DSYM_UNUMBER32, 1, 1 },
17587c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 39, "TcpKaGbF", DSYM_UNUMBER8, 1, 1 },
17597c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 40, "NISdmain", DSYM_ASCII, 1, 0 },
17607c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 41, "NISservs", DSYM_IP, 1, 0 },
17617c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 42, "NTPservs", DSYM_IP, 1, 0 },
17627c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 43, "Vendor", DSYM_OCTET, 1, 0 },
17637c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 44, "NetBNms", DSYM_IP, 1, 0 },
17647c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 45, "NetBDsts", DSYM_IP, 1, 0 },
17657c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 46, "NetBNdT", DSYM_UNUMBER8, 1, 1 },
17667c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 47, "NetBScop", DSYM_ASCII, 1, 0 },
17677c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 48, "XFontSrv", DSYM_IP, 1, 0 },
17687c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 49, "XDispMgr", DSYM_IP, 1, 0 },
17697c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 50, "ReqIP", DSYM_IP, 1, 1 },
17707c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 51, "LeaseTim", DSYM_UNUMBER32, 1, 1 },
17717c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 52, "OptOvrld", DSYM_UNUMBER8, 1, 1 },
17727c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 53, "DHCPType", DSYM_UNUMBER8, 1, 1 },
17737c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 54, "ServerID", DSYM_IP, 1, 1 },
17747c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 55, "ReqList", DSYM_OCTET, 1, 0 },
17757c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 56, "Message", DSYM_ASCII, 1, 0 },
17767c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 57, "DHCP_MTU", DSYM_UNUMBER16, 1, 1 },
17777c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 58, "T1Time", DSYM_UNUMBER32, 1, 1 },
17787c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 59, "T2Time", DSYM_UNUMBER32, 1, 1 },
17797c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 60, "ClassID", DSYM_ASCII, 1, 0 },
17807c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 61, "ClientID", DSYM_OCTET, 1, 0 },
17817c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 62, "NW_dmain", DSYM_ASCII, 1, 0 },
17827c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 63, "NWIPOpts", DSYM_OCTET, 1, 128 },
17837c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 64, "NIS+dom", DSYM_ASCII, 1, 0 },
17847c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 65, "NIS+serv", DSYM_IP, 1, 0 },
17857c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 66, "TFTPsrvN", DSYM_ASCII, 1, 64 },
17867c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 67, "OptBootF", DSYM_ASCII, 1, 128 },
17877c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 68, "MblIPAgt", DSYM_IP, 1, 0 },
17887c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 69, "SMTPserv", DSYM_IP, 1, 0 },
17897c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 70, "POP3serv", DSYM_IP, 1, 0 },
17907c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 71, "NNTPserv", DSYM_IP, 1, 0 },
17917c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 72, "WWWservs", DSYM_IP, 1, 0 },
17927c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 73, "Fingersv", DSYM_IP, 1, 0 },
17937c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 74, "IRCservs", DSYM_IP, 1, 0 },
17947c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 75, "STservs", DSYM_IP, 1, 0 },
17957c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 76, "STDAservs", DSYM_IP, 1, 0 },
17967c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 77, "UserClas", DSYM_ASCII, 1, 0 },
17977c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 78, "SLP_DA", DSYM_OCTET, 1, 0 },
17987c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 79, "SLP_SS", DSYM_OCTET, 1, 0 },
17997c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 82, "AgentOpt", DSYM_OCTET, 1, 0 },
18007c478bd9Sstevel@tonic-gate { DSYM_STANDARD, 89, "FQDN", DSYM_OCTET, 1, 0 },
18017c478bd9Sstevel@tonic-gate { 0, 0, "", 0, 0, 0 }
18027c478bd9Sstevel@tonic-gate };
1803