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.
2448bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate #include <stdarg.h>
337c478bd9Sstevel@tonic-gate #include <limits.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
357c478bd9Sstevel@tonic-gate #include <libgen.h>
367c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
377c478bd9Sstevel@tonic-gate #include <sys/socket.h>
38d04ccbb3Scarlsonj #include <net/if_arp.h>
397c478bd9Sstevel@tonic-gate #include <netinet/in.h>
407c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
427c478bd9Sstevel@tonic-gate #include <libinetutil.h>
43d04ccbb3Scarlsonj #include <libdlpi.h>
44d04ccbb3Scarlsonj #include <netinet/dhcp6.h>
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include "dhcp_symbol.h"
477c478bd9Sstevel@tonic-gate #include "dhcp_inittab.h"
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate static void inittab_msg(const char *, ...);
507c478bd9Sstevel@tonic-gate static uchar_t category_to_code(const char *);
517c478bd9Sstevel@tonic-gate static boolean_t encode_number(uint8_t, uint8_t, boolean_t, uint8_t,
527c478bd9Sstevel@tonic-gate const char *, uint8_t *, int *);
537c478bd9Sstevel@tonic-gate static boolean_t decode_number(uint8_t, uint8_t, boolean_t, uint8_t,
547c478bd9Sstevel@tonic-gate const uint8_t *, char *, int *);
557c478bd9Sstevel@tonic-gate static dhcp_symbol_t *inittab_lookup(uchar_t, char, const char *, int32_t,
567c478bd9Sstevel@tonic-gate size_t *);
577c478bd9Sstevel@tonic-gate static dsym_category_t itabcode_to_dsymcode(uchar_t);
587c478bd9Sstevel@tonic-gate static boolean_t parse_entry(char *, char **);
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * forward declaration of our internal inittab_table[]. too bulky to put
627c478bd9Sstevel@tonic-gate * up front -- check the end of this file for its definition.
63d04ccbb3Scarlsonj *
64d04ccbb3Scarlsonj * Note: we have only an IPv4 version here. The inittab_verify() function is
65d04ccbb3Scarlsonj * used by the DHCP server and manager. We'll need a new function if the
66d04ccbb3Scarlsonj * server is extended to DHCPv6.
677c478bd9Sstevel@tonic-gate */
687c478bd9Sstevel@tonic-gate static dhcp_symbol_t inittab_table[];
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate * the number of fields in the inittab and names for the fields. note that
727c478bd9Sstevel@tonic-gate * this order is meaningful to parse_entry(); other functions should just
737c478bd9Sstevel@tonic-gate * use them as indexes into the array returned from parse_entry().
747c478bd9Sstevel@tonic-gate */
757c478bd9Sstevel@tonic-gate #define ITAB_FIELDS 7
767c478bd9Sstevel@tonic-gate enum { ITAB_NAME, ITAB_CODE, ITAB_TYPE, ITAB_GRAN, ITAB_MAX, ITAB_CONS,
777c478bd9Sstevel@tonic-gate ITAB_CAT };
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate * the category_map_entry_t is used to map the inittab category codes to
817c478bd9Sstevel@tonic-gate * the dsym codes. the reason the codes are different is that the inittab
827c478bd9Sstevel@tonic-gate * needs to have the codes be ORable such that queries can retrieve more
837c478bd9Sstevel@tonic-gate * than one category at a time. this map is also used to map the inittab
847c478bd9Sstevel@tonic-gate * string representation of a category to its numerical code.
857c478bd9Sstevel@tonic-gate */
867c478bd9Sstevel@tonic-gate typedef struct category_map_entry {
877c478bd9Sstevel@tonic-gate dsym_category_t cme_dsymcode;
887c478bd9Sstevel@tonic-gate char *cme_name;
897c478bd9Sstevel@tonic-gate uchar_t cme_itabcode;
907c478bd9Sstevel@tonic-gate } category_map_entry_t;
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static category_map_entry_t category_map[] = {
937c478bd9Sstevel@tonic-gate { DSYM_STANDARD, "STANDARD", ITAB_CAT_STANDARD },
947c478bd9Sstevel@tonic-gate { DSYM_FIELD, "FIELD", ITAB_CAT_FIELD },
957c478bd9Sstevel@tonic-gate { DSYM_INTERNAL, "INTERNAL", ITAB_CAT_INTERNAL },
967c478bd9Sstevel@tonic-gate { DSYM_VENDOR, "VENDOR", ITAB_CAT_VENDOR },
977c478bd9Sstevel@tonic-gate { DSYM_SITE, "SITE", ITAB_CAT_SITE }
987c478bd9Sstevel@tonic-gate };
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate * inittab_load(): returns all inittab entries with the specified criteria
1027c478bd9Sstevel@tonic-gate *
1037c478bd9Sstevel@tonic-gate * input: uchar_t: the categories the consumer is interested in
1047c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1057c478bd9Sstevel@tonic-gate * size_t *: set to the number of entries returned
1067c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: an array of dynamically allocated entries
1077c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1087c478bd9Sstevel@tonic-gate */
109d04ccbb3Scarlsonj
1107c478bd9Sstevel@tonic-gate dhcp_symbol_t *
inittab_load(uchar_t categories,char consumer,size_t * n_entries)1117c478bd9Sstevel@tonic-gate inittab_load(uchar_t categories, char consumer, size_t *n_entries)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate return (inittab_lookup(categories, consumer, NULL, -1, n_entries));
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate * inittab_getbyname(): returns an inittab entry with the specified criteria
1187c478bd9Sstevel@tonic-gate *
1197c478bd9Sstevel@tonic-gate * input: int: the categories the consumer is interested in
1207c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1217c478bd9Sstevel@tonic-gate * char *: the name of the inittab entry the consumer wants
1227c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure
1237c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1247c478bd9Sstevel@tonic-gate */
125d04ccbb3Scarlsonj
1267c478bd9Sstevel@tonic-gate dhcp_symbol_t *
inittab_getbyname(uchar_t categories,char consumer,const char * name)1277c478bd9Sstevel@tonic-gate inittab_getbyname(uchar_t categories, char consumer, const char *name)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate return (inittab_lookup(categories, consumer, name, -1, NULL));
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate /*
1337c478bd9Sstevel@tonic-gate * inittab_getbycode(): returns an inittab entry with the specified criteria
1347c478bd9Sstevel@tonic-gate *
1357c478bd9Sstevel@tonic-gate * input: uchar_t: the categories the consumer is interested in
1367c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1377c478bd9Sstevel@tonic-gate * uint16_t: the code of the inittab entry the consumer wants
1387c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: a dynamically allocated dhcp_symbol structure
1397c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1407c478bd9Sstevel@tonic-gate */
141d04ccbb3Scarlsonj
1427c478bd9Sstevel@tonic-gate dhcp_symbol_t *
inittab_getbycode(uchar_t categories,char consumer,uint16_t code)1437c478bd9Sstevel@tonic-gate inittab_getbycode(uchar_t categories, char consumer, uint16_t code)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate return (inittab_lookup(categories, consumer, NULL, code, NULL));
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate * inittab_lookup(): returns inittab entries with the specified criteria
1507c478bd9Sstevel@tonic-gate *
1517c478bd9Sstevel@tonic-gate * input: uchar_t: the categories the consumer is interested in
1527c478bd9Sstevel@tonic-gate * char: the consumer type of the caller
1537c478bd9Sstevel@tonic-gate * const char *: the name of the entry the caller is interested
1547c478bd9Sstevel@tonic-gate * in, or NULL if the caller doesn't care
1557c478bd9Sstevel@tonic-gate * int32_t: the code the caller is interested in, or -1 if the
1567c478bd9Sstevel@tonic-gate * caller doesn't care
1577c478bd9Sstevel@tonic-gate * size_t *: set to the number of entries returned
1587c478bd9Sstevel@tonic-gate * output: dhcp_symbol_t *: dynamically allocated dhcp_symbol structures
1597c478bd9Sstevel@tonic-gate * on success, NULL upon failure
1607c478bd9Sstevel@tonic-gate */
161d04ccbb3Scarlsonj
1627c478bd9Sstevel@tonic-gate static dhcp_symbol_t *
inittab_lookup(uchar_t categories,char consumer,const char * name,int32_t code,size_t * n_entriesp)1637c478bd9Sstevel@tonic-gate inittab_lookup(uchar_t categories, char consumer, const char *name,
1647c478bd9Sstevel@tonic-gate int32_t code, size_t *n_entriesp)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate FILE *inittab_fp;
1677c478bd9Sstevel@tonic-gate dhcp_symbol_t *new_entries, *entries = NULL;
1687c478bd9Sstevel@tonic-gate dhcp_symbol_t entry;
1697c478bd9Sstevel@tonic-gate char buffer[ITAB_MAX_LINE_LEN];
1707c478bd9Sstevel@tonic-gate char *fields[ITAB_FIELDS];
1717c478bd9Sstevel@tonic-gate unsigned long line = 0;
1727c478bd9Sstevel@tonic-gate size_t i, n_entries = 0;
173d04ccbb3Scarlsonj const char *inittab_path;
1747c478bd9Sstevel@tonic-gate uchar_t category_code;
1757c478bd9Sstevel@tonic-gate dsym_cdtype_t type;
1767c478bd9Sstevel@tonic-gate
177d04ccbb3Scarlsonj if (categories & ITAB_CAT_V6) {
178d04ccbb3Scarlsonj inittab_path = getenv("DHCP_INITTAB6_PATH");
179d04ccbb3Scarlsonj if (inittab_path == NULL)
180d04ccbb3Scarlsonj inittab_path = ITAB_INITTAB6_PATH;
181d04ccbb3Scarlsonj } else {
182d04ccbb3Scarlsonj inittab_path = getenv("DHCP_INITTAB_PATH");
183d04ccbb3Scarlsonj if (inittab_path == NULL)
184d04ccbb3Scarlsonj inittab_path = ITAB_INITTAB_PATH;
185d04ccbb3Scarlsonj }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate inittab_fp = fopen(inittab_path, "r");
1887c478bd9Sstevel@tonic-gate if (inittab_fp == NULL) {
1897c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: fopen: %s: %s",
190d04ccbb3Scarlsonj inittab_path, strerror(errno));
1917c478bd9Sstevel@tonic-gate return (NULL);
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate (void) bufsplit(",\n", 0, NULL);
1957c478bd9Sstevel@tonic-gate while (fgets(buffer, sizeof (buffer), inittab_fp) != NULL) {
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate line++;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * make sure the string didn't overflow our buffer
2017c478bd9Sstevel@tonic-gate */
2027c478bd9Sstevel@tonic-gate if (strchr(buffer, '\n') == NULL) {
2037c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: too long, "
2047c478bd9Sstevel@tonic-gate "skipping", line);
2057c478bd9Sstevel@tonic-gate continue;
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate * skip `pure comment' lines
2107c478bd9Sstevel@tonic-gate */
2117c478bd9Sstevel@tonic-gate for (i = 0; buffer[i] != '\0'; i++)
2127c478bd9Sstevel@tonic-gate if (isspace(buffer[i]) == 0)
2137c478bd9Sstevel@tonic-gate break;
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate if (buffer[i] == ITAB_COMMENT_CHAR || buffer[i] == '\0')
2167c478bd9Sstevel@tonic-gate continue;
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate * parse the entry out into fields.
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate if (parse_entry(buffer, fields) == B_FALSE) {
2227c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: syntax error, "
2237c478bd9Sstevel@tonic-gate "skipping", line);
2247c478bd9Sstevel@tonic-gate continue;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate /*
2287c478bd9Sstevel@tonic-gate * validate the values in the entries; skip if invalid.
2297c478bd9Sstevel@tonic-gate */
2307c478bd9Sstevel@tonic-gate if (atoi(fields[ITAB_GRAN]) > ITAB_GRAN_MAX) {
2317c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: granularity `%s'"
2327c478bd9Sstevel@tonic-gate " out of range, skipping", line, fields[ITAB_GRAN]);
2337c478bd9Sstevel@tonic-gate continue;
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate if (atoi(fields[ITAB_MAX]) > ITAB_MAX_MAX) {
2377c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: maximum `%s' "
2387c478bd9Sstevel@tonic-gate "out of range, skipping", line, fields[ITAB_MAX]);
2397c478bd9Sstevel@tonic-gate continue;
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate if (dsym_get_type_id(fields[ITAB_TYPE], &type, B_FALSE) !=
2437c478bd9Sstevel@tonic-gate DSYM_SUCCESS) {
2447c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: line %li: type `%s' "
2457c478bd9Sstevel@tonic-gate "is invalid, skipping", line, fields[ITAB_TYPE]);
2467c478bd9Sstevel@tonic-gate continue;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * find out whether this entry of interest to our consumer,
2517c478bd9Sstevel@tonic-gate * and if so, throw it onto the set of entries we'll return.
2527c478bd9Sstevel@tonic-gate * check categories last since it's the most expensive check.
2537c478bd9Sstevel@tonic-gate */
2547c478bd9Sstevel@tonic-gate if (strchr(fields[ITAB_CONS], consumer) == NULL)
2557c478bd9Sstevel@tonic-gate continue;
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate if (code != -1 && atoi(fields[ITAB_CODE]) != code)
2587c478bd9Sstevel@tonic-gate continue;
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate if (name != NULL && strcasecmp(fields[ITAB_NAME], name) != 0)
2617c478bd9Sstevel@tonic-gate continue;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate category_code = category_to_code(fields[ITAB_CAT]);
2647c478bd9Sstevel@tonic-gate if ((category_code & categories) == 0)
2657c478bd9Sstevel@tonic-gate continue;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate * looks like a match. allocate an entry and fill it in
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate new_entries = realloc(entries, (n_entries + 1) *
2717c478bd9Sstevel@tonic-gate sizeof (dhcp_symbol_t));
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate /*
2747c478bd9Sstevel@tonic-gate * if we run out of memory, might as well return what we can
2757c478bd9Sstevel@tonic-gate */
2767c478bd9Sstevel@tonic-gate if (new_entries == NULL) {
2777c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: ran out of memory "
2787c478bd9Sstevel@tonic-gate "allocating dhcp_symbol_t's");
2797c478bd9Sstevel@tonic-gate break;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate entry.ds_max = atoi(fields[ITAB_MAX]);
2837c478bd9Sstevel@tonic-gate entry.ds_code = atoi(fields[ITAB_CODE]);
2847c478bd9Sstevel@tonic-gate entry.ds_type = type;
2857c478bd9Sstevel@tonic-gate entry.ds_gran = atoi(fields[ITAB_GRAN]);
2867c478bd9Sstevel@tonic-gate entry.ds_category = itabcode_to_dsymcode(category_code);
2877c478bd9Sstevel@tonic-gate entry.ds_classes.dc_cnt = 0;
2887c478bd9Sstevel@tonic-gate entry.ds_classes.dc_names = NULL;
2897c478bd9Sstevel@tonic-gate (void) strlcpy(entry.ds_name, fields[ITAB_NAME],
2907c478bd9Sstevel@tonic-gate sizeof (entry.ds_name));
291d04ccbb3Scarlsonj entry.ds_dhcpv6 = (categories & ITAB_CAT_V6) ? 1 : 0;
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate entries = new_entries;
2947c478bd9Sstevel@tonic-gate entries[n_entries++] = entry;
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate if (ferror(inittab_fp) != 0) {
2987c478bd9Sstevel@tonic-gate inittab_msg("inittab_lookup: error on inittab stream");
2997c478bd9Sstevel@tonic-gate clearerr(inittab_fp);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate (void) fclose(inittab_fp);
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate if (n_entriesp != NULL)
3057c478bd9Sstevel@tonic-gate *n_entriesp = n_entries;
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate return (entries);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate /*
3117c478bd9Sstevel@tonic-gate * parse_entry(): parses an entry out into its constituent fields
3127c478bd9Sstevel@tonic-gate *
3137c478bd9Sstevel@tonic-gate * input: char *: the entry
3147c478bd9Sstevel@tonic-gate * char **: an array of ITAB_FIELDS length which contains
3157c478bd9Sstevel@tonic-gate * pointers into the entry on upon return
3167c478bd9Sstevel@tonic-gate * output: boolean_t: B_TRUE on success, B_FALSE on failure
3177c478bd9Sstevel@tonic-gate */
318d04ccbb3Scarlsonj
3197c478bd9Sstevel@tonic-gate static boolean_t
parse_entry(char * entry,char ** fields)3207c478bd9Sstevel@tonic-gate parse_entry(char *entry, char **fields)
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate char *category, *spacep;
3237c478bd9Sstevel@tonic-gate size_t n_fields, i;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * due to a mistake made long ago, the first and second fields of
3277c478bd9Sstevel@tonic-gate * each entry are not separated by a comma, but rather by
3287c478bd9Sstevel@tonic-gate * whitespace -- have bufsplit() treat the two fields as one, then
3297c478bd9Sstevel@tonic-gate * pull them apart afterwards.
3307c478bd9Sstevel@tonic-gate */
3317c478bd9Sstevel@tonic-gate n_fields = bufsplit(entry, ITAB_FIELDS - 1, fields);
3327c478bd9Sstevel@tonic-gate if (n_fields != (ITAB_FIELDS - 1))
3337c478bd9Sstevel@tonic-gate return (B_FALSE);
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /*
3367c478bd9Sstevel@tonic-gate * pull the first and second fields apart. this is complicated
3377c478bd9Sstevel@tonic-gate * since the first field can contain embedded whitespace (so we
3387c478bd9Sstevel@tonic-gate * must separate the two fields by the last span of whitespace).
3397c478bd9Sstevel@tonic-gate *
3407c478bd9Sstevel@tonic-gate * first, find the initial span of whitespace. if there isn't one,
3417c478bd9Sstevel@tonic-gate * then the entry is malformed.
3427c478bd9Sstevel@tonic-gate */
3437c478bd9Sstevel@tonic-gate category = strpbrk(fields[ITAB_NAME], " \t");
3447c478bd9Sstevel@tonic-gate if (category == NULL)
3457c478bd9Sstevel@tonic-gate return (B_FALSE);
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate * find the last span of whitespace.
3497c478bd9Sstevel@tonic-gate */
3507c478bd9Sstevel@tonic-gate do {
3517c478bd9Sstevel@tonic-gate while (isspace(*category))
3527c478bd9Sstevel@tonic-gate category++;
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate spacep = strpbrk(category, " \t");
3557c478bd9Sstevel@tonic-gate if (spacep != NULL)
3567c478bd9Sstevel@tonic-gate category = spacep;
3577c478bd9Sstevel@tonic-gate } while (spacep != NULL);
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * NUL-terminate the first byte of the last span of whitespace, so
3617c478bd9Sstevel@tonic-gate * that the first field doesn't have any residual trailing
3627c478bd9Sstevel@tonic-gate * whitespace.
3637c478bd9Sstevel@tonic-gate */
3647c478bd9Sstevel@tonic-gate spacep = category - 1;
3657c478bd9Sstevel@tonic-gate while (isspace(*spacep))
3667c478bd9Sstevel@tonic-gate spacep--;
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate if (spacep <= fields[0])
3697c478bd9Sstevel@tonic-gate return (B_FALSE);
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate *++spacep = '\0';
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate * remove any whitespace from the fields.
3757c478bd9Sstevel@tonic-gate */
3767c478bd9Sstevel@tonic-gate for (i = 0; i < n_fields; i++) {
3777c478bd9Sstevel@tonic-gate while (isspace(*fields[i]))
3787c478bd9Sstevel@tonic-gate fields[i]++;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate fields[ITAB_CAT] = category;
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate return (B_TRUE);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate * inittab_verify(): verifies that a given inittab entry matches an internal
3877c478bd9Sstevel@tonic-gate * definition
3887c478bd9Sstevel@tonic-gate *
3897c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the inittab entry to verify
3907c478bd9Sstevel@tonic-gate * dhcp_symbol_t *: if non-NULL, a place to store the internal
3917c478bd9Sstevel@tonic-gate * inittab entry upon return
3927c478bd9Sstevel@tonic-gate * output: int: ITAB_FAILURE, ITAB_SUCCESS, or ITAB_UNKNOWN
393d04ccbb3Scarlsonj *
394d04ccbb3Scarlsonj * notes: IPv4 only
3957c478bd9Sstevel@tonic-gate */
396d04ccbb3Scarlsonj
3977c478bd9Sstevel@tonic-gate int
inittab_verify(const dhcp_symbol_t * inittab_ent,dhcp_symbol_t * internal_ent)398d04ccbb3Scarlsonj inittab_verify(const dhcp_symbol_t *inittab_ent, dhcp_symbol_t *internal_ent)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate unsigned int i;
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate for (i = 0; inittab_table[i].ds_name[0] != '\0'; i++) {
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate if (inittab_ent->ds_category != inittab_table[i].ds_category)
4057c478bd9Sstevel@tonic-gate continue;
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate if (inittab_ent->ds_code == inittab_table[i].ds_code) {
4087c478bd9Sstevel@tonic-gate if (internal_ent != NULL)
4097c478bd9Sstevel@tonic-gate *internal_ent = inittab_table[i];
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate if (inittab_table[i].ds_type != inittab_ent->ds_type ||
4127c478bd9Sstevel@tonic-gate inittab_table[i].ds_gran != inittab_ent->ds_gran ||
4137c478bd9Sstevel@tonic-gate inittab_table[i].ds_max != inittab_ent->ds_max)
4147c478bd9Sstevel@tonic-gate return (ITAB_FAILURE);
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate return (ITAB_SUCCESS);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate return (ITAB_UNKNOWN);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate
423d04ccbb3Scarlsonj /*
424d04ccbb3Scarlsonj * get_hw_type(): interpret ",hwtype" in the input string, as part of a DUID.
425d04ccbb3Scarlsonj * The hwtype string is optional, and must be 0-65535 if
426d04ccbb3Scarlsonj * present.
427d04ccbb3Scarlsonj *
428d04ccbb3Scarlsonj * input: char **: pointer to string pointer
429d04ccbb3Scarlsonj * int *: error return value
430d04ccbb3Scarlsonj * output: int: hardware type, or -1 for empty, or -2 for error.
431d04ccbb3Scarlsonj */
432d04ccbb3Scarlsonj
433d04ccbb3Scarlsonj static int
get_hw_type(char ** strp,int * ierrnop)434d04ccbb3Scarlsonj get_hw_type(char **strp, int *ierrnop)
435d04ccbb3Scarlsonj {
436d04ccbb3Scarlsonj char *str = *strp;
437d04ccbb3Scarlsonj ulong_t hwtype;
438d04ccbb3Scarlsonj
439d04ccbb3Scarlsonj if (*str++ != ',') {
440d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
441d04ccbb3Scarlsonj return (-2);
442d04ccbb3Scarlsonj }
443d04ccbb3Scarlsonj if (*str == ',' || *str == '\0') {
444d04ccbb3Scarlsonj *strp = str;
445d04ccbb3Scarlsonj return (-1);
446d04ccbb3Scarlsonj }
447d04ccbb3Scarlsonj hwtype = strtoul(str, strp, 0);
448d04ccbb3Scarlsonj if (errno != 0 || *strp == str || hwtype > 65535) {
449d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
450d04ccbb3Scarlsonj return (-2);
451d04ccbb3Scarlsonj } else {
452d04ccbb3Scarlsonj return ((int)hwtype);
453d04ccbb3Scarlsonj }
454d04ccbb3Scarlsonj }
455d04ccbb3Scarlsonj
456d04ccbb3Scarlsonj /*
457d04ccbb3Scarlsonj * get_mac_addr(): interpret ",macaddr" in the input string, as part of a DUID.
458d04ccbb3Scarlsonj * The 'macaddr' may be a hex string (in any standard format),
459d04ccbb3Scarlsonj * or the name of a physical interface. If an interface name
460d04ccbb3Scarlsonj * is given, then the interface type is extracted as well.
461d04ccbb3Scarlsonj *
462d04ccbb3Scarlsonj * input: const char *: input string
463d04ccbb3Scarlsonj * int *: error return value
464d04ccbb3Scarlsonj * uint16_t *: hardware type output (network byte order)
465d04ccbb3Scarlsonj * int: hardware type input; -1 for empty
466d04ccbb3Scarlsonj * uchar_t *: output buffer for MAC address
467d04ccbb3Scarlsonj * output: int: length of MAC address, or -1 for error
468d04ccbb3Scarlsonj */
469d04ccbb3Scarlsonj
470d04ccbb3Scarlsonj static int
get_mac_addr(const char * str,int * ierrnop,uint16_t * hwret,int hwtype,uchar_t * outbuf)471d04ccbb3Scarlsonj get_mac_addr(const char *str, int *ierrnop, uint16_t *hwret, int hwtype,
472d04ccbb3Scarlsonj uchar_t *outbuf)
473d04ccbb3Scarlsonj {
474d04ccbb3Scarlsonj int maclen;
475d04ccbb3Scarlsonj int dig, val;
476c7e4935fSss dlpi_handle_t dh;
477c7e4935fSss dlpi_info_t dlinfo;
478d04ccbb3Scarlsonj char chr;
479d04ccbb3Scarlsonj
480d04ccbb3Scarlsonj if (*str != '\0') {
481d04ccbb3Scarlsonj if (*str++ != ',')
482d04ccbb3Scarlsonj goto failed;
483c7e4935fSss if (dlpi_open(str, &dh, 0) != DLPI_SUCCESS) {
484d04ccbb3Scarlsonj maclen = 0;
485d04ccbb3Scarlsonj dig = val = 0;
486d04ccbb3Scarlsonj /*
487d04ccbb3Scarlsonj * Allow MAC addresses with separators matching regexp
488d04ccbb3Scarlsonj * (:|-| *).
489d04ccbb3Scarlsonj */
490d04ccbb3Scarlsonj while ((chr = *str++) != '\0') {
491d04ccbb3Scarlsonj if (isdigit(chr)) {
492d04ccbb3Scarlsonj val = (val << 4) + chr - '0';
493d04ccbb3Scarlsonj } else if (isxdigit(chr)) {
494d04ccbb3Scarlsonj val = (val << 4) + chr -
495d04ccbb3Scarlsonj (isupper(chr) ? 'A' : 'a') + 10;
496d04ccbb3Scarlsonj } else if (isspace(chr) && dig == 0) {
497d04ccbb3Scarlsonj continue;
498d04ccbb3Scarlsonj } else if (chr == ':' || chr == '-' ||
499d04ccbb3Scarlsonj isspace(chr)) {
500d04ccbb3Scarlsonj dig = 1;
501d04ccbb3Scarlsonj } else {
502d04ccbb3Scarlsonj goto failed;
503d04ccbb3Scarlsonj }
504d04ccbb3Scarlsonj if (++dig == 2) {
505d04ccbb3Scarlsonj *outbuf++ = val;
506d04ccbb3Scarlsonj maclen++;
507d04ccbb3Scarlsonj dig = val = 0;
508d04ccbb3Scarlsonj }
509d04ccbb3Scarlsonj }
510d04ccbb3Scarlsonj } else {
51135b6f047SDavid Höppner if (dlpi_bind(dh, DLPI_ANY_SAP, NULL) !=
51235b6f047SDavid Höppner DLPI_SUCCESS || dlpi_info(dh, &dlinfo, 0) !=
51335b6f047SDavid Höppner DLPI_SUCCESS) {
514c7e4935fSss dlpi_close(dh);
515d04ccbb3Scarlsonj goto failed;
516c7e4935fSss }
517c7e4935fSss maclen = dlinfo.di_physaddrlen;
518c7e4935fSss (void) memcpy(outbuf, dlinfo.di_physaddr, maclen);
519c7e4935fSss dlpi_close(dh);
520d04ccbb3Scarlsonj if (hwtype == -1)
521948f2876Sss hwtype = dlpi_arptype(dlinfo.di_mactype);
522d04ccbb3Scarlsonj }
523d04ccbb3Scarlsonj }
524d04ccbb3Scarlsonj if (hwtype == -1)
525d04ccbb3Scarlsonj goto failed;
526d04ccbb3Scarlsonj *hwret = htons(hwtype);
527d04ccbb3Scarlsonj return (maclen);
528d04ccbb3Scarlsonj
529d04ccbb3Scarlsonj failed:
530d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
531d04ccbb3Scarlsonj return (-1);
532d04ccbb3Scarlsonj }
533d04ccbb3Scarlsonj
5347c478bd9Sstevel@tonic-gate /*
5357c478bd9Sstevel@tonic-gate * inittab_encode_e(): converts a string representation of a given datatype into
5367c478bd9Sstevel@tonic-gate * binary; used for encoding ascii values into a form that
5377c478bd9Sstevel@tonic-gate * can be put in DHCP packets to be sent on the wire.
5387c478bd9Sstevel@tonic-gate *
539d04ccbb3Scarlsonj * input: const dhcp_symbol_t *: the entry describing the value option
5407c478bd9Sstevel@tonic-gate * const char *: the value to convert
5417c478bd9Sstevel@tonic-gate * uint16_t *: set to the length of the binary data returned
5427c478bd9Sstevel@tonic-gate * boolean_t: if false, return a full DHCP option
543d04ccbb3Scarlsonj * int *: error return value
5447c478bd9Sstevel@tonic-gate * output: uchar_t *: a dynamically allocated byte array with converted data
5457c478bd9Sstevel@tonic-gate */
546d04ccbb3Scarlsonj
5477c478bd9Sstevel@tonic-gate uchar_t *
inittab_encode_e(const dhcp_symbol_t * ie,const char * value,uint16_t * lengthp,boolean_t just_payload,int * ierrnop)548d04ccbb3Scarlsonj inittab_encode_e(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp,
5497c478bd9Sstevel@tonic-gate boolean_t just_payload, int *ierrnop)
5507c478bd9Sstevel@tonic-gate {
551d04ccbb3Scarlsonj int hlen = 0;
552d04ccbb3Scarlsonj uint16_t length;
5537c478bd9Sstevel@tonic-gate uchar_t n_entries = 0;
5547c478bd9Sstevel@tonic-gate const char *valuep;
5557c478bd9Sstevel@tonic-gate char *currp;
5567c478bd9Sstevel@tonic-gate uchar_t *result = NULL;
557d04ccbb3Scarlsonj uchar_t *optstart;
5587c478bd9Sstevel@tonic-gate unsigned int i;
5597c478bd9Sstevel@tonic-gate uint8_t type_size = inittab_type_to_size(ie);
5607c478bd9Sstevel@tonic-gate boolean_t is_signed;
5617c478bd9Sstevel@tonic-gate uint_t vallen, reslen;
562d04ccbb3Scarlsonj dhcpv6_option_t *d6o;
563d04ccbb3Scarlsonj int type;
564d04ccbb3Scarlsonj char *cp2;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate *ierrnop = 0;
5677c478bd9Sstevel@tonic-gate if (type_size == 0) {
5687c478bd9Sstevel@tonic-gate *ierrnop = ITAB_SYNTAX_ERROR;
5697c478bd9Sstevel@tonic-gate return (NULL);
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate
572d04ccbb3Scarlsonj switch (ie->ds_type) {
573d04ccbb3Scarlsonj case DSYM_ASCII:
5747c478bd9Sstevel@tonic-gate n_entries = strlen(value); /* no NUL */
575d04ccbb3Scarlsonj break;
576d04ccbb3Scarlsonj
577d04ccbb3Scarlsonj case DSYM_OCTET:
5787c478bd9Sstevel@tonic-gate vallen = strlen(value);
5797c478bd9Sstevel@tonic-gate n_entries = vallen / 2;
5807c478bd9Sstevel@tonic-gate n_entries += vallen % 2;
581d04ccbb3Scarlsonj break;
582d04ccbb3Scarlsonj
583d04ccbb3Scarlsonj case DSYM_DOMAIN:
584d04ccbb3Scarlsonj /*
585d04ccbb3Scarlsonj * Maximum (worst-case) encoded length is one byte more than
586d04ccbb3Scarlsonj * the number of characters on input.
587d04ccbb3Scarlsonj */
588d04ccbb3Scarlsonj n_entries = strlen(value) + 1;
589d04ccbb3Scarlsonj break;
590d04ccbb3Scarlsonj
591d04ccbb3Scarlsonj case DSYM_DUID:
592d04ccbb3Scarlsonj /* Worst case is ":::::" */
593d04ccbb3Scarlsonj n_entries = strlen(value);
594c7e4935fSss if (n_entries < DLPI_PHYSADDR_MAX)
595c7e4935fSss n_entries = DLPI_PHYSADDR_MAX;
596d04ccbb3Scarlsonj n_entries += sizeof (duid_llt_t);
597d04ccbb3Scarlsonj break;
598d04ccbb3Scarlsonj
599d04ccbb3Scarlsonj default:
6007c478bd9Sstevel@tonic-gate /*
6017c478bd9Sstevel@tonic-gate * figure out the number of entries by counting the spaces
6027c478bd9Sstevel@tonic-gate * in the value string
6037c478bd9Sstevel@tonic-gate */
6047c478bd9Sstevel@tonic-gate for (valuep = value; valuep++ != NULL; n_entries++)
6057c478bd9Sstevel@tonic-gate valuep = strchr(valuep, ' ');
606d04ccbb3Scarlsonj break;
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate /*
6107c478bd9Sstevel@tonic-gate * if we're gonna return a complete option, then include the
6117c478bd9Sstevel@tonic-gate * option length and code in the size of the packet we allocate
6127c478bd9Sstevel@tonic-gate */
613d04ccbb3Scarlsonj if (!just_payload)
614d04ccbb3Scarlsonj hlen = ie->ds_dhcpv6 ? sizeof (*d6o) : 2;
6157c478bd9Sstevel@tonic-gate
616d04ccbb3Scarlsonj length = n_entries * type_size;
617d04ccbb3Scarlsonj if (hlen + length > 0)
618d04ccbb3Scarlsonj result = malloc(hlen + length);
619d04ccbb3Scarlsonj
620d04ccbb3Scarlsonj if ((optstart = result) != NULL && !just_payload)
621d04ccbb3Scarlsonj optstart += hlen;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate switch (ie->ds_type) {
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate case DSYM_ASCII:
6267c478bd9Sstevel@tonic-gate
627d04ccbb3Scarlsonj if (optstart == NULL) {
628d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
629d04ccbb3Scarlsonj return (NULL);
630d04ccbb3Scarlsonj }
631d04ccbb3Scarlsonj
632d04ccbb3Scarlsonj (void) memcpy(optstart, value, length);
633d04ccbb3Scarlsonj break;
634d04ccbb3Scarlsonj
635d04ccbb3Scarlsonj case DSYM_DOMAIN:
636d04ccbb3Scarlsonj if (optstart == NULL) {
6377c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
6387c478bd9Sstevel@tonic-gate return (NULL);
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate
641d04ccbb3Scarlsonj /*
642d04ccbb3Scarlsonj * Note that this encoder always presents the trailing 0-octet
643d04ccbb3Scarlsonj * when dealing with a list. This means that you can't have
644d04ccbb3Scarlsonj * non-fully-qualified members anywhere but at the end of a
645d04ccbb3Scarlsonj * list (or as the only member of the list).
646d04ccbb3Scarlsonj */
647d04ccbb3Scarlsonj valuep = value;
648d04ccbb3Scarlsonj while (*valuep != '\0') {
649d04ccbb3Scarlsonj int dig, val, inchr;
650d04ccbb3Scarlsonj boolean_t escape;
651d04ccbb3Scarlsonj uchar_t *flen;
652d04ccbb3Scarlsonj
653d04ccbb3Scarlsonj /*
654d04ccbb3Scarlsonj * Skip over whitespace that delimits list members.
655d04ccbb3Scarlsonj */
656d04ccbb3Scarlsonj if (isascii(*valuep) && isspace(*valuep)) {
657d04ccbb3Scarlsonj valuep++;
658d04ccbb3Scarlsonj continue;
659d04ccbb3Scarlsonj }
660d04ccbb3Scarlsonj dig = val = 0;
661d04ccbb3Scarlsonj escape = B_FALSE;
662d04ccbb3Scarlsonj flen = optstart++;
663d04ccbb3Scarlsonj while ((inchr = *valuep) != '\0') {
664d04ccbb3Scarlsonj valuep++;
665d04ccbb3Scarlsonj /*
666d04ccbb3Scarlsonj * Just copy non-ASCII text directly to the
667d04ccbb3Scarlsonj * output string. This simplifies the use of
668d04ccbb3Scarlsonj * other ctype macros below, as, unlike the
669d04ccbb3Scarlsonj * special isascii function, they don't handle
670d04ccbb3Scarlsonj * non-ASCII.
671d04ccbb3Scarlsonj */
672d04ccbb3Scarlsonj if (!isascii(inchr)) {
673d04ccbb3Scarlsonj escape = B_FALSE;
674d04ccbb3Scarlsonj *optstart++ = inchr;
675d04ccbb3Scarlsonj continue;
676d04ccbb3Scarlsonj }
677d04ccbb3Scarlsonj if (escape) {
678d04ccbb3Scarlsonj /*
679d04ccbb3Scarlsonj * Handle any of \D, \DD, or \DDD for
680d04ccbb3Scarlsonj * a digit escape.
681d04ccbb3Scarlsonj */
682d04ccbb3Scarlsonj if (isdigit(inchr)) {
683d04ccbb3Scarlsonj val = val * 10 + inchr - '0';
684d04ccbb3Scarlsonj if (++dig == 3) {
685d04ccbb3Scarlsonj *optstart++ = val;
686d04ccbb3Scarlsonj dig = val = 0;
687d04ccbb3Scarlsonj escape = B_FALSE;
688d04ccbb3Scarlsonj }
689d04ccbb3Scarlsonj continue;
690d04ccbb3Scarlsonj } else if (dig > 0) {
691d04ccbb3Scarlsonj /*
692d04ccbb3Scarlsonj * User terminated \D or \DD
693d04ccbb3Scarlsonj * with non-digit. An error,
69448bbca81SDaniel Hoffman * but we can assume they mean
695d04ccbb3Scarlsonj * to treat as \00D or \0DD.
696d04ccbb3Scarlsonj */
697d04ccbb3Scarlsonj *optstart++ = val;
698d04ccbb3Scarlsonj dig = val = 0;
699d04ccbb3Scarlsonj }
700d04ccbb3Scarlsonj /* Fall through and copy character */
701d04ccbb3Scarlsonj escape = B_FALSE;
702d04ccbb3Scarlsonj } else if (inchr == '\\') {
703d04ccbb3Scarlsonj escape = B_TRUE;
704d04ccbb3Scarlsonj continue;
705d04ccbb3Scarlsonj } else if (inchr == '.') {
706d04ccbb3Scarlsonj /*
707d04ccbb3Scarlsonj * End of component. Write the length
708d04ccbb3Scarlsonj * prefix. If the component is zero
709d04ccbb3Scarlsonj * length (i.e., ".."), the just omit
710d04ccbb3Scarlsonj * it.
711d04ccbb3Scarlsonj */
712d04ccbb3Scarlsonj *flen = (optstart - flen) - 1;
713d04ccbb3Scarlsonj if (*flen > 0)
714d04ccbb3Scarlsonj flen = optstart++;
715d04ccbb3Scarlsonj continue;
716d04ccbb3Scarlsonj } else if (isspace(inchr)) {
717d04ccbb3Scarlsonj /*
718d04ccbb3Scarlsonj * Unescaped space; end of domain name
719d04ccbb3Scarlsonj * in list.
720d04ccbb3Scarlsonj */
721d04ccbb3Scarlsonj break;
722d04ccbb3Scarlsonj }
723d04ccbb3Scarlsonj *optstart++ = inchr;
724d04ccbb3Scarlsonj }
725d04ccbb3Scarlsonj /*
726d04ccbb3Scarlsonj * Handle trailing escape sequence. If string ends
727d04ccbb3Scarlsonj * with \, then assume user wants \ at end of encoded
728d04ccbb3Scarlsonj * string. If it ends with \D or \DD, assume \00D or
729d04ccbb3Scarlsonj * \0DD.
730d04ccbb3Scarlsonj */
731d04ccbb3Scarlsonj if (escape)
732d04ccbb3Scarlsonj *optstart++ = dig > 0 ? val : '\\';
733d04ccbb3Scarlsonj *flen = (optstart - flen) - 1;
734d04ccbb3Scarlsonj /*
735d04ccbb3Scarlsonj * If user specified FQDN with trailing '.', then above
736d04ccbb3Scarlsonj * will result in zero for the last component length.
737d04ccbb3Scarlsonj * We're done, and optstart already points to the start
738d04ccbb3Scarlsonj * of the next in list. Otherwise, we need to write a
739d04ccbb3Scarlsonj * single zero byte to end the entry, if there are more
740d04ccbb3Scarlsonj * entries that will be decoded.
741d04ccbb3Scarlsonj */
742d04ccbb3Scarlsonj while (isascii(*valuep) && isspace(*valuep))
743d04ccbb3Scarlsonj valuep++;
744d04ccbb3Scarlsonj if (*flen > 0 && *valuep != '\0')
745d04ccbb3Scarlsonj *optstart++ = '\0';
746d04ccbb3Scarlsonj }
747d04ccbb3Scarlsonj length = (optstart - result) - hlen;
748d04ccbb3Scarlsonj break;
749d04ccbb3Scarlsonj
750d04ccbb3Scarlsonj case DSYM_DUID:
751d04ccbb3Scarlsonj if (optstart == NULL) {
752d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
753d04ccbb3Scarlsonj return (NULL);
754d04ccbb3Scarlsonj }
755d04ccbb3Scarlsonj
756d04ccbb3Scarlsonj errno = 0;
757d04ccbb3Scarlsonj type = strtoul(value, &currp, 0);
758d04ccbb3Scarlsonj if (errno != 0 || value == currp || type > 65535 ||
759d04ccbb3Scarlsonj (*currp != ',' && *currp != '\0')) {
7607c478bd9Sstevel@tonic-gate free(result);
761d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
7627c478bd9Sstevel@tonic-gate return (NULL);
7637c478bd9Sstevel@tonic-gate }
764d04ccbb3Scarlsonj switch (type) {
765d04ccbb3Scarlsonj case DHCPV6_DUID_LLT: {
766d04ccbb3Scarlsonj duid_llt_t dllt;
767d04ccbb3Scarlsonj int hwtype;
768d04ccbb3Scarlsonj ulong_t tstamp;
769d04ccbb3Scarlsonj int maclen;
770d04ccbb3Scarlsonj
771d04ccbb3Scarlsonj if ((hwtype = get_hw_type(&currp, ierrnop)) == -2) {
772d04ccbb3Scarlsonj free(result);
773d04ccbb3Scarlsonj return (NULL);
774d04ccbb3Scarlsonj }
775d04ccbb3Scarlsonj if (*currp++ != ',') {
776d04ccbb3Scarlsonj free(result);
777d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
778d04ccbb3Scarlsonj return (NULL);
779d04ccbb3Scarlsonj }
780d04ccbb3Scarlsonj if (*currp == ',' || *currp == '\0') {
781d04ccbb3Scarlsonj tstamp = time(NULL) - DUID_TIME_BASE;
782d04ccbb3Scarlsonj } else {
783d04ccbb3Scarlsonj tstamp = strtoul(currp, &cp2, 0);
784d04ccbb3Scarlsonj if (errno != 0 || currp == cp2) {
785d04ccbb3Scarlsonj free(result);
786d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
787d04ccbb3Scarlsonj return (NULL);
788d04ccbb3Scarlsonj }
789d04ccbb3Scarlsonj currp = cp2;
790d04ccbb3Scarlsonj }
791d04ccbb3Scarlsonj maclen = get_mac_addr(currp, ierrnop,
792d04ccbb3Scarlsonj &dllt.dllt_hwtype, hwtype,
793d04ccbb3Scarlsonj optstart + sizeof (dllt));
794d04ccbb3Scarlsonj if (maclen == -1) {
795d04ccbb3Scarlsonj free(result);
796d04ccbb3Scarlsonj return (NULL);
797d04ccbb3Scarlsonj }
798d04ccbb3Scarlsonj dllt.dllt_dutype = htons(type);
799d04ccbb3Scarlsonj dllt.dllt_time = htonl(tstamp);
800d04ccbb3Scarlsonj (void) memcpy(optstart, &dllt, sizeof (dllt));
801d04ccbb3Scarlsonj length = maclen + sizeof (dllt);
802d04ccbb3Scarlsonj break;
803d04ccbb3Scarlsonj }
804d04ccbb3Scarlsonj case DHCPV6_DUID_EN: {
805d04ccbb3Scarlsonj duid_en_t den;
806d04ccbb3Scarlsonj ulong_t enterp;
8077c478bd9Sstevel@tonic-gate
808d04ccbb3Scarlsonj if (*currp++ != ',') {
809d04ccbb3Scarlsonj free(result);
810d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
811d04ccbb3Scarlsonj return (NULL);
812d04ccbb3Scarlsonj }
813d04ccbb3Scarlsonj enterp = strtoul(currp, &cp2, 0);
814d04ccbb3Scarlsonj DHCPV6_SET_ENTNUM(&den, enterp);
815d04ccbb3Scarlsonj if (errno != 0 || currp == cp2 ||
816d04ccbb3Scarlsonj enterp != DHCPV6_GET_ENTNUM(&den) ||
817d04ccbb3Scarlsonj (*cp2 != ',' && *cp2 != '\0')) {
818d04ccbb3Scarlsonj free(result);
819d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
820d04ccbb3Scarlsonj return (NULL);
821d04ccbb3Scarlsonj }
822d04ccbb3Scarlsonj if (*cp2 == ',')
823d04ccbb3Scarlsonj cp2++;
824d04ccbb3Scarlsonj vallen = strlen(cp2);
825d04ccbb3Scarlsonj reslen = (vallen + 1) / 2;
826d04ccbb3Scarlsonj if (hexascii_to_octet(cp2, vallen,
827d04ccbb3Scarlsonj optstart + sizeof (den), &reslen) != 0) {
828d04ccbb3Scarlsonj free(result);
829d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
830d04ccbb3Scarlsonj return (NULL);
831d04ccbb3Scarlsonj }
832d04ccbb3Scarlsonj den.den_dutype = htons(type);
833d04ccbb3Scarlsonj (void) memcpy(optstart, &den, sizeof (den));
834d04ccbb3Scarlsonj length = reslen + sizeof (den);
835d04ccbb3Scarlsonj break;
836d04ccbb3Scarlsonj }
837d04ccbb3Scarlsonj case DHCPV6_DUID_LL: {
838d04ccbb3Scarlsonj duid_ll_t dll;
839d04ccbb3Scarlsonj int hwtype;
840d04ccbb3Scarlsonj int maclen;
841d04ccbb3Scarlsonj
842d04ccbb3Scarlsonj if ((hwtype = get_hw_type(&currp, ierrnop)) == -2) {
843d04ccbb3Scarlsonj free(result);
844d04ccbb3Scarlsonj return (NULL);
845d04ccbb3Scarlsonj }
846d04ccbb3Scarlsonj maclen = get_mac_addr(currp, ierrnop, &dll.dll_hwtype,
847d04ccbb3Scarlsonj hwtype, optstart + sizeof (dll));
848d04ccbb3Scarlsonj if (maclen == -1) {
849d04ccbb3Scarlsonj free(result);
850d04ccbb3Scarlsonj return (NULL);
851d04ccbb3Scarlsonj }
852d04ccbb3Scarlsonj dll.dll_dutype = htons(type);
853d04ccbb3Scarlsonj (void) memcpy(optstart, &dll, sizeof (dll));
854d04ccbb3Scarlsonj length = maclen + sizeof (dll);
855d04ccbb3Scarlsonj break;
856d04ccbb3Scarlsonj }
857d04ccbb3Scarlsonj default:
858d04ccbb3Scarlsonj if (*currp == ',')
859d04ccbb3Scarlsonj currp++;
860d04ccbb3Scarlsonj vallen = strlen(currp);
861d04ccbb3Scarlsonj reslen = (vallen + 1) / 2;
862d04ccbb3Scarlsonj if (hexascii_to_octet(currp, vallen, optstart + 2,
863d04ccbb3Scarlsonj &reslen) != 0) {
864d04ccbb3Scarlsonj free(result);
865d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_NUMBER;
866d04ccbb3Scarlsonj return (NULL);
867d04ccbb3Scarlsonj }
868d04ccbb3Scarlsonj optstart[0] = type >> 8;
869d04ccbb3Scarlsonj optstart[1] = type;
870d04ccbb3Scarlsonj length = reslen + 2;
871d04ccbb3Scarlsonj break;
872d04ccbb3Scarlsonj }
8737c478bd9Sstevel@tonic-gate break;
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate case DSYM_OCTET:
8767c478bd9Sstevel@tonic-gate
877d04ccbb3Scarlsonj if (optstart == NULL) {
8787c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_OCTET;
8797c478bd9Sstevel@tonic-gate return (NULL);
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate reslen = length;
8837c478bd9Sstevel@tonic-gate /* Call libinetutil function to decode */
884d04ccbb3Scarlsonj if (hexascii_to_octet(value, vallen, optstart, &reslen) != 0) {
8857c478bd9Sstevel@tonic-gate free(result);
8867c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_OCTET;
8877c478bd9Sstevel@tonic-gate return (NULL);
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate break;
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate case DSYM_IP:
892d04ccbb3Scarlsonj case DSYM_IPV6:
8937c478bd9Sstevel@tonic-gate
894d04ccbb3Scarlsonj if (optstart == NULL) {
8957c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_IPADDR;
8967c478bd9Sstevel@tonic-gate return (NULL);
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate if (n_entries % ie->ds_gran != 0) {
8997c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_GRAN;
9007c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: number of entries "
9017c478bd9Sstevel@tonic-gate "not compatible with option granularity");
9027c478bd9Sstevel@tonic-gate free(result);
9037c478bd9Sstevel@tonic-gate return (NULL);
9047c478bd9Sstevel@tonic-gate }
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate for (valuep = value, i = 0; i < n_entries; i++, valuep++) {
9077c478bd9Sstevel@tonic-gate
9087c478bd9Sstevel@tonic-gate currp = strchr(valuep, ' ');
9097c478bd9Sstevel@tonic-gate if (currp != NULL)
9107c478bd9Sstevel@tonic-gate *currp = '\0';
911d04ccbb3Scarlsonj if (inet_pton(ie->ds_type == DSYM_IP ? AF_INET :
912d04ccbb3Scarlsonj AF_INET6, valuep, optstart) != 1) {
9137c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_IPADDR;
9147c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: bogus ip address");
9157c478bd9Sstevel@tonic-gate free(result);
9167c478bd9Sstevel@tonic-gate return (NULL);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate valuep = currp;
9207c478bd9Sstevel@tonic-gate if (valuep == NULL) {
9217c478bd9Sstevel@tonic-gate if (i < (n_entries - 1)) {
9227c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOT_ENOUGH_IP;
9237c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: too few "
9247c478bd9Sstevel@tonic-gate "ip addresses");
9257c478bd9Sstevel@tonic-gate free(result);
9267c478bd9Sstevel@tonic-gate return (NULL);
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate break;
9297c478bd9Sstevel@tonic-gate }
930d04ccbb3Scarlsonj optstart += type_size;
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate break;
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate case DSYM_NUMBER: /* FALLTHRU */
9357c478bd9Sstevel@tonic-gate case DSYM_UNUMBER8: /* FALLTHRU */
9367c478bd9Sstevel@tonic-gate case DSYM_SNUMBER8: /* FALLTHRU */
9377c478bd9Sstevel@tonic-gate case DSYM_UNUMBER16: /* FALLTHRU */
9387c478bd9Sstevel@tonic-gate case DSYM_SNUMBER16: /* FALLTHRU */
939d04ccbb3Scarlsonj case DSYM_UNUMBER24: /* FALLTHRU */
9407c478bd9Sstevel@tonic-gate case DSYM_UNUMBER32: /* FALLTHRU */
9417c478bd9Sstevel@tonic-gate case DSYM_SNUMBER32: /* FALLTHRU */
9427c478bd9Sstevel@tonic-gate case DSYM_UNUMBER64: /* FALLTHRU */
9437c478bd9Sstevel@tonic-gate case DSYM_SNUMBER64:
9447c478bd9Sstevel@tonic-gate
945d04ccbb3Scarlsonj if (optstart == NULL) {
9467c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_NUMBER;
9477c478bd9Sstevel@tonic-gate return (NULL);
9487c478bd9Sstevel@tonic-gate }
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate is_signed = (ie->ds_type == DSYM_SNUMBER64 ||
9517c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER32 ||
9527c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER16 ||
9537c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER8);
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate if (encode_number(n_entries, type_size, is_signed, 0, value,
956d04ccbb3Scarlsonj optstart, ierrnop) == B_FALSE) {
9577c478bd9Sstevel@tonic-gate free(result);
9587c478bd9Sstevel@tonic-gate return (NULL);
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate break;
9617c478bd9Sstevel@tonic-gate
9627c478bd9Sstevel@tonic-gate default:
9637c478bd9Sstevel@tonic-gate if (ie->ds_type == DSYM_BOOL)
9647c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_BOOLEAN;
9657c478bd9Sstevel@tonic-gate else
9667c478bd9Sstevel@tonic-gate *ierrnop = ITAB_SYNTAX_ERROR;
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate inittab_msg("inittab_encode: unsupported type `%d'",
9697c478bd9Sstevel@tonic-gate ie->ds_type);
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate free(result);
9727c478bd9Sstevel@tonic-gate return (NULL);
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate /*
976d04ccbb3Scarlsonj * if just_payload is false, then we need to add the option
977d04ccbb3Scarlsonj * code and length fields in.
9787c478bd9Sstevel@tonic-gate */
979d04ccbb3Scarlsonj if (!just_payload) {
980d04ccbb3Scarlsonj if (ie->ds_dhcpv6) {
981d04ccbb3Scarlsonj /* LINTED: alignment */
982d04ccbb3Scarlsonj d6o = (dhcpv6_option_t *)result;
983d04ccbb3Scarlsonj d6o->d6o_code = htons(ie->ds_code);
984d04ccbb3Scarlsonj d6o->d6o_len = htons(length);
985d04ccbb3Scarlsonj } else {
986d04ccbb3Scarlsonj result[0] = ie->ds_code;
987d04ccbb3Scarlsonj result[1] = length;
988d04ccbb3Scarlsonj }
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate if (lengthp != NULL)
992d04ccbb3Scarlsonj *lengthp = length + hlen;
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate return (result);
9957c478bd9Sstevel@tonic-gate }
9967c478bd9Sstevel@tonic-gate
9977c478bd9Sstevel@tonic-gate /*
9987c478bd9Sstevel@tonic-gate * inittab_decode_e(): converts a binary representation of a given datatype into
9997c478bd9Sstevel@tonic-gate * a string; used for decoding DHCP options in a packet off
10007c478bd9Sstevel@tonic-gate * the wire into ascii
10017c478bd9Sstevel@tonic-gate *
10027c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the entry describing the payload option
10037c478bd9Sstevel@tonic-gate * uchar_t *: the payload to convert
10047c478bd9Sstevel@tonic-gate * uint16_t: the payload length (only used if just_payload is true)
10057c478bd9Sstevel@tonic-gate * boolean_t: if false, payload is assumed to be a DHCP option
10067c478bd9Sstevel@tonic-gate * int *: set to extended error code if error occurs.
10077c478bd9Sstevel@tonic-gate * output: char *: a dynamically allocated string containing the converted data
10087c478bd9Sstevel@tonic-gate */
1009d04ccbb3Scarlsonj
10107c478bd9Sstevel@tonic-gate char *
inittab_decode_e(const dhcp_symbol_t * ie,const uchar_t * payload,uint16_t length,boolean_t just_payload,int * ierrnop)1011d04ccbb3Scarlsonj inittab_decode_e(const dhcp_symbol_t *ie, const uchar_t *payload,
1012d04ccbb3Scarlsonj uint16_t length, boolean_t just_payload, int *ierrnop)
10137c478bd9Sstevel@tonic-gate {
1014d04ccbb3Scarlsonj char *resultp, *result = NULL;
1015d04ccbb3Scarlsonj uint_t n_entries;
10167c478bd9Sstevel@tonic-gate struct in_addr in_addr;
1017d04ccbb3Scarlsonj in6_addr_t in6_addr;
10187c478bd9Sstevel@tonic-gate uint8_t type_size = inittab_type_to_size(ie);
10197c478bd9Sstevel@tonic-gate boolean_t is_signed;
1020d04ccbb3Scarlsonj int type;
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate *ierrnop = 0;
10237c478bd9Sstevel@tonic-gate if (type_size == 0) {
10247c478bd9Sstevel@tonic-gate *ierrnop = ITAB_SYNTAX_ERROR;
10257c478bd9Sstevel@tonic-gate return (NULL);
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate
1028d04ccbb3Scarlsonj if (!just_payload) {
1029d04ccbb3Scarlsonj if (ie->ds_dhcpv6) {
1030d04ccbb3Scarlsonj dhcpv6_option_t d6o;
1031d04ccbb3Scarlsonj
1032d04ccbb3Scarlsonj (void) memcpy(&d6o, payload, sizeof (d6o));
1033d04ccbb3Scarlsonj length = ntohs(d6o.d6o_len);
1034d04ccbb3Scarlsonj payload += sizeof (d6o);
1035d04ccbb3Scarlsonj } else {
1036d04ccbb3Scarlsonj length = payload[1];
1037d04ccbb3Scarlsonj payload += 2;
1038d04ccbb3Scarlsonj }
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate /*
10427c478bd9Sstevel@tonic-gate * figure out the number of elements to convert. note that
10437c478bd9Sstevel@tonic-gate * for ds_type NUMBER, the granularity is really 1 since the
10447c478bd9Sstevel@tonic-gate * value of ds_gran is the number of bytes in the number.
10457c478bd9Sstevel@tonic-gate */
10467c478bd9Sstevel@tonic-gate if (ie->ds_type == DSYM_NUMBER)
10477c478bd9Sstevel@tonic-gate n_entries = MIN(ie->ds_max, length / type_size);
10487c478bd9Sstevel@tonic-gate else
10497c478bd9Sstevel@tonic-gate n_entries = MIN(ie->ds_max * ie->ds_gran, length / type_size);
10507c478bd9Sstevel@tonic-gate
10517c478bd9Sstevel@tonic-gate if (n_entries == 0)
10527c478bd9Sstevel@tonic-gate n_entries = length / type_size;
10537c478bd9Sstevel@tonic-gate
10547c478bd9Sstevel@tonic-gate if ((length % type_size) != 0) {
10557c478bd9Sstevel@tonic-gate inittab_msg("inittab_decode: length of string not compatible "
10567c478bd9Sstevel@tonic-gate "with option type `%i'", ie->ds_type);
10577c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_STRING;
10587c478bd9Sstevel@tonic-gate return (NULL);
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate switch (ie->ds_type) {
10627c478bd9Sstevel@tonic-gate
10637c478bd9Sstevel@tonic-gate case DSYM_ASCII:
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate result = malloc(n_entries + 1);
10667c478bd9Sstevel@tonic-gate if (result == NULL) {
10677c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
10687c478bd9Sstevel@tonic-gate return (NULL);
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate (void) memcpy(result, payload, n_entries);
10727c478bd9Sstevel@tonic-gate result[n_entries] = '\0';
10737c478bd9Sstevel@tonic-gate break;
10747c478bd9Sstevel@tonic-gate
1075d04ccbb3Scarlsonj case DSYM_DOMAIN:
1076d04ccbb3Scarlsonj
1077d04ccbb3Scarlsonj /*
1078d04ccbb3Scarlsonj * A valid, decoded RFC 1035 domain string or sequence of
1079d04ccbb3Scarlsonj * strings is always the same size as the encoded form, but we
1080d04ccbb3Scarlsonj * allow for RFC 1035 \DDD and \\ and \. escaping.
1081d04ccbb3Scarlsonj *
1082d04ccbb3Scarlsonj * Decoding stops at the end of the input or the first coding
1083d04ccbb3Scarlsonj * violation. Coding violations result in discarding the
1084d04ccbb3Scarlsonj * offending list entry entirely. Note that we ignore the 255
1085d04ccbb3Scarlsonj * character overall limit on domain names.
1086d04ccbb3Scarlsonj */
1087d04ccbb3Scarlsonj if ((result = malloc(4 * length + 1)) == NULL) {
1088d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1089d04ccbb3Scarlsonj return (NULL);
1090d04ccbb3Scarlsonj }
1091d04ccbb3Scarlsonj resultp = result;
1092d04ccbb3Scarlsonj while (length > 0) {
1093d04ccbb3Scarlsonj char *dstart;
1094d04ccbb3Scarlsonj int slen;
1095d04ccbb3Scarlsonj
1096d04ccbb3Scarlsonj dstart = resultp;
1097d04ccbb3Scarlsonj while (length > 0) {
1098d04ccbb3Scarlsonj slen = *payload++;
1099d04ccbb3Scarlsonj length--;
1100d04ccbb3Scarlsonj /* Upper two bits of length must be zero */
1101d04ccbb3Scarlsonj if ((slen & 0xc0) != 0 || slen > length) {
1102d04ccbb3Scarlsonj length = 0;
1103d04ccbb3Scarlsonj resultp = dstart;
1104d04ccbb3Scarlsonj break;
1105d04ccbb3Scarlsonj }
1106d04ccbb3Scarlsonj if (resultp != dstart)
1107d04ccbb3Scarlsonj *resultp++ = '.';
1108d04ccbb3Scarlsonj if (slen == 0)
1109d04ccbb3Scarlsonj break;
1110d04ccbb3Scarlsonj length -= slen;
1111d04ccbb3Scarlsonj while (slen > 0) {
1112d04ccbb3Scarlsonj if (!isascii(*payload) ||
1113d04ccbb3Scarlsonj !isgraph(*payload)) {
1114d04ccbb3Scarlsonj (void) snprintf(resultp, 5,
1115d04ccbb3Scarlsonj "\\%03d",
1116d04ccbb3Scarlsonj *(unsigned char *)payload);
1117d04ccbb3Scarlsonj resultp += 4;
1118d04ccbb3Scarlsonj payload++;
1119d04ccbb3Scarlsonj } else {
1120d04ccbb3Scarlsonj if (*payload == '.' ||
1121d04ccbb3Scarlsonj *payload == '\\')
1122d04ccbb3Scarlsonj *resultp++ = '\\';
1123d04ccbb3Scarlsonj *resultp++ = *payload++;
1124d04ccbb3Scarlsonj }
1125d04ccbb3Scarlsonj slen--;
1126d04ccbb3Scarlsonj }
1127d04ccbb3Scarlsonj }
1128d04ccbb3Scarlsonj if (resultp != dstart && length > 0)
1129d04ccbb3Scarlsonj *resultp++ = ' ';
1130d04ccbb3Scarlsonj }
1131d04ccbb3Scarlsonj *resultp = '\0';
1132d04ccbb3Scarlsonj break;
1133d04ccbb3Scarlsonj
1134d04ccbb3Scarlsonj case DSYM_DUID:
1135d04ccbb3Scarlsonj
1136d04ccbb3Scarlsonj /*
1137d04ccbb3Scarlsonj * First, determine the type of DUID. We need at least two
1138d04ccbb3Scarlsonj * octets worth of data to grab the type code. Once we have
1139d04ccbb3Scarlsonj * that, the number of octets required for representation
1140d04ccbb3Scarlsonj * depends on the type.
1141d04ccbb3Scarlsonj */
1142d04ccbb3Scarlsonj
1143d04ccbb3Scarlsonj if (length < 2) {
1144d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1145d04ccbb3Scarlsonj return (NULL);
1146d04ccbb3Scarlsonj }
1147d04ccbb3Scarlsonj type = (payload[0] << 8) + payload[1];
1148d04ccbb3Scarlsonj switch (type) {
1149d04ccbb3Scarlsonj case DHCPV6_DUID_LLT: {
1150d04ccbb3Scarlsonj duid_llt_t dllt;
1151d04ccbb3Scarlsonj
1152d04ccbb3Scarlsonj if (length < sizeof (dllt)) {
1153d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1154d04ccbb3Scarlsonj return (NULL);
1155d04ccbb3Scarlsonj }
1156d04ccbb3Scarlsonj (void) memcpy(&dllt, payload, sizeof (dllt));
1157d04ccbb3Scarlsonj payload += sizeof (dllt);
1158d04ccbb3Scarlsonj length -= sizeof (dllt);
1159d04ccbb3Scarlsonj n_entries = sizeof ("1,65535,4294967295,") +
1160d04ccbb3Scarlsonj length * 3;
1161d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1162d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1163d04ccbb3Scarlsonj return (NULL);
1164d04ccbb3Scarlsonj }
1165d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,%u,%u,", type,
1166d04ccbb3Scarlsonj ntohs(dllt.dllt_hwtype), ntohl(dllt.dllt_time));
1167d04ccbb3Scarlsonj break;
1168d04ccbb3Scarlsonj }
1169d04ccbb3Scarlsonj case DHCPV6_DUID_EN: {
1170d04ccbb3Scarlsonj duid_en_t den;
1171d04ccbb3Scarlsonj
1172d04ccbb3Scarlsonj if (length < sizeof (den)) {
1173d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1174d04ccbb3Scarlsonj return (NULL);
1175d04ccbb3Scarlsonj }
1176d04ccbb3Scarlsonj (void) memcpy(&den, payload, sizeof (den));
1177d04ccbb3Scarlsonj payload += sizeof (den);
1178d04ccbb3Scarlsonj length -= sizeof (den);
1179d04ccbb3Scarlsonj n_entries = sizeof ("2,4294967295,") + length * 2;
1180d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1181d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1182d04ccbb3Scarlsonj return (NULL);
1183d04ccbb3Scarlsonj }
1184d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,%u,", type,
1185d04ccbb3Scarlsonj DHCPV6_GET_ENTNUM(&den));
1186d04ccbb3Scarlsonj break;
1187d04ccbb3Scarlsonj }
1188d04ccbb3Scarlsonj case DHCPV6_DUID_LL: {
1189d04ccbb3Scarlsonj duid_ll_t dll;
1190d04ccbb3Scarlsonj
1191d04ccbb3Scarlsonj if (length < sizeof (dll)) {
1192d04ccbb3Scarlsonj *ierrnop = ITAB_BAD_GRAN;
1193d04ccbb3Scarlsonj return (NULL);
1194d04ccbb3Scarlsonj }
1195d04ccbb3Scarlsonj (void) memcpy(&dll, payload, sizeof (dll));
1196d04ccbb3Scarlsonj payload += sizeof (dll);
1197d04ccbb3Scarlsonj length -= sizeof (dll);
1198d04ccbb3Scarlsonj n_entries = sizeof ("3,65535,") + length * 3;
1199d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1200d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1201d04ccbb3Scarlsonj return (NULL);
1202d04ccbb3Scarlsonj }
1203d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,%u,", type,
1204d04ccbb3Scarlsonj ntohs(dll.dll_hwtype));
1205d04ccbb3Scarlsonj break;
1206d04ccbb3Scarlsonj }
1207d04ccbb3Scarlsonj default:
1208d04ccbb3Scarlsonj n_entries = sizeof ("0,") + length * 2;
1209d04ccbb3Scarlsonj if ((result = malloc(n_entries)) == NULL) {
1210d04ccbb3Scarlsonj *ierrnop = ITAB_NOMEM;
1211d04ccbb3Scarlsonj return (NULL);
1212d04ccbb3Scarlsonj }
1213d04ccbb3Scarlsonj (void) snprintf(result, n_entries, "%d,", type);
1214d04ccbb3Scarlsonj break;
1215d04ccbb3Scarlsonj }
1216d04ccbb3Scarlsonj resultp = result + strlen(result);
1217d04ccbb3Scarlsonj n_entries -= strlen(result);
1218d04ccbb3Scarlsonj if (type == DHCPV6_DUID_LLT || type == DHCPV6_DUID_LL) {
1219d04ccbb3Scarlsonj if (length > 0) {
1220d04ccbb3Scarlsonj resultp += snprintf(resultp, 3, "%02X",
1221d04ccbb3Scarlsonj *payload++);
1222d04ccbb3Scarlsonj length--;
1223d04ccbb3Scarlsonj }
1224d04ccbb3Scarlsonj while (length-- > 0) {
1225d04ccbb3Scarlsonj resultp += snprintf(resultp, 4, ":%02X",
1226d04ccbb3Scarlsonj *payload++);
1227d04ccbb3Scarlsonj }
1228d04ccbb3Scarlsonj } else {
1229d04ccbb3Scarlsonj while (length-- > 0) {
1230d04ccbb3Scarlsonj resultp += snprintf(resultp, 3, "%02X",
1231d04ccbb3Scarlsonj *payload++);
1232d04ccbb3Scarlsonj }
1233d04ccbb3Scarlsonj }
1234d04ccbb3Scarlsonj break;
1235d04ccbb3Scarlsonj
12367c478bd9Sstevel@tonic-gate case DSYM_OCTET:
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate result = malloc(n_entries * (sizeof ("0xNN") + 1));
12397c478bd9Sstevel@tonic-gate if (result == NULL) {
12407c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
12417c478bd9Sstevel@tonic-gate return (NULL);
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate
1244d04ccbb3Scarlsonj result[0] = '\0';
1245d04ccbb3Scarlsonj resultp = result;
1246d04ccbb3Scarlsonj if (n_entries > 0) {
1247d04ccbb3Scarlsonj resultp += sprintf(resultp, "0x%02X", *payload++);
1248d04ccbb3Scarlsonj n_entries--;
12497c478bd9Sstevel@tonic-gate }
1250d04ccbb3Scarlsonj while (n_entries-- > 0)
1251d04ccbb3Scarlsonj resultp += sprintf(resultp, " 0x%02X", *payload++);
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate break;
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate case DSYM_IP:
1256d04ccbb3Scarlsonj case DSYM_IPV6:
1257d04ccbb3Scarlsonj if ((length / type_size) % ie->ds_gran != 0) {
12587c478bd9Sstevel@tonic-gate *ierrnop = ITAB_BAD_GRAN;
12597c478bd9Sstevel@tonic-gate inittab_msg("inittab_decode: number of entries "
12607c478bd9Sstevel@tonic-gate "not compatible with option granularity");
12617c478bd9Sstevel@tonic-gate return (NULL);
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate
1264d04ccbb3Scarlsonj result = malloc(n_entries * (ie->ds_type == DSYM_IP ?
1265d04ccbb3Scarlsonj INET_ADDRSTRLEN : INET6_ADDRSTRLEN));
12667c478bd9Sstevel@tonic-gate if (result == NULL) {
12677c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
12687c478bd9Sstevel@tonic-gate return (NULL);
12697c478bd9Sstevel@tonic-gate }
12707c478bd9Sstevel@tonic-gate
12717c478bd9Sstevel@tonic-gate for (resultp = result; n_entries != 0; n_entries--) {
1272d04ccbb3Scarlsonj if (ie->ds_type == DSYM_IP) {
1273d04ccbb3Scarlsonj (void) memcpy(&in_addr.s_addr, payload,
1274d04ccbb3Scarlsonj sizeof (ipaddr_t));
1275d04ccbb3Scarlsonj (void) strcpy(resultp, inet_ntoa(in_addr));
1276d04ccbb3Scarlsonj } else {
1277d04ccbb3Scarlsonj (void) memcpy(&in6_addr, payload,
1278d04ccbb3Scarlsonj sizeof (in6_addr));
1279d04ccbb3Scarlsonj (void) inet_ntop(AF_INET6, &in6_addr, resultp,
1280d04ccbb3Scarlsonj INET6_ADDRSTRLEN);
12817c478bd9Sstevel@tonic-gate }
1282d04ccbb3Scarlsonj resultp += strlen(resultp);
1283d04ccbb3Scarlsonj if (n_entries > 1)
1284d04ccbb3Scarlsonj *resultp++ = ' ';
1285d04ccbb3Scarlsonj payload += type_size;
12867c478bd9Sstevel@tonic-gate }
1287d04ccbb3Scarlsonj *resultp = '\0';
12887c478bd9Sstevel@tonic-gate break;
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate case DSYM_NUMBER: /* FALLTHRU */
12917c478bd9Sstevel@tonic-gate case DSYM_UNUMBER8: /* FALLTHRU */
12927c478bd9Sstevel@tonic-gate case DSYM_SNUMBER8: /* FALLTHRU */
12937c478bd9Sstevel@tonic-gate case DSYM_UNUMBER16: /* FALLTHRU */
12947c478bd9Sstevel@tonic-gate case DSYM_SNUMBER16: /* FALLTHRU */
12957c478bd9Sstevel@tonic-gate case DSYM_UNUMBER32: /* FALLTHRU */
12967c478bd9Sstevel@tonic-gate case DSYM_SNUMBER32: /* FALLTHRU */
12977c478bd9Sstevel@tonic-gate case DSYM_UNUMBER64: /* FALLTHRU */
12987c478bd9Sstevel@tonic-gate case DSYM_SNUMBER64:
12997c478bd9Sstevel@tonic-gate
13007c478bd9Sstevel@tonic-gate is_signed = (ie->ds_type == DSYM_SNUMBER64 ||
13017c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER32 ||
13027c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER16 ||
13037c478bd9Sstevel@tonic-gate ie->ds_type == DSYM_SNUMBER8);
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate result = malloc(n_entries * ITAB_MAX_NUMBER_LEN);
13067c478bd9Sstevel@tonic-gate if (result == NULL) {
13077c478bd9Sstevel@tonic-gate *ierrnop = ITAB_NOMEM;
13087c478bd9Sstevel@tonic-gate return (NULL);
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate if (decode_number(n_entries, type_size, is_signed, ie->ds_gran,
13127c478bd9Sstevel@tonic-gate payload, result, ierrnop) == B_FALSE) {
13137c478bd9Sstevel@tonic-gate free(result);
13147c478bd9Sstevel@tonic-gate return (NULL);
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate break;
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate default:
13197c478bd9Sstevel@tonic-gate inittab_msg("inittab_decode: unsupported type `%d'",
13207c478bd9Sstevel@tonic-gate ie->ds_type);
13217c478bd9Sstevel@tonic-gate break;
13227c478bd9Sstevel@tonic-gate }
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate return (result);
13257c478bd9Sstevel@tonic-gate }
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate /*
13287c478bd9Sstevel@tonic-gate * inittab_encode(): converts a string representation of a given datatype into
13297c478bd9Sstevel@tonic-gate * binary; used for encoding ascii values into a form that
13307c478bd9Sstevel@tonic-gate * can be put in DHCP packets to be sent on the wire.
13317c478bd9Sstevel@tonic-gate *
13327c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the entry describing the value option
13337c478bd9Sstevel@tonic-gate * const char *: the value to convert
13347c478bd9Sstevel@tonic-gate * uint16_t *: set to the length of the binary data returned
13357c478bd9Sstevel@tonic-gate * boolean_t: if false, return a full DHCP option
13367c478bd9Sstevel@tonic-gate * output: uchar_t *: a dynamically allocated byte array with converted data
13377c478bd9Sstevel@tonic-gate */
1338d04ccbb3Scarlsonj
13397c478bd9Sstevel@tonic-gate uchar_t *
inittab_encode(const dhcp_symbol_t * ie,const char * value,uint16_t * lengthp,boolean_t just_payload)1340d04ccbb3Scarlsonj inittab_encode(const dhcp_symbol_t *ie, const char *value, uint16_t *lengthp,
13417c478bd9Sstevel@tonic-gate boolean_t just_payload)
13427c478bd9Sstevel@tonic-gate {
13437c478bd9Sstevel@tonic-gate int ierrno;
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate return (inittab_encode_e(ie, value, lengthp, just_payload, &ierrno));
13467c478bd9Sstevel@tonic-gate }
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate /*
13497c478bd9Sstevel@tonic-gate * inittab_decode(): converts a binary representation of a given datatype into
13507c478bd9Sstevel@tonic-gate * a string; used for decoding DHCP options in a packet off
13517c478bd9Sstevel@tonic-gate * the wire into ascii
13527c478bd9Sstevel@tonic-gate *
13537c478bd9Sstevel@tonic-gate * input: dhcp_symbol_t *: the entry describing the payload option
13547c478bd9Sstevel@tonic-gate * uchar_t *: the payload to convert
13557c478bd9Sstevel@tonic-gate * uint16_t: the payload length (only used if just_payload is true)
13567c478bd9Sstevel@tonic-gate * boolean_t: if false, payload is assumed to be a DHCP option
13577c478bd9Sstevel@tonic-gate * output: char *: a dynamically allocated string containing the converted data
13587c478bd9Sstevel@tonic-gate */
1359d04ccbb3Scarlsonj
13607c478bd9Sstevel@tonic-gate char *
inittab_decode(const dhcp_symbol_t * ie,const uchar_t * payload,uint16_t length,boolean_t just_payload)1361d04ccbb3Scarlsonj inittab_decode(const dhcp_symbol_t *ie, const uchar_t *payload, uint16_t length,
13627c478bd9Sstevel@tonic-gate boolean_t just_payload)
13637c478bd9Sstevel@tonic-gate {
13647c478bd9Sstevel@tonic-gate int ierrno;
13657c478bd9Sstevel@tonic-gate
13667c478bd9Sstevel@tonic-gate return (inittab_decode_e(ie, payload, length, just_payload, &ierrno));
13677c478bd9Sstevel@tonic-gate }
13687c478bd9Sstevel@tonic-gate
13697c478bd9Sstevel@tonic-gate /*
13707c478bd9Sstevel@tonic-gate * inittab_msg(): prints diagnostic messages if INITTAB_DEBUG is set
13717c478bd9Sstevel@tonic-gate *
13727c478bd9Sstevel@tonic-gate * const char *: a printf-like format string
13737c478bd9Sstevel@tonic-gate * ...: arguments to the format string
13747c478bd9Sstevel@tonic-gate * output: void
13757c478bd9Sstevel@tonic-gate */
1376d04ccbb3Scarlsonj
13777c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
13787c478bd9Sstevel@tonic-gate static void
inittab_msg(const char * fmt,...)13797c478bd9Sstevel@tonic-gate inittab_msg(const char *fmt, ...)
13807c478bd9Sstevel@tonic-gate {
13817c478bd9Sstevel@tonic-gate enum { INITTAB_MSG_CHECK, INITTAB_MSG_RETURN, INITTAB_MSG_OUTPUT };
13827c478bd9Sstevel@tonic-gate
13837c478bd9Sstevel@tonic-gate va_list ap;
13847c478bd9Sstevel@tonic-gate char buf[512];
13857c478bd9Sstevel@tonic-gate static int action = INITTAB_MSG_CHECK;
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate /*
13887c478bd9Sstevel@tonic-gate * check DHCP_INITTAB_DEBUG the first time in; thereafter, use
13897c478bd9Sstevel@tonic-gate * the the cached result (stored in `action').
13907c478bd9Sstevel@tonic-gate */
13917c478bd9Sstevel@tonic-gate switch (action) {
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate case INITTAB_MSG_CHECK:
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate if (getenv("DHCP_INITTAB_DEBUG") == NULL) {
13967c478bd9Sstevel@tonic-gate action = INITTAB_MSG_RETURN;
13977c478bd9Sstevel@tonic-gate return;
13987c478bd9Sstevel@tonic-gate }
13997c478bd9Sstevel@tonic-gate
14007c478bd9Sstevel@tonic-gate action = INITTAB_MSG_OUTPUT;
1401*e5016785SToomas Soome /* FALLTHROUGH */
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:
1454d04ccbb3Scarlsonj 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);
1459d04ccbb3Scarlsonj 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);
1472d04ccbb3Scarlsonj 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);
1478d04ccbb3Scarlsonj 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 },
17154b56a003SDaniel Anderson { 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