1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * After having been declared, events, FMRIs and authorities must be defined 29 * (instantiated) before they can be used as the subjects of commands. 30 */ 31 32 #include <sys/sysmacros.h> 33 #include <libnvpair.h> 34 #include <string.h> 35 #include <assert.h> 36 37 #include <inj_event.h> 38 #include <inj_err.h> 39 #include <inj_lex.h> 40 #include <inj_string.h> 41 #include <inj.h> 42 43 static inj_hash_t inj_defns[3]; 44 static int inj_defns_initialized; 45 46 /* Intrinsics (signed and unsigned integer integer constants) */ 47 typedef struct intr { 48 uchar_t ei_signed; 49 uchar_t ei_width; 50 } intr_t; 51 52 static inj_hash_t * 53 item2hash(inj_itemtype_t item) 54 { 55 int i; 56 57 assert(item >= 0 && item < sizeof (inj_defns) / sizeof (inj_hash_t)); 58 59 if (!inj_defns_initialized) { 60 for (i = 0; i < sizeof (inj_defns) / sizeof (inj_hash_t); i++) 61 inj_strhash_create(&inj_defns[i]); 62 inj_defns_initialized = 1; 63 } 64 65 return (&inj_defns[item]); 66 } 67 68 inj_defn_t * 69 inj_defn_lookup(const char *name, inj_memtype_t type) 70 { 71 inj_hash_t *hash = item2hash(inj_mem2item(type)); 72 inj_var_t *v; 73 74 if ((v = inj_strhash_lookup(hash, name)) == NULL) 75 return (NULL); 76 77 return (inj_hash_get_cookie(v)); 78 } 79 80 static void 81 inj_defn_destroy_memlist(inj_defnmem_t *m) 82 { 83 inj_defnmem_t *n; 84 85 for (/* */; m != NULL; m = n) { 86 n = inj_list_next(m); 87 88 switch (m->dfm_type) { 89 case DEFNMEM_ARRAY: 90 case DEFNMEM_LIST: 91 inj_defn_destroy_memlist(inj_list_next(&m->dfm_list)); 92 break; 93 default: 94 inj_strfree(m->dfm_str); 95 } 96 } 97 } 98 99 void 100 inj_defn_destroy(inj_defn_t *defn) 101 { 102 if (defn->defn_name != NULL) 103 inj_strfree(defn->defn_name); 104 105 nvlist_free(defn->defn_nvl); 106 107 inj_defn_destroy_memlist(inj_list_next(&defn->defn_members)); 108 } 109 110 static inj_defnmem_t * 111 inj_defn_mem_create_common(inj_defnmemtype_t type) 112 { 113 inj_defnmem_t *dfm = inj_zalloc(sizeof (inj_defnmem_t)); 114 115 dfm->dfm_type = type; 116 dfm->dfm_lineno = yylineno; 117 118 return (dfm); 119 } 120 121 inj_defnmem_t * 122 inj_defn_mem_create(const char *str, inj_defnmemtype_t type) 123 { 124 inj_defnmem_t *dfm = inj_defn_mem_create_common(type); 125 126 dfm->dfm_str = str; 127 128 return (dfm); 129 } 130 131 inj_defnmem_t * 132 inj_defn_mem_create_list(inj_defn_t *list, inj_defnmemtype_t type) 133 { 134 inj_defnmem_t *dfm = inj_defn_mem_create_common(type); 135 136 dfm->dfm_list = list->defn_members; 137 138 inj_free(list, sizeof (inj_defn_t)); 139 140 return (dfm); 141 } 142 143 inj_defn_t * 144 inj_defn_create(inj_defnmem_t *dfm) 145 { 146 inj_defn_t *defn = inj_zalloc(sizeof (inj_defn_t)); 147 148 defn->defn_lineno = yylineno; 149 150 inj_list_append(&defn->defn_members, dfm); 151 152 return (defn); 153 } 154 155 void 156 inj_defn_addmem(inj_defn_t *defn, inj_defnmem_t *dfm) 157 { 158 inj_list_append(&defn->defn_members, dfm); 159 } 160 161 /* 162 * Validate the dimensions of an array. If the declared array size was zero, 163 * accept (and return) whatever the definition used. If fewer cells were 164 * defined than were declared, return the declared size - the calling code will 165 * fill the remaining cells with zeros. The definition of more than the 166 * declared number of cells triggers an error. We print and error message in 167 * this case and return the declared number. This will allow processing to 168 * continue. The act of emitting the error will guarantee that we never 169 * pass from parsing to program execution. 170 */ 171 static size_t 172 array_dim_check(inj_declmem_t *dlm, inj_defnmem_t *dfm) 173 { 174 inj_list_t *l; 175 size_t dfnelems; 176 177 for (dfnelems = 0, l = inj_list_next(&dfm->dfm_list); l != NULL; 178 l = inj_list_next(l), dfnelems++); 179 180 if (dlm->dlm_arrdim != 0 && dlm->dlm_arrdim != dfnelems) { 181 yyerror(" %d: defined array has %d elements, expected %d\n", 182 dfm->dfm_lineno, dfnelems, dlm->dlm_arrdim); 183 dfnelems = dlm->dlm_arrdim; 184 } 185 186 return (MAX(dfnelems, dlm->dlm_arrdim)); 187 } 188 189 /* 190 * The inj_defn_memcmp_* routines serve two purposes. First, they compare a 191 * given defined member with the corresponding declared member, signalling an 192 * error if the two are incompatible. 193 * 194 * Assuming that validation succeeds, an entry is added to the passed nvlist 195 * for the defined member. 196 */ 197 198 /* Used to ease signed and unsigned integer validation */ 199 static const intr_t inj_intrinsics[] = { 200 { 0, 0 }, /* MEMTYPE_UNKNOWN */ 201 { 1, 8 }, { 1, 16 }, { 1, 32 }, { 1, 64 }, 202 { 0, 8 }, { 0, 16 }, { 0, 32 }, { 0, 64 } 203 }; 204 205 static int 206 inj_defn_memcmp_signed(const intr_t *intr, inj_declmem_t *dlm, 207 inj_defnmem_t *dfm, nvlist_t *nvl) 208 { 209 longlong_t val; 210 211 if (dfm->dfm_type != DEFNMEM_IMM && dfm->dfm_type != DEFNMEM_IDENT) 212 return (inj_set_errno(EINVAL)); 213 214 if (inj_strtoll(dfm->dfm_str, intr->ei_width, &val) < 0) 215 return (-1); /* errno is set for us */ 216 217 switch (dlm->dlm_type) { 218 case MEMTYPE_INT8: 219 errno = nvlist_add_int8(nvl, (char *)dlm->dlm_name, 220 (int8_t)val); 221 break; 222 case MEMTYPE_INT16: 223 errno = nvlist_add_int16(nvl, (char *)dlm->dlm_name, 224 (int16_t)val); 225 break; 226 case MEMTYPE_INT32: 227 errno = nvlist_add_int32(nvl, (char *)dlm->dlm_name, 228 (int32_t)val); 229 break; 230 case MEMTYPE_INT64: 231 errno = nvlist_add_int64(nvl, (char *)dlm->dlm_name, 232 (int64_t)val); 233 } 234 235 if (errno != 0) 236 die("failed to add member %s\n", dlm->dlm_name); 237 238 return (0); 239 } 240 241 static int 242 inj_defn_memcmp_unsigned(const intr_t *intr, inj_declmem_t *dlm, 243 inj_defnmem_t *dfm, nvlist_t *nvl) 244 { 245 u_longlong_t val; 246 247 if (dfm->dfm_type != DEFNMEM_IMM && dfm->dfm_type != DEFNMEM_IDENT) 248 return (inj_set_errno(EINVAL)); 249 250 if (inj_strtoull(dfm->dfm_str, intr->ei_width, &val) < 0) 251 return (-1); /* errno is set for us */ 252 253 switch (dlm->dlm_type) { 254 case MEMTYPE_UINT8: 255 errno = nvlist_add_uint8(nvl, (char *)dlm->dlm_name, 256 (uint8_t)val); 257 break; 258 case MEMTYPE_UINT16: 259 errno = nvlist_add_uint16(nvl, (char *)dlm->dlm_name, 260 (uint16_t)val); 261 break; 262 case MEMTYPE_UINT32: 263 errno = nvlist_add_uint32(nvl, (char *)dlm->dlm_name, 264 (uint32_t)val); 265 break; 266 case MEMTYPE_UINT64: 267 errno = nvlist_add_uint64(nvl, (char *)dlm->dlm_name, 268 (uint64_t)val); 269 } 270 271 if (errno != 0) 272 die("failed to add member %s\n", dlm->dlm_name); 273 274 return (0); 275 } 276 277 /* Validate an array of (un)signed integers. */ 278 static int 279 inj_defn_memcmp_intr_array(const intr_t *cont, inj_declmem_t *dlm, 280 inj_defnmem_t *dfm, nvlist_t *nvl) 281 { 282 typedef int (*adder_t)(); 283 static const adder_t signed_adders[] = { 284 NULL, nvlist_add_int8_array, nvlist_add_int16_array, 285 NULL, nvlist_add_int32_array, NULL, NULL, NULL, 286 nvlist_add_int64_array 287 }; 288 static const adder_t unsigned_adders[] = { 289 NULL, 290 nvlist_add_uint8_array, nvlist_add_uint16_array, 291 NULL, nvlist_add_uint32_array, NULL, NULL, NULL, 292 nvlist_add_uint64_array 293 }; 294 295 union { 296 char *a; 297 int8_t *a8; uint8_t *au8; 298 int16_t *a16; uint16_t *au16; 299 int32_t *a32; uint32_t *au32; 300 int64_t *a64; uint64_t *au64; 301 } a; 302 303 int (*adder)(nvlist_t *, const char *, char *, uint_t); 304 size_t nelems; 305 inj_defnmem_t *elem; 306 char *arrbase, *arr; 307 size_t arrsz; 308 int err = 0; 309 int i; 310 311 if (dfm->dfm_type != DEFNMEM_ARRAY) 312 return (inj_set_errno(EINVAL)); 313 314 /* 315 * Each nvlist array adder wants an array of its own type as input, 316 * which is reasonable, but it complicates our general implementation. 317 * We fight back with casting magic. 318 */ 319 320 nelems = array_dim_check(dlm, dfm); 321 arrsz = (nelems + 1) * (cont->ei_width / NBBY); 322 arrbase = inj_zalloc(arrsz); 323 a.a = arr = (char *)P2ROUNDUP((uintptr_t)arrbase, 324 cont->ei_width / NBBY); 325 326 adder = (cont->ei_signed ? signed_adders : 327 unsigned_adders)[cont->ei_width / NBBY]; 328 assert(adder != NULL); 329 330 for (i = 1, elem = inj_list_next(&dfm->dfm_list); elem != NULL; 331 elem = inj_list_next(elem), i++) { 332 if (elem->dfm_type != DEFNMEM_IMM && 333 elem->dfm_type != DEFNMEM_IDENT) { 334 yyerror(" %d: array cell %d is invalid\n", 335 dfm->dfm_lineno, i); 336 err++; 337 continue; 338 } 339 340 if (cont->ei_signed) { 341 longlong_t val; 342 343 if (inj_strtoll(elem->dfm_str, cont->ei_width, 344 &val) < 0) { 345 yyerror(" %d: array cell %d %s\n", 346 dfm->dfm_lineno, i, (errno == ERANGE ? 347 "out of range for type" : "invalid")); 348 err++; 349 continue; 350 } 351 352 switch (cont->ei_width) { 353 case 8: 354 *a.a8++ = (int8_t)val; 355 break; 356 case 16: 357 *a.a16++ = (int16_t)val; 358 break; 359 case 32: 360 *a.a32++ = (int32_t)val; 361 break; 362 default: 363 *a.a64++ = (int64_t)val; 364 } 365 366 } else { 367 u_longlong_t val; 368 369 if (inj_strtoull(elem->dfm_str, cont->ei_width, 370 &val) < 0) { 371 yyerror(" %d: array cell %d %s\n", 372 dfm->dfm_lineno, i, (errno == ERANGE ? 373 "out of range for type" : "invalid")); 374 err++; 375 continue; 376 } 377 378 switch (cont->ei_width) { 379 case 8: 380 *a.au8++ = (uint8_t)val; 381 break; 382 case 16: 383 *a.au16++ = (uint16_t)val; 384 break; 385 case 32: 386 *a.au32++ = (uint32_t)val; 387 break; 388 default: 389 *a.au64++ = (uint64_t)val; 390 } 391 } 392 } 393 394 if (err == 0 && (errno = adder(nvl, dlm->dlm_name, arr, nelems)) != 0) 395 die("failed to add array member %s", dlm->dlm_name); 396 397 inj_free(arrbase, arrsz); 398 399 if (err != 0) 400 return (inj_set_errno(EINVAL)); 401 402 return (0); 403 } 404 405 static int 406 bool2val(const char *str, boolean_t *valp) 407 { 408 if (strcasecmp(str, "true") == 0) 409 *valp = 1; 410 else if (strcasecmp(str, "false") == 0) 411 *valp = 0; 412 else 413 return (-1); 414 415 return (0); 416 } 417 418 static int 419 inj_defn_memcmp_bool(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl) 420 { 421 boolean_t val; 422 423 if (dfm->dfm_type != DEFNMEM_IDENT) 424 return (inj_set_errno(EINVAL)); 425 426 if (bool2val(dfm->dfm_str, &val) < 0) 427 return (inj_set_errno(EINVAL)); 428 429 if ((errno = nvlist_add_boolean_value(nvl, (char *)dlm->dlm_name, 430 val)) != 0) 431 die("failed to add boolean member %s", dlm->dlm_name); 432 433 return (0); 434 } 435 436 static int 437 inj_defn_memcmp_bool_array(inj_declmem_t *dlm, inj_defnmem_t *dfm, 438 nvlist_t *nvl) 439 { 440 inj_defnmem_t *elem; 441 boolean_t *arr; 442 size_t nelems, arrsz; 443 int err = 0; 444 int i; 445 446 if (dfm->dfm_type != DEFNMEM_ARRAY) 447 return (inj_set_errno(EINVAL)); 448 449 nelems = array_dim_check(dlm, dfm); 450 arrsz = nelems * sizeof (boolean_t); 451 arr = inj_zalloc(arrsz); 452 453 for (i = 0, elem = inj_list_next(&dfm->dfm_list); elem != NULL; 454 elem = inj_list_next(elem), i++) { 455 if (elem->dfm_type != DEFNMEM_IDENT) { 456 yyerror(" %d: array cell %d is invalid\n", 457 dfm->dfm_lineno, i + 1); 458 err++; 459 continue; 460 } 461 462 if (bool2val(elem->dfm_str, &arr[i]) < 0) 463 return (inj_set_errno(EINVAL)); 464 } 465 466 if (err == 0 && (errno = nvlist_add_boolean_array(nvl, 467 (char *)dlm->dlm_name, arr, nelems)) != 0) 468 die("failed to add boolean array member %s", dlm->dlm_name); 469 470 inj_free(arr, arrsz); 471 472 return (0); 473 } 474 475 /* Used for both strings and enums */ 476 static int 477 inj_defn_memcmp_strenum(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl) 478 { 479 inj_defnmemtype_t defnmemtype = (dlm->dlm_type == MEMTYPE_ENUM ? 480 DEFNMEM_IDENT : DEFNMEM_QSTRING); 481 const char *strenum = (dlm->dlm_type == MEMTYPE_ENUM ? "enum" : 482 "string"); 483 484 if (dfm->dfm_type != defnmemtype) 485 return (inj_set_errno(EINVAL)); 486 487 if ((errno = nvlist_add_string(nvl, (char *)dlm->dlm_name, 488 (char *)dfm->dfm_str)) != 0) 489 die("failed to add %s member %s", strenum, dlm->dlm_name); 490 491 return (0); 492 } 493 494 static int 495 inj_defn_memcmp_strenum_array(inj_declmem_t *dlm, inj_defnmem_t *dfm, 496 nvlist_t *nvl) 497 { 498 inj_defnmemtype_t defnmemtype = (dlm->dlm_type == MEMTYPE_ENUM ? 499 DEFNMEM_IDENT : DEFNMEM_QSTRING); 500 const char *strenum = (dlm->dlm_type == MEMTYPE_ENUM ? "enum" : 501 "string"); 502 503 inj_defnmem_t *elem; 504 size_t nelems, arrsz; 505 const char **arr; 506 int err = 0; 507 int i; 508 509 if (dfm->dfm_type != DEFNMEM_ARRAY) 510 return (inj_set_errno(EINVAL)); 511 512 nelems = array_dim_check(dlm, dfm); 513 arrsz = nelems * sizeof (char *); 514 arr = inj_zalloc(arrsz); 515 516 for (i = 0, elem = inj_list_next(&dfm->dfm_list); elem != NULL; 517 elem = inj_list_next(elem), i++) { 518 if (elem->dfm_type != defnmemtype) { 519 yyerror(" %d: array cell %d is invalid\n", 520 dfm->dfm_lineno, i + 1); 521 err++; 522 continue; 523 } 524 525 if (dlm->dlm_type == MEMTYPE_ENUM && 526 inj_strhash_lookup(dlm->dlm_enumvals, elem->dfm_str) == 527 NULL) { 528 yyerror(" %d: invalid enum value %s\n", 529 dfm->dfm_lineno, elem->dfm_str); 530 err++; 531 continue; 532 } 533 534 arr[i] = elem->dfm_str; 535 } 536 537 if (err == 0 && (errno = nvlist_add_string_array(nvl, 538 dlm->dlm_name, (char **)arr, nelems)) != 0) 539 die("failed to add %s array member %s", strenum, dlm->dlm_name); 540 541 inj_free(arr, arrsz); 542 return (0); 543 } 544 545 /* 546 * Validator for embedded lists (events, fmris, authorities, lists, etc.). 547 * There are two cases to deal with here. The user could either have provided 548 * the name of a previously-defined list, in which case we just make a copy of 549 * said list for insertion into ours. Alternatively, the user could simply 550 * define a new list here. In that case, we recursively invoke the member 551 * comparator, but against the list type for the member being defined. 552 */ 553 static nvlist_t *inj_defn_validate_memlist(inj_declmem_t *, inj_defnmem_t *); 554 555 /* Embedded definition */ 556 static nvlist_t * 557 inj_defn_memcmp_sub_list(inj_declmem_t *dlm, inj_defnmem_t *dfm) 558 { 559 inj_declmem_t *subdlm = inj_list_next(&dlm->dlm_decl->decl_members); 560 inj_defnmem_t *subdfm = inj_list_next(&dfm->dfm_list); 561 562 return (inj_defn_validate_memlist(subdlm, subdfm)); 563 } 564 565 /* Reference to previously-defined thing */ 566 static nvlist_t * 567 inj_defn_memcmp_sub_defined(inj_declmem_t *dlm, inj_defnmem_t *dfm) 568 { 569 inj_defn_t *subdefn; 570 nvlist_t *new; 571 572 if ((subdefn = inj_defn_lookup(dfm->dfm_str, dlm->dlm_type)) == NULL) { 573 yyerror(" %d: reference to undefined %s %s\n", dfm->dfm_lineno, 574 inj_mem2str(dlm->dlm_type), dfm->dfm_str); 575 (void) inj_set_errno(EINVAL); 576 return (NULL); 577 } 578 579 if (subdefn->defn_decl != dlm->dlm_decl) { 580 yyerror(" %d: %s %s is not a(n) %s\n", dfm->dfm_lineno, 581 inj_mem2str(dlm->dlm_type), dfm->dfm_str, 582 subdefn->defn_decl->decl_name); 583 (void) inj_set_errno(EINVAL); 584 return (NULL); 585 } 586 587 assert(subdefn->defn_nvl != NULL); 588 589 if ((errno = nvlist_dup(subdefn->defn_nvl, &new, 0)) != 0) { 590 die("failed to duplicate %s list %s", 591 inj_item2str(subdefn->defn_decl->decl_type), dfm->dfm_str); 592 } 593 594 return (new); 595 } 596 597 static nvlist_t * 598 inj_defn_memcmp_sub_makenvl(inj_declmem_t *dlm, inj_defnmem_t *dfm) 599 { 600 inj_defnmemtype_t dftype = dfm->dfm_type; 601 inj_memtype_t dltype = dlm->dlm_type; 602 nvlist_t *new = NULL; 603 604 if (dftype == DEFNMEM_LIST) 605 new = inj_defn_memcmp_sub_list(dlm, dfm); 606 else if (dftype == DEFNMEM_IDENT && (dltype == MEMTYPE_EVENT || 607 dltype == MEMTYPE_FMRI || dltype == MEMTYPE_AUTH)) 608 new = inj_defn_memcmp_sub_defined(dlm, dfm); 609 else 610 (void) inj_set_errno(EINVAL); 611 612 return (new); 613 } 614 615 /* A single sub-list */ 616 static int 617 inj_defn_memcmp_sub(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl) 618 { 619 nvlist_t *new; 620 621 if ((new = inj_defn_memcmp_sub_makenvl(dlm, dfm)) == NULL) 622 return (-1); /* errno is set for us */ 623 624 if ((errno = nvlist_add_nvlist(nvl, (char *)dlm->dlm_name, 625 new)) != 0) 626 die("failed to add list member %s", dlm->dlm_name); 627 628 return (0); 629 } 630 631 /* An array of sub-lists (for example, an array of events of a given type) */ 632 static int 633 inj_defn_memcmp_sub_array(inj_declmem_t *dlm, inj_defnmem_t *dfm, nvlist_t *nvl) 634 { 635 size_t nelems, arrsz; 636 inj_defnmem_t *elem; 637 nvlist_t **arr; 638 int err = 0; 639 int i; 640 641 if (dfm->dfm_type != DEFNMEM_ARRAY) 642 return (inj_set_errno(EINVAL)); 643 644 nelems = array_dim_check(dlm, dfm); 645 arrsz = nelems * sizeof (char *); 646 arr = inj_zalloc(arrsz); 647 648 for (i = 0, elem = inj_list_next(&dfm->dfm_list); elem != NULL; 649 elem = inj_list_next(elem), i++) { 650 if ((arr[i] = inj_defn_memcmp_sub_makenvl(dlm, elem)) == NULL) { 651 yyerror(" %d: array cell %d is invalid\n", 652 elem->dfm_lineno, i + 1); 653 err++; 654 continue; 655 } 656 } 657 658 if (err == 0 && (errno = nvlist_add_nvlist_array(nvl, 659 (char *)dlm->dlm_name, arr, nelems)) != 0) 660 die("failed to add nvlist list member %s", dlm->dlm_name); 661 662 inj_free(arr, arrsz); 663 664 return (0); 665 } 666 667 /* 668 * The declaration-definition member comparator. Designed to recursive 669 * invocation to allow for the validation of embedded/referenced lists. 670 */ 671 nvlist_t * 672 inj_defn_validate_memlist(inj_declmem_t *dlm, inj_defnmem_t *dfm) 673 { 674 const intr_t *intr; 675 nvlist_t *nvl; 676 int rc, nmem, dlnmem, dfnmem; 677 int err = 0; 678 679 if ((errno = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) 680 die("failed to allocate nvl for event"); 681 682 for (nmem = 1; dlm != NULL && dfm != NULL; 683 dlm = inj_list_next(dlm), dfm = inj_list_next(dfm), nmem++) { 684 685 switch (dlm->dlm_type) { 686 case MEMTYPE_INT8: 687 case MEMTYPE_INT16: 688 case MEMTYPE_INT32: 689 case MEMTYPE_INT64: 690 intr = &inj_intrinsics[dlm->dlm_type]; 691 692 if (dlm->dlm_flags & DECLMEM_F_ARRAY) { 693 rc = inj_defn_memcmp_intr_array(intr, dlm, dfm, 694 nvl); 695 } else { 696 rc = inj_defn_memcmp_signed(intr, dlm, dfm, 697 nvl); 698 } 699 break; 700 701 case MEMTYPE_UINT8: 702 case MEMTYPE_UINT16: 703 case MEMTYPE_UINT32: 704 case MEMTYPE_UINT64: 705 intr = &inj_intrinsics[dlm->dlm_type]; 706 707 if (dlm->dlm_flags & DECLMEM_F_ARRAY) { 708 rc = inj_defn_memcmp_intr_array(intr, dlm, dfm, 709 nvl); 710 } else { 711 rc = inj_defn_memcmp_unsigned(intr, dlm, dfm, 712 nvl); 713 } 714 break; 715 716 case MEMTYPE_BOOL: 717 if (dlm->dlm_flags & DECLMEM_F_ARRAY) 718 rc = inj_defn_memcmp_bool_array(dlm, dfm, nvl); 719 else 720 rc = inj_defn_memcmp_bool(dlm, dfm, nvl); 721 break; 722 723 case MEMTYPE_STRING: 724 if (dlm->dlm_flags & DECLMEM_F_ARRAY) { 725 rc = inj_defn_memcmp_strenum_array(dlm, dfm, 726 nvl); 727 } else 728 rc = inj_defn_memcmp_strenum(dlm, dfm, nvl); 729 break; 730 731 case MEMTYPE_ENUM: 732 if (dlm->dlm_flags & DECLMEM_F_ARRAY) { 733 rc = inj_defn_memcmp_strenum_array(dlm, dfm, 734 nvl); 735 } else 736 rc = inj_defn_memcmp_strenum(dlm, dfm, nvl); 737 break; 738 739 case MEMTYPE_EVENT: 740 case MEMTYPE_FMRI: 741 case MEMTYPE_AUTH: 742 case MEMTYPE_LIST: 743 if (dlm->dlm_flags & DECLMEM_F_ARRAY) 744 rc = inj_defn_memcmp_sub_array(dlm, dfm, nvl); 745 else 746 rc = inj_defn_memcmp_sub(dlm, dfm, nvl); 747 break; 748 749 default: 750 die("unknown decl member type %d on member %s\n", 751 dlm->dlm_type, dlm->dlm_name); 752 } 753 754 if (rc < 0) { 755 yyerror(" %d: %s for member %s\n", dfm->dfm_lineno, 756 (errno == ERANGE ? "value out of range" : 757 "invalid value"), dlm->dlm_name); 758 err++; 759 } 760 } 761 762 dlnmem = dfnmem = nmem; 763 764 while (dlm != NULL) { 765 dlm = inj_list_next(dlm); 766 dlnmem++; 767 } 768 769 while (dfm != NULL) { 770 dfm = inj_list_next(dfm); 771 dfnmem++; 772 } 773 774 if (dlnmem != dfnmem) { 775 yyerror("%d members found, expected %d", dfnmem, dlnmem); 776 err++; 777 } 778 779 if (err > 0) { 780 nvlist_free(nvl); 781 return (NULL); 782 } 783 784 return (nvl); 785 } 786 787 /* 788 * The members have all been defined. Validate the members against the 789 * declaration, and add it to the appropriate "defined" list. 790 */ 791 void 792 inj_defn_finish(inj_defn_t *defn, const char *declnm, const char *name, 793 inj_itemtype_t type) 794 { 795 inj_decl_t *decl = inj_decl_lookup(declnm, type); 796 inj_hash_t *hash = item2hash(type); 797 inj_declmem_t *dlm; 798 inj_defnmem_t *dfm; 799 inj_var_t *v; 800 801 defn->defn_name = name; 802 defn->defn_decl = decl; 803 804 if (decl == NULL) { 805 yyerror("unknown %s type %s\n", inj_item2str(type), declnm); 806 inj_defn_destroy(defn); 807 return; 808 } 809 810 dlm = inj_list_next(&decl->decl_members); 811 dfm = inj_list_next(&defn->defn_members); 812 813 if ((defn->defn_nvl = inj_defn_validate_memlist(dlm, dfm)) == NULL) { 814 inj_defn_destroy(defn); 815 return; 816 } 817 818 if (type == ITEMTYPE_EVENT) { 819 if ((errno = nvlist_add_string(defn->defn_nvl, "class", 820 (char *)defn->defn_decl->decl_name)) != 0) 821 die("failed to add class to %s", name); 822 } 823 824 if ((v = inj_strhash_lookup(hash, name)) != NULL) { 825 inj_defn_t *other = inj_hash_get_cookie(v); 826 827 yyerror("duplicate %s name %s (other on line %d)\n", 828 inj_item2str(type), name, other->defn_lineno); 829 inj_defn_destroy(defn); 830 return; 831 } 832 833 (void) inj_strhash_insert(hash, name, (uintptr_t)defn); 834 } 835