1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <stdlib.h> 30*0Sstevel@tonic-gate #include <ctype.h> 31*0Sstevel@tonic-gate #include <strings.h> 32*0Sstevel@tonic-gate #include <limits.h> 33*0Sstevel@tonic-gate #include <errno.h> 34*0Sstevel@tonic-gate #include <dhcp_impl.h> 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include "dhcp_symbol.h" 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate /* 39*0Sstevel@tonic-gate * The following structure and table are used to define the attributes 40*0Sstevel@tonic-gate * of a DHCP symbol category. 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate typedef struct dsym_cat { 43*0Sstevel@tonic-gate char *dc_string; /* string value for the category */ 44*0Sstevel@tonic-gate int dc_minlen; /* min. chars of dc_string to match */ 45*0Sstevel@tonic-gate dsym_category_t dc_id; /* numerical value for the category */ 46*0Sstevel@tonic-gate boolean_t dc_dhcptab; /* valid for dhcptab use? */ 47*0Sstevel@tonic-gate ushort_t dc_min; /* minimum valid code */ 48*0Sstevel@tonic-gate ushort_t dc_max; /* maximum valid code */ 49*0Sstevel@tonic-gate } dsym_cat_t; 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate static dsym_cat_t cats[DSYM_CATEGORY_NUM] = { 52*0Sstevel@tonic-gate { "Extend", 6, DSYM_EXTEND, B_TRUE, DHCP_LAST_STD + 1, 53*0Sstevel@tonic-gate DHCP_SITE_OPT - 1 }, 54*0Sstevel@tonic-gate { "Vendor=", 6, DSYM_VENDOR, B_TRUE, DHCP_FIRST_OPT, 55*0Sstevel@tonic-gate DHCP_LAST_OPT }, 56*0Sstevel@tonic-gate { "Site", 4, DSYM_SITE, B_TRUE, DHCP_SITE_OPT, DHCP_LAST_OPT }, 57*0Sstevel@tonic-gate { "Standard", 8, DSYM_STANDARD, B_FALSE, DHCP_FIRST_OPT, 58*0Sstevel@tonic-gate DHCP_LAST_STD }, 59*0Sstevel@tonic-gate { "Field", 5, DSYM_FIELD, B_FALSE, CD_PACKET_START, 60*0Sstevel@tonic-gate CD_PACKET_END }, 61*0Sstevel@tonic-gate { "Internal", 8, DSYM_INTERNAL, B_FALSE, CD_INTRNL_START, 62*0Sstevel@tonic-gate CD_INTRNL_END } 63*0Sstevel@tonic-gate }; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate /* 66*0Sstevel@tonic-gate * The following structure and table are used to define the attributes 67*0Sstevel@tonic-gate * of a DHCP symbol type. 68*0Sstevel@tonic-gate */ 69*0Sstevel@tonic-gate typedef struct dsym_type { 70*0Sstevel@tonic-gate char *dt_string; /* string value for the type */ 71*0Sstevel@tonic-gate dsym_cdtype_t dt_id; /* numerical value for the type */ 72*0Sstevel@tonic-gate boolean_t dt_dhcptab; /* valid for dhcptab use? */ 73*0Sstevel@tonic-gate } dsym_type_t; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate static dsym_type_t types[DSYM_CDTYPE_NUM] = { 76*0Sstevel@tonic-gate { "ASCII", DSYM_ASCII, B_TRUE }, 77*0Sstevel@tonic-gate { "OCTET", DSYM_OCTET, B_TRUE }, 78*0Sstevel@tonic-gate { "IP", DSYM_IP, B_TRUE }, 79*0Sstevel@tonic-gate { "NUMBER", DSYM_NUMBER, B_TRUE }, 80*0Sstevel@tonic-gate { "BOOL", DSYM_BOOL, B_TRUE }, 81*0Sstevel@tonic-gate { "INCLUDE", DSYM_INCLUDE, B_FALSE }, 82*0Sstevel@tonic-gate { "UNUMBER8", DSYM_UNUMBER8, B_TRUE }, 83*0Sstevel@tonic-gate { "UNUMBER16", DSYM_UNUMBER16, B_TRUE }, 84*0Sstevel@tonic-gate { "UNUMBER32", DSYM_UNUMBER32, B_TRUE }, 85*0Sstevel@tonic-gate { "UNUMBER64", DSYM_UNUMBER64, B_TRUE }, 86*0Sstevel@tonic-gate { "SNUMBER8", DSYM_SNUMBER8, B_TRUE }, 87*0Sstevel@tonic-gate { "SNUMBER16", DSYM_SNUMBER16, B_TRUE }, 88*0Sstevel@tonic-gate { "SNUMBER32", DSYM_SNUMBER32, B_TRUE }, 89*0Sstevel@tonic-gate { "SNUMBER64", DSYM_SNUMBER64, B_TRUE } 90*0Sstevel@tonic-gate }; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * symbol delimiters and constants 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate #define DSYM_CLASS_DEL " \t\n" 96*0Sstevel@tonic-gate #define DSYM_FIELD_DEL "," 97*0Sstevel@tonic-gate #define DSYM_VENDOR_DEL '=' 98*0Sstevel@tonic-gate #define DSYM_QUOTE '"' 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* 101*0Sstevel@tonic-gate * dsym_trim(): trims all whitespace from either side of a string 102*0Sstevel@tonic-gate * 103*0Sstevel@tonic-gate * input: char **: a pointer to a string to trim of whitespace. 104*0Sstevel@tonic-gate * output: none 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate static void 107*0Sstevel@tonic-gate dsym_trim(char **str) 108*0Sstevel@tonic-gate { 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate char *tmpstr = *str; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate * Trim all whitespace from the front of the string. 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate while (*tmpstr != '\0' && isspace(*tmpstr)) { 116*0Sstevel@tonic-gate tmpstr++; 117*0Sstevel@tonic-gate } 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * Move the str pointer to first non-whitespace char. 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate *str = tmpstr; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* 125*0Sstevel@tonic-gate * Check case where the string is nothing but whitespace. 126*0Sstevel@tonic-gate */ 127*0Sstevel@tonic-gate if (*tmpstr == '\0') { 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate /* 130*0Sstevel@tonic-gate * Trim all whitespace from the end of the string. 131*0Sstevel@tonic-gate */ 132*0Sstevel@tonic-gate tmpstr = *str + strlen(*str) - 1; 133*0Sstevel@tonic-gate while (tmpstr >= *str && isspace(*tmpstr)) { 134*0Sstevel@tonic-gate tmpstr--; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* 138*0Sstevel@tonic-gate * terminate after last non-whitespace char. 139*0Sstevel@tonic-gate */ 140*0Sstevel@tonic-gate *(tmpstr+1) = '\0'; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate /* 145*0Sstevel@tonic-gate * dsym_get_token(): strtok_r() like routine, except consecutive delimiters 146*0Sstevel@tonic-gate * result in an empty string 147*0Sstevel@tonic-gate * 148*0Sstevel@tonic-gate * note: original string is modified 149*0Sstevel@tonic-gate * 150*0Sstevel@tonic-gate * input: char *: string in which to search for tokens 151*0Sstevel@tonic-gate * char *: list of possible token delimiter characters 152*0Sstevel@tonic-gate * char **: location for next call to routine 153*0Sstevel@tonic-gate * boolean_t: should delimiters be ignored if within quoted string? 154*0Sstevel@tonic-gate * output: char *: token, or NULL if no more tokens 155*0Sstevel@tonic-gate */ 156*0Sstevel@tonic-gate static char * 157*0Sstevel@tonic-gate dsym_get_token(char *str, char *dels, char **lasts, boolean_t quote_support) 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate char *ptr = str; 161*0Sstevel@tonic-gate char *del; 162*0Sstevel@tonic-gate boolean_t found = B_FALSE; 163*0Sstevel@tonic-gate boolean_t in_quote = B_FALSE; 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* 166*0Sstevel@tonic-gate * If incoming string has no tokens return a NULL 167*0Sstevel@tonic-gate * pointer to signify no more tokens. 168*0Sstevel@tonic-gate */ 169*0Sstevel@tonic-gate if (*ptr == '\0') { 170*0Sstevel@tonic-gate return (NULL); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* 174*0Sstevel@tonic-gate * Loop until either a token has been identified or until end 175*0Sstevel@tonic-gate * of string has been reached. 176*0Sstevel@tonic-gate */ 177*0Sstevel@tonic-gate while (!found && *ptr != '\0') { 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * If pointer currently lies within a quoted string, 181*0Sstevel@tonic-gate * then do not check for the delimiter. 182*0Sstevel@tonic-gate */ 183*0Sstevel@tonic-gate if (!in_quote) { 184*0Sstevel@tonic-gate for (del = dels; !found && *del != '\0'; del++) { 185*0Sstevel@tonic-gate if (*del == *ptr) { 186*0Sstevel@tonic-gate *ptr++ = '\0'; 187*0Sstevel@tonic-gate found = B_TRUE; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /* 193*0Sstevel@tonic-gate * If the pointer is pointing at a delimiter, then 194*0Sstevel@tonic-gate * check to see if it points to at a quote and update 195*0Sstevel@tonic-gate * the state appropriately. 196*0Sstevel@tonic-gate */ 197*0Sstevel@tonic-gate if (!found) { 198*0Sstevel@tonic-gate if (quote_support && *ptr == DSYM_QUOTE) { 199*0Sstevel@tonic-gate in_quote = !in_quote; 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate ptr++; 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate *lasts = ptr; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate return (str); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate /* 211*0Sstevel@tonic-gate * dsym_get_long(): given a numeric string, returns its long value 212*0Sstevel@tonic-gate * 213*0Sstevel@tonic-gate * input: const char *: the numeric string 214*0Sstevel@tonic-gate * long *: the return location for the long value 215*0Sstevel@tonic-gate * output: DSYM_SUCCESS, DSYM_VALUE_OUT_OF_RANGE or DSYM_SYNTAX_ERROR 216*0Sstevel@tonic-gate */ 217*0Sstevel@tonic-gate static dsym_errcode_t 218*0Sstevel@tonic-gate dsym_get_long(const char *str, long *val) 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate int ret = DSYM_SUCCESS; 222*0Sstevel@tonic-gate int i; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate for (i = 0; str[i] != '\0'; i++) { 225*0Sstevel@tonic-gate if (!isdigit(str[i])) { 226*0Sstevel@tonic-gate return (DSYM_SYNTAX_ERROR); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate errno = 0; 231*0Sstevel@tonic-gate *val = strtol(str, NULL, 10); 232*0Sstevel@tonic-gate if (errno != 0) { 233*0Sstevel@tonic-gate ret = DSYM_VALUE_OUT_OF_RANGE; 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate return (ret); 237*0Sstevel@tonic-gate } 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate /* 240*0Sstevel@tonic-gate * dsym_free_classes(): frees the classes allocated by dsym_parse_classes() 241*0Sstevel@tonic-gate * 242*0Sstevel@tonic-gate * input: dhcp_classes_t *: pointer to structure containing classes to free 243*0Sstevel@tonic-gate * output: none 244*0Sstevel@tonic-gate */ 245*0Sstevel@tonic-gate void 246*0Sstevel@tonic-gate dsym_free_classes(dhcp_classes_t *classes) 247*0Sstevel@tonic-gate { 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate int i; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if (classes->dc_names == NULL) { 252*0Sstevel@tonic-gate return; 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate for (i = 0; i < classes->dc_cnt; i++) { 256*0Sstevel@tonic-gate free(classes->dc_names[i]); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate free(classes->dc_names); 260*0Sstevel@tonic-gate classes->dc_names = NULL; 261*0Sstevel@tonic-gate classes->dc_cnt = 0; 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate /* 265*0Sstevel@tonic-gate * dsym_parse_classes(): given a "Vendor" class string, builds and returns 266*0Sstevel@tonic-gate * the list of vendor classes 267*0Sstevel@tonic-gate * 268*0Sstevel@tonic-gate * input: char *: the "Vendor" class string 269*0Sstevel@tonic-gate * dhcp_classes_t *: pointer to the classes structure 270*0Sstevel@tonic-gate * output: DSYM_SUCCESS, DSYM_INVALID_CAT, DSYM_EXCEEDS_MAX_CLASS_SIZE, 271*0Sstevel@tonic-gate * DSYM_EXCEEDS_CLASS_SIZE, DSYM_SYNTAX_ERROR, or DSYM_NO_MEMORY 272*0Sstevel@tonic-gate */ 273*0Sstevel@tonic-gate static dsym_errcode_t 274*0Sstevel@tonic-gate dsym_parse_classes(char *ptr, dhcp_classes_t *classes_ret) 275*0Sstevel@tonic-gate { 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate char **classes = NULL; 278*0Sstevel@tonic-gate char *cp; 279*0Sstevel@tonic-gate int len; 280*0Sstevel@tonic-gate int ret = DSYM_SUCCESS; 281*0Sstevel@tonic-gate int i; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate while (*ptr != '\0') { 284*0Sstevel@tonic-gate if (*ptr == DSYM_VENDOR_DEL) { 285*0Sstevel@tonic-gate ptr++; 286*0Sstevel@tonic-gate break; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate ptr++; 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate if (*ptr == '\0') { 292*0Sstevel@tonic-gate return (DSYM_INVALID_CAT); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate if (strlen(ptr) > DSYM_MAX_CLASS_SIZE) { 296*0Sstevel@tonic-gate return (DSYM_EXCEEDS_MAX_CLASS_SIZE); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate dsym_trim(&ptr); 300*0Sstevel@tonic-gate classes_ret->dc_cnt = 0; 301*0Sstevel@tonic-gate for (i = 0; ret == DSYM_SUCCESS; i++) { 302*0Sstevel@tonic-gate cp = dsym_get_token(ptr, DSYM_CLASS_DEL, &ptr, B_TRUE); 303*0Sstevel@tonic-gate if (cp == NULL) { 304*0Sstevel@tonic-gate break; 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate len = strlen(cp); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate if (len == 0) { 310*0Sstevel@tonic-gate continue; 311*0Sstevel@tonic-gate } else if (len > DSYM_CLASS_SIZE) { 312*0Sstevel@tonic-gate ret = DSYM_EXCEEDS_CLASS_SIZE; 313*0Sstevel@tonic-gate continue; 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate if (cp[0] == DSYM_QUOTE && cp[len-1] != DSYM_QUOTE) { 317*0Sstevel@tonic-gate ret = DSYM_SYNTAX_ERROR; 318*0Sstevel@tonic-gate continue; 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* Strip off the quotes */ 322*0Sstevel@tonic-gate if (cp[0] == DSYM_QUOTE) { 323*0Sstevel@tonic-gate cp[len-1] = '\0'; 324*0Sstevel@tonic-gate cp++; 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate classes = realloc(classes_ret->dc_names, 328*0Sstevel@tonic-gate (sizeof (char **)) * (classes_ret->dc_cnt + 1)); 329*0Sstevel@tonic-gate if (classes == NULL || 330*0Sstevel@tonic-gate (classes[classes_ret->dc_cnt] = strdup(cp)) 331*0Sstevel@tonic-gate == NULL) { 332*0Sstevel@tonic-gate ret = DSYM_NO_MEMORY; 333*0Sstevel@tonic-gate continue; 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate classes_ret->dc_names = classes; 336*0Sstevel@tonic-gate classes_ret->dc_cnt++; 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate if (ret != DSYM_SUCCESS) { 340*0Sstevel@tonic-gate dsym_free_classes(classes_ret); 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate return (ret); 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate /* 347*0Sstevel@tonic-gate * dsym_get_cat_by_name(): given a category field, returns the pointer to its 348*0Sstevel@tonic-gate * entry in the internal category table. 349*0Sstevel@tonic-gate * 350*0Sstevel@tonic-gate * input: const char *: the category name 351*0Sstevel@tonic-gate * dsym_cat_t *: the return location for the pointer to the table entry 352*0Sstevel@tonic-gate * boolean_t: case-sensitive name compare 353*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT 354*0Sstevel@tonic-gate */ 355*0Sstevel@tonic-gate static dsym_errcode_t 356*0Sstevel@tonic-gate dsym_get_cat_by_name(const char *cat, dsym_cat_t **entry, boolean_t cs) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate dsym_cat_t *entryp = NULL; 360*0Sstevel@tonic-gate int ret = DSYM_SUCCESS; 361*0Sstevel@tonic-gate int cnt = sizeof (cats) / sizeof (dsym_cat_t); 362*0Sstevel@tonic-gate int result; 363*0Sstevel@tonic-gate int len; 364*0Sstevel@tonic-gate int i; 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate len = cats[i].dc_minlen; 369*0Sstevel@tonic-gate if (cs) { 370*0Sstevel@tonic-gate result = strncmp(cat, cats[i].dc_string, len); 371*0Sstevel@tonic-gate } else { 372*0Sstevel@tonic-gate result = strncasecmp(cat, cats[i].dc_string, len); 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if (result == 0) { 376*0Sstevel@tonic-gate entryp = &cats[i]; 377*0Sstevel@tonic-gate break; 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate if (entryp != NULL) { 382*0Sstevel@tonic-gate /* 383*0Sstevel@tonic-gate * Special code required for the Vendor category, because we 384*0Sstevel@tonic-gate * allow whitespace between the keyword and the delimiter. 385*0Sstevel@tonic-gate * If there is no delimiter, then this is an illegal category. 386*0Sstevel@tonic-gate */ 387*0Sstevel@tonic-gate const char *ptr = cat + entryp->dc_minlen; 388*0Sstevel@tonic-gate if (entryp->dc_id == DSYM_VENDOR) { 389*0Sstevel@tonic-gate while (*ptr != '\0' && isspace(*ptr)) { 390*0Sstevel@tonic-gate ptr++; 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate if (*ptr != DSYM_VENDOR_DEL) { 393*0Sstevel@tonic-gate ret = DSYM_INVALID_CAT; 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate } else { 396*0Sstevel@tonic-gate if (*ptr != '\0') { 397*0Sstevel@tonic-gate ret = DSYM_INVALID_CAT; 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate } else { 401*0Sstevel@tonic-gate ret = DSYM_INVALID_CAT; 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 405*0Sstevel@tonic-gate *entry = entryp; 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate return (ret); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate /* 412*0Sstevel@tonic-gate * dsym_parse_cat(): given a category field, returns the category value 413*0Sstevel@tonic-gate * Note: The category must be a valid dhcptab category. 414*0Sstevel@tonic-gate * 415*0Sstevel@tonic-gate * input: const char *: a category field 416*0Sstevel@tonic-gate * dsym_category_t *: the return location for the category value 417*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate static dsym_errcode_t 420*0Sstevel@tonic-gate dsym_parse_cat(const char *field, dsym_category_t *cat) 421*0Sstevel@tonic-gate { 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate dsym_cat_t *entry; 424*0Sstevel@tonic-gate int ret; 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate ret = dsym_get_cat_by_name(field, &entry, B_TRUE); 427*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 428*0Sstevel@tonic-gate /* 429*0Sstevel@tonic-gate * Since this routine is meant to be used to parse dhcptab 430*0Sstevel@tonic-gate * symbol definitions, only a subset of the DHCP categories 431*0Sstevel@tonic-gate * are valid in this context. 432*0Sstevel@tonic-gate */ 433*0Sstevel@tonic-gate if (entry->dc_dhcptab) { 434*0Sstevel@tonic-gate *cat = entry->dc_id; 435*0Sstevel@tonic-gate } else { 436*0Sstevel@tonic-gate ret = DSYM_INVALID_CAT; 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate return (ret); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate /* 444*0Sstevel@tonic-gate * dsym_parse_intrange(): given a DHCP integer field, returns the value 445*0Sstevel@tonic-gate * 446*0Sstevel@tonic-gate * input: const char *: a DHCP code field 447*0Sstevel@tonic-gate * int *: the return location for the value 448*0Sstevel@tonic-gate * int: the minimum valid value 449*0Sstevel@tonic-gate * int: the maximum valid value 450*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, or DSYM_VALUE_OUT_OF_RANGE 451*0Sstevel@tonic-gate */ 452*0Sstevel@tonic-gate static dsym_errcode_t 453*0Sstevel@tonic-gate dsym_parse_intrange(const char *field, int *intval, int min, int max) 454*0Sstevel@tonic-gate { 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate int ret; 457*0Sstevel@tonic-gate long longval; 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate ret = dsym_get_long(field, &longval); 460*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 461*0Sstevel@tonic-gate if (longval < min || longval > max) { 462*0Sstevel@tonic-gate ret = DSYM_VALUE_OUT_OF_RANGE; 463*0Sstevel@tonic-gate } else { 464*0Sstevel@tonic-gate *intval = (int)longval; 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate return (ret); 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate /* 471*0Sstevel@tonic-gate * dsym_validate_code(): given a symbol category and code, validates 472*0Sstevel@tonic-gate * that the code is valid for the category 473*0Sstevel@tonic-gate * 474*0Sstevel@tonic-gate * input: dsym_category_t: the symbol category 475*0Sstevel@tonic-gate * uint16_t: the symbol code 476*0Sstevel@tonic-gate * output: DSYM_SUCCESS, DSYM_INVALID_CAT or DSYM_CODE_OUT_OF_RANGE 477*0Sstevel@tonic-gate */ 478*0Sstevel@tonic-gate static dsym_errcode_t 479*0Sstevel@tonic-gate dsym_validate_code(dsym_category_t cat, ushort_t code) 480*0Sstevel@tonic-gate { 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate int cnt = sizeof (cats) / sizeof (dsym_cat_t); 483*0Sstevel@tonic-gate int i; 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate /* 486*0Sstevel@tonic-gate * Find the category entry from the internal table. 487*0Sstevel@tonic-gate */ 488*0Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 489*0Sstevel@tonic-gate dsym_cat_t *entry; 490*0Sstevel@tonic-gate if (cat == cats[i].dc_id) { 491*0Sstevel@tonic-gate entry = &cats[i]; 492*0Sstevel@tonic-gate if (code < entry->dc_min || code > entry->dc_max) { 493*0Sstevel@tonic-gate return (DSYM_CODE_OUT_OF_RANGE); 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate return (DSYM_SUCCESS); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate return (DSYM_INVALID_CAT); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate /* 503*0Sstevel@tonic-gate * dsym_validate_granularity(): given a symbol type, validates 504*0Sstevel@tonic-gate * that the granularity is valid for the type 505*0Sstevel@tonic-gate * 506*0Sstevel@tonic-gate * input: dsym_cdtype_t: the symbol type 507*0Sstevel@tonic-gate * uchar_t: the symbol granularity 508*0Sstevel@tonic-gate * output: DSYM_SUCCESS or DSYM_VALUE_OUT_OF_RANGE 509*0Sstevel@tonic-gate */ 510*0Sstevel@tonic-gate static dsym_errcode_t 511*0Sstevel@tonic-gate dsym_validate_granularity(dsym_cdtype_t type, uchar_t gran) 512*0Sstevel@tonic-gate { 513*0Sstevel@tonic-gate /* 514*0Sstevel@tonic-gate * We only need to check for a 0 with non-boolean types, as 515*0Sstevel@tonic-gate * anything else is already validated by the ranges passed to 516*0Sstevel@tonic-gate * dsym_parse_intrange() in dsym_parse_field(). 517*0Sstevel@tonic-gate */ 518*0Sstevel@tonic-gate if (gran == 0 && type != DSYM_BOOL) { 519*0Sstevel@tonic-gate return (DSYM_VALUE_OUT_OF_RANGE); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate return (DSYM_SUCCESS); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate /* 525*0Sstevel@tonic-gate * dsym_get_type_by_name(): given a type field, returns the pointer to its 526*0Sstevel@tonic-gate * entry in the internal type table. 527*0Sstevel@tonic-gate * 528*0Sstevel@tonic-gate * input: const char *: the type name 529*0Sstevel@tonic-gate * dsym_type_t *: the return location for the pointer to the table entry 530*0Sstevel@tonic-gate * boolean_t: case-sensitive name compare 531*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE 532*0Sstevel@tonic-gate */ 533*0Sstevel@tonic-gate static dsym_errcode_t 534*0Sstevel@tonic-gate dsym_get_type_by_name(const char *type, dsym_type_t **entry, boolean_t cs) 535*0Sstevel@tonic-gate { 536*0Sstevel@tonic-gate int cnt = sizeof (types) / sizeof (dsym_type_t); 537*0Sstevel@tonic-gate int result; 538*0Sstevel@tonic-gate int i; 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate for (i = 0; i < cnt; i++) { 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate if (cs) { 543*0Sstevel@tonic-gate result = strcmp(type, types[i].dt_string); 544*0Sstevel@tonic-gate } else { 545*0Sstevel@tonic-gate result = strcasecmp(type, types[i].dt_string); 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate if (result == 0) { 549*0Sstevel@tonic-gate *entry = &types[i]; 550*0Sstevel@tonic-gate return (DSYM_SUCCESS); 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate return (DSYM_INVALID_TYPE); 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate /* 558*0Sstevel@tonic-gate * dsym_parse_type(): given a DHCP type string, returns the type id 559*0Sstevel@tonic-gate * 560*0Sstevel@tonic-gate * input: char *: a DHCP type string 561*0Sstevel@tonic-gate * dsym_cdtype_t *: the return location for the type id 562*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE 563*0Sstevel@tonic-gate */ 564*0Sstevel@tonic-gate static dsym_errcode_t 565*0Sstevel@tonic-gate dsym_parse_type(char *field, dsym_cdtype_t *type) 566*0Sstevel@tonic-gate { 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate dsym_type_t *entry; 569*0Sstevel@tonic-gate int ret; 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate ret = dsym_get_type_by_name(field, &entry, B_TRUE); 572*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 573*0Sstevel@tonic-gate /* 574*0Sstevel@tonic-gate * Since this routine is meant to be used to parse dhcptab 575*0Sstevel@tonic-gate * symbol definitions, only a subset of the DHCP type 576*0Sstevel@tonic-gate * are valid in this context. 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate if (entry->dt_dhcptab) { 579*0Sstevel@tonic-gate *type = entry->dt_id; 580*0Sstevel@tonic-gate } else { 581*0Sstevel@tonic-gate ret = DSYM_INVALID_TYPE; 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate return (ret); 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate /* 589*0Sstevel@tonic-gate * dsym_free_fields(): frees an array of fields allocated by 590*0Sstevel@tonic-gate * dsym_init_parser(). 591*0Sstevel@tonic-gate * 592*0Sstevel@tonic-gate * input: char **: array of fields to free 593*0Sstevel@tonic-gate * output: none 594*0Sstevel@tonic-gate */ 595*0Sstevel@tonic-gate void 596*0Sstevel@tonic-gate dsym_free_fields(char **fields) 597*0Sstevel@tonic-gate { 598*0Sstevel@tonic-gate int i; 599*0Sstevel@tonic-gate if (fields != NULL) { 600*0Sstevel@tonic-gate for (i = 0; i < DSYM_NUM_FIELDS; i++) { 601*0Sstevel@tonic-gate free(fields[i]); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate free(fields); 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate /* 608*0Sstevel@tonic-gate * dsym_close_parser(): free up all resources associated with the parser 609*0Sstevel@tonic-gate * 610*0Sstevel@tonic-gate * input: char **: the fields allocated by dsym_init_parser() 611*0Sstevel@tonic-gate * dhcp_symbol_t *: the structure populated by dsym_init_parser() 612*0Sstevel@tonic-gate * output: none 613*0Sstevel@tonic-gate */ 614*0Sstevel@tonic-gate void 615*0Sstevel@tonic-gate dsym_close_parser(char **fields, dhcp_symbol_t *sym) 616*0Sstevel@tonic-gate { 617*0Sstevel@tonic-gate dsym_free_fields(fields); 618*0Sstevel@tonic-gate dsym_free_classes(&sym->ds_classes); 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate /* 622*0Sstevel@tonic-gate * dsym_init_parser(): initializes the structures used to parse a symbol 623*0Sstevel@tonic-gate * value. 624*0Sstevel@tonic-gate * 625*0Sstevel@tonic-gate * input: const char *: the symbol name 626*0Sstevel@tonic-gate * const char *: the symbol value in dhcptab format 627*0Sstevel@tonic-gate * char ***: the return location for the symbol fields 628*0Sstevel@tonic-gate * dhcp_symbol_t *: the structure which eventually will 629*0Sstevel@tonic-gate * be the repository for the parsed symbol data 630*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DYSM_NO_MEMORY, DSYM_NULL_FIELD or 631*0Sstevel@tonic-gate * DSYM_TOO_MANY_FIELDS 632*0Sstevel@tonic-gate */ 633*0Sstevel@tonic-gate dsym_errcode_t 634*0Sstevel@tonic-gate dsym_init_parser(const char *name, const char *value, char ***fields_ret, 635*0Sstevel@tonic-gate dhcp_symbol_t *sym) 636*0Sstevel@tonic-gate { 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate int ret = DSYM_SUCCESS; 639*0Sstevel@tonic-gate char *cp; 640*0Sstevel@tonic-gate char *next; 641*0Sstevel@tonic-gate char *field; 642*0Sstevel@tonic-gate char **fields; 643*0Sstevel@tonic-gate int i; 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate /* 646*0Sstevel@tonic-gate * Initialize the symbol structure. 647*0Sstevel@tonic-gate */ 648*0Sstevel@tonic-gate sym->ds_category = 0; 649*0Sstevel@tonic-gate sym->ds_code = 0; 650*0Sstevel@tonic-gate (void) strlcpy(sym->ds_name, name, DSYM_MAX_SYM_LEN); 651*0Sstevel@tonic-gate sym->ds_type = 0; 652*0Sstevel@tonic-gate sym->ds_gran = 0; 653*0Sstevel@tonic-gate sym->ds_max = 0; 654*0Sstevel@tonic-gate sym->ds_classes.dc_names = NULL; 655*0Sstevel@tonic-gate sym->ds_classes.dc_cnt = 0; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate if ((cp = strdup(value)) == NULL || 658*0Sstevel@tonic-gate (fields = calloc(DSYM_NUM_FIELDS, sizeof (char *))) == NULL) { 659*0Sstevel@tonic-gate ret = DSYM_NO_MEMORY; 660*0Sstevel@tonic-gate } 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate next = cp; 663*0Sstevel@tonic-gate for (i = 0; ret == DSYM_SUCCESS && i < DSYM_NUM_FIELDS; i++) { 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate field = dsym_get_token(next, DSYM_FIELD_DEL, &next, 666*0Sstevel@tonic-gate B_FALSE); 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate if (field == NULL) { 669*0Sstevel@tonic-gate ret = DSYM_NULL_FIELD; 670*0Sstevel@tonic-gate continue; 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate dsym_trim(&field); 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate if (strlen(field) == 0) { 676*0Sstevel@tonic-gate ret = DSYM_NULL_FIELD; 677*0Sstevel@tonic-gate continue; 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate if ((fields[i] = strdup(field)) == NULL) { 681*0Sstevel@tonic-gate ret = DSYM_NO_MEMORY; 682*0Sstevel@tonic-gate continue; 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate } 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS && 687*0Sstevel@tonic-gate dsym_get_token(next, DSYM_FIELD_DEL, &next, B_FALSE) != NULL) { 688*0Sstevel@tonic-gate ret = DSYM_TOO_MANY_FIELDS; 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate if (ret != DSYM_SUCCESS) { 692*0Sstevel@tonic-gate dsym_free_fields(fields); 693*0Sstevel@tonic-gate } else { 694*0Sstevel@tonic-gate *fields_ret = fields; 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate free(cp); 698*0Sstevel@tonic-gate return (ret); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate /* 702*0Sstevel@tonic-gate * dsym_parse_field(): parses the specified symbol field. 703*0Sstevel@tonic-gate * 704*0Sstevel@tonic-gate * input: int: the field number to be parsed. 705*0Sstevel@tonic-gate * char **: symbol fields initialized by dsym_init_parser() 706*0Sstevel@tonic-gate * dhcp_symbol_t *: the structure which will be the repository 707*0Sstevel@tonic-gate * for the parsed field 708*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, DSYM_CODE_OUT_OF_RANGE, 709*0Sstevel@tonic-gate * DSYM_INVALID_CAT, DSYM_INVALID_TYPE, DSYM_EXCEEDS_CLASS_SIZE, 710*0Sstevel@tonic-gate * DSYM_EXCEEDS_MAX_CLASS_SIZE, DSYM_NO_MEMORY, 711*0Sstevel@tonic-gate * DSYM_INVALID_FIELD_NUM, DSYM_VALUE_OUT_OF_RANGE 712*0Sstevel@tonic-gate */ 713*0Sstevel@tonic-gate dsym_errcode_t 714*0Sstevel@tonic-gate dsym_parse_field(int field_num, char **fields, dhcp_symbol_t *sym) 715*0Sstevel@tonic-gate { 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate int ret = DSYM_SUCCESS; 718*0Sstevel@tonic-gate int intval; 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate switch (field_num) { 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate case DSYM_CAT_FIELD: 723*0Sstevel@tonic-gate ret = dsym_parse_cat(fields[field_num], &sym->ds_category); 724*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS && sym->ds_category == DSYM_VENDOR) { 725*0Sstevel@tonic-gate ret = dsym_parse_classes(fields[field_num], 726*0Sstevel@tonic-gate &sym->ds_classes); 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate break; 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate case DSYM_CODE_FIELD: 731*0Sstevel@tonic-gate ret = dsym_parse_intrange(fields[field_num], &intval, 0, 732*0Sstevel@tonic-gate USHRT_MAX); 733*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 734*0Sstevel@tonic-gate sym->ds_code = (ushort_t)intval; 735*0Sstevel@tonic-gate ret = dsym_validate_code(sym->ds_category, 736*0Sstevel@tonic-gate sym->ds_code); 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate break; 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate case DSYM_TYPE_FIELD: 741*0Sstevel@tonic-gate ret = dsym_parse_type(fields[field_num], &sym->ds_type); 742*0Sstevel@tonic-gate break; 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate case DSYM_GRAN_FIELD: 745*0Sstevel@tonic-gate ret = dsym_parse_intrange(fields[field_num], &intval, 0, 746*0Sstevel@tonic-gate UCHAR_MAX); 747*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 748*0Sstevel@tonic-gate sym->ds_gran = (uchar_t)intval; 749*0Sstevel@tonic-gate ret = dsym_validate_granularity(sym->ds_type, 750*0Sstevel@tonic-gate sym->ds_gran); 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate break; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate case DSYM_MAX_FIELD: 755*0Sstevel@tonic-gate ret = dsym_parse_intrange(fields[field_num], &intval, 0, 756*0Sstevel@tonic-gate UCHAR_MAX); 757*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 758*0Sstevel@tonic-gate sym->ds_max = (uchar_t)intval; 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate break; 761*0Sstevel@tonic-gate default: 762*0Sstevel@tonic-gate ret = DSYM_INVALID_FIELD_NUM; 763*0Sstevel@tonic-gate } 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate return (ret); 766*0Sstevel@tonic-gate } 767*0Sstevel@tonic-gate 768*0Sstevel@tonic-gate /* 769*0Sstevel@tonic-gate * dsym_parser(): parses a DHCP symbol value 770*0Sstevel@tonic-gate * 771*0Sstevel@tonic-gate * input: char **: symbol fields initialized by dsym_init_parser() 772*0Sstevel@tonic-gate * dhcp_symbol_t *: the structure which will be the repository 773*0Sstevel@tonic-gate * for the parsed field 774*0Sstevel@tonic-gate * int *: last field processed 775*0Sstevel@tonic-gate * boolean_t: parse all fields even though errors occur? 776*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS, DSYM_SYNTAX_ERROR, DSYM_CODE_OUT_OF_RANGE, 777*0Sstevel@tonic-gate * DSYM_INVALID_CAT, DSYM_INVALID_TYPE, DSYM_EXCEEDS_CLASS_SIZE, 778*0Sstevel@tonic-gate * DSYM_EXCEEDS_MAX_CLASS_SIZE, DSYM_NO_MEMORY 779*0Sstevel@tonic-gate * DSYM_INVALID_FIELD_NUM, DSYM_VALUE_OUT_OF_RANGE 780*0Sstevel@tonic-gate */ 781*0Sstevel@tonic-gate dsym_errcode_t 782*0Sstevel@tonic-gate dsym_parser(char **fields, dhcp_symbol_t *sym, int *lastField, 783*0Sstevel@tonic-gate boolean_t bestEffort) 784*0Sstevel@tonic-gate { 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate int ret = DSYM_SUCCESS; 787*0Sstevel@tonic-gate int tret = DSYM_SUCCESS; 788*0Sstevel@tonic-gate int i; 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate *lastField = -1; 791*0Sstevel@tonic-gate for (i = DSYM_FIRST_FIELD; 792*0Sstevel@tonic-gate tret == DSYM_SUCCESS && i < DSYM_NUM_FIELDS; i++) { 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate tret = dsym_parse_field(i, fields, sym); 795*0Sstevel@tonic-gate if (tret != DSYM_SUCCESS) { 796*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 797*0Sstevel@tonic-gate ret = tret; 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate if (bestEffort) { 800*0Sstevel@tonic-gate *lastField = i; 801*0Sstevel@tonic-gate tret = DSYM_SUCCESS; 802*0Sstevel@tonic-gate } 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate if (*lastField == -1) { 807*0Sstevel@tonic-gate *lastField = i - 1; 808*0Sstevel@tonic-gate } 809*0Sstevel@tonic-gate 810*0Sstevel@tonic-gate return (ret); 811*0Sstevel@tonic-gate } 812*0Sstevel@tonic-gate 813*0Sstevel@tonic-gate /* 814*0Sstevel@tonic-gate * dsym_get_cat_id(): given a category string, return the associated id. 815*0Sstevel@tonic-gate * 816*0Sstevel@tonic-gate * input: const char *: the category name 817*0Sstevel@tonic-gate * dsym_category_t *: the return location for the id 818*0Sstevel@tonic-gate * boolean_t: case-sensitive name compare 819*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT 820*0Sstevel@tonic-gate */ 821*0Sstevel@tonic-gate dsym_errcode_t 822*0Sstevel@tonic-gate dsym_get_cat_id(const char *cat, dsym_category_t *id, boolean_t cs) 823*0Sstevel@tonic-gate { 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate dsym_cat_t *entry; 826*0Sstevel@tonic-gate int ret; 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate ret = dsym_get_cat_by_name(cat, &entry, cs); 829*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 830*0Sstevel@tonic-gate *id = entry->dc_id; 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate return (ret); 834*0Sstevel@tonic-gate } 835*0Sstevel@tonic-gate 836*0Sstevel@tonic-gate /* 837*0Sstevel@tonic-gate * dsym_get_code_ranges(): given a category field, returns its valid code 838*0Sstevel@tonic-gate * ranges. 839*0Sstevel@tonic-gate * 840*0Sstevel@tonic-gate * input: const char *: the category name 841*0Sstevel@tonic-gate * ushort *: return location for the minimum code value. 842*0Sstevel@tonic-gate * ushort *: return location for the maximum code value. 843*0Sstevel@tonic-gate * boolean_t: case-sensitive name compare 844*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_CAT 845*0Sstevel@tonic-gate */ 846*0Sstevel@tonic-gate dsym_errcode_t 847*0Sstevel@tonic-gate dsym_get_code_ranges(const char *cat, ushort_t *min, ushort_t *max, 848*0Sstevel@tonic-gate boolean_t cs) 849*0Sstevel@tonic-gate { 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate dsym_cat_t *entry; 852*0Sstevel@tonic-gate int ret; 853*0Sstevel@tonic-gate 854*0Sstevel@tonic-gate ret = dsym_get_cat_by_name(cat, &entry, cs); 855*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 856*0Sstevel@tonic-gate *min = entry->dc_min; 857*0Sstevel@tonic-gate *max = entry->dc_max; 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate return (ret); 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate 863*0Sstevel@tonic-gate /* 864*0Sstevel@tonic-gate * dsym_get_type_id(): given a type string, return the associated type id. 865*0Sstevel@tonic-gate * 866*0Sstevel@tonic-gate * input: const char *: the type name 867*0Sstevel@tonic-gate * dsym_cdtype_t *: the return location for the id 868*0Sstevel@tonic-gate * boolean_t: case-sensitive name compare 869*0Sstevel@tonic-gate * output: int: DSYM_SUCCESS or DSYM_INVALID_TYPE 870*0Sstevel@tonic-gate */ 871*0Sstevel@tonic-gate dsym_errcode_t 872*0Sstevel@tonic-gate dsym_get_type_id(const char *type, dsym_cdtype_t *id, boolean_t cs) 873*0Sstevel@tonic-gate { 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate dsym_type_t *entry; 876*0Sstevel@tonic-gate int ret; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate ret = dsym_get_type_by_name(type, &entry, cs); 879*0Sstevel@tonic-gate if (ret == DSYM_SUCCESS) { 880*0Sstevel@tonic-gate *id = entry->dt_id; 881*0Sstevel@tonic-gate } 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate return (ret); 884*0Sstevel@tonic-gate } 885