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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/modctl.h> 31 #include <sys/sysmacros.h> 32 #include <sys/kmem.h> 33 #include <sys/cmn_err.h> 34 #include <sys/ddi.h> 35 #include <sys/sunddi.h> 36 #include <sys/spl.h> 37 #include <sys/time.h> 38 #include <sys/varargs.h> 39 #include <ipp/ipp.h> 40 #include <ipp/ipp_impl.h> 41 #include <ipp/ipgpc/ipgpc.h> 42 43 /* 44 * Debug switch. 45 */ 46 47 #if defined(DEBUG) 48 #define IPP_DBG 49 #endif 50 51 /* 52 * Globals 53 */ 54 55 /* 56 * ipp_action_count is not static because it is imported by inet/ipp_common.h 57 */ 58 uint32_t ipp_action_count = 0; 59 60 static kmem_cache_t *ipp_mod_cache = NULL; 61 static uint32_t ipp_mod_count = 0; 62 static uint32_t ipp_max_mod = IPP_NMOD; 63 static ipp_mod_t **ipp_mod_byid; 64 static krwlock_t ipp_mod_byid_lock[1]; 65 66 static ipp_mod_id_t ipp_next_mid = IPP_MOD_RESERVED + 1; 67 static ipp_mod_id_t ipp_mid_limit; 68 69 static ipp_ref_t *ipp_mod_byname[IPP_NBUCKET]; 70 static krwlock_t ipp_mod_byname_lock[1]; 71 72 static kmem_cache_t *ipp_action_cache = NULL; 73 static uint32_t ipp_max_action = IPP_NACTION; 74 static ipp_action_t **ipp_action_byid; 75 static krwlock_t ipp_action_byid_lock[1]; 76 77 static ipp_action_id_t ipp_next_aid = IPP_ACTION_RESERVED + 1; 78 static ipp_action_id_t ipp_aid_limit; 79 80 static ipp_ref_t *ipp_action_byname[IPP_NBUCKET]; 81 static krwlock_t ipp_action_byname_lock[1]; 82 static ipp_ref_t *ipp_action_noname; 83 84 static kmem_cache_t *ipp_packet_cache = NULL; 85 static uint_t ipp_packet_classes = IPP_NCLASS; 86 static uint_t ipp_packet_logging = 0; 87 static uint_t ipp_packet_log_entries = IPP_NLOG; 88 89 /* 90 * Prototypes 91 */ 92 93 void ipp_init(void); 94 95 int ipp_list_mods(ipp_mod_id_t **, int *); 96 97 ipp_mod_id_t ipp_mod_lookup(const char *); 98 int ipp_mod_name(ipp_mod_id_t, char **); 99 int ipp_mod_register(const char *, ipp_ops_t *); 100 int ipp_mod_unregister(ipp_mod_id_t); 101 int ipp_mod_list_actions(ipp_mod_id_t, ipp_action_id_t **, 102 int *); 103 104 ipp_action_id_t ipp_action_lookup(const char *); 105 int ipp_action_name(ipp_action_id_t, char **); 106 int ipp_action_mod(ipp_action_id_t, ipp_mod_id_t *); 107 int ipp_action_create(ipp_mod_id_t, const char *, 108 nvlist_t **, ipp_flags_t, ipp_action_id_t *); 109 int ipp_action_modify(ipp_action_id_t, nvlist_t **, 110 ipp_flags_t); 111 int ipp_action_destroy(ipp_action_id_t, ipp_flags_t); 112 int ipp_action_info(ipp_action_id_t, int (*)(nvlist_t *, 113 void *), void *, ipp_flags_t); 114 void ipp_action_set_ptr(ipp_action_id_t, void *); 115 void *ipp_action_get_ptr(ipp_action_id_t); 116 int ipp_action_ref(ipp_action_id_t, ipp_action_id_t, 117 ipp_flags_t); 118 int ipp_action_unref(ipp_action_id_t, ipp_action_id_t, 119 ipp_flags_t); 120 121 int ipp_packet_alloc(ipp_packet_t **, const char *, 122 ipp_action_id_t); 123 void ipp_packet_free(ipp_packet_t *); 124 int ipp_packet_add_class(ipp_packet_t *, const char *, 125 ipp_action_id_t); 126 int ipp_packet_process(ipp_packet_t **); 127 int ipp_packet_next(ipp_packet_t *, ipp_action_id_t); 128 void ipp_packet_set_data(ipp_packet_t *, mblk_t *); 129 mblk_t *ipp_packet_get_data(ipp_packet_t *); 130 void ipp_packet_set_private(ipp_packet_t *, void *, 131 void (*)(void *)); 132 void *ipp_packet_get_private(ipp_packet_t *); 133 134 int ipp_stat_create(ipp_action_id_t, const char *, int, 135 int (*)(ipp_stat_t *, void *, int), void *, ipp_stat_t **); 136 void ipp_stat_install(ipp_stat_t *); 137 void ipp_stat_destroy(ipp_stat_t *); 138 int ipp_stat_named_init(ipp_stat_t *, const char *, uchar_t, 139 ipp_named_t *); 140 int ipp_stat_named_op(ipp_named_t *, void *, int); 141 142 static int ref_mod(ipp_action_t *, ipp_mod_t *); 143 static void unref_mod(ipp_action_t *, ipp_mod_t *); 144 static int is_mod_busy(ipp_mod_t *); 145 static int get_mod_ref(ipp_mod_t *, ipp_action_id_t **, int *); 146 static int get_mods(ipp_mod_id_t **bufp, int *); 147 static ipp_mod_id_t find_mod(const char *); 148 static int alloc_mod(const char *, ipp_mod_id_t *); 149 static void free_mod(ipp_mod_t *); 150 static ipp_mod_t *hold_mod(ipp_mod_id_t); 151 static void rele_mod(ipp_mod_t *); 152 static ipp_mod_id_t get_mid(void); 153 154 static int condemn_action(ipp_ref_t **, ipp_action_t *); 155 static int destroy_action(ipp_action_t *, ipp_flags_t); 156 static int ref_action(ipp_action_t *, ipp_action_t *); 157 static int unref_action(ipp_action_t *, ipp_action_t *); 158 static int is_action_refd(ipp_action_t *); 159 static ipp_action_id_t find_action(const char *); 160 static int alloc_action(const char *, ipp_action_id_t *); 161 static void free_action(ipp_action_t *); 162 static ipp_action_t *hold_action(ipp_action_id_t); 163 static void rele_action(ipp_action_t *); 164 static ipp_action_id_t get_aid(void); 165 166 static int alloc_packet(const char *, ipp_action_id_t, 167 ipp_packet_t **); 168 static int realloc_packet(ipp_packet_t *); 169 static void free_packet(ipp_packet_t *); 170 171 static int hash(const char *); 172 static int update_stats(kstat_t *, int); 173 static void init_mods(void); 174 static void init_actions(void); 175 static void init_packets(void); 176 static int mod_constructor(void *, void *, int); 177 static void mod_destructor(void *, void *); 178 static int action_constructor(void *, void *, int); 179 static void action_destructor(void *, void *); 180 static int packet_constructor(void *, void *, int); 181 static void packet_destructor(void *, void *); 182 183 /* 184 * Debug message macros 185 */ 186 187 #ifdef IPP_DBG 188 189 #define DBG_MOD 0x00000001ull 190 #define DBG_ACTION 0x00000002ull 191 #define DBG_PACKET 0x00000004ull 192 #define DBG_STATS 0x00000008ull 193 #define DBG_LIST 0x00000010ull 194 195 static uint64_t ipp_debug_flags = 196 /* 197 * DBG_PACKET | 198 * DBG_STATS | 199 * DBG_LIST | 200 * DBG_MOD | 201 * DBG_ACTION | 202 */ 203 0; 204 205 static kmutex_t debug_mutex[1]; 206 207 /*PRINTFLIKE3*/ 208 static void ipp_debug(uint64_t, const char *, char *, ...) 209 __KPRINTFLIKE(3); 210 211 #define DBG0(_type, _fmt) \ 212 ipp_debug((_type), __FN__, (_fmt)); 213 214 #define DBG1(_type, _fmt, _a1) \ 215 ipp_debug((_type), __FN__, (_fmt), (_a1)); 216 217 #define DBG2(_type, _fmt, _a1, _a2) \ 218 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2)); 219 220 #define DBG3(_type, _fmt, _a1, _a2, _a3) \ 221 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 222 (_a3)); 223 224 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \ 225 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 226 (_a3), (_a4)); 227 228 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \ 229 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 230 (_a3), (_a4), (_a5)); 231 232 #else /* IPP_DBG */ 233 234 #define DBG0(_type, _fmt) 235 #define DBG1(_type, _fmt, _a1) 236 #define DBG2(_type, _fmt, _a1, _a2) 237 #define DBG3(_type, _fmt, _a1, _a2, _a3) 238 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) 239 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) 240 241 #endif /* IPP_DBG */ 242 243 /* 244 * Lock macros 245 */ 246 247 #define LOCK_MOD(_imp, _rw) \ 248 rw_enter((_imp)->ippm_lock, (_rw)) 249 #define UNLOCK_MOD(_imp) \ 250 rw_exit((_imp)->ippm_lock) 251 252 #define LOCK_ACTION(_ap, _rw) \ 253 rw_enter((_ap)->ippa_lock, (_rw)) 254 #define UNLOCK_ACTION(_imp) \ 255 rw_exit((_imp)->ippa_lock) 256 257 #define CONFIG_WRITE_START(_ap) \ 258 CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_WRITE) 259 260 #define CONFIG_WRITE_END(_ap) \ 261 CONFIG_LOCK_EXIT((_ap)->ippa_config_lock) 262 263 #define CONFIG_READ_START(_ap) \ 264 CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_READ) 265 266 #define CONFIG_READ_END(_ap) \ 267 CONFIG_LOCK_EXIT((_ap)->ippa_config_lock) 268 269 /* 270 * Exported functions 271 */ 272 273 #define __FN__ "ipp_init" 274 void 275 ipp_init( 276 void) 277 { 278 #ifdef IPP_DBG 279 mutex_init(debug_mutex, NULL, MUTEX_ADAPTIVE, 280 (void *)ipltospl(LOCK_LEVEL)); 281 #endif /* IPP_DBG */ 282 283 /* 284 * Initialize module and action structure caches and associated locks. 285 */ 286 287 init_mods(); 288 init_actions(); 289 init_packets(); 290 } 291 #undef __FN__ 292 293 #define __FN__ "ipp_list_mods" 294 int 295 ipp_list_mods( 296 ipp_mod_id_t **bufp, 297 int *neltp) 298 { 299 ASSERT(bufp != NULL); 300 ASSERT(neltp != NULL); 301 302 return (get_mods(bufp, neltp)); 303 } 304 #undef __FN__ 305 306 /* 307 * Module manipulation interface. 308 */ 309 310 #define __FN__ "ipp_mod_lookup" 311 ipp_mod_id_t 312 ipp_mod_lookup( 313 const char *modname) 314 { 315 ipp_mod_id_t mid; 316 #define FIRST_TIME 0 317 int try = FIRST_TIME; 318 319 /* 320 * Sanity check the module name. 321 */ 322 323 if (modname == NULL || strlen(modname) > MAXNAMELEN - 1) 324 return (IPP_MOD_INVAL); 325 326 try_again: 327 if ((mid = find_mod(modname)) == IPP_MOD_INVAL) { 328 329 /* 330 * Module not installed. 331 */ 332 333 if (try++ == FIRST_TIME) { 334 335 /* 336 * This is the first attempt to find the module so 337 * try to 'demand load' it. 338 */ 339 340 DBG1(DBG_MOD, "loading module '%s'\n", modname); 341 (void) modload("ipp", (char *)modname); 342 goto try_again; 343 } 344 } 345 346 return (mid); 347 348 #undef FIRST_TIME 349 } 350 #undef __FN__ 351 352 #define __FN__ "ipp_mod_name" 353 int 354 ipp_mod_name( 355 ipp_mod_id_t mid, 356 char **modnamep) 357 { 358 ipp_mod_t *imp; 359 char *modname; 360 char *buf; 361 362 ASSERT(modnamep != NULL); 363 364 /* 365 * Translate the module id into the module pointer. 366 */ 367 368 if ((imp = hold_mod(mid)) == NULL) 369 return (ENOENT); 370 371 LOCK_MOD(imp, RW_READER); 372 modname = imp->ippm_name; 373 374 /* 375 * Allocate a buffer to pass back to the caller. 376 */ 377 378 if ((buf = kmem_zalloc(strlen(modname) + 1, KM_NOSLEEP)) == NULL) { 379 UNLOCK_MOD(imp); 380 rele_mod(imp); 381 return (ENOMEM); 382 } 383 384 /* 385 * Copy the module name into the buffer. 386 */ 387 388 (void) strcpy(buf, modname); 389 UNLOCK_MOD(imp); 390 391 *modnamep = buf; 392 393 rele_mod(imp); 394 return (0); 395 } 396 #undef __FN__ 397 398 #define __FN__ "ipp_mod_register" 399 int 400 ipp_mod_register( 401 const char *modname, 402 ipp_ops_t *ipp_ops) 403 { 404 ipp_mod_id_t mid; 405 ipp_mod_t *imp; 406 int rc; 407 408 ASSERT(ipp_ops != NULL); 409 410 /* 411 * Sanity check the module name. 412 */ 413 414 if (modname == NULL || strlen(modname) > MAXNAMELEN - 1) 415 return (EINVAL); 416 417 /* 418 * Allocate a module structure. 419 */ 420 421 if ((rc = alloc_mod(modname, &mid)) != 0) 422 return (rc); 423 424 imp = hold_mod(mid); 425 ASSERT(imp != NULL); 426 427 /* 428 * Make module available for use. 429 */ 430 431 LOCK_MOD(imp, RW_WRITER); 432 DBG1(DBG_MOD, "registering module '%s'\n", imp->ippm_name); 433 imp->ippm_ops = ipp_ops; 434 imp->ippm_state = IPP_MODSTATE_AVAILABLE; 435 UNLOCK_MOD(imp); 436 437 rele_mod(imp); 438 return (0); 439 } 440 #undef __FN__ 441 442 #define __FN__ "ipp_mod_unregister" 443 int 444 ipp_mod_unregister( 445 ipp_mod_id_t mid) 446 { 447 ipp_mod_t *imp; 448 449 /* 450 * Translate the module id into the module pointer. 451 */ 452 453 if ((imp = hold_mod(mid)) == NULL) 454 return (ENOENT); 455 456 LOCK_MOD(imp, RW_WRITER); 457 ASSERT(imp->ippm_state == IPP_MODSTATE_AVAILABLE); 458 459 /* 460 * Check to see if there are any actions that reference the module. 461 */ 462 463 if (is_mod_busy(imp)) { 464 UNLOCK_MOD(imp); 465 rele_mod(imp); 466 return (EBUSY); 467 } 468 469 /* 470 * Prevent further use of the module. 471 */ 472 473 DBG1(DBG_MOD, "unregistering module '%s'\n", imp->ippm_name); 474 imp->ippm_state = IPP_MODSTATE_PROTO; 475 imp->ippm_ops = NULL; 476 UNLOCK_MOD(imp); 477 478 /* 479 * Free the module structure. 480 */ 481 482 free_mod(imp); 483 rele_mod(imp); 484 485 return (0); 486 } 487 #undef __FN__ 488 489 #define __FN__ "ipp_mod_list_actions" 490 int 491 ipp_mod_list_actions( 492 ipp_mod_id_t mid, 493 ipp_action_id_t **bufp, 494 int *neltp) 495 { 496 ipp_mod_t *imp; 497 int rc; 498 499 ASSERT(bufp != NULL); 500 ASSERT(neltp != NULL); 501 502 /* 503 * Translate the module id into the module pointer. 504 */ 505 506 if ((imp = hold_mod(mid)) == NULL) 507 return (ENOENT); 508 509 /* 510 * Get the list of actions referencing the module. 511 */ 512 513 LOCK_MOD(imp, RW_READER); 514 rc = get_mod_ref(imp, bufp, neltp); 515 UNLOCK_MOD(imp); 516 517 rele_mod(imp); 518 return (rc); 519 } 520 #undef __FN__ 521 522 /* 523 * Action manipulation interface. 524 */ 525 526 #define __FN__ "ipp_action_lookup" 527 ipp_action_id_t 528 ipp_action_lookup( 529 const char *aname) 530 { 531 if (aname == NULL) 532 return (IPP_ACTION_INVAL); 533 534 /* 535 * Check for special case 'virtual action' names. 536 */ 537 538 if (strcmp(aname, IPP_ANAME_CONT) == 0) 539 return (IPP_ACTION_CONT); 540 else if (strcmp(aname, IPP_ANAME_DEFER) == 0) 541 return (IPP_ACTION_DEFER); 542 else if (strcmp(aname, IPP_ANAME_DROP) == 0) 543 return (IPP_ACTION_DROP); 544 545 /* 546 * Now check real actions. 547 */ 548 549 return (find_action(aname)); 550 } 551 #undef __FN__ 552 553 #define __FN__ "ipp_action_name" 554 int 555 ipp_action_name( 556 ipp_action_id_t aid, 557 char **anamep) 558 { 559 ipp_action_t *ap; 560 char *aname; 561 char *buf; 562 int rc; 563 564 ASSERT(anamep != NULL); 565 566 /* 567 * Check for special case 'virtual action' ids. 568 */ 569 570 switch (aid) { 571 case IPP_ACTION_CONT: 572 ap = NULL; 573 aname = IPP_ANAME_CONT; 574 break; 575 case IPP_ACTION_DEFER: 576 ap = NULL; 577 aname = IPP_ANAME_DEFER; 578 break; 579 case IPP_ACTION_DROP: 580 ap = NULL; 581 aname = IPP_ANAME_DROP; 582 break; 583 default: 584 585 /* 586 * Not a special case. Check for a real action. 587 */ 588 589 if ((ap = hold_action(aid)) == NULL) 590 return (ENOENT); 591 592 LOCK_ACTION(ap, RW_READER); 593 aname = ap->ippa_name; 594 break; 595 } 596 597 /* 598 * Allocate a buffer to pass back to the caller. 599 */ 600 601 if ((buf = kmem_zalloc(strlen(aname) + 1, KM_NOSLEEP)) == NULL) { 602 rc = ENOMEM; 603 goto done; 604 } 605 606 /* 607 * Copy the action name into the buffer. 608 */ 609 610 (void) strcpy(buf, aname); 611 *anamep = buf; 612 rc = 0; 613 done: 614 /* 615 * Unlock the action if necessary (i.e. it wasn't a virtual action). 616 */ 617 618 if (ap != NULL) { 619 UNLOCK_ACTION(ap); 620 rele_action(ap); 621 } 622 623 return (rc); 624 } 625 #undef __FN__ 626 627 #define __FN__ "ipp_action_mod" 628 int 629 ipp_action_mod( 630 ipp_action_id_t aid, 631 ipp_mod_id_t *midp) 632 { 633 ipp_action_t *ap; 634 ipp_mod_t *imp; 635 636 ASSERT(midp != NULL); 637 638 /* 639 * Return an error for 'virtual action' ids. 640 */ 641 642 switch (aid) { 643 case IPP_ACTION_CONT: 644 /*FALLTHRU*/ 645 case IPP_ACTION_DEFER: 646 /*FALLTHRU*/ 647 case IPP_ACTION_DROP: 648 return (EINVAL); 649 default: 650 break; 651 } 652 653 /* 654 * This is a real action. 655 */ 656 657 if ((ap = hold_action(aid)) == NULL) 658 return (ENOENT); 659 660 /* 661 * Check that the action is not in prototype state. 662 */ 663 664 LOCK_ACTION(ap, RW_READER); 665 if (ap->ippa_state == IPP_ASTATE_PROTO) { 666 UNLOCK_ACTION(ap); 667 rele_action(ap); 668 return (ENOENT); 669 } 670 671 imp = ap->ippa_mod; 672 ASSERT(imp != NULL); 673 UNLOCK_ACTION(ap); 674 675 *midp = imp->ippm_id; 676 677 rele_action(ap); 678 return (0); 679 } 680 #undef __FN__ 681 682 #define __FN__ "ipp_action_create" 683 int 684 ipp_action_create( 685 ipp_mod_id_t mid, 686 const char *aname, 687 nvlist_t **nvlpp, 688 ipp_flags_t flags, 689 ipp_action_id_t *aidp) 690 { 691 ipp_ops_t *ippo; 692 ipp_mod_t *imp; 693 ipp_action_id_t aid; 694 ipp_action_t *ap; 695 int rc; 696 697 ASSERT(nvlpp != NULL); 698 ASSERT(*nvlpp != NULL); 699 700 /* 701 * Sanity check the action name (NULL means the framework chooses the 702 * name). 703 */ 704 705 if (aname != NULL && strlen(aname) > MAXNAMELEN - 1) 706 return (EINVAL); 707 708 /* 709 * Translate the module id into the module pointer. 710 */ 711 712 if ((imp = hold_mod(mid)) == NULL) 713 return (ENOENT); 714 715 /* 716 * Allocate an action. 717 */ 718 719 if ((rc = alloc_action(aname, &aid)) != 0) { 720 rele_mod(imp); 721 return (rc); 722 } 723 724 ap = hold_action(aid); 725 ASSERT(ap != NULL); 726 727 /* 728 * Note that the action is in the process of creation/destruction. 729 */ 730 731 LOCK_ACTION(ap, RW_WRITER); 732 ap->ippa_state = IPP_ASTATE_CONFIG_PENDING; 733 734 /* 735 * Reference the module for which the action is being created. 736 */ 737 738 LOCK_MOD(imp, RW_WRITER); 739 if ((rc = ref_mod(ap, imp)) != 0) { 740 UNLOCK_MOD(imp); 741 ap->ippa_state = IPP_ASTATE_PROTO; 742 UNLOCK_ACTION(ap); 743 744 free_action(ap); 745 rele_action(ap); 746 rele_mod(imp); 747 return (rc); 748 } 749 750 UNLOCK_ACTION(ap); 751 752 ippo = imp->ippm_ops; 753 ASSERT(ippo != NULL); 754 UNLOCK_MOD(imp); 755 756 /* 757 * Call into the module to create the action context. 758 */ 759 760 CONFIG_WRITE_START(ap); 761 DBG2(DBG_ACTION, "creating action '%s' in module '%s'\n", 762 ap->ippa_name, imp->ippm_name); 763 if ((rc = ippo->ippo_action_create(ap->ippa_id, nvlpp, flags)) != 0) { 764 LOCK_ACTION(ap, RW_WRITER); 765 LOCK_MOD(imp, RW_WRITER); 766 unref_mod(ap, imp); 767 UNLOCK_MOD(imp); 768 ap->ippa_state = IPP_ASTATE_PROTO; 769 UNLOCK_ACTION(ap); 770 771 CONFIG_WRITE_END(ap); 772 773 free_action(ap); 774 rele_action(ap); 775 rele_mod(imp); 776 return (rc); 777 } 778 CONFIG_WRITE_END(ap); 779 780 /* 781 * Make the action available for use. 782 */ 783 784 LOCK_ACTION(ap, RW_WRITER); 785 ap->ippa_state = IPP_ASTATE_AVAILABLE; 786 if (aidp != NULL) 787 *aidp = ap->ippa_id; 788 UNLOCK_ACTION(ap); 789 790 rele_action(ap); 791 rele_mod(imp); 792 return (0); 793 } 794 #undef __FN__ 795 796 #define __FN__ "ipp_action_destroy" 797 int 798 ipp_action_destroy( 799 ipp_action_id_t aid, 800 ipp_flags_t flags) 801 { 802 ipp_ref_t *rp = NULL; 803 ipp_ref_t *tmp; 804 ipp_action_t *ap; 805 int rc; 806 807 /* 808 * Translate the action id into the action pointer. 809 */ 810 811 if ((ap = hold_action(aid)) == NULL) 812 return (ENOENT); 813 814 /* 815 * Set the condemned action list pointer and destroy the action. 816 */ 817 818 ap->ippa_condemned = &rp; 819 if ((rc = destroy_action(ap, flags)) == 0) { 820 821 /* 822 * Destroy any other actions condemned by the destruction of 823 * the first action. 824 */ 825 826 for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) { 827 ap = tmp->ippr_action; 828 ap->ippa_condemned = &rp; 829 (void) destroy_action(ap, flags); 830 } 831 } else { 832 833 /* 834 * Unreference any condemned actions since the destruction of 835 * the first action failed. 836 */ 837 838 for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) { 839 ap = tmp->ippr_action; 840 rele_action(ap); 841 } 842 } 843 844 /* 845 * Clean up the condemned list. 846 */ 847 848 while (rp != NULL) { 849 tmp = rp; 850 rp = rp->ippr_nextp; 851 kmem_free(tmp, sizeof (ipp_ref_t)); 852 } 853 854 return (rc); 855 } 856 #undef __FN__ 857 858 #define __FN__ "ipp_action_modify" 859 int 860 ipp_action_modify( 861 ipp_action_id_t aid, 862 nvlist_t **nvlpp, 863 ipp_flags_t flags) 864 { 865 ipp_action_t *ap; 866 ipp_ops_t *ippo; 867 ipp_mod_t *imp; 868 int rc; 869 870 ASSERT(nvlpp != NULL); 871 ASSERT(*nvlpp != NULL); 872 873 /* 874 * Translate the action id into the action pointer. 875 */ 876 877 if ((ap = hold_action(aid)) == NULL) 878 return (ENOENT); 879 880 /* 881 * Check that the action is either available for use or is in the 882 * process of creation/destruction. 883 * 884 * NOTE: It is up to the module to lock multiple configuration 885 * operations against each other if necessary. 886 */ 887 888 LOCK_ACTION(ap, RW_READER); 889 if (ap->ippa_state != IPP_ASTATE_AVAILABLE && 890 ap->ippa_state != IPP_ASTATE_CONFIG_PENDING) { 891 UNLOCK_ACTION(ap); 892 rele_action(ap); 893 return (EPROTO); 894 } 895 896 imp = ap->ippa_mod; 897 ASSERT(imp != NULL); 898 UNLOCK_ACTION(ap); 899 900 ippo = imp->ippm_ops; 901 ASSERT(ippo != NULL); 902 903 /* 904 * Call into the module to modify the action context. 905 */ 906 907 DBG1(DBG_ACTION, "modifying action '%s'\n", ap->ippa_name); 908 CONFIG_WRITE_START(ap); 909 rc = ippo->ippo_action_modify(aid, nvlpp, flags); 910 CONFIG_WRITE_END(ap); 911 912 rele_action(ap); 913 return (rc); 914 } 915 #undef __FN__ 916 917 #define __FN__ "ipp_action_info" 918 int 919 ipp_action_info( 920 ipp_action_id_t aid, 921 int (*fn)(nvlist_t *, void *), 922 void *arg, 923 ipp_flags_t flags) 924 { 925 ipp_action_t *ap; 926 ipp_mod_t *imp; 927 ipp_ops_t *ippo; 928 int rc; 929 930 /* 931 * Translate the action id into the action pointer. 932 */ 933 934 if ((ap = hold_action(aid)) == NULL) 935 return (ENOENT); 936 937 /* 938 * Check that the action is available for use. We don't want to 939 * read back parameters while the action is in the process of 940 * creation/destruction. 941 */ 942 943 LOCK_ACTION(ap, RW_READER); 944 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) { 945 UNLOCK_ACTION(ap); 946 rele_action(ap); 947 return (EPROTO); 948 } 949 950 imp = ap->ippa_mod; 951 ASSERT(imp != NULL); 952 UNLOCK_ACTION(ap); 953 954 ippo = imp->ippm_ops; 955 ASSERT(ippo != NULL); 956 957 /* 958 * Call into the module to get the action configuration information. 959 */ 960 961 DBG1(DBG_ACTION, 962 "getting configuration information from action '%s'\n", 963 ap->ippa_name); 964 CONFIG_READ_START(ap); 965 if ((rc = ippo->ippo_action_info(aid, fn, arg, flags)) != 0) { 966 CONFIG_READ_END(ap); 967 rele_action(ap); 968 return (rc); 969 } 970 CONFIG_READ_END(ap); 971 972 rele_action(ap); 973 return (0); 974 } 975 #undef __FN__ 976 977 #define __FN__ "ipp_action_set_ptr" 978 void 979 ipp_action_set_ptr( 980 ipp_action_id_t aid, 981 void *ptr) 982 { 983 ipp_action_t *ap; 984 985 /* 986 * Translate the action id into the action pointer. 987 */ 988 989 ap = hold_action(aid); 990 ASSERT(ap != NULL); 991 992 /* 993 * Set the private data pointer. 994 */ 995 996 ap->ippa_ptr = ptr; 997 rele_action(ap); 998 } 999 #undef __FN__ 1000 1001 #define __FN__ "ipp_action_get_ptr" 1002 void * 1003 ipp_action_get_ptr( 1004 ipp_action_id_t aid) 1005 { 1006 ipp_action_t *ap; 1007 void *ptr; 1008 1009 /* 1010 * Translate the action id into the action pointer. 1011 */ 1012 1013 ap = hold_action(aid); 1014 ASSERT(ap != NULL); 1015 1016 /* 1017 * Return the private data pointer. 1018 */ 1019 1020 ptr = ap->ippa_ptr; 1021 rele_action(ap); 1022 1023 return (ptr); 1024 } 1025 #undef __FN__ 1026 1027 #define __FN__ "ipp_action_ref" 1028 /*ARGSUSED*/ 1029 int 1030 ipp_action_ref( 1031 ipp_action_id_t aid, 1032 ipp_action_id_t ref_aid, 1033 ipp_flags_t flags) 1034 { 1035 ipp_action_t *ap; 1036 ipp_action_t *ref_ap; 1037 int rc; 1038 1039 /* 1040 * Actions are not allowed to reference themselves. 1041 */ 1042 1043 if (aid == ref_aid) 1044 return (EINVAL); 1045 1046 /* 1047 * Check for a special case 'virtual action' id. 1048 */ 1049 1050 switch (ref_aid) { 1051 case IPP_ACTION_CONT: 1052 /*FALLTHRU*/ 1053 case IPP_ACTION_DEFER: 1054 /*FALLTHRU*/ 1055 case IPP_ACTION_DROP: 1056 return (0); 1057 default: 1058 break; 1059 } 1060 1061 /* 1062 * Translate the action ids into action pointers. 1063 */ 1064 1065 if ((ap = hold_action(aid)) == NULL) 1066 return (ENOENT); 1067 1068 if ((ref_ap = hold_action(ref_aid)) == NULL) { 1069 rele_action(ap); 1070 return (ENOENT); 1071 } 1072 1073 LOCK_ACTION(ap, RW_WRITER); 1074 LOCK_ACTION(ref_ap, RW_WRITER); 1075 1076 if (ref_ap->ippa_state != IPP_ASTATE_AVAILABLE) { 1077 UNLOCK_ACTION(ref_ap); 1078 UNLOCK_ACTION(ap); 1079 1080 rele_action(ref_ap); 1081 rele_action(ap); 1082 return (EPROTO); 1083 } 1084 1085 /* 1086 * Create references between the two actions. 1087 */ 1088 1089 rc = ref_action(ap, ref_ap); 1090 UNLOCK_ACTION(ref_ap); 1091 UNLOCK_ACTION(ap); 1092 1093 rele_action(ref_ap); 1094 rele_action(ap); 1095 return (rc); 1096 } 1097 #undef __FN__ 1098 1099 #define __FN__ "ipp_action_unref" 1100 int 1101 ipp_action_unref( 1102 ipp_action_id_t aid, 1103 ipp_action_id_t ref_aid, 1104 ipp_flags_t flags) 1105 { 1106 ipp_action_t *ap; 1107 ipp_action_t *ref_ap; 1108 int ref_is_busy; 1109 int rc; 1110 1111 if (aid == ref_aid) 1112 return (EINVAL); 1113 1114 /* 1115 * Check for a special case 'virtual action' id. 1116 */ 1117 1118 switch (ref_aid) { 1119 case IPP_ACTION_CONT: 1120 /*FALLTHRU*/ 1121 case IPP_ACTION_DEFER: 1122 /*FALLTHRU*/ 1123 case IPP_ACTION_DROP: 1124 return (0); 1125 default: 1126 break; 1127 } 1128 1129 /* 1130 * Translate the action ids into action pointers. 1131 */ 1132 1133 if ((ap = hold_action(aid)) == NULL) 1134 return (ENOENT); 1135 1136 if ((ref_ap = hold_action(ref_aid)) == NULL) { 1137 rele_action(ap); 1138 return (ENOENT); 1139 } 1140 1141 LOCK_ACTION(ap, RW_WRITER); 1142 LOCK_ACTION(ref_ap, RW_WRITER); 1143 1144 /* 1145 * Remove the reference between the actions. 1146 */ 1147 1148 if ((rc = unref_action(ap, ref_ap)) != 0) { 1149 UNLOCK_ACTION(ref_ap); 1150 UNLOCK_ACTION(ap); 1151 rele_action(ref_ap); 1152 rele_action(ap); 1153 return (rc); 1154 } 1155 1156 ref_is_busy = is_action_refd(ref_ap); 1157 1158 UNLOCK_ACTION(ref_ap); 1159 UNLOCK_ACTION(ap); 1160 1161 if (flags & IPP_DESTROY_REF) { 1162 if (!ref_is_busy) { 1163 1164 /* 1165 * Condemn the action so that it will be destroyed. 1166 */ 1167 1168 (void) condemn_action(ap->ippa_condemned, ref_ap); 1169 return (0); 1170 } 1171 } 1172 1173 rele_action(ref_ap); 1174 rele_action(ap); 1175 return (0); 1176 } 1177 #undef __FN__ 1178 1179 /* 1180 * Packet manipulation interface. 1181 */ 1182 1183 #define __FN__ "ipp_packet_alloc" 1184 int 1185 ipp_packet_alloc( 1186 ipp_packet_t **ppp, 1187 const char *name, 1188 ipp_action_id_t aid) 1189 { 1190 ipp_packet_t *pp; 1191 int rc; 1192 1193 ASSERT(ppp != NULL); 1194 1195 /* 1196 * A name is required. 1197 */ 1198 1199 if (name == NULL || strlen(name) > MAXNAMELEN - 1) 1200 return (EINVAL); 1201 1202 /* 1203 * Allocate a packet structure from the cache. 1204 */ 1205 1206 if ((rc = alloc_packet(name, aid, &pp)) != 0) 1207 return (rc); 120