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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * IP Policy Framework config driver
31 #include <sys/types.h>
32 #include <sys/cmn_err.h>
34 #include <sys/errno.h>
35 #include <sys/cpuvar.h>
40 #include <sys/sunddi.h>
41 #include <sys/modctl.h>
42 #include <sys/stream.h>
44 #include <ipp/ippctl.h>
45 #include <sys/nvpair.h>
46 #include <sys/policy.h>
62 #define DBG_MODLINK 0x00000001ull
63 #define DBG_DEVOPS 0x00000002ull
64 #define DBG_CBOPS 0x00000004ull
66 static uint64_t ippctl_debug_flags
=
74 static kmutex_t debug_mutex
[1];
77 static void ippctl_debug(uint64_t, char *, char *, ...)
80 #define DBG0(_type, _fmt) \
81 ippctl_debug((_type), __FN__, (_fmt));
83 #define DBG1(_type, _fmt, _a1) \
84 ippctl_debug((_type), __FN__, (_fmt), (_a1));
86 #define DBG2(_type, _fmt, _a1, _a2) \
87 ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2));
89 #define DBG3(_type, _fmt, _a1, _a2, _a3) \
90 ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
93 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \
94 ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
97 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \
98 ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
101 #else /* IPPCTL_DBG */
103 #define DBG0(_type, _fmt)
104 #define DBG1(_type, _fmt, _a1)
105 #define DBG2(_type, _fmt, _a1, _a2)
106 #define DBG3(_type, _fmt, _a1, _a2, _a3)
107 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4)
108 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5)
110 #endif /* IPPCTL_DBG */
116 static int ippctl_open(dev_t
*, int, int, cred_t
*);
117 static int ippctl_close(dev_t
, int, int, cred_t
*);
118 static int ippctl_ioctl(dev_t
, int, intptr_t, int, cred_t
*, int *);
120 static struct cb_ops ippctl_cb_ops
= {
121 ippctl_open
, /* cb_open */
122 ippctl_close
, /* cb_close */
123 nodev
, /* cb_strategy */
124 nodev
, /* cb_print */
127 nodev
, /* cb_write */
128 ippctl_ioctl
, /* cb_ioctl */
129 nodev
, /* cb_devmap */
131 nodev
, /* cb_segmap */
132 nochpoll
, /* cb_chpoll */
133 ddi_prop_op
, /* cb_prop_op */
135 D_NEW
| D_MP
, /* cb_flag */
137 nodev
, /* cb_aread */
138 nodev
/* cb_awrite */
145 static int ippctl_info(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
146 static int ippctl_attach(dev_info_t
*, ddi_attach_cmd_t
);
147 static int ippctl_detach(dev_info_t
*, ddi_detach_cmd_t
);
149 static struct dev_ops ippctl_dev_ops
= {
150 DEVO_REV
, /* devo_rev, */
152 ippctl_info
, /* devo_getinfo */
153 nulldev
, /* devo_identify */
154 nulldev
, /* devo_probe */
155 ippctl_attach
, /* devo_attach */
156 ippctl_detach
, /* devo_detach */
157 nodev
, /* devo_reset */
158 &ippctl_cb_ops
, /* devo_cb_ops */
159 NULL
, /* devo_bus_ops */
160 NULL
, /* devo_power */
161 ddi_quiesce_not_needed
, /* devo_quiesce */
164 static struct modldrv modldrv
= {
166 "IP Policy Configuration Driver",
170 static struct modlinkage modlinkage
= {
177 * Local definitions, types and prototypes.
180 #define MAXUBUFLEN (1 << 16)
182 #define FREE_TEXT(_string) \
183 kmem_free((_string), strlen(_string) + 1)
185 #define FREE_TEXT_ARRAY(_array, _nelt) \
189 for (j = 0; j < (_nelt); j++) \
190 if ((_array)[j] != NULL) \
191 FREE_TEXT((_array)[j]); \
192 kmem_free((_array), (_nelt) * sizeof (char *)); \
195 typedef struct ippctl_buf ippctl_buf_t
;
202 static int ippctl_copyin(caddr_t
, int, char **, size_t *);
203 static int ippctl_copyout(caddr_t
, int, char *, size_t);
204 static int ippctl_extract_op(nvlist_t
*, uint8_t *);
205 static int ippctl_extract_aname(nvlist_t
*, char **);
206 static int ippctl_extract_modname(nvlist_t
*, char **);
207 static int ippctl_attach_modname(nvlist_t
*nvlp
, char *val
);
208 static int ippctl_attach_modname_array(nvlist_t
*nvlp
, char **val
, int);
209 static int ippctl_attach_aname_array(nvlist_t
*nvlp
, char **val
, int);
210 static int ippctl_extract_flags(nvlist_t
*, ipp_flags_t
*);
211 static int ippctl_cmd(char *, size_t, size_t *);
212 static int ippctl_action_create(char *, char *, nvlist_t
*, ipp_flags_t
);
213 static int ippctl_action_destroy(char *, ipp_flags_t
);
214 static int ippctl_action_modify(char *, nvlist_t
*, ipp_flags_t
);
215 static int ippctl_action_info(char *, ipp_flags_t
);
216 static int ippctl_action_mod(char *);
217 static int ippctl_list_mods(void);
218 static int ippctl_mod_list_actions(char *);
219 static int ippctl_data(char **, size_t *, size_t *);
220 static void ippctl_flush(void);
221 static int ippctl_add_nvlist(nvlist_t
*, int);
222 static int ippctl_callback(nvlist_t
*, void *);
223 static int ippctl_set_rc(int);
224 static void ippctl_alloc(int);
225 static void ippctl_realloc(void);
226 static void ippctl_free(void);
232 static dev_info_t
*ippctl_dip
= NULL
;
233 static kmutex_t ippctl_lock
;
234 static boolean_t ippctl_busy
;
235 static ippctl_buf_t
*ippctl_array
= NULL
;
236 static int ippctl_limit
= -1;
237 static int ippctl_rindex
= -1;
238 static int ippctl_windex
= -1;
241 * Module linkage functions
244 #define __FN__ "_init"
251 if ((rc
= mod_install(&modlinkage
)) != 0) {
252 DBG0(DBG_MODLINK
, "mod_install failed\n");
260 #define __FN__ "_fini"
267 if ((rc
= mod_remove(&modlinkage
)) == 0) {
271 DBG0(DBG_MODLINK
, "mod_remove failed\n");
276 #define __FN__ "_info"
279 struct modinfo
*modinfop
)
281 DBG0(DBG_MODLINK
, "calling mod_info\n");
282 return (mod_info(&modlinkage
, modinfop
));
287 * Driver interface functions (dev_ops and cb_ops)
290 #define __FN__ "ippctl_info"
299 int rc
= DDI_FAILURE
;
302 case DDI_INFO_DEVT2INSTANCE
:
303 *result
= NULL
; /* Single instance driver */
306 case DDI_INFO_DEVT2DEVINFO
:
307 *result
= (void *)ippctl_dip
;
318 #define __FN__ "ippctl_attach"
322 ddi_attach_cmd_t cmd
)
332 return (DDI_FAILURE
);
335 DBG0(DBG_DEVOPS
, "DDI_ATTACH\n");
338 * This is strictly a single instance driver.
341 if (ippctl_dip
!= NULL
)
342 return (DDI_FAILURE
);
348 if (ddi_create_minor_node(dip
, "ctl", S_IFCHR
, 0,
349 DDI_PSEUDO
, 0) != DDI_SUCCESS
)
350 return (DDI_FAILURE
);
353 * No need for per-instance structure, just store vital data in
358 mutex_init(&ippctl_lock
, NULL
, MUTEX_DRIVER
, NULL
);
359 ippctl_busy
= B_FALSE
;
361 return (DDI_SUCCESS
);
365 #define __FN__ "ippctl_detach"
370 ddi_detach_cmd_t cmd
)
380 return (DDI_FAILURE
);
383 DBG0(DBG_DEVOPS
, "DDI_DETACH\n");
385 ASSERT(dip
== ippctl_dip
);
387 ddi_remove_minor_node(dip
, NULL
);
388 mutex_destroy(&ippctl_lock
);
391 return (DDI_SUCCESS
);
395 #define __FN__ "ippctl_open"
404 minor_t minor
= getminor(*devp
);
407 DBG0(DBG_CBOPS
, "open\n");
410 * Only allow privileged users to open our device.
413 if (secpolicy_net_config(credp
, B_FALSE
) != 0) {
414 DBG0(DBG_CBOPS
, "not privileged user\n");
419 * Sanity check other arguments.
423 DBG0(DBG_CBOPS
, "bad minor\n");
427 if (otyp
!= OTYP_CHR
) {
428 DBG0(DBG_CBOPS
, "bad device type\n");
433 * This is also a single dev_t driver.
436 mutex_enter(&ippctl_lock
);
438 mutex_exit(&ippctl_lock
);
441 ippctl_busy
= B_TRUE
;
442 mutex_exit(&ippctl_lock
);
445 * Allocate data buffer array (starting with length LIMIT, defined
446 * at the start of this function).
451 DBG0(DBG_CBOPS
, "success\n");
459 #define __FN__ "ippctl_close"
468 minor_t minor
= getminor(dev
);
470 DBG0(DBG_CBOPS
, "close\n");
475 * Free the data buffer array.
480 mutex_enter(&ippctl_lock
);
481 ippctl_busy
= B_FALSE
;
482 mutex_exit(&ippctl_lock
);
484 DBG0(DBG_CBOPS
, "success\n");
490 #define __FN__ "ippctl_ioctl"
500 minor_t minor
= getminor(dev
);
512 if (secpolicy_net_config(credp
, B_FALSE
) != 0) {
513 DBG0(DBG_CBOPS
, "not privileged user\n");
518 DBG0(DBG_CBOPS
, "bad minor\n");
524 DBG0(DBG_CBOPS
, "command\n");
527 * Copy in the command buffer from user space.
530 if ((rc
= ippctl_copyin((caddr_t
)arg
, mode
, &cbuf
,
535 * Execute the command.
538 rc
= ippctl_cmd(cbuf
, cbuflen
, &nextbuflen
);
541 * Pass back the length of the first data buffer.
544 DBG1(DBG_CBOPS
, "nextbuflen = %lu\n", nextbuflen
);
548 * Free the kernel copy of the command buffer.
551 kmem_free(cbuf
, cbuflen
);
555 DBG0(DBG_CBOPS
, "data\n");
558 * Grab the next data buffer from the array of pending
562 if ((rc
= ippctl_data(&dbuf
, &dbuflen
, &nextbuflen
)) != 0)
566 * Copy it out to user space.
569 rc
= ippctl_copyout((caddr_t
)arg
, mode
, dbuf
, dbuflen
);
572 * Pass back the length of the next data buffer.
575 DBG1(DBG_CBOPS
, "nextbuflen = %lu\n", nextbuflen
);
580 DBG0(DBG_CBOPS
, "unrecognized ioctl\n");
585 DBG1(DBG_CBOPS
, "rc = %d\n", rc
);
594 #define __FN__ "ippctl_copyin"
607 DBG0(DBG_CBOPS
, "copying in ioctl structure\n");
610 * Copy in the ioctl structure from user-space, converting from 32-bit
614 #ifdef _MULTI_DATAMODEL
615 switch (ddi_model_convert_from(mode
& FMODELS
)) {
616 case DDI_MODEL_ILP32
:
618 ippctl_ioctl32_t iioc32
;
620 DBG0(DBG_CBOPS
, "converting from 32-bit\n");
622 if (ddi_copyin(arg
, (caddr_t
)&iioc32
,
623 sizeof (ippctl_ioctl32_t
), mode
) != 0)
626 ubuf
= (caddr_t
)(uintptr_t)iioc32
.ii32_buf
;
627 ubuflen
= (size_t)iioc32
.ii32_buflen
;
631 if (ddi_copyin(arg
, (caddr_t
)&iioc
, sizeof (ippctl_ioctl_t
),
636 ubuflen
= iioc
.ii_buflen
;
641 #else /* _MULTI_DATAMODEL */
642 if (ddi_copyin(arg
, (caddr_t
)&iioc
, sizeof (ippctl_ioctl_t
),
647 ubuflen
= iioc
.ii_buflen
;
648 #endif /* _MULTI_DATAMODEL */
650 DBG1(DBG_CBOPS
, "ubuf = 0x%p\n", (void *)ubuf
);
651 DBG1(DBG_CBOPS
, "ubuflen = %lu\n", ubuflen
);
654 * Sanity check the command buffer information.
657 if (ubuflen
== 0 || ubuf
== NULL
)
659 if (ubuflen
> MAXUBUFLEN
)
663 * Allocate some memory for the command buffer and copy it in.
666 kbuf
= kmem_zalloc(ubuflen
, KM_SLEEP
);
667 DBG0(DBG_CBOPS
, "copying in nvlist\n");
668 if (ddi_copyin(ubuf
, (caddr_t
)kbuf
, ubuflen
, mode
) != 0) {
669 kmem_free(kbuf
, ubuflen
);
679 #define __FN__ "ippctl_copyout"
691 DBG0(DBG_CBOPS
, "copying out ioctl structure\n");
694 * Copy in the ioctl structure from user-space, converting from 32-bit
698 #ifdef _MULTI_DATAMODEL
699 switch (ddi_model_convert_from(mode
& FMODELS
)) {
700 case DDI_MODEL_ILP32
:
702 ippctl_ioctl32_t iioc32
;
704 if (ddi_copyin(arg
, (caddr_t
)&iioc32
,
705 sizeof (ippctl_ioctl32_t
), mode
) != 0)
708 ubuf
= (caddr_t
)(uintptr_t)iioc32
.ii32_buf
;
709 ubuflen
= iioc32
.ii32_buflen
;
713 if (ddi_copyin(arg
, (caddr_t
)&iioc
, sizeof (ippctl_ioctl_t
),
718 ubuflen
= iioc
.ii_buflen
;
723 #else /* _MULTI_DATAMODEL */
724 if (ddi_copyin(arg
, (caddr_t
)&iioc
, sizeof (ippctl_ioctl_t
),
729 ubuflen
= iioc
.ii_buflen
;
730 #endif /* _MULTI_DATAMODEL */
732 DBG1(DBG_CBOPS
, "ubuf = 0x%p\n", (void *)ubuf
);
733 DBG1(DBG_CBOPS
, "ubuflen = %d\n", ubuflen
);
736 * Sanity check the data buffer details.
739 if (ubuflen
== 0 || ubuf
== NULL
)
742 if (ubuflen
< kbuflen
)
744 if (ubuflen
> MAXUBUFLEN
)
748 * Copy out the data buffer to user space.
751 DBG0(DBG_CBOPS
, "copying out nvlist\n");
752 if (ddi_copyout((caddr_t
)kbuf
, ubuf
, kbuflen
, mode
) != 0)
759 #define __FN__ "ippctl_extract_op"
768 * Look-up and remove the opcode passed from libipp from the
772 if ((rc
= nvlist_lookup_byte(nvlp
, IPPCTL_OP
, valp
)) != 0)
775 (void) nvlist_remove_all(nvlp
, IPPCTL_OP
);
780 #define __FN__ "ippctl_extract_aname"
782 ippctl_extract_aname(
790 * Look-up and remove the action name passed from libipp from the
794 if ((rc
= nvlist_lookup_string(nvlp
, IPPCTL_ANAME
, &ptr
)) != 0)
797 *valp
= kmem_alloc(strlen(ptr
) + 1, KM_SLEEP
);
798 (void) strcpy(*valp
, ptr
);
799 (void) nvlist_remove_all(nvlp
, IPPCTL_ANAME
);
804 #define __FN__ "ippctl_extract_modname"
806 ippctl_extract_modname(
814 * Look-up and remove the module name passed from libipp from the
818 if ((rc
= nvlist_lookup_string(nvlp
, IPPCTL_MODNAME
, &ptr
)) != 0)
821 *valp
= kmem_alloc(strlen(ptr
) + 1, KM_SLEEP
);
822 (void) strcpy(*valp
, ptr
);
823 (void) nvlist_remove_all(nvlp
, IPPCTL_MODNAME
);
828 #define __FN__ "ippctl_attach_modname"
830 ippctl_attach_modname(
835 * Add a module name to an nvlist for passing back to user
839 return (nvlist_add_string(nvlp
, IPPCTL_MODNAME
, modname
));
843 #define __FN__ "ippctl_attach_modname_array"
845 ippctl_attach_modname_array(
847 char **modname_array
,
851 * Add a module name array to an nvlist for passing back to user
855 return (nvlist_add_string_array(nvlp
, IPPCTL_MODNAME_ARRAY
,
856 modname_array
, nelt
));
860 #define __FN__ "ippctl_attach_aname_array"
862 ippctl_attach_aname_array(
868 * Add an action name array to an nvlist for passing back to user
872 return (nvlist_add_string_array(nvlp
, IPPCTL_ANAME_ARRAY
,
877 #define __FN__ "ippctl_extract_flags"
879 ippctl_extract_flags(
886 * Look-up and remove the flags passed from libipp from the
890 if ((rc
= nvlist_lookup_uint32(nvlp
, IPPCTL_FLAGS
,
891 (uint32_t *)valp
)) != 0)
894 (void) nvlist_remove_all(nvlp
, IPPCTL_FLAGS
);
899 #define __FN__ "ippctl_cmd"
906 nvlist_t
*nvlp
= NULL
;
909 char *modname
= NULL
;
914 * Start a new command cycle by flushing any previous data buffers.
921 * Unpack the nvlist from the command buffer.
924 if ((rc
= nvlist_unpack(cbuf
, cbuflen
, &nvlp
, KM_SLEEP
)) != 0)
928 * Extract the opcode to find out what we should do.
931 if ((rc
= ippctl_extract_op(nvlp
, &op
)) != 0) {
937 case IPPCTL_OP_ACTION_CREATE
:
939 * Create a new action.
942 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_ACTION_CREATE\n");
945 * Extract the module name, action name and flags from the
949 if ((rc
= ippctl_extract_modname(nvlp
, &modname
)) != 0) {
954 if ((rc
= ippctl_extract_aname(nvlp
, &aname
)) != 0) {
960 if ((rc
= ippctl_extract_flags(nvlp
, &flags
)) != 0) {
968 rc
= ippctl_action_create(modname
, aname
, nvlp
, flags
);
971 case IPPCTL_OP_ACTION_MODIFY
:
974 * Modify an existing action.
977 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_ACTION_MODIFY\n");
980 * Extract the action name and flags from the nvlist.
983 if ((rc
= ippctl_extract_aname(nvlp
, &aname
)) != 0) {
988 if ((rc
= ippctl_extract_flags(nvlp
, &flags
)) != 0) {
994 rc
= ippctl_action_modify(aname
, nvlp
, flags
);
997 case IPPCTL_OP_ACTION_DESTROY
:
1000 * Destroy an action.
1003 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_ACTION_DESTROY\n");
1006 * Extract the action name and flags from the nvlist.
1009 if ((rc
= ippctl_extract_aname(nvlp
, &aname
)) != 0) {
1014 if ((rc
= ippctl_extract_flags(nvlp
, &flags
)) != 0) {
1021 rc
= ippctl_action_destroy(aname
, flags
);
1024 case IPPCTL_OP_ACTION_INFO
:
1027 * Retrive the configuration of an action.
1030 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_ACTION_INFO\n");
1033 * Extract the action name and flags from the nvlist.
1036 if ((rc
= ippctl_extract_aname(nvlp
, &aname
)) != 0) {
1041 if ((rc
= ippctl_extract_flags(nvlp
, &flags
)) != 0) {
1048 rc
= ippctl_action_info(aname
, flags
);
1051 case IPPCTL_OP_ACTION_MOD
:
1054 * Find the module that implements a given action.
1057 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_ACTION_MOD\n");
1060 * Extract the action name from the nvlist.
1063 if ((rc
= ippctl_extract_aname(nvlp
, &aname
)) != 0) {
1069 rc
= ippctl_action_mod(aname
);
1072 case IPPCTL_OP_LIST_MODS
:
1075 * List all the modules.
1078 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_LIST_MODS\n");
1081 rc
= ippctl_list_mods();
1084 case IPPCTL_OP_MOD_LIST_ACTIONS
:
1087 * List all the actions for a given module.
1090 DBG0(DBG_CBOPS
, "op = IPPCTL_OP_LIST_MODS\n");
1092 if ((rc
= ippctl_extract_modname(nvlp
, &modname
)) != 0) {
1098 rc
= ippctl_mod_list_actions(modname
);
1104 * Unrecognized opcode.
1113 * The length of buffer that we need to notify back to libipp with
1114 * the command ioctl's return is the length of the first data buffer
1115 * in the array. We only expact to pass back data buffers if the
1116 * operation succeeds (NOTE: this does not mean the kernel call has
1117 * to succeed, merely that we successfully issued it and processed
1122 *nextbuflenp
= ippctl_array
[0].buflen
;
1128 #define __FN__ "ippctl_action_create"
1130 ippctl_action_create(
1139 ipp_action_id_t aid
;
1142 * Look up the module id from the name and create the new
1146 mid
= ipp_mod_lookup(modname
);
1149 ipp_rc
= ipp_action_create(mid
, aname
, &nvlp
, flags
, &aid
);
1153 * Add an nvlist containing the kernel return code to the
1154 * set of nvlists to pass back to libipp.
1157 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0) {
1160 if (ipp_action_destroy(aid
, 0) != 0) {
1162 "ippctl: unrecoverable error (aid = %d)",
1171 * If the module passed back an nvlist, add this as
1176 rc
= ippctl_callback(nvlp
, NULL
);
1185 #define __FN__ "ippctl_action_destroy"
1187 ippctl_action_destroy(
1191 ipp_action_id_t aid
;
1196 * Look up the action id and destroy the action.
1199 aid
= ipp_action_lookup(aname
);
1202 ipp_rc
= ipp_action_destroy(aid
, flags
);
1205 * Add an nvlist containing the kernel return code to the
1206 * set of nvlists to pass back to libipp.
1209 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0)
1213 * There's no more information to pass back.
1220 #define __FN__ "ippctl_action_modify"
1222 ippctl_action_modify(
1227 ipp_action_id_t aid
;
1232 * Look up the action id and modify the action.
1235 aid
= ipp_action_lookup(aname
);
1238 ipp_rc
= ipp_action_modify(aid
, &nvlp
, flags
);
1241 * Add an nvlist containing the kernel return code to the
1242 * set of nvlists to pass back to libipp.
1245 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0) {
1251 * If the module passed back an nvlist, add this as
1256 rc
= ippctl_callback(nvlp
, NULL
);
1265 #define __FN__ "ippctl_action_info"
1271 ipp_action_id_t aid
;
1276 * Look up the action and call the information retrieval
1279 * NOTE: The callback function that is passed in packs and
1280 * stores each of the nvlists it is called with in the array
1281 * that will be passed back to libipp.
1284 aid
= ipp_action_lookup(aname
);
1287 ipp_rc
= ipp_action_info(aid
, ippctl_callback
, NULL
, flags
);
1290 * Add an nvlist containing the kernel return code to the
1291 * set of nvlists to pass back to libipp.
1294 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0)
1298 * There's no more information to pass back.
1305 #define __FN__ "ippctl_action_mod"
1311 ipp_action_id_t aid
;
1318 * Look up the action id and get the id of the module that
1319 * implements the action. If that succeeds then look up the
1320 * name of the module.
1323 aid
= ipp_action_lookup(aname
);
1326 if ((ipp_rc
= ipp_action_mod(aid
, &mid
)) == 0)
1327 ipp_rc
= ipp_mod_name(mid
, &modname
);
1330 * Add an nvlist containing the kernel return code to the
1331 * set of nvlists to pass back to libipp.
1334 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0)
1338 * If everything succeeded add an nvlist containing the
1339 * module name to the set of nvlists to pass back to libipp.
1343 if ((rc
= nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
, KM_SLEEP
)) != 0)
1346 if ((rc
= ippctl_attach_modname(nvlp
, modname
)) != 0) {
1353 rc
= ippctl_callback(nvlp
, NULL
);
1362 #define __FN__ "ippctl_list_mods"
1370 ipp_mod_id_t
*mid_array
;
1371 char **modname_array
= NULL
;
1377 * Get a list of all the module ids. If that succeeds,
1378 * translate the ids into names.
1380 * NOTE: This translation may fail if a module is
1381 * unloaded during this operation. If this occurs, EAGAIN
1382 * will be passed back to libipp note that a transient
1386 if ((ipp_rc
= ipp_list_mods(&mid_array
, &nelt
)) == 0) {
1389 * It is possible that there are no modules
1394 length
= nelt
* sizeof (char *);
1395 modname_array
= kmem_zalloc(length
, KM_SLEEP
);
1397 for (i
= 0; i
< nelt
; i
++) {
1398 if (ipp_mod_name(mid_array
[i
],
1399 &modname_array
[i
]) != 0) {
1400 kmem_free(mid_array
, nelt
*
1401 sizeof (ipp_mod_id_t
));
1402 FREE_TEXT_ARRAY(modname_array
, nelt
);
1408 kmem_free(mid_array
, nelt
* sizeof (ipp_mod_id_t
));
1410 if ((rc
= nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
,
1412 FREE_TEXT_ARRAY(modname_array
, nelt
);
1416 if ((rc
= ippctl_attach_modname_array(nvlp
,
1417 modname_array
, nelt
)) != 0) {
1418 FREE_TEXT_ARRAY(modname_array
, nelt
);
1423 FREE_TEXT_ARRAY(modname_array
, nelt
);
1425 if ((rc
= ippctl_callback(nvlp
, NULL
)) != 0) {
1436 * Add an nvlist containing the kernel return code to the
1437 * set of nvlists to pass back to libipp.
1440 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0)
1447 #define __FN__ "ippctl_mod_list_actions"
1449 ippctl_mod_list_actions(
1456 ipp_action_id_t
*aid_array
;
1457 char **aname_array
= NULL
;
1463 * Get the module id.
1466 mid
= ipp_mod_lookup(modname
);
1470 * Get a list of all the action ids for the module. If that succeeds,
1471 * translate the ids into names.
1473 * NOTE: This translation may fail if an action is
1474 * destroyed during this operation. If this occurs, EAGAIN
1475 * will be passed back to libipp note that a transient
1479 if ((ipp_rc
= ipp_mod_list_actions(mid
, &aid_array
, &nelt
)) == 0) {
1482 * It is possible that there are no actions defined.
1483 * (This is unlikely though as the module would normally
1484 * be auto-unloaded fairly quickly)
1488 length
= nelt
* sizeof (char *);
1489 aname_array
= kmem_zalloc(length
, KM_SLEEP
);
1491 for (i
= 0; i
< nelt
; i
++) {
1492 if (ipp_action_name(aid_array
[i
],
1493 &aname_array
[i
]) != 0) {
1494 kmem_free(aid_array
, nelt
*
1495 sizeof (ipp_action_id_t
));
1496 FREE_TEXT_ARRAY(aname_array
, nelt
);
1502 kmem_free(aid_array
, nelt
* sizeof (ipp_action_id_t
));
1504 if ((rc
= nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
,
1506 FREE_TEXT_ARRAY(aname_array
, nelt
);
1510 if ((rc
= ippctl_attach_aname_array(nvlp
, aname_array
,
1512 FREE_TEXT_ARRAY(aname_array
, nelt
);
1517 FREE_TEXT_ARRAY(aname_array
, nelt
);
1519 if ((rc
= ippctl_callback(nvlp
, NULL
)) != 0) {
1530 * Add an nvlist containing the kernel return code to the
1531 * set of nvlists to pass back to libipp.
1534 if ((rc
= ippctl_set_rc(ipp_rc
)) != 0)
1541 #define __FN__ "ippctl_data"
1546 size_t *nextbuflenp
)
1550 DBG0(DBG_CBOPS
, "called\n");
1553 * Get the next data buffer from the array by looking at the
1554 * 'read index'. If this is the same as the 'write index' then
1555 * there's no more buffers in the array.
1559 if (i
== ippctl_windex
)
1563 * Extract the buffer details. It is a pre-packed nvlist.
1566 *dbufp
= ippctl_array
[i
].buf
;
1567 *dbuflenp
= ippctl_array
[i
].buflen
;
1569 DBG2(DBG_CBOPS
, "accessing nvlist[%d], length %lu\n", i
, *dbuflenp
);
1570 ASSERT(*dbufp
!= NULL
);
1573 * Advance the 'read index' and check if there's another buffer.
1574 * If there is then we need to pass back its length to libipp so that
1575 * another data ioctl will be issued.
1579 if (i
< ippctl_windex
)
1580 *nextbuflenp
= ippctl_array
[i
].buflen
;
1589 #define __FN__ "ippctl_flush"
1599 * Free any buffers left in the array.
1602 for (i
= 0; i
< ippctl_limit
; i
++) {
1603 if ((buflen
= ippctl_array
[i
].buflen
) > 0) {
1604 buf
= ippctl_array
[i
].buf
;
1605 ASSERT(buf
!= NULL
);
1606 kmem_free(buf
, buflen
);
1611 * NULL all the entries.
1614 bzero(ippctl_array
, ippctl_limit
* sizeof (ippctl_buf_t
));
1617 * Reset the indexes.
1625 #define __FN__ "ippctl_add_nvlist"
1636 * NULL the buffer pointer so that a buffer is automatically
1643 * Pack the nvlist and get back the buffer pointer and length.
1646 if ((rc
= nvlist_pack(nvlp
, &buf
, &buflen
, NV_ENCODE_NATIVE
,
1648 ippctl_array
[i
].buf
= NULL
;
1649 ippctl_array
[i
].buflen
= 0;
1653 DBG2(DBG_CBOPS
, "added nvlist[%d]: length %lu\n", i
, buflen
);
1656 * Store the pointer an length in the array at the given index.
1659 ippctl_array
[i
].buf
= buf
;
1660 ippctl_array
[i
].buflen
= buflen
;
1666 #define __FN__ "ippctl_callback"
1677 * Check the 'write index' to see if there's space in the array for
1685 * If there's no space, re-allocate the array (see comments in
1686 * ippctl_realloc() for details).
1689 if (i
== ippctl_limit
)
1693 * Add the nvlist to the array.
1696 if ((rc
= ippctl_add_nvlist(nvlp
, i
)) == 0)
1703 #define __FN__ "ippctl_set_rc"
1712 * Create an nvlist to store the return code,
1715 if ((rc
= nvlist_alloc(&nvlp
, NV_UNIQUE_NAME
, KM_SLEEP
)) != 0)
1718 if ((rc
= nvlist_add_int32(nvlp
, IPPCTL_RC
, val
)) != 0) {
1724 * Add it at the beginning of the array.
1727 rc
= ippctl_add_nvlist(nvlp
, 0);
1734 #define __FN__ "ippctl_alloc"
1740 * Allocate the data buffer array and initialize the indexes.
1743 ippctl_array
= kmem_zalloc(limit
* sizeof (ippctl_buf_t
), KM_SLEEP
);
1744 ippctl_limit
= limit
;
1750 #define __FN__ "ippctl_realloc"
1755 ippctl_buf_t
*array
;
1760 * Allocate a new array twice the size of the old one.
1763 limit
= ippctl_limit
<< 1;
1764 array
= kmem_zalloc(limit
* sizeof (ippctl_buf_t
), KM_SLEEP
);
1767 * Copy across the information from the old array into the new one.
1770 for (i
= 0; i
< ippctl_limit
; i
++)
1771 array
[i
] = ippctl_array
[i
];
1774 * Free the old array.
1777 kmem_free(ippctl_array
, ippctl_limit
* sizeof (ippctl_buf_t
));
1779 ippctl_array
= array
;
1780 ippctl_limit
= limit
;
1784 #define __FN__ "ippctl_free"
1790 * Flush the array prior to freeing it to make sure no buffers are
1800 kmem_free(ippctl_array
, ippctl_limit
* sizeof (ippctl_buf_t
));
1801 ippctl_array
= NULL
;
1819 if ((type
& ippctl_debug_flags
) == 0)
1822 mutex_enter(debug_mutex
);
1824 (void) vsnprintf(buf
, 255, fmt
, adx
);
1827 printf("%s: %s", fn
, buf
);
1828 mutex_exit(debug_mutex
);
1830 #endif /* IPPCTL_DBG */