Home | History | Annotate | Download | only in ipp
      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