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
5*d04ccbb3Scarlsonj * Common Development and Distribution License (the "License").
6*d04ccbb3Scarlsonj * 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 /*
22*d04ccbb3Scarlsonj * Copyright 2007 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 <stdlib.h>
277c478bd9Sstevel@tonic-gate #include <ctype.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <limits.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <dhcp_impl.h>
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include "dhcp_symbol.h"
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate * The following structure and table are used to define the attributes
377c478bd9Sstevel@tonic-gate * of a DHCP symbol category.
387c478bd9Sstevel@tonic-gate */
397c478bd9Sstevel@tonic-gate typedef struct dsym_cat {
407c478bd9Sstevel@tonic-gate char *dc_string; /* string value for the category */
417c478bd9Sstevel@tonic-gate int dc_minlen; /* min. chars of dc_string to match */
427c478bd9Sstevel@tonic-gate dsym_category_t dc_id; /* numerical value for the category */
437c478bd9Sstevel@tonic-gate boolean_t dc_dhcptab; /* valid for dhcptab use? */
447c478bd9Sstevel@tonic-gate ushort_t dc_min; /* minimum valid code */
457c478bd9Sstevel@tonic-gate ushort_t dc_max; /* maximum valid code */
467c478bd9Sstevel@tonic-gate } dsym_cat_t;
477c478bd9Sstevel@tonic-gate
48*d04ccbb3Scarlsonj static dsym_cat_t cats[] = {
497c478bd9Sstevel@tonic-gate { "Extend", 6, DSYM_EXTEND, B_TRUE, DHCP_LAST_STD + 1,
507c478bd9Sstevel@tonic-gate DHCP_SITE_OPT - 1 },
517c478bd9Sstevel@tonic-gate { "Vendor=", 6, DSYM_VENDOR, B_TRUE, DHCP_FIRST_OPT,
527c478bd9Sstevel@tonic-gate DHCP_LAST_OPT },
537c478bd9Sstevel@tonic-gate { "Site", 4, DSYM_SITE, B_TRUE, DHCP_SITE_OPT, DHCP_LAST_OPT },
547c478bd9Sstevel@tonic-gate { "Standard", 8, DSYM_STANDARD, B_FALSE, DHCP_FIRST_OPT,
557c478bd9Sstevel@tonic-gate DHCP_LAST_STD },
567c478bd9Sstevel@tonic-gate { "Field", 5, DSYM_FIELD, B_FALSE, CD_PACKET_START,
577c478bd9Sstevel@tonic-gate CD_PACKET_END },
587c478bd9Sstevel@tonic-gate { "Internal", 8, DSYM_INTERNAL, B_FALSE, CD_INTRNL_START,
597c478bd9Sstevel@tonic-gate CD_INTRNL_END }
607c478bd9Sstevel@tonic-gate };
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate * The following structure and table are used to define the attributes
647c478bd9Sstevel@tonic-gate * of a DHCP symbol type.
657c478bd9Sstevel@tonic-gate */
667c478bd9Sstevel@tonic-gate typedef struct dsym_type {
677c478bd9Sstevel@tonic-gate char *dt_string; /* string value for the type */
687c478bd9Sstevel@tonic-gate dsym_cdtype_t dt_id; /* numerical value for the type */
697c478bd9Sstevel@tonic-gate boolean_t dt_dhcptab; /* valid for dhcptab use? */
707c478bd9Sstevel@tonic-gate } dsym_type_t;
717c478bd9Sstevel@tonic-gate
72*d04ccbb3Scarlsonj static dsym_type_t types[] = {
737c478bd9Sstevel@tonic-gate { "ASCII", DSYM_ASCII, B_TRUE },
747c478bd9Sstevel@tonic-gate { "OCTET", DSYM_OCTET, B_TRUE },
757c478bd9Sstevel@tonic-gate { "IP", DSYM_IP, B_TRUE },
767c478bd9Sstevel@tonic-gate { "NUMBER", DSYM_NUMBER, B_TRUE },
777c478bd9Sstevel@tonic-gate { "BOOL", DSYM_BOOL, B_TRUE },
787c478bd9Sstevel@tonic-gate { "INCLUDE", DSYM_INCLUDE, B_FALSE },
797c478bd9Sstevel@tonic-gate { "UNUMBER8", DSYM_UNUMBER8, B_TRUE },
807c478bd9Sstevel@tonic-gate { "UNUMBER16", DSYM_UNUMBER16, B_TRUE },
81*d04ccbb3Scarlsonj { "UNUMBER24", DSYM_UNUMBER24, B_TRUE },
827c478bd9Sstevel@tonic-gate { "UNUMBER32", DSYM_UNUMBER32, B_TRUE },
837c478bd9Sstevel@tonic-gate { "UNUMBER64", DSYM_UNUMBER64, B_TRUE },
847c478bd9Sstevel@tonic-gate { "SNUMBER8", DSYM_SNUMBER8, B_TRUE },
857c478bd9Sstevel@tonic-gate { "SNUMBER16", DSYM_SNUMBER16, B_TRUE },
867c478bd9Sstevel@tonic-gate { "SNUMBER32", DSYM_SNUMBER32, B_TRUE },
87*d04ccbb3Scarlsonj { "SNUMBER64", DSYM_SNUMBER64, B_TRUE },
88*d04ccbb3Scarlsonj { "IPV6", DSYM_IPV6, B_TRUE },
89*d04ccbb3Scarlsonj { "DUID", DSYM_DUID, B_TRUE },
90*d04ccbb3Scarlsonj { "DOMAIN", DSYM_DOMAIN, B_TRUE }
917c478bd9Sstevel@tonic-gate };
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate * symbol delimiters and constants
957c478bd9Sstevel@tonic-gate */
967c478bd9Sstevel@tonic-gate #define DSYM_CLASS_DEL " \t\n"
977c478bd9Sstevel@tonic-gate #define DSYM_FIELD_DEL ","
987c478bd9Sstevel@tonic-gate #define DSYM_VENDOR_DEL '='
997c478bd9Sstevel@tonic-gate #define DSYM_QUOTE '"'
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate * dsym_trim(): trims all whitespace from either side of a string
1037c478bd9Sstevel@tonic-gate *
1047c478bd9Sstevel@tonic-gate * input: char **: a pointer to a string to trim of whitespace.
1057c478bd9Sstevel@tonic-gate * output: none
1067c478bd9Sstevel@tonic-gate */
107*d04ccbb3Scarlsonj
1087c478bd9Sstevel@tonic-gate static void
dsym_trim(char ** str)1097c478bd9Sstevel@tonic-gate dsym_trim(char **str)
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate char *tmpstr = *str;
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate * Trim all whitespace from the front of the string.
1167c478bd9Sstevel@tonic-gate */
1177c478bd9Sstevel@tonic-gate while (*tmpstr != '\0' && isspace(*tmpstr)) {
1187c478bd9Sstevel@tonic-gate tmpstr++;
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * Move the str pointer to first non-whitespace char.
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate *str = tmpstr;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * Check case where the string is nothing but whitespace.
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate if (*tmpstr == '\0') {
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * Trim all whitespace from the end of the string.
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate tmpstr = *str + strlen(*str) - 1;
1357c478bd9Sstevel@tonic-gate while (tmpstr >= *str && isspace(*tmpstr)) {
1367c478bd9Sstevel@tonic-gate tmpstr--;
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate /*
1407c478bd9Sstevel@tonic-gate * terminate after last non-whitespace char.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate *(tmpstr+1) = '\0';
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate * dsym_get_token(): strtok_r() like routine, except consecutive delimiters
1487c478bd9Sstevel@tonic-gate * result in an empty string
1497c478bd9Sstevel@tonic-gate *
1507c478bd9Sstevel@tonic-gate * note: original string is modified
1517c478bd9Sstevel@tonic-gate *
1527c478bd9Sstevel@tonic-gate * input: char *: string in which to search for tokens
1537c478bd9Sstevel@tonic-gate * char *: list of possible token delimiter characters
1547c478bd9Sstevel@tonic-gate * char **: location for next call to routine
1557c478bd9Sstevel@tonic-gate * boolean_t: should delimiters be ignored if within quoted string?
1567c478bd9Sstevel@tonic-gate * output: char *: token, or NULL if no more tokens
1577c478bd9Sstevel@tonic-gate */
158*d04ccbb3Scarlsonj
1597c478bd9Sstevel@tonic-gate static char *
dsym_get_token(char * str,char * dels,char ** lasts,boolean_t quote_support)1607c478bd9Sstevel@tonic-gate dsym_get_token(char *str, char *dels, char **lasts, boolean_t quote_support)
1617c478bd9Sstevel@tonic-gate {
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate char *ptr = str;
1647c478bd9Sstevel@tonic-gate char *del;
1657c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE;
1667c478bd9Sstevel@tonic-gate boolean_t in_quote = B_FALSE;
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate * If incoming string has no tokens return a NULL
1707c478bd9Sstevel@tonic-gate * pointer to signify no more tokens.
1717c478bd9Sstevel@tonic-gate */
1727c478bd9Sstevel@tonic-gate if (*ptr == '\0') {
1737c478bd9Sstevel@tonic-gate return (NULL);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * Loop until either a token has been identified or until end
1787c478bd9Sstevel@tonic-gate * of string has been reached.
1797c478bd9Sstevel@tonic-gate */
1807c478bd9Sstevel@tonic-gate while (!found && *ptr != '\0') {
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate * If pointer currently lies within a quoted string,
1847c478bd9Sstevel@tonic-gate * then do not check for the delimiter.
1857c478bd9Sstevel@tonic-gate */
1867c478bd9Sstevel@tonic-gate if (!in_quote) {
1877c478bd9Sstevel@tonic-gate for (del = dels; !found && *del != '\0'; del++) {
1887c478bd9Sstevel@tonic-gate if (*del == *ptr) {
1897c478bd9Sstevel@tonic-gate *ptr++ = '\0';
1907c478bd9Sstevel@tonic-gate found = B_TRUE;
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate * If the pointer is pointing at a delimiter, then
1977c478bd9Sstevel@tonic-gate * check to see if it points to at a quote and update
1987c478bd9Sstevel@tonic-gate * the state appropriately.
1997c478bd9Sstevel@tonic-gate */
2007c478bd9Sstevel@tonic-gate if (!found) {
2017c478bd9Sstevel@tonic-gate if (quote_support && *ptr == DSYM_QUOTE) {
2027c478bd9Sstevel@tonic-gate in_quote = !in_quote;
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate ptr++;
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate *lasts = ptr;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate return (str);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate * dsym_get_long(): given a numeric string, returns its long value
2157c478bd9Sstevel@tonic-gate *
2167c478bd9Sstevel@tonic-gate * input: const char *: the numeric string
2177c478bd9Sstevel@tonic-gate * long *: the return location for the long value
2187c478bd9Sstevel@tonic-gate * output: DSYM_SUCCESS, DSYM_VALUE_OUT_OF_RANGE or DSYM_SYNTAX_ERROR
2197c478bd9Sstevel@tonic-gate */
220*d04ccbb3Scarlsonj
2217c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_get_long(const char * str,long * val)2227c478bd9Sstevel@tonic-gate dsym_get_long(const char *str, long *val)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate int ret = DSYM_SUCCESS;
2267c478bd9Sstevel@tonic-gate int i;
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate for (i = 0; str[i] != '\0'; i++) {
2297c478bd9Sstevel@tonic-gate if (!isdigit(str[i])) {
2307c478bd9Sstevel@tonic-gate return (DSYM_SYNTAX_ERROR);
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate errno = 0;
2357c478bd9Sstevel@tonic-gate *val = strtol(str, NULL, 10);
2367c478bd9Sstevel@tonic-gate if (errno != 0) {
2377c478bd9Sstevel@tonic-gate ret = DSYM_VALUE_OUT_OF_RANGE;
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate return (ret);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate /*
2447c478bd9Sstevel@tonic-gate * dsym_free_classes(): frees the classes allocated by dsym_parse_classes()
2457c478bd9Sstevel@tonic-gate *
2467c478bd9Sstevel@tonic-gate * input: dhcp_classes_t *: pointer to structure containing classes to free
2477c478bd9Sstevel@tonic-gate * output: none
2487c478bd9Sstevel@tonic-gate */
249*d04ccbb3Scarlsonj
2507c478bd9Sstevel@tonic-gate void
dsym_free_classes(dhcp_classes_t * classes)2517c478bd9Sstevel@tonic-gate dsym_free_classes(dhcp_classes_t *classes)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate int i;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate if (classes->dc_names == NULL) {
2577c478bd9Sstevel@tonic-gate return;
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate for (i = 0; i < classes->dc_cnt; i++) {
2617c478bd9Sstevel@tonic-gate free(classes->dc_names[i]);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate free(classes->dc_names);
2657c478bd9Sstevel@tonic-gate classes->dc_names = NULL;
2667c478bd9Sstevel@tonic-gate classes->dc_cnt = 0;
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate /*
2707c478bd9Sstevel@tonic-gate * dsym_parse_classes(): given a "Vendor" class string, builds and returns
2717c478bd9Sstevel@tonic-gate * the list of vendor classes
2727c478bd9Sstevel@tonic-gate *
2737c478bd9Sstevel@tonic-gate * input: char *: the "Vendor" class string
2747c478bd9Sstevel@tonic-gate * dhcp_classes_t *: pointer to the classes structure
2757c478bd9Sstevel@tonic-gate * output: DSYM_SUCCESS, DSYM_INVALID_CAT, DSYM_EXCEEDS_MAX_CLASS_SIZE,
2767c478bd9Sstevel@tonic-gate * DSYM_EXCEEDS_CLASS_SIZE, DSYM_SYNTAX_ERROR, or DSYM_NO_MEMORY
2777c478bd9Sstevel@tonic-gate */
278*d04ccbb3Scarlsonj
2797c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_parse_classes(char * ptr,dhcp_classes_t * classes_ret)2807c478bd9Sstevel@tonic-gate dsym_parse_classes(char *ptr, dhcp_classes_t *classes_ret)
2817c478bd9Sstevel@tonic-gate {
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate char **classes = NULL;
2847c478bd9Sstevel@tonic-gate char *cp;
2857c478bd9Sstevel@tonic-gate int len;
2867c478bd9Sstevel@tonic-gate int ret = DSYM_SUCCESS;
2877c478bd9Sstevel@tonic-gate int i;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate while (*ptr != '\0') {
2907c478bd9Sstevel@tonic-gate if (*ptr == DSYM_VENDOR_DEL) {
2917c478bd9Sstevel@tonic-gate ptr++;
2927c478bd9Sstevel@tonic-gate break;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate ptr++;
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate if (*ptr == '\0') {
2987c478bd9Sstevel@tonic-gate return (DSYM_INVALID_CAT);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate if (strlen(ptr) > DSYM_MAX_CLASS_SIZE) {
3027c478bd9Sstevel@tonic-gate return (DSYM_EXCEEDS_MAX_CLASS_SIZE);
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate dsym_trim(&ptr);
3067c478bd9Sstevel@tonic-gate classes_ret->dc_cnt = 0;
3077c478bd9Sstevel@tonic-gate for (i = 0; ret == DSYM_SUCCESS; i++) {
3087c478bd9Sstevel@tonic-gate cp = dsym_get_token(ptr, DSYM_CLASS_DEL, &ptr, B_TRUE);
3097c478bd9Sstevel@tonic-gate if (cp == NULL) {
3107c478bd9Sstevel@tonic-gate break;
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate len = strlen(cp);
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate if (len == 0) {
3167c478bd9Sstevel@tonic-gate continue;
3177c478bd9Sstevel@tonic-gate } else if (len > DSYM_CLASS_SIZE) {
3187c478bd9Sstevel@tonic-gate ret = DSYM_EXCEEDS_CLASS_SIZE;
3197c478bd9Sstevel@tonic-gate continue;
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate if (cp[0] == DSYM_QUOTE && cp[len-1] != DSYM_QUOTE) {
3237c478bd9Sstevel@tonic-gate ret = DSYM_SYNTAX_ERROR;
3247c478bd9Sstevel@tonic-gate continue;
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate /* Strip off the quotes */
3287c478bd9Sstevel@tonic-gate if (cp[0] == DSYM_QUOTE) {
3297c478bd9Sstevel@tonic-gate cp[len-1] = '\0';
3307c478bd9Sstevel@tonic-gate cp++;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate classes = realloc(classes_ret->dc_names,
3347c478bd9Sstevel@tonic-gate (sizeof (char **)) * (classes_ret->dc_cnt + 1));
3357c478bd9Sstevel@tonic-gate if (classes == NULL ||
3367c478bd9Sstevel@tonic-gate (classes[classes_ret->dc_cnt] = strdup(cp))
3377c478bd9Sstevel@tonic-gate == NULL) {
3387c478bd9Sstevel@tonic-gate ret = DSYM_NO_MEMORY;
3397c478bd9Sstevel@tonic-gate continue;
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate classes_ret->dc_names = classes;
3427c478bd9Sstevel@tonic-gate classes_ret->dc_cnt++;
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate if (ret != DSYM_SUCCESS) {
3467c478bd9Sstevel@tonic-gate dsym_free_classes(classes_ret);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate return (ret);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate * dsym_get_cat_by_name(): given a category field, returns the pointer to its
3547c478bd9Sstevel@tonic-gate * entry in the internal category table.
3557c478bd9Sstevel@tonic-gate *
3567c478bd9Sstevel@tonic-gate * input: const char *: the category name
3577c478bd9Sstevel@tonic-gate * dsym_cat_t *: the return location for the pointer to the table entry
3587c478bd9Sstevel@tonic-gate * boolean_t: case-sensitive name compare
3597c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT
3607c478bd9Sstevel@tonic-gate */
361*d04ccbb3Scarlsonj
3627c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_get_cat_by_name(const char * cat,dsym_cat_t ** entry,boolean_t cs)3637c478bd9Sstevel@tonic-gate dsym_get_cat_by_name(const char *cat, dsym_cat_t **entry, boolean_t cs)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate dsym_cat_t *entryp = NULL;
3677c478bd9Sstevel@tonic-gate int ret = DSYM_SUCCESS;
3687c478bd9Sstevel@tonic-gate int cnt = sizeof (cats) / sizeof (dsym_cat_t);
3697c478bd9Sstevel@tonic-gate int result;
3707c478bd9Sstevel@tonic-gate int len;
3717c478bd9Sstevel@tonic-gate int i;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) {
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate len = cats[i].dc_minlen;
3767c478bd9Sstevel@tonic-gate if (cs) {
3777c478bd9Sstevel@tonic-gate result = strncmp(cat, cats[i].dc_string, len);
3787c478bd9Sstevel@tonic-gate } else {
3797c478bd9Sstevel@tonic-gate result = strncasecmp(cat, cats[i].dc_string, len);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate if (result == 0) {
3837c478bd9Sstevel@tonic-gate entryp = &cats[i];
3847c478bd9Sstevel@tonic-gate break;
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate if (entryp != NULL) {
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate * Special code required for the Vendor category, because we
3917c478bd9Sstevel@tonic-gate * allow whitespace between the keyword and the delimiter.
3927c478bd9Sstevel@tonic-gate * If there is no delimiter, then this is an illegal category.
3937c478bd9Sstevel@tonic-gate */
3947c478bd9Sstevel@tonic-gate const char *ptr = cat + entryp->dc_minlen;
3957c478bd9Sstevel@tonic-gate if (entryp->dc_id == DSYM_VENDOR) {
3967c478bd9Sstevel@tonic-gate while (*ptr != '\0' && isspace(*ptr)) {
3977c478bd9Sstevel@tonic-gate ptr++;
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate if (*ptr != DSYM_VENDOR_DEL) {
4007c478bd9Sstevel@tonic-gate ret = DSYM_INVALID_CAT;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate } else {
4037c478bd9Sstevel@tonic-gate if (*ptr != '\0') {
4047c478bd9Sstevel@tonic-gate ret = DSYM_INVALID_CAT;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate } else {
4087c478bd9Sstevel@tonic-gate ret = DSYM_INVALID_CAT;
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
4127c478bd9Sstevel@tonic-gate *entry = entryp;
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate return (ret);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate /*
4197c478bd9Sstevel@tonic-gate * dsym_parse_cat(): given a category field, returns the category value
4207c478bd9Sstevel@tonic-gate * Note: The category must be a valid dhcptab category.
4217c478bd9Sstevel@tonic-gate *
4227c478bd9Sstevel@tonic-gate * input: const char *: a category field
4237c478bd9Sstevel@tonic-gate * dsym_category_t *: the return location for the category value
4247c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT
4257c478bd9Sstevel@tonic-gate */
426*d04ccbb3Scarlsonj
4277c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_parse_cat(const char * field,dsym_category_t * cat)4287c478bd9Sstevel@tonic-gate dsym_parse_cat(const char *field, dsym_category_t *cat)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate dsym_cat_t *entry;
4327c478bd9Sstevel@tonic-gate int ret;
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate ret = dsym_get_cat_by_name(field, &entry, B_TRUE);
4357c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
4367c478bd9Sstevel@tonic-gate /*
4377c478bd9Sstevel@tonic-gate * Since this routine is meant to be used to parse dhcptab
4387c478bd9Sstevel@tonic-gate * symbol definitions, only a subset of the DHCP categories
4397c478bd9Sstevel@tonic-gate * are valid in this context.
4407c478bd9Sstevel@tonic-gate */
4417c478bd9Sstevel@tonic-gate if (entry->dc_dhcptab) {
4427c478bd9Sstevel@tonic-gate *cat = entry->dc_id;
4437c478bd9Sstevel@tonic-gate } else {
4447c478bd9Sstevel@tonic-gate ret = DSYM_INVALID_CAT;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate return (ret);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate /*
4527c478bd9Sstevel@tonic-gate * dsym_parse_intrange(): given a DHCP integer field, returns the value
4537c478bd9Sstevel@tonic-gate *
4547c478bd9Sstevel@tonic-gate * input: const char *: a DHCP code field
4557c478bd9Sstevel@tonic-gate * int *: the return location for the value
4567c478bd9Sstevel@tonic-gate * int: the minimum valid value
4577c478bd9Sstevel@tonic-gate * int: the maximum valid value
4587c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, or DSYM_VALUE_OUT_OF_RANGE
4597c478bd9Sstevel@tonic-gate */
460*d04ccbb3Scarlsonj
4617c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_parse_intrange(const char * field,int * intval,int min,int max)4627c478bd9Sstevel@tonic-gate dsym_parse_intrange(const char *field, int *intval, int min, int max)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate int ret;
4667c478bd9Sstevel@tonic-gate long longval;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate ret = dsym_get_long(field, &longval);
4697c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
4707c478bd9Sstevel@tonic-gate if (longval < min || longval > max) {
4717c478bd9Sstevel@tonic-gate ret = DSYM_VALUE_OUT_OF_RANGE;
4727c478bd9Sstevel@tonic-gate } else {
4737c478bd9Sstevel@tonic-gate *intval = (int)longval;
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate return (ret);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * dsym_validate_code(): given a symbol category and code, validates
4817c478bd9Sstevel@tonic-gate * that the code is valid for the category
4827c478bd9Sstevel@tonic-gate *
4837c478bd9Sstevel@tonic-gate * input: dsym_category_t: the symbol category
4847c478bd9Sstevel@tonic-gate * uint16_t: the symbol code
4857c478bd9Sstevel@tonic-gate * output: DSYM_SUCCESS, DSYM_INVALID_CAT or DSYM_CODE_OUT_OF_RANGE
4867c478bd9Sstevel@tonic-gate */
487*d04ccbb3Scarlsonj
4887c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_validate_code(dsym_category_t cat,ushort_t code)4897c478bd9Sstevel@tonic-gate dsym_validate_code(dsym_category_t cat, ushort_t code)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate int cnt = sizeof (cats) / sizeof (dsym_cat_t);
4937c478bd9Sstevel@tonic-gate int i;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate /*
4967c478bd9Sstevel@tonic-gate * Find the category entry from the internal table.
4977c478bd9Sstevel@tonic-gate */
4987c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) {
4997c478bd9Sstevel@tonic-gate dsym_cat_t *entry;
5007c478bd9Sstevel@tonic-gate if (cat == cats[i].dc_id) {
5017c478bd9Sstevel@tonic-gate entry = &cats[i];
5027c478bd9Sstevel@tonic-gate if (code < entry->dc_min || code > entry->dc_max) {
5037c478bd9Sstevel@tonic-gate return (DSYM_CODE_OUT_OF_RANGE);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate return (DSYM_SUCCESS);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate return (DSYM_INVALID_CAT);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate /*
5137c478bd9Sstevel@tonic-gate * dsym_validate_granularity(): given a symbol type, validates
5147c478bd9Sstevel@tonic-gate * that the granularity is valid for the type
5157c478bd9Sstevel@tonic-gate *
5167c478bd9Sstevel@tonic-gate * input: dsym_cdtype_t: the symbol type
5177c478bd9Sstevel@tonic-gate * uchar_t: the symbol granularity
5187c478bd9Sstevel@tonic-gate * output: DSYM_SUCCESS or DSYM_VALUE_OUT_OF_RANGE
5197c478bd9Sstevel@tonic-gate */
520*d04ccbb3Scarlsonj
5217c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_validate_granularity(dsym_cdtype_t type,uchar_t gran)5227c478bd9Sstevel@tonic-gate dsym_validate_granularity(dsym_cdtype_t type, uchar_t gran)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate * We only need to check for a 0 with non-boolean types, as
5267c478bd9Sstevel@tonic-gate * anything else is already validated by the ranges passed to
5277c478bd9Sstevel@tonic-gate * dsym_parse_intrange() in dsym_parse_field().
5287c478bd9Sstevel@tonic-gate */
5297c478bd9Sstevel@tonic-gate if (gran == 0 && type != DSYM_BOOL) {
5307c478bd9Sstevel@tonic-gate return (DSYM_VALUE_OUT_OF_RANGE);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate return (DSYM_SUCCESS);
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate /*
5367c478bd9Sstevel@tonic-gate * dsym_get_type_by_name(): given a type field, returns the pointer to its
5377c478bd9Sstevel@tonic-gate * entry in the internal type table.
5387c478bd9Sstevel@tonic-gate *
5397c478bd9Sstevel@tonic-gate * input: const char *: the type name
5407c478bd9Sstevel@tonic-gate * dsym_type_t *: the return location for the pointer to the table entry
5417c478bd9Sstevel@tonic-gate * boolean_t: case-sensitive name compare
5427c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE
5437c478bd9Sstevel@tonic-gate */
544*d04ccbb3Scarlsonj
5457c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_get_type_by_name(const char * type,dsym_type_t ** entry,boolean_t cs)5467c478bd9Sstevel@tonic-gate dsym_get_type_by_name(const char *type, dsym_type_t **entry, boolean_t cs)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate int cnt = sizeof (types) / sizeof (dsym_type_t);
5497c478bd9Sstevel@tonic-gate int result;
5507c478bd9Sstevel@tonic-gate int i;
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate for (i = 0; i < cnt; i++) {
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate if (cs) {
5557c478bd9Sstevel@tonic-gate result = strcmp(type, types[i].dt_string);
5567c478bd9Sstevel@tonic-gate } else {
5577c478bd9Sstevel@tonic-gate result = strcasecmp(type, types[i].dt_string);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate if (result == 0) {
5617c478bd9Sstevel@tonic-gate *entry = &types[i];
5627c478bd9Sstevel@tonic-gate return (DSYM_SUCCESS);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate return (DSYM_INVALID_TYPE);
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate * dsym_parse_type(): given a DHCP type string, returns the type id
5717c478bd9Sstevel@tonic-gate *
5727c478bd9Sstevel@tonic-gate * input: char *: a DHCP type string
5737c478bd9Sstevel@tonic-gate * dsym_cdtype_t *: the return location for the type id
5747c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE
5757c478bd9Sstevel@tonic-gate */
576*d04ccbb3Scarlsonj
5777c478bd9Sstevel@tonic-gate static dsym_errcode_t
dsym_parse_type(char * field,dsym_cdtype_t * type)5787c478bd9Sstevel@tonic-gate dsym_parse_type(char *field, dsym_cdtype_t *type)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate dsym_type_t *entry;
5827c478bd9Sstevel@tonic-gate int ret;
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate ret = dsym_get_type_by_name(field, &entry, B_TRUE);
5857c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * Since this routine is meant to be used to parse dhcptab
5887c478bd9Sstevel@tonic-gate * symbol definitions, only a subset of the DHCP type
5897c478bd9Sstevel@tonic-gate * are valid in this context.
5907c478bd9Sstevel@tonic-gate */
5917c478bd9Sstevel@tonic-gate if (entry->dt_dhcptab) {
5927c478bd9Sstevel@tonic-gate *type = entry->dt_id;
5937c478bd9Sstevel@tonic-gate } else {
5947c478bd9Sstevel@tonic-gate ret = DSYM_INVALID_TYPE;
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate return (ret);
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate /*
6027c478bd9Sstevel@tonic-gate * dsym_free_fields(): frees an array of fields allocated by
6037c478bd9Sstevel@tonic-gate * dsym_init_parser().
6047c478bd9Sstevel@tonic-gate *
6057c478bd9Sstevel@tonic-gate * input: char **: array of fields to free
6067c478bd9Sstevel@tonic-gate * output: none
6077c478bd9Sstevel@tonic-gate */
608*d04ccbb3Scarlsonj
6097c478bd9Sstevel@tonic-gate void
dsym_free_fields(char ** fields)6107c478bd9Sstevel@tonic-gate dsym_free_fields(char **fields)
6117c478bd9Sstevel@tonic-gate {
6127c478bd9Sstevel@tonic-gate int i;
6137c478bd9Sstevel@tonic-gate if (fields != NULL) {
6147c478bd9Sstevel@tonic-gate for (i = 0; i < DSYM_NUM_FIELDS; i++) {
6157c478bd9Sstevel@tonic-gate free(fields[i]);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate free(fields);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate /*
6227c478bd9Sstevel@tonic-gate * dsym_close_parser(): free up all resources associated with the parser
6237c478bd9Sstevel@tonic-gate *
6247c478bd9Sstevel@tonic-gate * input: char **: the fields allocated by dsym_init_parser()
6257c478bd9Sstevel@tonic-gate * dhcp_symbol_t *: the structure populated by dsym_init_parser()
6267c478bd9Sstevel@tonic-gate * output: none
6277c478bd9Sstevel@tonic-gate */
628*d04ccbb3Scarlsonj
6297c478bd9Sstevel@tonic-gate void
dsym_close_parser(char ** fields,dhcp_symbol_t * sym)6307c478bd9Sstevel@tonic-gate dsym_close_parser(char **fields, dhcp_symbol_t *sym)
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate dsym_free_fields(fields);
6337c478bd9Sstevel@tonic-gate dsym_free_classes(&sym->ds_classes);
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate * dsym_init_parser(): initializes the structures used to parse a symbol
6387c478bd9Sstevel@tonic-gate * value.
6397c478bd9Sstevel@tonic-gate *
6407c478bd9Sstevel@tonic-gate * input: const char *: the symbol name
6417c478bd9Sstevel@tonic-gate * const char *: the symbol value in dhcptab format
6427c478bd9Sstevel@tonic-gate * char ***: the return location for the symbol fields
6437c478bd9Sstevel@tonic-gate * dhcp_symbol_t *: the structure which eventually will
6447c478bd9Sstevel@tonic-gate * be the repository for the parsed symbol data
6457c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DYSM_NO_MEMORY, DSYM_NULL_FIELD or
6467c478bd9Sstevel@tonic-gate * DSYM_TOO_MANY_FIELDS
6477c478bd9Sstevel@tonic-gate */
648*d04ccbb3Scarlsonj
6497c478bd9Sstevel@tonic-gate dsym_errcode_t
dsym_init_parser(const char * name,const char * value,char *** fields_ret,dhcp_symbol_t * sym)6507c478bd9Sstevel@tonic-gate dsym_init_parser(const char *name, const char *value, char ***fields_ret,
6517c478bd9Sstevel@tonic-gate dhcp_symbol_t *sym)
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate int ret = DSYM_SUCCESS;
6557c478bd9Sstevel@tonic-gate char *cp;
6567c478bd9Sstevel@tonic-gate char *next;
6577c478bd9Sstevel@tonic-gate char *field;
6587c478bd9Sstevel@tonic-gate char **fields;
6597c478bd9Sstevel@tonic-gate int i;
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate /*
6627c478bd9Sstevel@tonic-gate * Initialize the symbol structure.
6637c478bd9Sstevel@tonic-gate */
6647c478bd9Sstevel@tonic-gate sym->ds_category = 0;
6657c478bd9Sstevel@tonic-gate sym->ds_code = 0;
6667c478bd9Sstevel@tonic-gate (void) strlcpy(sym->ds_name, name, DSYM_MAX_SYM_LEN);
6677c478bd9Sstevel@tonic-gate sym->ds_type = 0;
6687c478bd9Sstevel@tonic-gate sym->ds_gran = 0;
6697c478bd9Sstevel@tonic-gate sym->ds_max = 0;
6707c478bd9Sstevel@tonic-gate sym->ds_classes.dc_names = NULL;
6717c478bd9Sstevel@tonic-gate sym->ds_classes.dc_cnt = 0;
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate if ((cp = strdup(value)) == NULL ||
6747c478bd9Sstevel@tonic-gate (fields = calloc(DSYM_NUM_FIELDS, sizeof (char *))) == NULL) {
6757c478bd9Sstevel@tonic-gate ret = DSYM_NO_MEMORY;
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate next = cp;
6797c478bd9Sstevel@tonic-gate for (i = 0; ret == DSYM_SUCCESS && i < DSYM_NUM_FIELDS; i++) {
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate field = dsym_get_token(next, DSYM_FIELD_DEL, &next,
6827c478bd9Sstevel@tonic-gate B_FALSE);
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate if (field == NULL) {
6857c478bd9Sstevel@tonic-gate ret = DSYM_NULL_FIELD;
6867c478bd9Sstevel@tonic-gate continue;
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate dsym_trim(&field);
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate if (strlen(field) == 0) {
6927c478bd9Sstevel@tonic-gate ret = DSYM_NULL_FIELD;
6937c478bd9Sstevel@tonic-gate continue;
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate if ((fields[i] = strdup(field)) == NULL) {
6977c478bd9Sstevel@tonic-gate ret = DSYM_NO_MEMORY;
6987c478bd9Sstevel@tonic-gate continue;
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS &&
7037c478bd9Sstevel@tonic-gate dsym_get_token(next, DSYM_FIELD_DEL, &next, B_FALSE) != NULL) {
7047c478bd9Sstevel@tonic-gate ret = DSYM_TOO_MANY_FIELDS;
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate if (ret != DSYM_SUCCESS) {
7087c478bd9Sstevel@tonic-gate dsym_free_fields(fields);
7097c478bd9Sstevel@tonic-gate } else {
7107c478bd9Sstevel@tonic-gate *fields_ret = fields;
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate free(cp);
7147c478bd9Sstevel@tonic-gate return (ret);
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate * dsym_parse_field(): parses the specified symbol field.
7197c478bd9Sstevel@tonic-gate *
7207c478bd9Sstevel@tonic-gate * input: int: the field number to be parsed.
7217c478bd9Sstevel@tonic-gate * char **: symbol fields initialized by dsym_init_parser()
7227c478bd9Sstevel@tonic-gate * dhcp_symbol_t *: the structure which will be the repository
7237c478bd9Sstevel@tonic-gate * for the parsed field
7247c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, DSYM_CODE_OUT_OF_RANGE,
7257c478bd9Sstevel@tonic-gate * DSYM_INVALID_CAT, DSYM_INVALID_TYPE, DSYM_EXCEEDS_CLASS_SIZE,
7267c478bd9Sstevel@tonic-gate * DSYM_EXCEEDS_MAX_CLASS_SIZE, DSYM_NO_MEMORY,
7277c478bd9Sstevel@tonic-gate * DSYM_INVALID_FIELD_NUM, DSYM_VALUE_OUT_OF_RANGE
7287c478bd9Sstevel@tonic-gate */
729*d04ccbb3Scarlsonj
7307c478bd9Sstevel@tonic-gate dsym_errcode_t
dsym_parse_field(int field_num,char ** fields,dhcp_symbol_t * sym)7317c478bd9Sstevel@tonic-gate dsym_parse_field(int field_num, char **fields, dhcp_symbol_t *sym)
7327c478bd9Sstevel@tonic-gate {
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate int ret = DSYM_SUCCESS;
7357c478bd9Sstevel@tonic-gate int intval;
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate switch (field_num) {
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate case DSYM_CAT_FIELD:
7407c478bd9Sstevel@tonic-gate ret = dsym_parse_cat(fields[field_num], &sym->ds_category);
7417c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS && sym->ds_category == DSYM_VENDOR) {
7427c478bd9Sstevel@tonic-gate ret = dsym_parse_classes(fields[field_num],
7437c478bd9Sstevel@tonic-gate &sym->ds_classes);
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate break;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate case DSYM_CODE_FIELD:
7487c478bd9Sstevel@tonic-gate ret = dsym_parse_intrange(fields[field_num], &intval, 0,
7497c478bd9Sstevel@tonic-gate USHRT_MAX);
7507c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
7517c478bd9Sstevel@tonic-gate sym->ds_code = (ushort_t)intval;
7527c478bd9Sstevel@tonic-gate ret = dsym_validate_code(sym->ds_category,
7537c478bd9Sstevel@tonic-gate sym->ds_code);
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate break;
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate case DSYM_TYPE_FIELD:
7587c478bd9Sstevel@tonic-gate ret = dsym_parse_type(fields[field_num], &sym->ds_type);
7597c478bd9Sstevel@tonic-gate break;
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate case DSYM_GRAN_FIELD:
7627c478bd9Sstevel@tonic-gate ret = dsym_parse_intrange(fields[field_num], &intval, 0,
7637c478bd9Sstevel@tonic-gate UCHAR_MAX);
7647c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
7657c478bd9Sstevel@tonic-gate sym->ds_gran = (uchar_t)intval;
7667c478bd9Sstevel@tonic-gate ret = dsym_validate_granularity(sym->ds_type,
7677c478bd9Sstevel@tonic-gate sym->ds_gran);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate case DSYM_MAX_FIELD:
7727c478bd9Sstevel@tonic-gate ret = dsym_parse_intrange(fields[field_num], &intval, 0,
7737c478bd9Sstevel@tonic-gate UCHAR_MAX);
7747c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
7757c478bd9Sstevel@tonic-gate sym->ds_max = (uchar_t)intval;
7767c478bd9Sstevel@tonic-gate }
7777c478bd9Sstevel@tonic-gate break;
7787c478bd9Sstevel@tonic-gate default:
7797c478bd9Sstevel@tonic-gate ret = DSYM_INVALID_FIELD_NUM;
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate return (ret);
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * dsym_parser(): parses a DHCP symbol value
7877c478bd9Sstevel@tonic-gate *
7887c478bd9Sstevel@tonic-gate * input: char **: symbol fields initialized by dsym_init_parser()
7897c478bd9Sstevel@tonic-gate * dhcp_symbol_t *: the structure which will be the repository
7907c478bd9Sstevel@tonic-gate * for the parsed field
7917c478bd9Sstevel@tonic-gate * int *: last field processed
7927c478bd9Sstevel@tonic-gate * boolean_t: parse all fields even though errors occur?
7937c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, DSYM_CODE_OUT_OF_RANGE,
7947c478bd9Sstevel@tonic-gate * DSYM_INVALID_CAT, DSYM_INVALID_TYPE, DSYM_EXCEEDS_CLASS_SIZE,
7957c478bd9Sstevel@tonic-gate * DSYM_EXCEEDS_MAX_CLASS_SIZE, DSYM_NO_MEMORY
7967c478bd9Sstevel@tonic-gate * DSYM_INVALID_FIELD_NUM, DSYM_VALUE_OUT_OF_RANGE
7977c478bd9Sstevel@tonic-gate */
798*d04ccbb3Scarlsonj
7997c478bd9Sstevel@tonic-gate dsym_errcode_t
dsym_parser(char ** fields,dhcp_symbol_t * sym,int * lastField,boolean_t bestEffort)8007c478bd9Sstevel@tonic-gate dsym_parser(char **fields, dhcp_symbol_t *sym, int *lastField,
8017c478bd9Sstevel@tonic-gate boolean_t bestEffort)
8027c478bd9Sstevel@tonic-gate {
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate int ret = DSYM_SUCCESS;
8057c478bd9Sstevel@tonic-gate int tret = DSYM_SUCCESS;
8067c478bd9Sstevel@tonic-gate int i;
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate *lastField = -1;
8097c478bd9Sstevel@tonic-gate for (i = DSYM_FIRST_FIELD;
8107c478bd9Sstevel@tonic-gate tret == DSYM_SUCCESS && i < DSYM_NUM_FIELDS; i++) {
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate tret = dsym_parse_field(i, fields, sym);
8137c478bd9Sstevel@tonic-gate if (tret != DSYM_SUCCESS) {
8147c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
8157c478bd9Sstevel@tonic-gate ret = tret;
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate if (bestEffort) {
8187c478bd9Sstevel@tonic-gate *lastField = i;
8197c478bd9Sstevel@tonic-gate tret = DSYM_SUCCESS;
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate }
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate if (*lastField == -1) {
8257c478bd9Sstevel@tonic-gate *lastField = i - 1;
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate return (ret);
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate * dsym_get_cat_id(): given a category string, return the associated id.
8337c478bd9Sstevel@tonic-gate *
8347c478bd9Sstevel@tonic-gate * input: const char *: the category name
8357c478bd9Sstevel@tonic-gate * dsym_category_t *: the return location for the id
8367c478bd9Sstevel@tonic-gate * boolean_t: case-sensitive name compare
8377c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT
8387c478bd9Sstevel@tonic-gate */
839*d04ccbb3Scarlsonj
8407c478bd9Sstevel@tonic-gate dsym_errcode_t
dsym_get_cat_id(const char * cat,dsym_category_t * id,boolean_t cs)8417c478bd9Sstevel@tonic-gate dsym_get_cat_id(const char *cat, dsym_category_t *id, boolean_t cs)
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate dsym_cat_t *entry;
8457c478bd9Sstevel@tonic-gate int ret;
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate ret = dsym_get_cat_by_name(cat, &entry, cs);
8487c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
8497c478bd9Sstevel@tonic-gate *id = entry->dc_id;
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate return (ret);
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate
8557c478bd9Sstevel@tonic-gate /*
8567c478bd9Sstevel@tonic-gate * dsym_get_code_ranges(): given a category field, returns its valid code
8577c478bd9Sstevel@tonic-gate * ranges.
8587c478bd9Sstevel@tonic-gate *
8597c478bd9Sstevel@tonic-gate * input: const char *: the category name
8607c478bd9Sstevel@tonic-gate * ushort *: return location for the minimum code value.
8617c478bd9Sstevel@tonic-gate * ushort *: return location for the maximum code value.
8627c478bd9Sstevel@tonic-gate * boolean_t: case-sensitive name compare
8637c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT
8647c478bd9Sstevel@tonic-gate */
865*d04ccbb3Scarlsonj
8667c478bd9Sstevel@tonic-gate dsym_errcode_t
dsym_get_code_ranges(const char * cat,ushort_t * min,ushort_t * max,boolean_t cs)8677c478bd9Sstevel@tonic-gate dsym_get_code_ranges(const char *cat, ushort_t *min, ushort_t *max,
8687c478bd9Sstevel@tonic-gate boolean_t cs)
8697c478bd9Sstevel@tonic-gate {
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate dsym_cat_t *entry;
8727c478bd9Sstevel@tonic-gate int ret;
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate ret = dsym_get_cat_by_name(cat, &entry, cs);
8757c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
8767c478bd9Sstevel@tonic-gate *min = entry->dc_min;
8777c478bd9Sstevel@tonic-gate *max = entry->dc_max;
8787c478bd9Sstevel@tonic-gate }
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate return (ret);
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate /*
8847c478bd9Sstevel@tonic-gate * dsym_get_type_id(): given a type string, return the associated type id.
8857c478bd9Sstevel@tonic-gate *
8867c478bd9Sstevel@tonic-gate * input: const char *: the type name
8877c478bd9Sstevel@tonic-gate * dsym_cdtype_t *: the return location for the id
8887c478bd9Sstevel@tonic-gate * boolean_t: case-sensitive name compare
8897c478bd9Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE
8907c478bd9Sstevel@tonic-gate */
891*d04ccbb3Scarlsonj
8927c478bd9Sstevel@tonic-gate dsym_errcode_t
dsym_get_type_id(const char * type,dsym_cdtype_t * id,boolean_t cs)8937c478bd9Sstevel@tonic-gate dsym_get_type_id(const char *type, dsym_cdtype_t *id, boolean_t cs)
8947c478bd9Sstevel@tonic-gate {
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate dsym_type_t *entry;
8977c478bd9Sstevel@tonic-gate int ret;
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate ret = dsym_get_type_by_name(type, &entry, cs);
9007c478bd9Sstevel@tonic-gate if (ret == DSYM_SUCCESS) {
9017c478bd9Sstevel@tonic-gate *id = entry->dt_id;
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate return (ret);
9057c478bd9Sstevel@tonic-gate }
906