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