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