10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7656SSherry.Moore@Sun.COM * Common Development and Distribution License (the "License").
6*7656SSherry.Moore@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*7656SSherry.Moore@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * IP Policy Framework config driver
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <sys/cmn_err.h>
330Sstevel@tonic-gate #include <sys/kmem.h>
340Sstevel@tonic-gate #include <sys/errno.h>
350Sstevel@tonic-gate #include <sys/cpuvar.h>
360Sstevel@tonic-gate #include <sys/open.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate #include <sys/conf.h>
390Sstevel@tonic-gate #include <sys/ddi.h>
400Sstevel@tonic-gate #include <sys/sunddi.h>
410Sstevel@tonic-gate #include <sys/modctl.h>
420Sstevel@tonic-gate #include <sys/stream.h>
430Sstevel@tonic-gate #include <ipp/ipp.h>
440Sstevel@tonic-gate #include <ipp/ippctl.h>
450Sstevel@tonic-gate #include <sys/nvpair.h>
460Sstevel@tonic-gate #include <sys/policy.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate * Debug switch.
500Sstevel@tonic-gate */
510Sstevel@tonic-gate
520Sstevel@tonic-gate #if defined(DEBUG)
530Sstevel@tonic-gate #define IPPCTL_DEBUG
540Sstevel@tonic-gate #endif
550Sstevel@tonic-gate
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate * Debug macros.
580Sstevel@tonic-gate */
590Sstevel@tonic-gate
600Sstevel@tonic-gate #ifdef IPPCTL_DEBUG
610Sstevel@tonic-gate
620Sstevel@tonic-gate #define DBG_MODLINK 0x00000001ull
630Sstevel@tonic-gate #define DBG_DEVOPS 0x00000002ull
640Sstevel@tonic-gate #define DBG_CBOPS 0x00000004ull
650Sstevel@tonic-gate
660Sstevel@tonic-gate static uint64_t ippctl_debug_flags =
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate * DBG_MODLINK |
690Sstevel@tonic-gate * DBG_DEVOPS |
700Sstevel@tonic-gate * DBG_CBOPS |
710Sstevel@tonic-gate */
720Sstevel@tonic-gate 0;
730Sstevel@tonic-gate
740Sstevel@tonic-gate static kmutex_t debug_mutex[1];
750Sstevel@tonic-gate
760Sstevel@tonic-gate /*PRINTFLIKE3*/
770Sstevel@tonic-gate static void ippctl_debug(uint64_t, char *, char *, ...)
780Sstevel@tonic-gate __PRINTFLIKE(3);
790Sstevel@tonic-gate
800Sstevel@tonic-gate #define DBG0(_type, _fmt) \
810Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt));
820Sstevel@tonic-gate
830Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1) \
840Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1));
850Sstevel@tonic-gate
860Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2) \
870Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2));
880Sstevel@tonic-gate
890Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3) \
900Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
910Sstevel@tonic-gate (_a3));
920Sstevel@tonic-gate
930Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \
940Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
950Sstevel@tonic-gate (_a3), (_a4));
960Sstevel@tonic-gate
970Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \
980Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
990Sstevel@tonic-gate (_a3), (_a4), (_a5));
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate #else /* IPPCTL_DBG */
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate #define DBG0(_type, _fmt)
1040Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1)
1050Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2)
1060Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3)
1070Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4)
1080Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5)
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate #endif /* IPPCTL_DBG */
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * cb_ops
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate static int ippctl_open(dev_t *, int, int, cred_t *);
1170Sstevel@tonic-gate static int ippctl_close(dev_t, int, int, cred_t *);
1180Sstevel@tonic-gate static int ippctl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate static struct cb_ops ippctl_cb_ops = {
1210Sstevel@tonic-gate ippctl_open, /* cb_open */
1220Sstevel@tonic-gate ippctl_close, /* cb_close */
1230Sstevel@tonic-gate nodev, /* cb_strategy */
1240Sstevel@tonic-gate nodev, /* cb_print */
1250Sstevel@tonic-gate nodev, /* cb_dump */
1260Sstevel@tonic-gate nodev, /* cb_read */
1270Sstevel@tonic-gate nodev, /* cb_write */
1280Sstevel@tonic-gate ippctl_ioctl, /* cb_ioctl */
1290Sstevel@tonic-gate nodev, /* cb_devmap */
1300Sstevel@tonic-gate nodev, /* cb_mmap */
1310Sstevel@tonic-gate nodev, /* cb_segmap */
1320Sstevel@tonic-gate nochpoll, /* cb_chpoll */
1330Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */
1340Sstevel@tonic-gate 0, /* cb_str */
1350Sstevel@tonic-gate D_NEW | D_MP, /* cb_flag */
1360Sstevel@tonic-gate CB_REV, /* cb_rev */
1370Sstevel@tonic-gate nodev, /* cb_aread */
1380Sstevel@tonic-gate nodev /* cb_awrite */
1390Sstevel@tonic-gate };
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate /*
1420Sstevel@tonic-gate * dev_ops
1430Sstevel@tonic-gate */
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate static int ippctl_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
1460Sstevel@tonic-gate static int ippctl_attach(dev_info_t *, ddi_attach_cmd_t);
1470Sstevel@tonic-gate static int ippctl_detach(dev_info_t *, ddi_detach_cmd_t);
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate static struct dev_ops ippctl_dev_ops = {
1500Sstevel@tonic-gate DEVO_REV, /* devo_rev, */
1510Sstevel@tonic-gate 0, /* devo_refcnt */
1520Sstevel@tonic-gate ippctl_info, /* devo_getinfo */
1530Sstevel@tonic-gate nulldev, /* devo_identify */
1540Sstevel@tonic-gate nulldev, /* devo_probe */
1550Sstevel@tonic-gate ippctl_attach, /* devo_attach */
1560Sstevel@tonic-gate ippctl_detach, /* devo_detach */
1570Sstevel@tonic-gate nodev, /* devo_reset */
1580Sstevel@tonic-gate &ippctl_cb_ops, /* devo_cb_ops */
159*7656SSherry.Moore@Sun.COM (struct bus_ops *)0, /* devo_bus_ops */
160*7656SSherry.Moore@Sun.COM NULL, /* devo_power */
161*7656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* devo_quiesce */
1620Sstevel@tonic-gate };
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate static struct modldrv modldrv = {
1650Sstevel@tonic-gate &mod_driverops,
166*7656SSherry.Moore@Sun.COM "IP Policy Configuration Driver",
1670Sstevel@tonic-gate &ippctl_dev_ops,
1680Sstevel@tonic-gate };
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate static struct modlinkage modlinkage = {
1710Sstevel@tonic-gate MODREV_1,
1720Sstevel@tonic-gate &modldrv,
1730Sstevel@tonic-gate NULL
1740Sstevel@tonic-gate };
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate /*
1770Sstevel@tonic-gate * Local definitions, types and prototypes.
1780Sstevel@tonic-gate */
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate #define MAXUBUFLEN (1 << 16)
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate #define FREE_TEXT(_string) \
1830Sstevel@tonic-gate kmem_free((_string), strlen(_string) + 1)
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate #define FREE_TEXT_ARRAY(_array, _nelt) \
1860Sstevel@tonic-gate { \
1870Sstevel@tonic-gate int j; \
1880Sstevel@tonic-gate \
1890Sstevel@tonic-gate for (j = 0; j < (_nelt); j++) \
1900Sstevel@tonic-gate if ((_array)[j] != NULL) \
1910Sstevel@tonic-gate FREE_TEXT((_array)[j]); \
1920Sstevel@tonic-gate kmem_free((_array), (_nelt) * sizeof (char *)); \
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate typedef struct ippctl_buf ippctl_buf_t;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate struct ippctl_buf {
1980Sstevel@tonic-gate char *buf;
1990Sstevel@tonic-gate size_t buflen;
2000Sstevel@tonic-gate };
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate static int ippctl_copyin(caddr_t, int, char **, size_t *);
2030Sstevel@tonic-gate static int ippctl_copyout(caddr_t, int, char *, size_t);
2040Sstevel@tonic-gate static int ippctl_extract_op(nvlist_t *, uint8_t *);
2050Sstevel@tonic-gate static int ippctl_extract_aname(nvlist_t *, char **);
2060Sstevel@tonic-gate static int ippctl_extract_modname(nvlist_t *, char **);
2070Sstevel@tonic-gate static int ippctl_attach_modname(nvlist_t *nvlp, char *val);
2080Sstevel@tonic-gate static int ippctl_attach_modname_array(nvlist_t *nvlp, char **val, int);
2090Sstevel@tonic-gate static int ippctl_attach_aname_array(nvlist_t *nvlp, char **val, int);
2100Sstevel@tonic-gate static int ippctl_extract_flags(nvlist_t *, ipp_flags_t *);
2110Sstevel@tonic-gate static int ippctl_cmd(char *, size_t, size_t *);
2120Sstevel@tonic-gate static int ippctl_action_create(char *, char *, nvlist_t *, ipp_flags_t);
2130Sstevel@tonic-gate static int ippctl_action_destroy(char *, ipp_flags_t);
2140Sstevel@tonic-gate static int ippctl_action_modify(char *, nvlist_t *, ipp_flags_t);
2150Sstevel@tonic-gate static int ippctl_action_info(char *, ipp_flags_t);
2160Sstevel@tonic-gate static int ippctl_action_mod(char *);
2170Sstevel@tonic-gate static int ippctl_list_mods(void);
2180Sstevel@tonic-gate static int ippctl_mod_list_actions(char *);
2190Sstevel@tonic-gate static int ippctl_data(char **, size_t *, size_t *);
2200Sstevel@tonic-gate static void ippctl_flush(void);
2210Sstevel@tonic-gate static int ippctl_add_nvlist(nvlist_t *, int);
2220Sstevel@tonic-gate static int ippctl_callback(nvlist_t *, void *);
2230Sstevel@tonic-gate static int ippctl_set_rc(int);
2240Sstevel@tonic-gate static void ippctl_alloc(int);
2250Sstevel@tonic-gate static void ippctl_realloc(void);
2260Sstevel@tonic-gate static void ippctl_free(void);
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate /*
2290Sstevel@tonic-gate * Global data
2300Sstevel@tonic-gate */
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate static dev_info_t *ippctl_dip = NULL;
2330Sstevel@tonic-gate static kmutex_t ippctl_lock;
2340Sstevel@tonic-gate static boolean_t ippctl_busy;
2350Sstevel@tonic-gate static ippctl_buf_t *ippctl_array = NULL;
2360Sstevel@tonic-gate static int ippctl_limit = -1;
2370Sstevel@tonic-gate static int ippctl_rindex = -1;
2380Sstevel@tonic-gate static int ippctl_windex = -1;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate /*
2410Sstevel@tonic-gate * Module linkage functions
2420Sstevel@tonic-gate */
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate #define __FN__ "_init"
2450Sstevel@tonic-gate int
_init(void)2460Sstevel@tonic-gate _init(
2470Sstevel@tonic-gate void)
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate int rc;
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate if ((rc = mod_install(&modlinkage)) != 0) {
2520Sstevel@tonic-gate DBG0(DBG_MODLINK, "mod_install failed\n");
2530Sstevel@tonic-gate return (rc);
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate return (rc);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate #undef __FN__
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate #define __FN__ "_fini"
2610Sstevel@tonic-gate int
_fini(void)2620Sstevel@tonic-gate _fini(
2630Sstevel@tonic-gate void)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate int rc;
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate if ((rc = mod_remove(&modlinkage)) == 0) {
2680Sstevel@tonic-gate return (rc);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate DBG0(DBG_MODLINK, "mod_remove failed\n");
2720Sstevel@tonic-gate return (rc);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate #undef __FN__
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate #define __FN__ "_info"
2770Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2780Sstevel@tonic-gate _info(
2790Sstevel@tonic-gate struct modinfo *modinfop)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate DBG0(DBG_MODLINK, "calling mod_info\n");
2820Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate #undef __FN__
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate /*
2870Sstevel@tonic-gate * Driver interface functions (dev_ops and cb_ops)
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate #define __FN__ "ippctl_info"
2910Sstevel@tonic-gate /*ARGSUSED*/
2920Sstevel@tonic-gate static int
ippctl_info(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)2930Sstevel@tonic-gate ippctl_info(
2940Sstevel@tonic-gate dev_info_t *dip,
2950Sstevel@tonic-gate ddi_info_cmd_t cmd,
2960Sstevel@tonic-gate void *arg,
2970Sstevel@tonic-gate void **result)
2980Sstevel@tonic-gate {
2990Sstevel@tonic-gate int rc = DDI_FAILURE;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate switch (cmd) {
3020Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE:
3030Sstevel@tonic-gate *result = (void *)0; /* Single instance driver */
3040Sstevel@tonic-gate rc = DDI_SUCCESS;
3050Sstevel@tonic-gate break;
3060Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO:
3070Sstevel@tonic-gate *result = (void *)ippctl_dip;
3080Sstevel@tonic-gate rc = DDI_SUCCESS;
3090Sstevel@tonic-gate break;
3100Sstevel@tonic-gate default:
3110Sstevel@tonic-gate break;
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate return (rc);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate #undef __FN__
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate #define __FN__ "ippctl_attach"
3190Sstevel@tonic-gate static int
ippctl_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)3200Sstevel@tonic-gate ippctl_attach(
3210Sstevel@tonic-gate dev_info_t *dip,
3220Sstevel@tonic-gate ddi_attach_cmd_t cmd)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate switch (cmd) {
3250Sstevel@tonic-gate case DDI_ATTACH:
3260Sstevel@tonic-gate break;
3270Sstevel@tonic-gate case DDI_PM_RESUME:
3280Sstevel@tonic-gate /*FALLTHRU*/
3290Sstevel@tonic-gate case DDI_RESUME:
3300Sstevel@tonic-gate /*FALLTHRU*/
3310Sstevel@tonic-gate default:
3320Sstevel@tonic-gate return (DDI_FAILURE);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate DBG0(DBG_DEVOPS, "DDI_ATTACH\n");
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate /*
3380Sstevel@tonic-gate * This is strictly a single instance driver.
3390Sstevel@tonic-gate */
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate if (ippctl_dip != NULL)
3420Sstevel@tonic-gate return (DDI_FAILURE);
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * Create minor node.
3460Sstevel@tonic-gate */
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate if (ddi_create_minor_node(dip, "ctl", S_IFCHR, 0,
3490Sstevel@tonic-gate DDI_PSEUDO, 0) != DDI_SUCCESS)
3500Sstevel@tonic-gate return (DDI_FAILURE);
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /*
3530Sstevel@tonic-gate * No need for per-instance structure, just store vital data in
3540Sstevel@tonic-gate * globals.
3550Sstevel@tonic-gate */
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate ippctl_dip = dip;
3580Sstevel@tonic-gate mutex_init(&ippctl_lock, NULL, MUTEX_DRIVER, NULL);
3590Sstevel@tonic-gate ippctl_busy = B_FALSE;
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate return (DDI_SUCCESS);
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate #undef __FN__
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate #define __FN__ "ippctl_detach"
3660Sstevel@tonic-gate /*ARGSUSED*/
3670Sstevel@tonic-gate static int
ippctl_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3680Sstevel@tonic-gate ippctl_detach(
3690Sstevel@tonic-gate dev_info_t *dip,
3700Sstevel@tonic-gate ddi_detach_cmd_t cmd)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate switch (cmd) {
3730Sstevel@tonic-gate case DDI_DETACH:
3740Sstevel@tonic-gate break;
3750Sstevel@tonic-gate case DDI_PM_SUSPEND:
3760Sstevel@tonic-gate /*FALLTHRU*/
3770Sstevel@tonic-gate case DDI_SUSPEND:
3780Sstevel@tonic-gate /*FALLTHRU*/
3790Sstevel@tonic-gate default:
3800Sstevel@tonic-gate return (DDI_FAILURE);
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate DBG0(DBG_DEVOPS, "DDI_DETACH\n");
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate ASSERT(dip == ippctl_dip);
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
3880Sstevel@tonic-gate mutex_destroy(&ippctl_lock);
3890Sstevel@tonic-gate ippctl_dip = NULL;
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate return (DDI_SUCCESS);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate #undef __FN__
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate #define __FN__ "ippctl_open"
3960Sstevel@tonic-gate /*ARGSUSED*/
3970Sstevel@tonic-gate static int
ippctl_open(dev_t * devp,int flag,int otyp,cred_t * credp)3980Sstevel@tonic-gate ippctl_open(
3990Sstevel@tonic-gate dev_t *devp,
4000Sstevel@tonic-gate int flag,
4010Sstevel@tonic-gate int otyp,
4020Sstevel@tonic-gate cred_t *credp)
4030Sstevel@tonic-gate {
4040Sstevel@tonic-gate minor_t minor = getminor(*devp);
4050Sstevel@tonic-gate #define LIMIT 4
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate DBG0(DBG_CBOPS, "open\n");
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * Only allow privileged users to open our device.
4110Sstevel@tonic-gate */
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate if (secpolicy_net_config(credp, B_FALSE) != 0) {
4140Sstevel@tonic-gate DBG0(DBG_CBOPS, "not privileged user\n");
4150Sstevel@tonic-gate return (EPERM);
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate /*
4190Sstevel@tonic-gate * Sanity check other arguments.
4200Sstevel@tonic-gate */
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate if (minor != 0) {
4230Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad minor\n");
4240Sstevel@tonic-gate return (ENXIO);
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate if (otyp != OTYP_CHR) {
4280Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad device type\n");
4290Sstevel@tonic-gate return (EINVAL);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate /*
4330Sstevel@tonic-gate * This is also a single dev_t driver.
4340Sstevel@tonic-gate */
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate mutex_enter(&ippctl_lock);
4370Sstevel@tonic-gate if (ippctl_busy) {
4380Sstevel@tonic-gate mutex_exit(&ippctl_lock);
4390Sstevel@tonic-gate return (EBUSY);
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate ippctl_busy = B_TRUE;
4420Sstevel@tonic-gate mutex_exit(&ippctl_lock);
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate * Allocate data buffer array (starting with length LIMIT, defined
4460Sstevel@tonic-gate * at the start of this function).
4470Sstevel@tonic-gate */
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate ippctl_alloc(LIMIT);
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate DBG0(DBG_CBOPS, "success\n");
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate return (0);
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate #undef LIMIT
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate #undef __FN__
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate #define __FN__ "ippctl_close"
4600Sstevel@tonic-gate /*ARGSUSED*/
4610Sstevel@tonic-gate static int
ippctl_close(dev_t dev,int flag,int otyp,cred_t * credp)4620Sstevel@tonic-gate ippctl_close(
4630Sstevel@tonic-gate dev_t dev,
4640Sstevel@tonic-gate int flag,
4650Sstevel@tonic-gate int otyp,
4660Sstevel@tonic-gate cred_t *credp)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate minor_t minor = getminor(dev);
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate DBG0(DBG_CBOPS, "close\n");
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate ASSERT(minor == 0);
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate * Free the data buffer array.
4760Sstevel@tonic-gate */
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate ippctl_free();
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate mutex_enter(&ippctl_lock);
4810Sstevel@tonic-gate ippctl_busy = B_FALSE;
4820Sstevel@tonic-gate mutex_exit(&ippctl_lock);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate DBG0(DBG_CBOPS, "success\n");
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate return (0);
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate #undef __FN__
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate #define __FN__ "ippctl_ioctl"
4910Sstevel@tonic-gate static int
ippctl_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)4920Sstevel@tonic-gate ippctl_ioctl(
4930Sstevel@tonic-gate dev_t dev,
4940Sstevel@tonic-gate int cmd,
4950Sstevel@tonic-gate intptr_t arg,
4960Sstevel@tonic-gate int mode,
4970Sstevel@tonic-gate cred_t *credp,
4980Sstevel@tonic-gate int *rvalp)
4990Sstevel@tonic-gate {
5000Sstevel@tonic-gate minor_t minor = getminor(dev);
5010Sstevel@tonic-gate char *cbuf;
5020Sstevel@tonic-gate char *dbuf;
5030Sstevel@tonic-gate size_t cbuflen;
5040Sstevel@tonic-gate size_t dbuflen;
5050Sstevel@tonic-gate size_t nextbuflen;
5060Sstevel@tonic-gate int rc;
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate /*
5090Sstevel@tonic-gate * Paranoia check.
5100Sstevel@tonic-gate */
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate if (secpolicy_net_config(credp, B_FALSE) != 0) {
5130Sstevel@tonic-gate DBG0(DBG_CBOPS, "not privileged user\n");
5140Sstevel@tonic-gate return (EPERM);
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate if (minor != 0) {
5180Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad minor\n");
5190Sstevel@tonic-gate return (ENXIO);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate switch (cmd) {
5230Sstevel@tonic-gate case IPPCTL_CMD:
5240Sstevel@tonic-gate DBG0(DBG_CBOPS, "command\n");
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate /*
5270Sstevel@tonic-gate * Copy in the command buffer from user space.
5280Sstevel@tonic-gate */
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate if ((rc = ippctl_copyin((caddr_t)arg, mode, &cbuf,
5310Sstevel@tonic-gate &cbuflen)) != 0)
5320Sstevel@tonic-gate break;
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate /*
5350Sstevel@tonic-gate * Execute the command.
5360Sstevel@tonic-gate */
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate rc = ippctl_cmd(cbuf, cbuflen, &nextbuflen);
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate /*
5410Sstevel@tonic-gate * Pass back the length of the first data buffer.
5420Sstevel@tonic-gate */
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate DBG1(DBG_CBOPS, "nextbuflen = %lu\n", nextbuflen);
5450Sstevel@tonic-gate *rvalp = nextbuflen;
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * Free the kernel copy of the command buffer.
5490Sstevel@tonic-gate */
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate kmem_free(cbuf, cbuflen);
5520Sstevel@tonic-gate break;
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate case IPPCTL_DATA:
5550Sstevel@tonic-gate DBG0(DBG_CBOPS, "data\n");
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate /*
5580Sstevel@tonic-gate * Grab the next data buffer from the array of pending
5590Sstevel@tonic-gate * buffers.
5600Sstevel@tonic-gate */
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate if ((rc = ippctl_data(&dbuf, &dbuflen, &nextbuflen)) != 0)
5630Sstevel@tonic-gate break;
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate /*
5660Sstevel@tonic-gate * Copy it out to user space.
5670Sstevel@tonic-gate */
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate rc = ippctl_copyout((caddr_t)arg, mode, dbuf, dbuflen);
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate /*
5720Sstevel@tonic-gate * Pass back the length of the next data buffer.
5730Sstevel@tonic-gate */
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate DBG1(DBG_CBOPS, "nextbuflen = %lu\n", nextbuflen);
5760Sstevel@tonic-gate *rvalp = nextbuflen;
5770Sstevel@tonic-gate break;
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate default:
5800Sstevel@tonic-gate DBG0(DBG_CBOPS, "unrecognized ioctl\n");
5810Sstevel@tonic-gate rc = EINVAL;
5820Sstevel@tonic-gate break;
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate DBG1(DBG_CBOPS, "rc = %d\n", rc);
5860Sstevel@tonic-gate return (rc);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate #undef __FN__
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate /*
5910Sstevel@tonic-gate * Local functions
5920Sstevel@tonic-gate */
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate #define __FN__ "ippctl_copyin"
5950Sstevel@tonic-gate static int
ippctl_copyin(caddr_t arg,int mode,char ** kbufp,size_t * kbuflenp)5960Sstevel@tonic-gate ippctl_copyin(
5970Sstevel@tonic-gate caddr_t arg,
5980Sstevel@tonic-gate int mode,
5990Sstevel@tonic-gate char **kbufp,
6000Sstevel@tonic-gate size_t *kbuflenp)
6010Sstevel@tonic-gate {
6020Sstevel@tonic-gate ippctl_ioctl_t iioc;
6030Sstevel@tonic-gate caddr_t ubuf;
6040Sstevel@tonic-gate char *kbuf;
6050Sstevel@tonic-gate size_t ubuflen;
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying in ioctl structure\n");
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate /*
6100Sstevel@tonic-gate * Copy in the ioctl structure from user-space, converting from 32-bit
6110Sstevel@tonic-gate * as necessary.
6120Sstevel@tonic-gate */
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
6150Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) {
6160Sstevel@tonic-gate case DDI_MODEL_ILP32:
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate ippctl_ioctl32_t iioc32;
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate DBG0(DBG_CBOPS, "converting from 32-bit\n");
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc32,
6230Sstevel@tonic-gate sizeof (ippctl_ioctl32_t), mode) != 0)
6240Sstevel@tonic-gate return (EFAULT);
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate ubuf = (caddr_t)(uintptr_t)iioc32.ii32_buf;
6270Sstevel@tonic-gate ubuflen = (size_t)iioc32.ii32_buflen;
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate break;
6300Sstevel@tonic-gate case DDI_MODEL_NONE:
6310Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t),
6320Sstevel@tonic-gate mode) != 0)
6330Sstevel@tonic-gate return (EFAULT);
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate ubuf = iioc.ii_buf;
6360Sstevel@tonic-gate ubuflen = iioc.ii_buflen;
6370Sstevel@tonic-gate break;
6380Sstevel@tonic-gate default:
6390Sstevel@tonic-gate return (EFAULT);
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate #else /* _MULTI_DATAMODEL */
6420Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t),
6430Sstevel@tonic-gate mode) != 0)
6440Sstevel@tonic-gate return (EFAULT);
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate ubuf = iioc.ii_buf;
6470Sstevel@tonic-gate ubuflen = iioc.ii_buflen;
6480Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuf = 0x%p\n", (void *)ubuf);
6510Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuflen = %lu\n", ubuflen);
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate /*
6540Sstevel@tonic-gate * Sanity check the command buffer information.
6550Sstevel@tonic-gate */
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate if (ubuflen == 0 || ubuf == NULL)
6580Sstevel@tonic-gate return (EINVAL);
6590Sstevel@tonic-gate if (ubuflen > MAXUBUFLEN)
6600Sstevel@tonic-gate return (E2BIG);
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate /*
6630Sstevel@tonic-gate * Allocate some memory for the command buffer and copy it in.
6640Sstevel@tonic-gate */
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate kbuf = kmem_zalloc(ubuflen, KM_SLEEP);
6670Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying in nvlist\n");
6680Sstevel@tonic-gate if (ddi_copyin(ubuf, (caddr_t)kbuf, ubuflen, mode) != 0) {
6690Sstevel@tonic-gate kmem_free(kbuf, ubuflen);
6700Sstevel@tonic-gate return (EFAULT);
6710Sstevel@tonic-gate }
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate *kbufp = kbuf;
6740Sstevel@tonic-gate *kbuflenp = ubuflen;
6750Sstevel@tonic-gate return (0);
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate #undef __FN__
6780Sstevel@tonic-gate
6790Sstevel@tonic-gate #define __FN__ "ippctl_copyout"
6800Sstevel@tonic-gate static int
ippctl_copyout(caddr_t arg,int mode,char * kbuf,size_t kbuflen)6810Sstevel@tonic-gate ippctl_copyout(
6820Sstevel@tonic-gate caddr_t arg,
6830Sstevel@tonic-gate int mode,
6840Sstevel@tonic-gate char *kbuf,
6850Sstevel@tonic-gate size_t kbuflen)
6860Sstevel@tonic-gate {
6870Sstevel@tonic-gate ippctl_ioctl_t iioc;
6880Sstevel@tonic-gate caddr_t ubuf;
6890Sstevel@tonic-gate int ubuflen;
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying out ioctl structure\n");
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate /*
6940Sstevel@tonic-gate * Copy in the ioctl structure from user-space, converting from 32-bit
6950Sstevel@tonic-gate * as necessary.
6960Sstevel@tonic-gate */
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
6990Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) {
7000Sstevel@tonic-gate case DDI_MODEL_ILP32:
7010Sstevel@tonic-gate {
7020Sstevel@tonic-gate ippctl_ioctl32_t iioc32;
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc32,
7050Sstevel@tonic-gate sizeof (ippctl_ioctl32_t), mode) != 0)
7060Sstevel@tonic-gate return (EFAULT);
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate ubuf = (caddr_t)(uintptr_t)iioc32.ii32_buf;
7090Sstevel@tonic-gate ubuflen = iioc32.ii32_buflen;
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate break;
7120Sstevel@tonic-gate case DDI_MODEL_NONE:
7130Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t),
7140Sstevel@tonic-gate mode) != 0)
7150Sstevel@tonic-gate return (EFAULT);
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate ubuf = iioc.ii_buf;
7180Sstevel@tonic-gate ubuflen = iioc.ii_buflen;
7190Sstevel@tonic-gate break;
7200Sstevel@tonic-gate default:
7210Sstevel@tonic-gate return (EFAULT);
7220Sstevel@tonic-gate }
7230Sstevel@tonic-gate #else /* _MULTI_DATAMODEL */
7240Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t),
7250Sstevel@tonic-gate mode) != 0)
7260Sstevel@tonic-gate return (EFAULT);
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate ubuf = iioc.ii_buf;
7290Sstevel@tonic-gate ubuflen = iioc.ii_buflen;
7300Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuf = 0x%p\n", (void *)ubuf);
7330Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuflen = %d\n", ubuflen);
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate /*
7360Sstevel@tonic-gate * Sanity check the data buffer details.
7370Sstevel@tonic-gate */
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate if (ubuflen == 0 || ubuf == NULL)
7400Sstevel@tonic-gate return (EINVAL);
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate if (ubuflen < kbuflen)
7430Sstevel@tonic-gate return (ENOSPC);
7440Sstevel@tonic-gate if (ubuflen > MAXUBUFLEN)
7450Sstevel@tonic-gate return (E2BIG);
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate /*
7480Sstevel@tonic-gate * Copy out the data buffer to user space.
7490Sstevel@tonic-gate */
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying out nvlist\n");
7520Sstevel@tonic-gate if (ddi_copyout((caddr_t)kbuf, ubuf, kbuflen, mode) != 0)
7530Sstevel@tonic-gate return (EFAULT);
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate return (0);
7560Sstevel@tonic-gate }
7570Sstevel@tonic-gate #undef __FN__
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate #define __FN__ "ippctl_extract_op"
7600Sstevel@tonic-gate static int
ippctl_extract_op(nvlist_t * nvlp,uint8_t * valp)7610Sstevel@tonic-gate ippctl_extract_op(
7620Sstevel@tonic-gate nvlist_t *nvlp,
7630Sstevel@tonic-gate uint8_t *valp)
7640Sstevel@tonic-gate {
7650Sstevel@tonic-gate int rc;
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate /*
7680Sstevel@tonic-gate * Look-up and remove the opcode passed from libipp from the
7690Sstevel@tonic-gate * nvlist.
7700Sstevel@tonic-gate */
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate if ((rc = nvlist_lookup_byte(nvlp, IPPCTL_OP, valp)) != 0)
7730Sstevel@tonic-gate return (rc);
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_OP);
7760Sstevel@tonic-gate return (0);
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate #undef __FN__
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate #define __FN__ "ippctl_extract_aname"
7810Sstevel@tonic-gate static int
ippctl_extract_aname(nvlist_t * nvlp,char ** valp)7820Sstevel@tonic-gate ippctl_extract_aname(
7830Sstevel@tonic-gate nvlist_t *nvlp,
7840Sstevel@tonic-gate char **valp)
7850Sstevel@tonic-gate {
7860Sstevel@tonic-gate int rc;
7870Sstevel@tonic-gate char *ptr;
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate /*
7900Sstevel@tonic-gate * Look-up and remove the action name passed from libipp from the
7910Sstevel@tonic-gate * nvlist.
7920Sstevel@tonic-gate */
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_ANAME, &ptr)) != 0)
7950Sstevel@tonic-gate return (rc);
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate *valp = kmem_alloc(strlen(ptr) + 1, KM_SLEEP);
7980Sstevel@tonic-gate (void) strcpy(*valp, ptr);
7990Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_ANAME);
8000Sstevel@tonic-gate return (0);
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate #undef __FN__
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate #define __FN__ "ippctl_extract_modname"
8050Sstevel@tonic-gate static int
ippctl_extract_modname(nvlist_t * nvlp,char ** valp)8060Sstevel@tonic-gate ippctl_extract_modname(
8070Sstevel@tonic-gate nvlist_t *nvlp,
8080Sstevel@tonic-gate char **valp)
8090Sstevel@tonic-gate {
8100Sstevel@tonic-gate int rc;
8110Sstevel@tonic-gate char *ptr;
8120Sstevel@tonic-gate
8130Sstevel@tonic-gate /*
8140Sstevel@tonic-gate * Look-up and remove the module name passed from libipp from the
8150Sstevel@tonic-gate * nvlist.
8160Sstevel@tonic-gate */
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_MODNAME, &ptr)) != 0)
8190Sstevel@tonic-gate return (rc);
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate *valp = kmem_alloc(strlen(ptr) + 1, KM_SLEEP);
8220Sstevel@tonic-gate (void) strcpy(*valp, ptr);
8230Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_MODNAME);
8240Sstevel@tonic-gate return (0);
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate #undef __FN__
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate #define __FN__ "ippctl_attach_modname"
8290Sstevel@tonic-gate static int
ippctl_attach_modname(nvlist_t * nvlp,char * modname)8300Sstevel@tonic-gate ippctl_attach_modname(
8310Sstevel@tonic-gate nvlist_t *nvlp,
8320Sstevel@tonic-gate char *modname)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate /*
8350Sstevel@tonic-gate * Add a module name to an nvlist for passing back to user
8360Sstevel@tonic-gate * space.
8370Sstevel@tonic-gate */
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate return (nvlist_add_string(nvlp, IPPCTL_MODNAME, modname));
8400Sstevel@tonic-gate }
8410Sstevel@tonic-gate #undef __FN__
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate #define __FN__ "ippctl_attach_modname_array"
8440Sstevel@tonic-gate static int
ippctl_attach_modname_array(nvlist_t * nvlp,char ** modname_array,int nelt)8450Sstevel@tonic-gate ippctl_attach_modname_array(
8460Sstevel@tonic-gate nvlist_t *nvlp,
8470Sstevel@tonic-gate char **modname_array,
8480Sstevel@tonic-gate int nelt)
8490Sstevel@tonic-gate {
8500Sstevel@tonic-gate /*
8510Sstevel@tonic-gate * Add a module name array to an nvlist for passing back to user
8520Sstevel@tonic-gate * space.
8530Sstevel@tonic-gate */
8540Sstevel@tonic-gate
8550Sstevel@tonic-gate return (nvlist_add_string_array(nvlp, IPPCTL_MODNAME_ARRAY,
8560Sstevel@tonic-gate modname_array, nelt));
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate #undef __FN__
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate #define __FN__ "ippctl_attach_aname_array"
8610Sstevel@tonic-gate static int
ippctl_attach_aname_array(nvlist_t * nvlp,char ** aname_array,int nelt)8620Sstevel@tonic-gate ippctl_attach_aname_array(
8630Sstevel@tonic-gate nvlist_t *nvlp,
8640Sstevel@tonic-gate char **aname_array,
8650Sstevel@tonic-gate int nelt)
8660Sstevel@tonic-gate {
8670Sstevel@tonic-gate /*
8680Sstevel@tonic-gate * Add an action name array to an nvlist for passing back to user
8690Sstevel@tonic-gate * space.
8700Sstevel@tonic-gate */
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate return (nvlist_add_string_array(nvlp, IPPCTL_ANAME_ARRAY,
8730Sstevel@tonic-gate aname_array, nelt));
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate #undef __FN__
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate #define __FN__ "ippctl_extract_flags"
8780Sstevel@tonic-gate static int
ippctl_extract_flags(nvlist_t * nvlp,ipp_flags_t * valp)8790Sstevel@tonic-gate ippctl_extract_flags(
8800Sstevel@tonic-gate nvlist_t *nvlp,
8810Sstevel@tonic-gate ipp_flags_t *valp)
8820Sstevel@tonic-gate {
8830Sstevel@tonic-gate int rc;
8840Sstevel@tonic-gate
8850Sstevel@tonic-gate /*
8860Sstevel@tonic-gate * Look-up and remove the flags passed from libipp from the
8870Sstevel@tonic-gate * nvlist.
8880Sstevel@tonic-gate */
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate if ((rc = nvlist_lookup_uint32(nvlp, IPPCTL_FLAGS,
8910Sstevel@tonic-gate (uint32_t *)valp)) != 0)
8920Sstevel@tonic-gate return (rc);
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_FLAGS);
8950Sstevel@tonic-gate return (0);
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate #undef __FN__
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate #define __FN__ "ippctl_cmd"
9000Sstevel@tonic-gate static int
ippctl_cmd(char * cbuf,size_t cbuflen,size_t * nextbuflenp)9010Sstevel@tonic-gate ippctl_cmd(
9020Sstevel@tonic-gate char *cbuf,
9030Sstevel@tonic-gate size_t cbuflen,
9040Sstevel@tonic-gate size_t *nextbuflenp)
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate nvlist_t *nvlp = NULL;
9070Sstevel@tonic-gate int rc;
9080Sstevel@tonic-gate char *aname = NULL;
9090Sstevel@tonic-gate char *modname = NULL;
9100Sstevel@tonic-gate ipp_flags_t flags;
9110Sstevel@tonic-gate uint8_t op;
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate /*
9140Sstevel@tonic-gate * Start a new command cycle by flushing any previous data buffers.
9150Sstevel@tonic-gate */
9160Sstevel@tonic-gate
9170Sstevel@tonic-gate ippctl_flush();
9180Sstevel@tonic-gate *nextbuflenp = 0;
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate /*
9210Sstevel@tonic-gate * Unpack the nvlist from the command buffer.
9220Sstevel@tonic-gate */
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate if ((rc = nvlist_unpack(cbuf, cbuflen, &nvlp, KM_SLEEP)) != 0)
9250Sstevel@tonic-gate return (rc);
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate /*
9280Sstevel@tonic-gate * Extract the opcode to find out what we should do.
9290Sstevel@tonic-gate */
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate if ((rc = ippctl_extract_op(nvlp, &op)) != 0) {
9320Sstevel@tonic-gate nvlist_free(nvlp);
9330Sstevel@tonic-gate return (rc);
9340Sstevel@tonic-gate }
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate switch (op) {
9370Sstevel@tonic-gate case IPPCTL_OP_ACTION_CREATE:
9380Sstevel@tonic-gate /*
9390Sstevel@tonic-gate * Create a new action.
9400Sstevel@tonic-gate */
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_CREATE\n");
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate /*
9450Sstevel@tonic-gate * Extract the module name, action name and flags from the
9460Sstevel@tonic-gate * nvlist.
9470Sstevel@tonic-gate */
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate if ((rc = ippctl_extract_modname(nvlp, &modname)) != 0) {
9500Sstevel@tonic-gate nvlist_free(nvlp);
9510Sstevel@tonic-gate return (rc);
9520Sstevel@tonic-gate }
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) {
9550Sstevel@tonic-gate FREE_TEXT(modname);
9560Sstevel@tonic-gate nvlist_free(nvlp);
9570Sstevel@tonic-gate return (rc);
9580Sstevel@tonic-gate }
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) {
9610Sstevel@tonic-gate FREE_TEXT(aname);
9620Sstevel@tonic-gate FREE_TEXT(modname);
9630Sstevel@tonic-gate nvlist_free(nvlp);
9640Sstevel@tonic-gate return (rc);
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate rc = ippctl_action_create(modname, aname, nvlp, flags);
9690Sstevel@tonic-gate break;
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate case IPPCTL_OP_ACTION_MODIFY:
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate /*
9740Sstevel@tonic-gate * Modify an existing action.
9750Sstevel@tonic-gate */
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_MODIFY\n");
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate /*
9800Sstevel@tonic-gate * Extract the action name and flags from the nvlist.
9810Sstevel@tonic-gate */
9820Sstevel@tonic-gate
9830Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) {
9840Sstevel@tonic-gate nvlist_free(nvlp);
9850Sstevel@tonic-gate return (rc);
9860Sstevel@tonic-gate }
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) {
9890Sstevel@tonic-gate FREE_TEXT(aname);
9900Sstevel@tonic-gate nvlist_free(nvlp);
9910Sstevel@tonic-gate return (rc);
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate
9940Sstevel@tonic-gate rc = ippctl_action_modify(aname, nvlp, flags);
9950Sstevel@tonic-gate break;
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate case IPPCTL_OP_ACTION_DESTROY:
9980Sstevel@tonic-gate
9990Sstevel@tonic-gate /*
10000Sstevel@tonic-gate * Destroy an action.
10010Sstevel@tonic-gate */
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_DESTROY\n");
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate /*
10060Sstevel@tonic-gate * Extract the action name and flags from the nvlist.
10070Sstevel@tonic-gate */
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) {
10100Sstevel@tonic-gate nvlist_free(nvlp);
10110Sstevel@tonic-gate return (rc);
10120Sstevel@tonic-gate }
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) {
10150Sstevel@tonic-gate FREE_TEXT(aname);
10160Sstevel@tonic-gate nvlist_free(nvlp);
10170Sstevel@tonic-gate return (rc);
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate nvlist_free(nvlp);
10210Sstevel@tonic-gate rc = ippctl_action_destroy(aname, flags);
10220Sstevel@tonic-gate break;
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate case IPPCTL_OP_ACTION_INFO:
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate /*
10270Sstevel@tonic-gate * Retrive the configuration of an action.
10280Sstevel@tonic-gate */
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_INFO\n");
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate /*
10330Sstevel@tonic-gate * Extract the action name and flags from the nvlist.
10340Sstevel@tonic-gate */
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) {
10370Sstevel@tonic-gate nvlist_free(nvlp);
10380Sstevel@tonic-gate return (rc);
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) {
10420Sstevel@tonic-gate nvlist_free(nvlp);
10430Sstevel@tonic-gate FREE_TEXT(aname);
10440Sstevel@tonic-gate return (rc);
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate nvlist_free(nvlp);
10480Sstevel@tonic-gate rc = ippctl_action_info(aname, flags);
10490Sstevel@tonic-gate break;
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate case IPPCTL_OP_ACTION_MOD:
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate /*
10540Sstevel@tonic-gate * Find the module that implements a given action.
10550Sstevel@tonic-gate */
10560Sstevel@tonic-gate
10570Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_MOD\n");
10580Sstevel@tonic-gate
10590Sstevel@tonic-gate /*
10600Sstevel@tonic-gate * Extract the action name from the nvlist.
10610Sstevel@tonic-gate */
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) {
10640Sstevel@tonic-gate nvlist_free(nvlp);
10650Sstevel@tonic-gate return (rc);
10660Sstevel@tonic-gate }
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate nvlist_free(nvlp);
10690Sstevel@tonic-gate rc = ippctl_action_mod(aname);
10700Sstevel@tonic-gate break;
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate case IPPCTL_OP_LIST_MODS:
10730Sstevel@tonic-gate
10740Sstevel@tonic-gate /*
10750Sstevel@tonic-gate * List all the modules.
10760Sstevel@tonic-gate */
10770Sstevel@tonic-gate
10780Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_LIST_MODS\n");
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate nvlist_free(nvlp);
10810Sstevel@tonic-gate rc = ippctl_list_mods();
10820Sstevel@tonic-gate break;
10830Sstevel@tonic-gate
10840Sstevel@tonic-gate case IPPCTL_OP_MOD_LIST_ACTIONS:
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate /*
10870Sstevel@tonic-gate * List all the actions for a given module.
10880Sstevel@tonic-gate */
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_LIST_MODS\n");
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate if ((rc = ippctl_extract_modname(nvlp, &modname)) != 0) {
10930Sstevel@tonic-gate nvlist_free(nvlp);
10940Sstevel@tonic-gate return (rc);
10950Sstevel@tonic-gate }
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate nvlist_free(nvlp);
10980Sstevel@tonic-gate rc = ippctl_mod_list_actions(modname);
10990Sstevel@tonic-gate break;
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate default:
11020Sstevel@tonic-gate
11030Sstevel@tonic-gate /*
11040Sstevel@tonic-gate * Unrecognized opcode.
11050Sstevel@tonic-gate */
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate nvlist_free(nvlp);
11080Sstevel@tonic-gate rc = EINVAL;
11090Sstevel@tonic-gate break;
11100Sstevel@tonic-gate }
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate /*
11130Sstevel@tonic-gate * The length of buffer that we need to notify back to libipp with
11140Sstevel@tonic-gate * the command ioctl's return is the length of the first data buffer
11150Sstevel@tonic-gate * in the array. We only expact to pass back data buffers if the
11160Sstevel@tonic-gate * operation succeeds (NOTE: this does not mean the kernel call has
11170Sstevel@tonic-gate * to succeed, merely that we successfully issued it and processed
11180Sstevel@tonic-gate * the results).
11190Sstevel@tonic-gate */
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate if (rc == 0)
11220Sstevel@tonic-gate *nextbuflenp = ippctl_array[0].buflen;
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate return (rc);
11250Sstevel@tonic-gate }
11260Sstevel@tonic-gate #undef __FN__
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate #define __FN__ "ippctl_action_create"
11290Sstevel@tonic-gate static int
ippctl_action_create(char * modname,char * aname,nvlist_t * nvlp,ipp_flags_t flags)11300Sstevel@tonic-gate ippctl_action_create(
11310Sstevel@tonic-gate char *modname,
11320Sstevel@tonic-gate char *aname,
11330Sstevel@tonic-gate nvlist_t *nvlp,
11340Sstevel@tonic-gate ipp_flags_t flags)
11350Sstevel@tonic-gate {
11360Sstevel@tonic-gate int ipp_rc;
11370Sstevel@tonic-gate int rc;
11380Sstevel@tonic-gate ipp_mod_id_t mid;
11390Sstevel@tonic-gate ipp_action_id_t aid;
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate /*
11420Sstevel@tonic-gate * Look up the module id from the name and create the new
11430Sstevel@tonic-gate * action.
11440Sstevel@tonic-gate */
11450Sstevel@tonic-gate
11460Sstevel@tonic-gate mid = ipp_mod_lookup(modname);
11470Sstevel@tonic-gate FREE_TEXT(modname);
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate ipp_rc = ipp_action_create(mid, aname, &nvlp, flags, &aid);
11500Sstevel@tonic-gate FREE_TEXT(aname);
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate /*
11530Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
11540Sstevel@tonic-gate * set of nvlists to pass back to libipp.
11550Sstevel@tonic-gate */
11560Sstevel@tonic-gate
11570Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) {
11580Sstevel@tonic-gate if (nvlp != NULL) {
11590Sstevel@tonic-gate nvlist_free(nvlp);
11600Sstevel@tonic-gate if (ipp_action_destroy(aid, 0) != 0) {
11610Sstevel@tonic-gate cmn_err(CE_PANIC,
11620Sstevel@tonic-gate "ippctl: unrecoverable error (aid = %d)",
11630Sstevel@tonic-gate aid);
11640Sstevel@tonic-gate /*NOTREACHED*/
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate }
11670Sstevel@tonic-gate return (rc);
11680Sstevel@tonic-gate }
11690Sstevel@tonic-gate
11700Sstevel@tonic-gate /*
11710Sstevel@tonic-gate * If the module passed back an nvlist, add this as
11720Sstevel@tonic-gate * well.
11730Sstevel@tonic-gate */
11740Sstevel@tonic-gate
11750Sstevel@tonic-gate if (nvlp != NULL) {
11760Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL);
11770Sstevel@tonic-gate nvlist_free(nvlp);
11780Sstevel@tonic-gate } else
11790Sstevel@tonic-gate rc = 0;
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate return (rc);
11820Sstevel@tonic-gate }
11830Sstevel@tonic-gate #undef __FN__
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate #define __FN__ "ippctl_action_destroy"
11860Sstevel@tonic-gate static int
ippctl_action_destroy(char * aname,ipp_flags_t flags)11870Sstevel@tonic-gate ippctl_action_destroy(
11880Sstevel@tonic-gate char *aname,
11890Sstevel@tonic-gate ipp_flags_t flags)
11900Sstevel@tonic-gate {
11910Sstevel@tonic-gate ipp_action_id_t aid;
11920Sstevel@tonic-gate int ipp_rc;
11930Sstevel@tonic-gate int rc;
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate /*
11960Sstevel@tonic-gate * Look up the action id and destroy the action.
11970Sstevel@tonic-gate */
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate aid = ipp_action_lookup(aname);
12000Sstevel@tonic-gate FREE_TEXT(aname);
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate ipp_rc = ipp_action_destroy(aid, flags);
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate /*
12050Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
12060Sstevel@tonic-gate * set of nvlists to pass back to libipp.
12070Sstevel@tonic-gate */
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0)
12100Sstevel@tonic-gate return (rc);
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate /*
12130Sstevel@tonic-gate * There's no more information to pass back.
12140Sstevel@tonic-gate */
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate return (0);
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate #undef __FN__
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate #define __FN__ "ippctl_action_modify"
12210Sstevel@tonic-gate static int
ippctl_action_modify(char * aname,nvlist_t * nvlp,ipp_flags_t flags)12220Sstevel@tonic-gate ippctl_action_modify(
12230Sstevel@tonic-gate char *aname,
12240Sstevel@tonic-gate nvlist_t *nvlp,
12250Sstevel@tonic-gate ipp_flags_t flags)
12260Sstevel@tonic-gate {
12270Sstevel@tonic-gate ipp_action_id_t aid;
12280Sstevel@tonic-gate int ipp_rc;
12290Sstevel@tonic-gate int rc;
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate /*
12320Sstevel@tonic-gate * Look up the action id and modify the action.
12330Sstevel@tonic-gate */
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate aid = ipp_action_lookup(aname);
12360Sstevel@tonic-gate FREE_TEXT(aname);
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate ipp_rc = ipp_action_modify(aid, &nvlp, flags);
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate /*
12410Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
12420Sstevel@tonic-gate * set of nvlists to pass back to libipp.
12430Sstevel@tonic-gate */
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) {
12460Sstevel@tonic-gate if (nvlp != NULL)
12470Sstevel@tonic-gate nvlist_free(nvlp);
12480Sstevel@tonic-gate return (rc);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate
12510Sstevel@tonic-gate /*
12520Sstevel@tonic-gate * If the module passed back an nvlist, add this as
12530Sstevel@tonic-gate * well.
12540Sstevel@tonic-gate */
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate if (nvlp != NULL) {
12570Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL);
12580Sstevel@tonic-gate nvlist_free(nvlp);
12590Sstevel@tonic-gate } else
12600Sstevel@tonic-gate rc = 0;
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate return (rc);
12630Sstevel@tonic-gate }
12640Sstevel@tonic-gate #undef __FN__
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate #define __FN__ "ippctl_action_info"
12670Sstevel@tonic-gate static int
ippctl_action_info(char * aname,ipp_flags_t flags)12680Sstevel@tonic-gate ippctl_action_info(
12690Sstevel@tonic-gate char *aname,
12700Sstevel@tonic-gate ipp_flags_t flags)
12710Sstevel@tonic-gate {
12720Sstevel@tonic-gate ipp_action_id_t aid;
12730Sstevel@tonic-gate int ipp_rc;
12740Sstevel@tonic-gate int rc;
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate /*
12770Sstevel@tonic-gate * Look up the action and call the information retrieval
12780Sstevel@tonic-gate * entry point.
12790Sstevel@tonic-gate *
12800Sstevel@tonic-gate * NOTE: The callback function that is passed in packs and
12810Sstevel@tonic-gate * stores each of the nvlists it is called with in the array
12820Sstevel@tonic-gate * that will be passed back to libipp.
12830Sstevel@tonic-gate */
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate aid = ipp_action_lookup(aname);
12860Sstevel@tonic-gate FREE_TEXT(aname);
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate ipp_rc = ipp_action_info(aid, ippctl_callback, NULL, flags);
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate /*
12910Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
12920Sstevel@tonic-gate * set of nvlists to pass back to libipp.
12930Sstevel@tonic-gate */
12940Sstevel@tonic-gate
12950Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0)
12960Sstevel@tonic-gate return (rc);
12970Sstevel@tonic-gate
12980Sstevel@tonic-gate /*
12990Sstevel@tonic-gate * There's no more information to pass back.
13000Sstevel@tonic-gate */
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate return (0);
13030Sstevel@tonic-gate }
13040Sstevel@tonic-gate #undef __FN__
13050Sstevel@tonic-gate
13060Sstevel@tonic-gate #define __FN__ "ippctl_action_mod"
13070Sstevel@tonic-gate static int
ippctl_action_mod(char * aname)13080Sstevel@tonic-gate ippctl_action_mod(
13090Sstevel@tonic-gate char *aname)
13100Sstevel@tonic-gate {
13110Sstevel@tonic-gate ipp_mod_id_t mid;
13120Sstevel@tonic-gate ipp_action_id_t aid;
13130Sstevel@tonic-gate char *modname;
13140Sstevel@tonic-gate nvlist_t *nvlp;
13150Sstevel@tonic-gate int ipp_rc;
13160Sstevel@tonic-gate int rc;
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate /*
13190Sstevel@tonic-gate * Look up the action id and get the id of the module that
13200Sstevel@tonic-gate * implements the action. If that succeeds then look up the
13210Sstevel@tonic-gate * name of the module.
13220Sstevel@tonic-gate */
13230Sstevel@tonic-gate
13240Sstevel@tonic-gate aid = ipp_action_lookup(aname);
13250Sstevel@tonic-gate FREE_TEXT(aname);
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate if ((ipp_rc = ipp_action_mod(aid, &mid)) == 0)
13280Sstevel@tonic-gate ipp_rc = ipp_mod_name(mid, &modname);
13290Sstevel@tonic-gate
13300Sstevel@tonic-gate /*
13310Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
13320Sstevel@tonic-gate * set of nvlists to pass back to libipp.
13330Sstevel@tonic-gate */
13340Sstevel@tonic-gate
13350Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0)
13360Sstevel@tonic-gate return (rc);
13370Sstevel@tonic-gate
13380Sstevel@tonic-gate /*
13390Sstevel@tonic-gate * If everything succeeded add an nvlist containing the
13400Sstevel@tonic-gate * module name to the set of nvlists to pass back to libipp.
13410Sstevel@tonic-gate */
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate if (ipp_rc == 0) {
13440Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_SLEEP)) != 0)
13450Sstevel@tonic-gate return (rc);
13460Sstevel@tonic-gate
13470Sstevel@tonic-gate if ((rc = ippctl_attach_modname(nvlp, modname)) != 0) {
13480Sstevel@tonic-gate nvlist_free(nvlp);
13490Sstevel@tonic-gate return (rc);
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate FREE_TEXT(modname);
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL);
13550Sstevel@tonic-gate nvlist_free(nvlp);
13560Sstevel@tonic-gate } else
13570Sstevel@tonic-gate rc = 0;
13580Sstevel@tonic-gate
13590Sstevel@tonic-gate return (rc);
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate #undef __FN__
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate #define __FN__ "ippctl_list_mods"
13640Sstevel@tonic-gate static int
ippctl_list_mods(void)13650Sstevel@tonic-gate ippctl_list_mods(
13660Sstevel@tonic-gate void)
13670Sstevel@tonic-gate {
13680Sstevel@tonic-gate nvlist_t *nvlp;
13690Sstevel@tonic-gate int ipp_rc;
13700Sstevel@tonic-gate int rc = 0;
13710Sstevel@tonic-gate ipp_mod_id_t *mid_array;
13720Sstevel@tonic-gate char **modname_array = NULL;
13730Sstevel@tonic-gate int nelt;
13740Sstevel@tonic-gate int length;
13750Sstevel@tonic-gate int i;
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate /*
13780Sstevel@tonic-gate * Get a list of all the module ids. If that succeeds,
13790Sstevel@tonic-gate * translate the ids into names.
13800Sstevel@tonic-gate *
13810Sstevel@tonic-gate * NOTE: This translation may fail if a module is
13820Sstevel@tonic-gate * unloaded during this operation. If this occurs, EAGAIN
13830Sstevel@tonic-gate * will be passed back to libipp note that a transient
13840Sstevel@tonic-gate * problem occured.
13850Sstevel@tonic-gate */
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate if ((ipp_rc = ipp_list_mods(&mid_array, &nelt)) == 0) {
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate /*
13900Sstevel@tonic-gate * It is possible that there are no modules
13910Sstevel@tonic-gate * registered.
13920Sstevel@tonic-gate */
13930Sstevel@tonic-gate
13940Sstevel@tonic-gate if (nelt > 0) {
13950Sstevel@tonic-gate length = nelt * sizeof (char *);
13960Sstevel@tonic-gate modname_array = kmem_zalloc(length, KM_SLEEP);
13970Sstevel@tonic-gate
13980Sstevel@tonic-gate for (i = 0; i < nelt; i++) {
13990Sstevel@tonic-gate if (ipp_mod_name(mid_array[i],
14000Sstevel@tonic-gate &modname_array[i]) != 0) {
14010Sstevel@tonic-gate kmem_free(mid_array, nelt *
14020Sstevel@tonic-gate sizeof (ipp_mod_id_t));
14030Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt);
14040Sstevel@tonic-gate ipp_rc = EAGAIN;
14050Sstevel@tonic-gate goto done;
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate }
14080Sstevel@tonic-gate
14090Sstevel@tonic-gate kmem_free(mid_array, nelt * sizeof (ipp_mod_id_t));
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME,
14120Sstevel@tonic-gate KM_SLEEP)) != 0) {
14130Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt);
14140Sstevel@tonic-gate return (rc);
14150Sstevel@tonic-gate }
14160Sstevel@tonic-gate
14170Sstevel@tonic-gate if ((rc = ippctl_attach_modname_array(nvlp,
14180Sstevel@tonic-gate modname_array, nelt)) != 0) {
14190Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt);
14200Sstevel@tonic-gate nvlist_free(nvlp);
14210Sstevel@tonic-gate return (rc);
14220Sstevel@tonic-gate }
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt);
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate if ((rc = ippctl_callback(nvlp, NULL)) != 0) {
14270Sstevel@tonic-gate nvlist_free(nvlp);
14280Sstevel@tonic-gate return (rc);
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate nvlist_free(nvlp);
14320Sstevel@tonic-gate }
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate done:
14360Sstevel@tonic-gate /*
14370Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
14380Sstevel@tonic-gate * set of nvlists to pass back to libipp.
14390Sstevel@tonic-gate */
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0)
14420Sstevel@tonic-gate return (rc);
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate return (0);
14450Sstevel@tonic-gate }
14460Sstevel@tonic-gate #undef __FN__
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate #define __FN__ "ippctl_mod_list_actions"
14490Sstevel@tonic-gate static int
ippctl_mod_list_actions(char * modname)14500Sstevel@tonic-gate ippctl_mod_list_actions(
14510Sstevel@tonic-gate char *modname)
14520Sstevel@tonic-gate {
14530Sstevel@tonic-gate ipp_mod_id_t mid;
14540Sstevel@tonic-gate nvlist_t *nvlp;
14550Sstevel@tonic-gate int ipp_rc;
14560Sstevel@tonic-gate int rc = 0;
14570Sstevel@tonic-gate ipp_action_id_t *aid_array;
14580Sstevel@tonic-gate char **aname_array = NULL;
14590Sstevel@tonic-gate int nelt;
14600Sstevel@tonic-gate int length;
14610Sstevel@tonic-gate int i;
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate /*
14640Sstevel@tonic-gate * Get the module id.
14650Sstevel@tonic-gate */
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate mid = ipp_mod_lookup(modname);
14680Sstevel@tonic-gate FREE_TEXT(modname);
14690Sstevel@tonic-gate
14700Sstevel@tonic-gate /*
14710Sstevel@tonic-gate * Get a list of all the action ids for the module. If that succeeds,
14720Sstevel@tonic-gate * translate the ids into names.
14730Sstevel@tonic-gate *
14740Sstevel@tonic-gate * NOTE: This translation may fail if an action is
14750Sstevel@tonic-gate * destroyed during this operation. If this occurs, EAGAIN
14760Sstevel@tonic-gate * will be passed back to libipp note that a transient
14770Sstevel@tonic-gate * problem occured.
14780Sstevel@tonic-gate */
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate if ((ipp_rc = ipp_mod_list_actions(mid, &aid_array, &nelt)) == 0) {
14810Sstevel@tonic-gate
14820Sstevel@tonic-gate /*
14830Sstevel@tonic-gate * It is possible that there are no actions defined.
14840Sstevel@tonic-gate * (This is unlikely though as the module would normally
14850Sstevel@tonic-gate * be auto-unloaded fairly quickly)
14860Sstevel@tonic-gate */
14870Sstevel@tonic-gate
14880Sstevel@tonic-gate if (nelt > 0) {
14890Sstevel@tonic-gate length = nelt * sizeof (char *);
14900Sstevel@tonic-gate aname_array = kmem_zalloc(length, KM_SLEEP);
14910Sstevel@tonic-gate
14920Sstevel@tonic-gate for (i = 0; i < nelt; i++) {
14930Sstevel@tonic-gate if (ipp_action_name(aid_array[i],
14940Sstevel@tonic-gate &aname_array[i]) != 0) {
14950Sstevel@tonic-gate kmem_free(aid_array, nelt *
14960Sstevel@tonic-gate sizeof (ipp_action_id_t));
14970Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt);
14980Sstevel@tonic-gate ipp_rc = EAGAIN;
14990Sstevel@tonic-gate goto done;
15000Sstevel@tonic-gate }
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate
15030Sstevel@tonic-gate kmem_free(aid_array, nelt * sizeof (ipp_action_id_t));
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME,
15060Sstevel@tonic-gate KM_SLEEP)) != 0) {
15070Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt);
15080Sstevel@tonic-gate return (rc);
15090Sstevel@tonic-gate }
15100Sstevel@tonic-gate
15110Sstevel@tonic-gate if ((rc = ippctl_attach_aname_array(nvlp, aname_array,
15120Sstevel@tonic-gate nelt)) != 0) {
15130Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt);
15140Sstevel@tonic-gate nvlist_free(nvlp);
15150Sstevel@tonic-gate return (rc);
15160Sstevel@tonic-gate }
15170Sstevel@tonic-gate
15180Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt);
15190Sstevel@tonic-gate
15200Sstevel@tonic-gate if ((rc = ippctl_callback(nvlp, NULL)) != 0) {
15210Sstevel@tonic-gate nvlist_free(nvlp);
15220Sstevel@tonic-gate return (rc);
15230Sstevel@tonic-gate }
15240Sstevel@tonic-gate
15250Sstevel@tonic-gate nvlist_free(nvlp);
15260Sstevel@tonic-gate }
15270Sstevel@tonic-gate }
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate done:
15300Sstevel@tonic-gate /*
15310Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the
15320Sstevel@tonic-gate * set of nvlists to pass back to libipp.
15330Sstevel@tonic-gate */
15340Sstevel@tonic-gate
15350Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0)
15360Sstevel@tonic-gate return (rc);
15370Sstevel@tonic-gate
15380Sstevel@tonic-gate return (0);
15390Sstevel@tonic-gate }
15400Sstevel@tonic-gate #undef __FN__
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate #define __FN__ "ippctl_data"
15430Sstevel@tonic-gate static int
ippctl_data(char ** dbufp,size_t * dbuflenp,size_t * nextbuflenp)15440Sstevel@tonic-gate ippctl_data(
15450Sstevel@tonic-gate char **dbufp,
15460Sstevel@tonic-gate size_t *dbuflenp,
15470Sstevel@tonic-gate size_t *nextbuflenp)
15480Sstevel@tonic-gate {
15490Sstevel@tonic-gate int i;
15500Sstevel@tonic-gate
15510Sstevel@tonic-gate DBG0(DBG_CBOPS, "called\n");
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate /*
15540Sstevel@tonic-gate * Get the next data buffer from the array by looking at the
15550Sstevel@tonic-gate * 'read index'. If this is the same as the 'write index' then
15560Sstevel@tonic-gate * there's no more buffers in the array.
15570Sstevel@tonic-gate */
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate i = ippctl_rindex;
15600Sstevel@tonic-gate if (i == ippctl_windex)
15610Sstevel@tonic-gate return (ENOENT);
15620Sstevel@tonic-gate
15630Sstevel@tonic-gate /*
15640Sstevel@tonic-gate * Extract the buffer details. It is a pre-packed nvlist.
15650Sstevel@tonic-gate */
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate *dbufp = ippctl_array[i].buf;
15680Sstevel@tonic-gate *dbuflenp = ippctl_array[i].buflen;
15690Sstevel@tonic-gate
15700Sstevel@tonic-gate DBG2(DBG_CBOPS, "accessing nvlist[%d], length %lu\n", i, *dbuflenp);
15710Sstevel@tonic-gate ASSERT(*dbufp != NULL);
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate /*
15740Sstevel@tonic-gate * Advance the 'read index' and check if there's another buffer.
15750Sstevel@tonic-gate * If there is then we need to pass back its length to libipp so that
15760Sstevel@tonic-gate * another data ioctl will be issued.
15770Sstevel@tonic-gate */
15780Sstevel@tonic-gate
15790Sstevel@tonic-gate i++;
15800Sstevel@tonic-gate if (i < ippctl_windex)
15810Sstevel@tonic-gate *nextbuflenp = ippctl_array[i].buflen;
15820Sstevel@tonic-gate else
15830Sstevel@tonic-gate *nextbuflenp = 0;
15840Sstevel@tonic-gate
15850Sstevel@tonic-gate ippctl_rindex = i;
15860Sstevel@tonic-gate return (0);
15870Sstevel@tonic-gate }
15880Sstevel@tonic-gate #undef __FN__
15890Sstevel@tonic-gate
15900Sstevel@tonic-gate #define __FN__ "ippctl_flush"
15910Sstevel@tonic-gate static void
ippctl_flush(void)15920Sstevel@tonic-gate ippctl_flush(
15930Sstevel@tonic-gate void)
15940Sstevel@tonic-gate {
15950Sstevel@tonic-gate int i;
15960Sstevel@tonic-gate char *buf;
15970Sstevel@tonic-gate size_t buflen;
15980Sstevel@tonic-gate
15990Sstevel@tonic-gate /*
16000Sstevel@tonic-gate * Free any buffers left in the array.
16010Sstevel@tonic-gate */
16020Sstevel@tonic-gate
16030Sstevel@tonic-gate for (i = 0; i < ippctl_limit; i++) {
16040Sstevel@tonic-gate if ((buflen = ippctl_array[i].buflen) > 0) {
16050Sstevel@tonic-gate buf = ippctl_array[i].buf;
16060Sstevel@tonic-gate ASSERT(buf != NULL);
16070Sstevel@tonic-gate kmem_free(buf, buflen);
16080Sstevel@tonic-gate }
16090Sstevel@tonic-gate }
16100Sstevel@tonic-gate
16110Sstevel@tonic-gate /*
16120Sstevel@tonic-gate * NULL all the entries.
16130Sstevel@tonic-gate */
16140Sstevel@tonic-gate
16150Sstevel@tonic-gate bzero(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t));
16160Sstevel@tonic-gate
16170Sstevel@tonic-gate /*
16180Sstevel@tonic-gate * Reset the indexes.
16190Sstevel@tonic-gate */
16200Sstevel@tonic-gate
16210Sstevel@tonic-gate ippctl_rindex = 0;
16220Sstevel@tonic-gate ippctl_windex = 1;
16230Sstevel@tonic-gate }
16240Sstevel@tonic-gate #undef __FN__
16250Sstevel@tonic-gate
16260Sstevel@tonic-gate #define __FN__ "ippctl_add_nvlist"
16270Sstevel@tonic-gate static int
ippctl_add_nvlist(nvlist_t * nvlp,int i)16280Sstevel@tonic-gate ippctl_add_nvlist(
16290Sstevel@tonic-gate nvlist_t *nvlp,
16300Sstevel@tonic-gate int i)
16310Sstevel@tonic-gate {
16320Sstevel@tonic-gate char *buf;
16330Sstevel@tonic-gate size_t buflen;
16340Sstevel@tonic-gate int rc;
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate /*
16370Sstevel@tonic-gate * NULL the buffer pointer so that a buffer is automatically
16380Sstevel@tonic-gate * allocated for us.
16390Sstevel@tonic-gate */
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate buf = NULL;
16420Sstevel@tonic-gate
16430Sstevel@tonic-gate /*
16440Sstevel@tonic-gate * Pack the nvlist and get back the buffer pointer and length.
16450Sstevel@tonic-gate */
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate if ((rc = nvlist_pack(nvlp, &buf, &buflen, NV_ENCODE_NATIVE,
16480Sstevel@tonic-gate KM_SLEEP)) != 0) {
16490Sstevel@tonic-gate ippctl_array[i].buf = NULL;
16500Sstevel@tonic-gate ippctl_array[i].buflen = 0;
16510Sstevel@tonic-gate return (rc);
16520Sstevel@tonic-gate }
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate DBG2(DBG_CBOPS, "added nvlist[%d]: length %lu\n", i, buflen);
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate /*
16570Sstevel@tonic-gate * Store the pointer an length in the array at the given index.
16580Sstevel@tonic-gate */
16590Sstevel@tonic-gate
16600Sstevel@tonic-gate ippctl_array[i].buf = buf;
16610Sstevel@tonic-gate ippctl_array[i].buflen = buflen;
16620Sstevel@tonic-gate
16630Sstevel@tonic-gate return (0);
16640Sstevel@tonic-gate }
16650Sstevel@tonic-gate #undef __FN__
16660Sstevel@tonic-gate
16670Sstevel@tonic-gate #define __FN__ "ippctl_callback"
16680Sstevel@tonic-gate /*ARGSUSED*/
16690Sstevel@tonic-gate static int
ippctl_callback(nvlist_t * nvlp,void * arg)16700Sstevel@tonic-gate ippctl_callback(
16710Sstevel@tonic-gate nvlist_t *nvlp,
16720Sstevel@tonic-gate void *arg)
16730Sstevel@tonic-gate {
16740Sstevel@tonic-gate int i;
16750Sstevel@tonic-gate int rc;
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate /*
16780Sstevel@tonic-gate * Check the 'write index' to see if there's space in the array for
16790Sstevel@tonic-gate * a new entry.
16800Sstevel@tonic-gate */
16810Sstevel@tonic-gate
16820Sstevel@tonic-gate i = ippctl_windex;
16830Sstevel@tonic-gate ASSERT(i != 0);
16840Sstevel@tonic-gate
16850Sstevel@tonic-gate /*
16860Sstevel@tonic-gate * If there's no space, re-allocate the array (see comments in
16870Sstevel@tonic-gate * ippctl_realloc() for details).
16880Sstevel@tonic-gate */
16890Sstevel@tonic-gate
16900Sstevel@tonic-gate if (i == ippctl_limit)
16910Sstevel@tonic-gate ippctl_realloc();
16920Sstevel@tonic-gate
16930Sstevel@tonic-gate /*
16940Sstevel@tonic-gate * Add the nvlist to the array.
16950Sstevel@tonic-gate */
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate if ((rc = ippctl_add_nvlist(nvlp, i)) == 0)
16980Sstevel@tonic-gate ippctl_windex++;
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate return (rc);
17010Sstevel@tonic-gate }
17020Sstevel@tonic-gate #undef __FN__
17030Sstevel@tonic-gate
17040Sstevel@tonic-gate #define __FN__ "ippctl_set_rc"
17050Sstevel@tonic-gate static int
ippctl_set_rc(int val)17060Sstevel@tonic-gate ippctl_set_rc(
17070Sstevel@tonic-gate int val)
17080Sstevel@tonic-gate {
17090Sstevel@tonic-gate nvlist_t *nvlp;
17100Sstevel@tonic-gate int rc;
17110Sstevel@tonic-gate
17120Sstevel@tonic-gate /*
17130Sstevel@tonic-gate * Create an nvlist to store the return code,
17140Sstevel@tonic-gate */
17150Sstevel@tonic-gate
17160Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_SLEEP)) != 0)
17170Sstevel@tonic-gate return (ENOMEM);
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate if ((rc = nvlist_add_int32(nvlp, IPPCTL_RC, val)) != 0) {
17200Sstevel@tonic-gate nvlist_free(nvlp);
17210Sstevel@tonic-gate return (rc);
17220Sstevel@tonic-gate }
17230Sstevel@tonic-gate
17240Sstevel@tonic-gate /*
17250Sstevel@tonic-gate * Add it at the beginning of the array.
17260Sstevel@tonic-gate */
17270Sstevel@tonic-gate
17280Sstevel@tonic-gate rc = ippctl_add_nvlist(nvlp, 0);
17290Sstevel@tonic-gate
17300Sstevel@tonic-gate nvlist_free(nvlp);
17310Sstevel@tonic-gate return (rc);
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate #undef __FN__
17340Sstevel@tonic-gate
17350Sstevel@tonic-gate #define __FN__ "ippctl_alloc"
17360Sstevel@tonic-gate static void
ippctl_alloc(int limit)17370Sstevel@tonic-gate ippctl_alloc(
17380Sstevel@tonic-gate int limit)
17390Sstevel@tonic-gate {
17400Sstevel@tonic-gate /*
17410Sstevel@tonic-gate * Allocate the data buffer array and initialize the indexes.
17420Sstevel@tonic-gate */
17430Sstevel@tonic-gate
17440Sstevel@tonic-gate ippctl_array = kmem_zalloc(limit * sizeof (ippctl_buf_t), KM_SLEEP);
17450Sstevel@tonic-gate ippctl_limit = limit;
17460Sstevel@tonic-gate ippctl_rindex = 0;
17470Sstevel@tonic-gate ippctl_windex = 1;
17480Sstevel@tonic-gate }
17490Sstevel@tonic-gate #undef __FN__
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate #define __FN__ "ippctl_realloc"
17520Sstevel@tonic-gate static void
ippctl_realloc(void)17530Sstevel@tonic-gate ippctl_realloc(
17540Sstevel@tonic-gate void)
17550Sstevel@tonic-gate {
17560Sstevel@tonic-gate ippctl_buf_t *array;
17570Sstevel@tonic-gate int limit;
17580Sstevel@tonic-gate int i;
17590Sstevel@tonic-gate
17600Sstevel@tonic-gate /*
17610Sstevel@tonic-gate * Allocate a new array twice the size of the old one.
17620Sstevel@tonic-gate */
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate limit = ippctl_limit << 1;
17650Sstevel@tonic-gate array = kmem_zalloc(limit * sizeof (ippctl_buf_t), KM_SLEEP);
17660Sstevel@tonic-gate
17670Sstevel@tonic-gate /*
17680Sstevel@tonic-gate * Copy across the information from the old array into the new one.
17690Sstevel@tonic-gate */
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate for (i = 0; i < ippctl_limit; i++)
17720Sstevel@tonic-gate array[i] = ippctl_array[i];
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate /*
17750Sstevel@tonic-gate * Free the old array.
17760Sstevel@tonic-gate */
17770Sstevel@tonic-gate
17780Sstevel@tonic-gate kmem_free(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t));
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate ippctl_array = array;
17810Sstevel@tonic-gate ippctl_limit = limit;
17820Sstevel@tonic-gate }
17830Sstevel@tonic-gate #undef __FN__
17840Sstevel@tonic-gate
17850Sstevel@tonic-gate #define __FN__ "ippctl_free"
17860Sstevel@tonic-gate static void
ippctl_free(void)17870Sstevel@tonic-gate ippctl_free(
17880Sstevel@tonic-gate void)
17890Sstevel@tonic-gate {
17900Sstevel@tonic-gate /*
17910Sstevel@tonic-gate * Flush the array prior to freeing it to make sure no buffers are
17920Sstevel@tonic-gate * leaked.
17930Sstevel@tonic-gate */
17940Sstevel@tonic-gate
17950Sstevel@tonic-gate ippctl_flush();
17960Sstevel@tonic-gate
17970Sstevel@tonic-gate /*
17980Sstevel@tonic-gate * Free the array.
17990Sstevel@tonic-gate */
18000Sstevel@tonic-gate
18010Sstevel@tonic-gate kmem_free(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t));
18020Sstevel@tonic-gate ippctl_array = NULL;
18030Sstevel@tonic-gate ippctl_limit = -1;
18040Sstevel@tonic-gate ippctl_rindex = -1;
18050Sstevel@tonic-gate ippctl_windex = -1;
18060Sstevel@tonic-gate }
18070Sstevel@tonic-gate #undef __FN__
18080Sstevel@tonic-gate
18090Sstevel@tonic-gate #ifdef IPPCTL_DEBUG
18100Sstevel@tonic-gate static void
ippctl_debug(uint64_t type,char * fn,char * fmt,...)18110Sstevel@tonic-gate ippctl_debug(
18120Sstevel@tonic-gate uint64_t type,
18130Sstevel@tonic-gate char *fn,
18140Sstevel@tonic-gate char *fmt,
18150Sstevel@tonic-gate ...)
18160Sstevel@tonic-gate {
18170Sstevel@tonic-gate char buf[255];
18180Sstevel@tonic-gate va_list adx;
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate if ((type & ippctl_debug_flags) == 0)
18210Sstevel@tonic-gate return;
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate mutex_enter(debug_mutex);
18240Sstevel@tonic-gate va_start(adx, fmt);
18250Sstevel@tonic-gate (void) vsnprintf(buf, 255, fmt, adx);
18260Sstevel@tonic-gate va_end(adx);
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate printf("%s: %s", fn, buf);
18290Sstevel@tonic-gate mutex_exit(debug_mutex);
18300Sstevel@tonic-gate }
18310Sstevel@tonic-gate #endif /* IPPCTL_DBG */
1832