1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * IP Policy Framework config driver 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/open.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 45*7c478bd9Sstevel@tonic-gate #include <ipp/ipp.h> 46*7c478bd9Sstevel@tonic-gate #include <ipp/ippctl.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/nvpair.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * Debug switch. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) 55*7c478bd9Sstevel@tonic-gate #define IPPCTL_DEBUG 56*7c478bd9Sstevel@tonic-gate #endif 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * Debug macros. 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #ifdef IPPCTL_DEBUG 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #define DBG_MODLINK 0x00000001ull 65*7c478bd9Sstevel@tonic-gate #define DBG_DEVOPS 0x00000002ull 66*7c478bd9Sstevel@tonic-gate #define DBG_CBOPS 0x00000004ull 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate static uint64_t ippctl_debug_flags = 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * DBG_MODLINK | 71*7c478bd9Sstevel@tonic-gate * DBG_DEVOPS | 72*7c478bd9Sstevel@tonic-gate * DBG_CBOPS | 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate 0; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate static kmutex_t debug_mutex[1]; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 79*7c478bd9Sstevel@tonic-gate static void ippctl_debug(uint64_t, char *, char *, ...) 80*7c478bd9Sstevel@tonic-gate __PRINTFLIKE(3); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate #define DBG0(_type, _fmt) \ 83*7c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt)); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1) \ 86*7c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1)); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2) \ 89*7c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2)); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3) \ 92*7c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 93*7c478bd9Sstevel@tonic-gate (_a3)); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \ 96*7c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 97*7c478bd9Sstevel@tonic-gate (_a3), (_a4)); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \ 100*7c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 101*7c478bd9Sstevel@tonic-gate (_a3), (_a4), (_a5)); 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate #else /* IPPCTL_DBG */ 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate #define DBG0(_type, _fmt) 106*7c478bd9Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1) 107*7c478bd9Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2) 108*7c478bd9Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3) 109*7c478bd9Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) 110*7c478bd9Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate #endif /* IPPCTL_DBG */ 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * cb_ops 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate static int ippctl_open(dev_t *, int, int, cred_t *); 119*7c478bd9Sstevel@tonic-gate static int ippctl_close(dev_t, int, int, cred_t *); 120*7c478bd9Sstevel@tonic-gate static int ippctl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate static struct cb_ops ippctl_cb_ops = { 123*7c478bd9Sstevel@tonic-gate ippctl_open, /* cb_open */ 124*7c478bd9Sstevel@tonic-gate ippctl_close, /* cb_close */ 125*7c478bd9Sstevel@tonic-gate nodev, /* cb_strategy */ 126*7c478bd9Sstevel@tonic-gate nodev, /* cb_print */ 127*7c478bd9Sstevel@tonic-gate nodev, /* cb_dump */ 128*7c478bd9Sstevel@tonic-gate nodev, /* cb_read */ 129*7c478bd9Sstevel@tonic-gate nodev, /* cb_write */ 130*7c478bd9Sstevel@tonic-gate ippctl_ioctl, /* cb_ioctl */ 131*7c478bd9Sstevel@tonic-gate nodev, /* cb_devmap */ 132*7c478bd9Sstevel@tonic-gate nodev, /* cb_mmap */ 133*7c478bd9Sstevel@tonic-gate nodev, /* cb_segmap */ 134*7c478bd9Sstevel@tonic-gate nochpoll, /* cb_chpoll */ 135*7c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 136*7c478bd9Sstevel@tonic-gate 0, /* cb_str */ 137*7c478bd9Sstevel@tonic-gate D_NEW | D_MP, /* cb_flag */ 138*7c478bd9Sstevel@tonic-gate CB_REV, /* cb_rev */ 139*7c478bd9Sstevel@tonic-gate nodev, /* cb_aread */ 140*7c478bd9Sstevel@tonic-gate nodev /* cb_awrite */ 141*7c478bd9Sstevel@tonic-gate }; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * dev_ops 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate static int ippctl_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 148*7c478bd9Sstevel@tonic-gate static int ippctl_attach(dev_info_t *, ddi_attach_cmd_t); 149*7c478bd9Sstevel@tonic-gate static int ippctl_detach(dev_info_t *, ddi_detach_cmd_t); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate static struct dev_ops ippctl_dev_ops = { 152*7c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 153*7c478bd9Sstevel@tonic-gate 0, /* devo_refcnt */ 154*7c478bd9Sstevel@tonic-gate ippctl_info, /* devo_getinfo */ 155*7c478bd9Sstevel@tonic-gate nulldev, /* devo_identify */ 156*7c478bd9Sstevel@tonic-gate nulldev, /* devo_probe */ 157*7c478bd9Sstevel@tonic-gate ippctl_attach, /* devo_attach */ 158*7c478bd9Sstevel@tonic-gate ippctl_detach, /* devo_detach */ 159*7c478bd9Sstevel@tonic-gate nodev, /* devo_reset */ 160*7c478bd9Sstevel@tonic-gate &ippctl_cb_ops, /* devo_cb_ops */ 161*7c478bd9Sstevel@tonic-gate (struct bus_ops *)0 /* devo_bus_ops */ 162*7c478bd9Sstevel@tonic-gate }; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 165*7c478bd9Sstevel@tonic-gate &mod_driverops, 166*7c478bd9Sstevel@tonic-gate "IP Policy Configuration Driver v%I%", 167*7c478bd9Sstevel@tonic-gate &ippctl_dev_ops, 168*7c478bd9Sstevel@tonic-gate }; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 171*7c478bd9Sstevel@tonic-gate MODREV_1, 172*7c478bd9Sstevel@tonic-gate &modldrv, 173*7c478bd9Sstevel@tonic-gate NULL 174*7c478bd9Sstevel@tonic-gate }; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Local definitions, types and prototypes. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate #define MAXUBUFLEN (1 << 16) 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate #define FREE_TEXT(_string) \ 183*7c478bd9Sstevel@tonic-gate kmem_free((_string), strlen(_string) + 1) 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate #define FREE_TEXT_ARRAY(_array, _nelt) \ 186*7c478bd9Sstevel@tonic-gate { \ 187*7c478bd9Sstevel@tonic-gate int j; \ 188*7c478bd9Sstevel@tonic-gate \ 189*7c478bd9Sstevel@tonic-gate for (j = 0; j < (_nelt); j++) \ 190*7c478bd9Sstevel@tonic-gate if ((_array)[j] != NULL) \ 191*7c478bd9Sstevel@tonic-gate FREE_TEXT((_array)[j]); \ 192*7c478bd9Sstevel@tonic-gate kmem_free((_array), (_nelt) * sizeof (char *)); \ 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate typedef struct ippctl_buf ippctl_buf_t; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate struct ippctl_buf { 198*7c478bd9Sstevel@tonic-gate char *buf; 199*7c478bd9Sstevel@tonic-gate size_t buflen; 200*7c478bd9Sstevel@tonic-gate }; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate static int ippctl_copyin(caddr_t, int, char **, size_t *); 203*7c478bd9Sstevel@tonic-gate static int ippctl_copyout(caddr_t, int, char *, size_t); 204*7c478bd9Sstevel@tonic-gate static int ippctl_extract_op(nvlist_t *, uint8_t *); 205*7c478bd9Sstevel@tonic-gate static int ippctl_extract_aname(nvlist_t *, char **); 206*7c478bd9Sstevel@tonic-gate static int ippctl_extract_modname(nvlist_t *, char **); 207*7c478bd9Sstevel@tonic-gate static int ippctl_attach_modname(nvlist_t *nvlp, char *val); 208*7c478bd9Sstevel@tonic-gate static int ippctl_attach_modname_array(nvlist_t *nvlp, char **val, int); 209*7c478bd9Sstevel@tonic-gate static int ippctl_attach_aname_array(nvlist_t *nvlp, char **val, int); 210*7c478bd9Sstevel@tonic-gate static int ippctl_extract_flags(nvlist_t *, ipp_flags_t *); 211*7c478bd9Sstevel@tonic-gate static int ippctl_cmd(char *, size_t, size_t *); 212*7c478bd9Sstevel@tonic-gate static int ippctl_action_create(char *, char *, nvlist_t *, ipp_flags_t); 213*7c478bd9Sstevel@tonic-gate static int ippctl_action_destroy(char *, ipp_flags_t); 214*7c478bd9Sstevel@tonic-gate static int ippctl_action_modify(char *, nvlist_t *, ipp_flags_t); 215*7c478bd9Sstevel@tonic-gate static int ippctl_action_info(char *, ipp_flags_t); 216*7c478bd9Sstevel@tonic-gate static int ippctl_action_mod(char *); 217*7c478bd9Sstevel@tonic-gate static int ippctl_list_mods(void); 218*7c478bd9Sstevel@tonic-gate static int ippctl_mod_list_actions(char *); 219*7c478bd9Sstevel@tonic-gate static int ippctl_data(char **, size_t *, size_t *); 220*7c478bd9Sstevel@tonic-gate static void ippctl_flush(void); 221*7c478bd9Sstevel@tonic-gate static int ippctl_add_nvlist(nvlist_t *, int); 222*7c478bd9Sstevel@tonic-gate static int ippctl_callback(nvlist_t *, void *); 223*7c478bd9Sstevel@tonic-gate static int ippctl_set_rc(int); 224*7c478bd9Sstevel@tonic-gate static void ippctl_alloc(int); 225*7c478bd9Sstevel@tonic-gate static void ippctl_realloc(void); 226*7c478bd9Sstevel@tonic-gate static void ippctl_free(void); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* 229*7c478bd9Sstevel@tonic-gate * Global data 230*7c478bd9Sstevel@tonic-gate */ 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate static dev_info_t *ippctl_dip = NULL; 233*7c478bd9Sstevel@tonic-gate static kmutex_t ippctl_lock; 234*7c478bd9Sstevel@tonic-gate static boolean_t ippctl_busy; 235*7c478bd9Sstevel@tonic-gate static ippctl_buf_t *ippctl_array = NULL; 236*7c478bd9Sstevel@tonic-gate static int ippctl_limit = -1; 237*7c478bd9Sstevel@tonic-gate static int ippctl_rindex = -1; 238*7c478bd9Sstevel@tonic-gate static int ippctl_windex = -1; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * Module linkage functions 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate #define __FN__ "_init" 245*7c478bd9Sstevel@tonic-gate int 246*7c478bd9Sstevel@tonic-gate _init( 247*7c478bd9Sstevel@tonic-gate void) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate int rc; 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate if ((rc = mod_install(&modlinkage)) != 0) { 252*7c478bd9Sstevel@tonic-gate DBG0(DBG_MODLINK, "mod_install failed\n"); 253*7c478bd9Sstevel@tonic-gate return (rc); 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate return (rc); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate #undef __FN__ 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate #define __FN__ "_fini" 261*7c478bd9Sstevel@tonic-gate int 262*7c478bd9Sstevel@tonic-gate _fini( 263*7c478bd9Sstevel@tonic-gate void) 264*7c478bd9Sstevel@tonic-gate { 265*7c478bd9Sstevel@tonic-gate int rc; 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate if ((rc = mod_remove(&modlinkage)) == 0) { 268*7c478bd9Sstevel@tonic-gate return (rc); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate DBG0(DBG_MODLINK, "mod_remove failed\n"); 272*7c478bd9Sstevel@tonic-gate return (rc); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate #undef __FN__ 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate #define __FN__ "_info" 277*7c478bd9Sstevel@tonic-gate int 278*7c478bd9Sstevel@tonic-gate _info( 279*7c478bd9Sstevel@tonic-gate struct modinfo *modinfop) 280*7c478bd9Sstevel@tonic-gate { 281*7c478bd9Sstevel@tonic-gate DBG0(DBG_MODLINK, "calling mod_info\n"); 282*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate #undef __FN__ 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate /* 287*7c478bd9Sstevel@tonic-gate * Driver interface functions (dev_ops and cb_ops) 288*7c478bd9Sstevel@tonic-gate */ 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_info" 291*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 292*7c478bd9Sstevel@tonic-gate static int 293*7c478bd9Sstevel@tonic-gate ippctl_info( 294*7c478bd9Sstevel@tonic-gate dev_info_t *dip, 295*7c478bd9Sstevel@tonic-gate ddi_info_cmd_t cmd, 296*7c478bd9Sstevel@tonic-gate void *arg, 297*7c478bd9Sstevel@tonic-gate void **result) 298*7c478bd9Sstevel@tonic-gate { 299*7c478bd9Sstevel@tonic-gate int rc = DDI_FAILURE; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate switch (cmd) { 302*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 303*7c478bd9Sstevel@tonic-gate *result = (void *)0; /* Single instance driver */ 304*7c478bd9Sstevel@tonic-gate rc = DDI_SUCCESS; 305*7c478bd9Sstevel@tonic-gate break; 306*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 307*7c478bd9Sstevel@tonic-gate *result = (void *)ippctl_dip; 308*7c478bd9Sstevel@tonic-gate rc = DDI_SUCCESS; 309*7c478bd9Sstevel@tonic-gate break; 310*7c478bd9Sstevel@tonic-gate default: 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate return (rc); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate #undef __FN__ 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach" 319*7c478bd9Sstevel@tonic-gate static int 320*7c478bd9Sstevel@tonic-gate ippctl_attach( 321*7c478bd9Sstevel@tonic-gate dev_info_t *dip, 322*7c478bd9Sstevel@tonic-gate ddi_attach_cmd_t cmd) 323*7c478bd9Sstevel@tonic-gate { 324*7c478bd9Sstevel@tonic-gate switch (cmd) { 325*7c478bd9Sstevel@tonic-gate case DDI_ATTACH: 326*7c478bd9Sstevel@tonic-gate break; 327*7c478bd9Sstevel@tonic-gate case DDI_PM_RESUME: 328*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 329*7c478bd9Sstevel@tonic-gate case DDI_RESUME: 330*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 331*7c478bd9Sstevel@tonic-gate default: 332*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate DBG0(DBG_DEVOPS, "DDI_ATTACH\n"); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * This is strictly a single instance driver. 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate if (ippctl_dip != NULL) 342*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Create minor node. 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, "ctl", S_IFCHR, 0, 349*7c478bd9Sstevel@tonic-gate DDI_PSEUDO, 0) != DDI_SUCCESS) 350*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * No need for per-instance structure, just store vital data in 354*7c478bd9Sstevel@tonic-gate * globals. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate ippctl_dip = dip; 358*7c478bd9Sstevel@tonic-gate mutex_init(&ippctl_lock, NULL, MUTEX_DRIVER, NULL); 359*7c478bd9Sstevel@tonic-gate ippctl_busy = B_FALSE; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate #undef __FN__ 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_detach" 366*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 367*7c478bd9Sstevel@tonic-gate static int 368*7c478bd9Sstevel@tonic-gate ippctl_detach( 369*7c478bd9Sstevel@tonic-gate dev_info_t *dip, 370*7c478bd9Sstevel@tonic-gate ddi_detach_cmd_t cmd) 371*7c478bd9Sstevel@tonic-gate { 372*7c478bd9Sstevel@tonic-gate switch (cmd) { 373*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 374*7c478bd9Sstevel@tonic-gate break; 375*7c478bd9Sstevel@tonic-gate case DDI_PM_SUSPEND: 376*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 377*7c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 378*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 379*7c478bd9Sstevel@tonic-gate default: 380*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate DBG0(DBG_DEVOPS, "DDI_DETACH\n"); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate ASSERT(dip == ippctl_dip); 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 388*7c478bd9Sstevel@tonic-gate mutex_destroy(&ippctl_lock); 389*7c478bd9Sstevel@tonic-gate ippctl_dip = NULL; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate #undef __FN__ 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_open" 396*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 397*7c478bd9Sstevel@tonic-gate static int 398*7c478bd9Sstevel@tonic-gate ippctl_open( 399*7c478bd9Sstevel@tonic-gate dev_t *devp, 400*7c478bd9Sstevel@tonic-gate int flag, 401*7c478bd9Sstevel@tonic-gate int otyp, 402*7c478bd9Sstevel@tonic-gate cred_t *credp) 403*7c478bd9Sstevel@tonic-gate { 404*7c478bd9Sstevel@tonic-gate minor_t minor = getminor(*devp); 405*7c478bd9Sstevel@tonic-gate #define LIMIT 4 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "open\n"); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * Only allow privileged users to open our device. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (secpolicy_net_config(credp, B_FALSE) != 0) { 414*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "not privileged user\n"); 415*7c478bd9Sstevel@tonic-gate return (EPERM); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate /* 419*7c478bd9Sstevel@tonic-gate * Sanity check other arguments. 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (minor != 0) { 423*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad minor\n"); 424*7c478bd9Sstevel@tonic-gate return (ENXIO); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate if (otyp != OTYP_CHR) { 428*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad device type\n"); 429*7c478bd9Sstevel@tonic-gate return (EINVAL); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* 433*7c478bd9Sstevel@tonic-gate * This is also a single dev_t driver. 434*7c478bd9Sstevel@tonic-gate */ 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate mutex_enter(&ippctl_lock); 437*7c478bd9Sstevel@tonic-gate if (ippctl_busy) { 438*7c478bd9Sstevel@tonic-gate mutex_exit(&ippctl_lock); 439*7c478bd9Sstevel@tonic-gate return (EBUSY); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate ippctl_busy = B_TRUE; 442*7c478bd9Sstevel@tonic-gate mutex_exit(&ippctl_lock); 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * Allocate data buffer array (starting with length LIMIT, defined 446*7c478bd9Sstevel@tonic-gate * at the start of this function). 447*7c478bd9Sstevel@tonic-gate */ 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate ippctl_alloc(LIMIT); 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "success\n"); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate return (0); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate #undef LIMIT 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate #undef __FN__ 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_close" 460*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 461*7c478bd9Sstevel@tonic-gate static int 462*7c478bd9Sstevel@tonic-gate ippctl_close( 463*7c478bd9Sstevel@tonic-gate dev_t dev, 464*7c478bd9Sstevel@tonic-gate int flag, 465*7c478bd9Sstevel@tonic-gate int otyp, 466*7c478bd9Sstevel@tonic-gate cred_t *credp) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "close\n"); 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate ASSERT(minor == 0); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate /* 475*7c478bd9Sstevel@tonic-gate * Free the data buffer array. 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate ippctl_free(); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate mutex_enter(&ippctl_lock); 481*7c478bd9Sstevel@tonic-gate ippctl_busy = B_FALSE; 482*7c478bd9Sstevel@tonic-gate mutex_exit(&ippctl_lock); 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "success\n"); 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate return (0); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate #undef __FN__ 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_ioctl" 491*7c478bd9Sstevel@tonic-gate static int 492*7c478bd9Sstevel@tonic-gate ippctl_ioctl( 493*7c478bd9Sstevel@tonic-gate dev_t dev, 494*7c478bd9Sstevel@tonic-gate int cmd, 495*7c478bd9Sstevel@tonic-gate intptr_t arg, 496*7c478bd9Sstevel@tonic-gate int mode, 497*7c478bd9Sstevel@tonic-gate cred_t *credp, 498*7c478bd9Sstevel@tonic-gate int *rvalp) 499*7c478bd9Sstevel@tonic-gate { 500*7c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev); 501*7c478bd9Sstevel@tonic-gate char *cbuf; 502*7c478bd9Sstevel@tonic-gate char *dbuf; 503*7c478bd9Sstevel@tonic-gate size_t cbuflen; 504*7c478bd9Sstevel@tonic-gate size_t dbuflen; 505*7c478bd9Sstevel@tonic-gate size_t nextbuflen; 506*7c478bd9Sstevel@tonic-gate int rc; 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * Paranoia check. 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate if (secpolicy_net_config(credp, B_FALSE) != 0) { 513*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "not privileged user\n"); 514*7c478bd9Sstevel@tonic-gate return (EPERM); 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (minor != 0) { 518*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad minor\n"); 519*7c478bd9Sstevel@tonic-gate return (ENXIO); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate switch (cmd) { 523*7c478bd9Sstevel@tonic-gate case IPPCTL_CMD: 524*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "command\n"); 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate /* 527*7c478bd9Sstevel@tonic-gate * Copy in the command buffer from user space. 528*7c478bd9Sstevel@tonic-gate */ 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_copyin((caddr_t)arg, mode, &cbuf, 531*7c478bd9Sstevel@tonic-gate &cbuflen)) != 0) 532*7c478bd9Sstevel@tonic-gate break; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate /* 535*7c478bd9Sstevel@tonic-gate * Execute the command. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate rc = ippctl_cmd(cbuf, cbuflen, &nextbuflen); 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * Pass back the length of the first data buffer. 542*7c478bd9Sstevel@tonic-gate */ 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "nextbuflen = %lu\n", nextbuflen); 545*7c478bd9Sstevel@tonic-gate *rvalp = nextbuflen; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate /* 548*7c478bd9Sstevel@tonic-gate * Free the kernel copy of the command buffer. 549*7c478bd9Sstevel@tonic-gate */ 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate kmem_free(cbuf, cbuflen); 552*7c478bd9Sstevel@tonic-gate break; 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate case IPPCTL_DATA: 555*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "data\n"); 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* 558*7c478bd9Sstevel@tonic-gate * Grab the next data buffer from the array of pending 559*7c478bd9Sstevel@tonic-gate * buffers. 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_data(&dbuf, &dbuflen, &nextbuflen)) != 0) 563*7c478bd9Sstevel@tonic-gate break; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * Copy it out to user space. 567*7c478bd9Sstevel@tonic-gate */ 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate rc = ippctl_copyout((caddr_t)arg, mode, dbuf, dbuflen); 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate /* 572*7c478bd9Sstevel@tonic-gate * Pass back the length of the next data buffer. 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "nextbuflen = %lu\n", nextbuflen); 576*7c478bd9Sstevel@tonic-gate *rvalp = nextbuflen; 577*7c478bd9Sstevel@tonic-gate break; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate default: 580*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "unrecognized ioctl\n"); 581*7c478bd9Sstevel@tonic-gate rc = EINVAL; 582*7c478bd9Sstevel@tonic-gate break; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "rc = %d\n", rc); 586*7c478bd9Sstevel@tonic-gate return (rc); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate #undef __FN__ 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* 591*7c478bd9Sstevel@tonic-gate * Local functions 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_copyin" 595*7c478bd9Sstevel@tonic-gate static int 596*7c478bd9Sstevel@tonic-gate ippctl_copyin( 597*7c478bd9Sstevel@tonic-gate caddr_t arg, 598*7c478bd9Sstevel@tonic-gate int mode, 599*7c478bd9Sstevel@tonic-gate char **kbufp, 600*7c478bd9Sstevel@tonic-gate size_t *kbuflenp) 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate ippctl_ioctl_t iioc; 603*7c478bd9Sstevel@tonic-gate caddr_t ubuf; 604*7c478bd9Sstevel@tonic-gate char *kbuf; 605*7c478bd9Sstevel@tonic-gate size_t ubuflen; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying in ioctl structure\n"); 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate /* 610*7c478bd9Sstevel@tonic-gate * Copy in the ioctl structure from user-space, converting from 32-bit 611*7c478bd9Sstevel@tonic-gate * as necessary. 612*7c478bd9Sstevel@tonic-gate */ 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 615*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 616*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 617*7c478bd9Sstevel@tonic-gate { 618*7c478bd9Sstevel@tonic-gate ippctl_ioctl32_t iioc32; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "converting from 32-bit\n"); 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc32, 623*7c478bd9Sstevel@tonic-gate sizeof (ippctl_ioctl32_t), mode) != 0) 624*7c478bd9Sstevel@tonic-gate return (EFAULT); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate ubuf = (caddr_t)(uintptr_t)iioc32.ii32_buf; 627*7c478bd9Sstevel@tonic-gate ubuflen = (size_t)iioc32.ii32_buflen; 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate break; 630*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 631*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 632*7c478bd9Sstevel@tonic-gate mode) != 0) 633*7c478bd9Sstevel@tonic-gate return (EFAULT); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 636*7c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 637*7c478bd9Sstevel@tonic-gate break; 638*7c478bd9Sstevel@tonic-gate default: 639*7c478bd9Sstevel@tonic-gate return (EFAULT); 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate #else /* _MULTI_DATAMODEL */ 642*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 643*7c478bd9Sstevel@tonic-gate mode) != 0) 644*7c478bd9Sstevel@tonic-gate return (EFAULT); 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 647*7c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 648*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuf = 0x%p\n", (void *)ubuf); 651*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuflen = %lu\n", ubuflen); 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate /* 654*7c478bd9Sstevel@tonic-gate * Sanity check the command buffer information. 655*7c478bd9Sstevel@tonic-gate */ 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate if (ubuflen == 0 || ubuf == NULL) 658*7c478bd9Sstevel@tonic-gate return (EINVAL); 659*7c478bd9Sstevel@tonic-gate if (ubuflen > MAXUBUFLEN) 660*7c478bd9Sstevel@tonic-gate return (E2BIG); 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* 663*7c478bd9Sstevel@tonic-gate * Allocate some memory for the command buffer and copy it in. 664*7c478bd9Sstevel@tonic-gate */ 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate kbuf = kmem_zalloc(ubuflen, KM_SLEEP); 667*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying in nvlist\n"); 668*7c478bd9Sstevel@tonic-gate if (ddi_copyin(ubuf, (caddr_t)kbuf, ubuflen, mode) != 0) { 669*7c478bd9Sstevel@tonic-gate kmem_free(kbuf, ubuflen); 670*7c478bd9Sstevel@tonic-gate return (EFAULT); 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate *kbufp = kbuf; 674*7c478bd9Sstevel@tonic-gate *kbuflenp = ubuflen; 675*7c478bd9Sstevel@tonic-gate return (0); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate #undef __FN__ 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_copyout" 680*7c478bd9Sstevel@tonic-gate static int 681*7c478bd9Sstevel@tonic-gate ippctl_copyout( 682*7c478bd9Sstevel@tonic-gate caddr_t arg, 683*7c478bd9Sstevel@tonic-gate int mode, 684*7c478bd9Sstevel@tonic-gate char *kbuf, 685*7c478bd9Sstevel@tonic-gate size_t kbuflen) 686*7c478bd9Sstevel@tonic-gate { 687*7c478bd9Sstevel@tonic-gate ippctl_ioctl_t iioc; 688*7c478bd9Sstevel@tonic-gate caddr_t ubuf; 689*7c478bd9Sstevel@tonic-gate int ubuflen; 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying out ioctl structure\n"); 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate /* 694*7c478bd9Sstevel@tonic-gate * Copy in the ioctl structure from user-space, converting from 32-bit 695*7c478bd9Sstevel@tonic-gate * as necessary. 696*7c478bd9Sstevel@tonic-gate */ 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 699*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 700*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 701*7c478bd9Sstevel@tonic-gate { 702*7c478bd9Sstevel@tonic-gate ippctl_ioctl32_t iioc32; 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc32, 705*7c478bd9Sstevel@tonic-gate sizeof (ippctl_ioctl32_t), mode) != 0) 706*7c478bd9Sstevel@tonic-gate return (EFAULT); 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate ubuf = (caddr_t)(uintptr_t)iioc32.ii32_buf; 709*7c478bd9Sstevel@tonic-gate ubuflen = iioc32.ii32_buflen; 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate break; 712*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 713*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 714*7c478bd9Sstevel@tonic-gate mode) != 0) 715*7c478bd9Sstevel@tonic-gate return (EFAULT); 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 718*7c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 719*7c478bd9Sstevel@tonic-gate break; 720*7c478bd9Sstevel@tonic-gate default: 721*7c478bd9Sstevel@tonic-gate return (EFAULT); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate #else /* _MULTI_DATAMODEL */ 724*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 725*7c478bd9Sstevel@tonic-gate mode) != 0) 726*7c478bd9Sstevel@tonic-gate return (EFAULT); 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 729*7c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 730*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuf = 0x%p\n", (void *)ubuf); 733*7c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuflen = %d\n", ubuflen); 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate /* 736*7c478bd9Sstevel@tonic-gate * Sanity check the data buffer details. 737*7c478bd9Sstevel@tonic-gate */ 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate if (ubuflen == 0 || ubuf == NULL) 740*7c478bd9Sstevel@tonic-gate return (EINVAL); 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate if (ubuflen < kbuflen) 743*7c478bd9Sstevel@tonic-gate return (ENOSPC); 744*7c478bd9Sstevel@tonic-gate if (ubuflen > MAXUBUFLEN) 745*7c478bd9Sstevel@tonic-gate return (E2BIG); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate /* 748*7c478bd9Sstevel@tonic-gate * Copy out the data buffer to user space. 749*7c478bd9Sstevel@tonic-gate */ 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying out nvlist\n"); 752*7c478bd9Sstevel@tonic-gate if (ddi_copyout((caddr_t)kbuf, ubuf, kbuflen, mode) != 0) 753*7c478bd9Sstevel@tonic-gate return (EFAULT); 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate return (0); 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate #undef __FN__ 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_op" 760*7c478bd9Sstevel@tonic-gate static int 761*7c478bd9Sstevel@tonic-gate ippctl_extract_op( 762*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 763*7c478bd9Sstevel@tonic-gate uint8_t *valp) 764*7c478bd9Sstevel@tonic-gate { 765*7c478bd9Sstevel@tonic-gate int rc; 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate /* 768*7c478bd9Sstevel@tonic-gate * Look-up and remove the opcode passed from libipp from the 769*7c478bd9Sstevel@tonic-gate * nvlist. 770*7c478bd9Sstevel@tonic-gate */ 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_byte(nvlp, IPPCTL_OP, valp)) != 0) 773*7c478bd9Sstevel@tonic-gate return (rc); 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_OP); 776*7c478bd9Sstevel@tonic-gate return (0); 777*7c478bd9Sstevel@tonic-gate } 778*7c478bd9Sstevel@tonic-gate #undef __FN__ 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_aname" 781*7c478bd9Sstevel@tonic-gate static int 782*7c478bd9Sstevel@tonic-gate ippctl_extract_aname( 783*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 784*7c478bd9Sstevel@tonic-gate char **valp) 785*7c478bd9Sstevel@tonic-gate { 786*7c478bd9Sstevel@tonic-gate int rc; 787*7c478bd9Sstevel@tonic-gate char *ptr; 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate /* 790*7c478bd9Sstevel@tonic-gate * Look-up and remove the action name passed from libipp from the 791*7c478bd9Sstevel@tonic-gate * nvlist. 792*7c478bd9Sstevel@tonic-gate */ 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_ANAME, &ptr)) != 0) 795*7c478bd9Sstevel@tonic-gate return (rc); 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate *valp = kmem_alloc(strlen(ptr) + 1, KM_SLEEP); 798*7c478bd9Sstevel@tonic-gate (void) strcpy(*valp, ptr); 799*7c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_ANAME); 800*7c478bd9Sstevel@tonic-gate return (0); 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate #undef __FN__ 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_modname" 805*7c478bd9Sstevel@tonic-gate static int 806*7c478bd9Sstevel@tonic-gate ippctl_extract_modname( 807*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 808*7c478bd9Sstevel@tonic-gate char **valp) 809*7c478bd9Sstevel@tonic-gate { 810*7c478bd9Sstevel@tonic-gate int rc; 811*7c478bd9Sstevel@tonic-gate char *ptr; 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate /* 814*7c478bd9Sstevel@tonic-gate * Look-up and remove the module name passed from libipp from the 815*7c478bd9Sstevel@tonic-gate * nvlist. 816*7c478bd9Sstevel@tonic-gate */ 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_MODNAME, &ptr)) != 0) 819*7c478bd9Sstevel@tonic-gate return (rc); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate *valp = kmem_alloc(strlen(ptr) + 1, KM_SLEEP); 822*7c478bd9Sstevel@tonic-gate (void) strcpy(*valp, ptr); 823*7c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_MODNAME); 824*7c478bd9Sstevel@tonic-gate return (0); 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate #undef __FN__ 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach_modname" 829*7c478bd9Sstevel@tonic-gate static int 830*7c478bd9Sstevel@tonic-gate ippctl_attach_modname( 831*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 832*7c478bd9Sstevel@tonic-gate char *modname) 833*7c478bd9Sstevel@tonic-gate { 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * Add a module name to an nvlist for passing back to user 836*7c478bd9Sstevel@tonic-gate * space. 837*7c478bd9Sstevel@tonic-gate */ 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate return (nvlist_add_string(nvlp, IPPCTL_MODNAME, modname)); 840*7c478bd9Sstevel@tonic-gate } 841*7c478bd9Sstevel@tonic-gate #undef __FN__ 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach_modname_array" 844*7c478bd9Sstevel@tonic-gate static int 845*7c478bd9Sstevel@tonic-gate ippctl_attach_modname_array( 846*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 847*7c478bd9Sstevel@tonic-gate char **modname_array, 848*7c478bd9Sstevel@tonic-gate int nelt) 849*7c478bd9Sstevel@tonic-gate { 850*7c478bd9Sstevel@tonic-gate /* 851*7c478bd9Sstevel@tonic-gate * Add a module name array to an nvlist for passing back to user 852*7c478bd9Sstevel@tonic-gate * space. 853*7c478bd9Sstevel@tonic-gate */ 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate return (nvlist_add_string_array(nvlp, IPPCTL_MODNAME_ARRAY, 856*7c478bd9Sstevel@tonic-gate modname_array, nelt)); 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate #undef __FN__ 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach_aname_array" 861*7c478bd9Sstevel@tonic-gate static int 862*7c478bd9Sstevel@tonic-gate ippctl_attach_aname_array( 863*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 864*7c478bd9Sstevel@tonic-gate char **aname_array, 865*7c478bd9Sstevel@tonic-gate int nelt) 866*7c478bd9Sstevel@tonic-gate { 867*7c478bd9Sstevel@tonic-gate /* 868*7c478bd9Sstevel@tonic-gate * Add an action name array to an nvlist for passing back to user 869*7c478bd9Sstevel@tonic-gate * space. 870*7c478bd9Sstevel@tonic-gate */ 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate return (nvlist_add_string_array(nvlp, IPPCTL_ANAME_ARRAY, 873*7c478bd9Sstevel@tonic-gate aname_array, nelt)); 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate #undef __FN__ 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_flags" 878*7c478bd9Sstevel@tonic-gate static int 879*7c478bd9Sstevel@tonic-gate ippctl_extract_flags( 880*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 881*7c478bd9Sstevel@tonic-gate ipp_flags_t *valp) 882*7c478bd9Sstevel@tonic-gate { 883*7c478bd9Sstevel@tonic-gate int rc; 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate /* 886*7c478bd9Sstevel@tonic-gate * Look-up and remove the flags passed from libipp from the 887*7c478bd9Sstevel@tonic-gate * nvlist. 888*7c478bd9Sstevel@tonic-gate */ 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_uint32(nvlp, IPPCTL_FLAGS, 891*7c478bd9Sstevel@tonic-gate (uint32_t *)valp)) != 0) 892*7c478bd9Sstevel@tonic-gate return (rc); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_FLAGS); 895*7c478bd9Sstevel@tonic-gate return (0); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate #undef __FN__ 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_cmd" 900*7c478bd9Sstevel@tonic-gate static int 901*7c478bd9Sstevel@tonic-gate ippctl_cmd( 902*7c478bd9Sstevel@tonic-gate char *cbuf, 903*7c478bd9Sstevel@tonic-gate size_t cbuflen, 904*7c478bd9Sstevel@tonic-gate size_t *nextbuflenp) 905*7c478bd9Sstevel@tonic-gate { 906*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp = NULL; 907*7c478bd9Sstevel@tonic-gate int rc; 908*7c478bd9Sstevel@tonic-gate char *aname = NULL; 909*7c478bd9Sstevel@tonic-gate char *modname = NULL; 910*7c478bd9Sstevel@tonic-gate ipp_flags_t flags; 911*7c478bd9Sstevel@tonic-gate uint8_t op; 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate /* 914*7c478bd9Sstevel@tonic-gate * Start a new command cycle by flushing any previous data buffers. 915*7c478bd9Sstevel@tonic-gate */ 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate ippctl_flush(); 918*7c478bd9Sstevel@tonic-gate *nextbuflenp = 0; 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate /* 921*7c478bd9Sstevel@tonic-gate * Unpack the nvlist from the command buffer. 922*7c478bd9Sstevel@tonic-gate */ 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_unpack(cbuf, cbuflen, &nvlp, KM_SLEEP)) != 0) 925*7c478bd9Sstevel@tonic-gate return (rc); 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate /* 928*7c478bd9Sstevel@tonic-gate * Extract the opcode to find out what we should do. 929*7c478bd9Sstevel@tonic-gate */ 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_op(nvlp, &op)) != 0) { 932*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 933*7c478bd9Sstevel@tonic-gate return (rc); 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate switch (op) { 937*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_CREATE: 938*7c478bd9Sstevel@tonic-gate /* 939*7c478bd9Sstevel@tonic-gate * Create a new action. 940*7c478bd9Sstevel@tonic-gate */ 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_CREATE\n"); 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate /* 945*7c478bd9Sstevel@tonic-gate * Extract the module name, action name and flags from the 946*7c478bd9Sstevel@tonic-gate * nvlist. 947*7c478bd9Sstevel@tonic-gate */ 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_modname(nvlp, &modname)) != 0) { 950*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 951*7c478bd9Sstevel@tonic-gate return (rc); 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 955*7c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 956*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 957*7c478bd9Sstevel@tonic-gate return (rc); 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 961*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 962*7c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 963*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 964*7c478bd9Sstevel@tonic-gate return (rc); 965*7c478bd9Sstevel@tonic-gate } 966*7c478bd9Sstevel@tonic-gate 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate rc = ippctl_action_create(modname, aname, nvlp, flags); 969*7c478bd9Sstevel@tonic-gate break; 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_MODIFY: 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * Modify an existing action. 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_MODIFY\n"); 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate /* 980*7c478bd9Sstevel@tonic-gate * Extract the action name and flags from the nvlist. 981*7c478bd9Sstevel@tonic-gate */ 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 984*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 985*7c478bd9Sstevel@tonic-gate return (rc); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 989*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 990*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 991*7c478bd9Sstevel@tonic-gate return (rc); 992*7c478bd9Sstevel@tonic-gate } 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate rc = ippctl_action_modify(aname, nvlp, flags); 995*7c478bd9Sstevel@tonic-gate break; 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_DESTROY: 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * Destroy an action. 1001*7c478bd9Sstevel@tonic-gate */ 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_DESTROY\n"); 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate /* 1006*7c478bd9Sstevel@tonic-gate * Extract the action name and flags from the nvlist. 1007*7c478bd9Sstevel@tonic-gate */ 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 1010*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1011*7c478bd9Sstevel@tonic-gate return (rc); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 1015*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1016*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1017*7c478bd9Sstevel@tonic-gate return (rc); 1018*7c478bd9Sstevel@tonic-gate } 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1021*7c478bd9Sstevel@tonic-gate rc = ippctl_action_destroy(aname, flags); 1022*7c478bd9Sstevel@tonic-gate break; 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_INFO: 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate /* 1027*7c478bd9Sstevel@tonic-gate * Retrive the configuration of an action. 1028*7c478bd9Sstevel@tonic-gate */ 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_INFO\n"); 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate /* 1033*7c478bd9Sstevel@tonic-gate * Extract the action name and flags from the nvlist. 1034*7c478bd9Sstevel@tonic-gate */ 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 1037*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1038*7c478bd9Sstevel@tonic-gate return (rc); 1039*7c478bd9Sstevel@tonic-gate } 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 1042*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1043*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1044*7c478bd9Sstevel@tonic-gate return (rc); 1045*7c478bd9Sstevel@tonic-gate } 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1048*7c478bd9Sstevel@tonic-gate rc = ippctl_action_info(aname, flags); 1049*7c478bd9Sstevel@tonic-gate break; 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_MOD: 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate /* 1054*7c478bd9Sstevel@tonic-gate * Find the module that implements a given action. 1055*7c478bd9Sstevel@tonic-gate */ 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_MOD\n"); 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate /* 1060*7c478bd9Sstevel@tonic-gate * Extract the action name from the nvlist. 1061*7c478bd9Sstevel@tonic-gate */ 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 1064*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1065*7c478bd9Sstevel@tonic-gate return (rc); 1066*7c478bd9Sstevel@tonic-gate } 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1069*7c478bd9Sstevel@tonic-gate rc = ippctl_action_mod(aname); 1070*7c478bd9Sstevel@tonic-gate break; 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_LIST_MODS: 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate /* 1075*7c478bd9Sstevel@tonic-gate * List all the modules. 1076*7c478bd9Sstevel@tonic-gate */ 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_LIST_MODS\n"); 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1081*7c478bd9Sstevel@tonic-gate rc = ippctl_list_mods(); 1082*7c478bd9Sstevel@tonic-gate break; 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate case IPPCTL_OP_MOD_LIST_ACTIONS: 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate /* 1087*7c478bd9Sstevel@tonic-gate * List all the actions for a given module. 1088*7c478bd9Sstevel@tonic-gate */ 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_LIST_MODS\n"); 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_modname(nvlp, &modname)) != 0) { 1093*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1094*7c478bd9Sstevel@tonic-gate return (rc); 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1098*7c478bd9Sstevel@tonic-gate rc = ippctl_mod_list_actions(modname); 1099*7c478bd9Sstevel@tonic-gate break; 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate default: 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate /* 1104*7c478bd9Sstevel@tonic-gate * Unrecognized opcode. 1105*7c478bd9Sstevel@tonic-gate */ 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1108*7c478bd9Sstevel@tonic-gate rc = EINVAL; 1109*7c478bd9Sstevel@tonic-gate break; 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate /* 1113*7c478bd9Sstevel@tonic-gate * The length of buffer that we need to notify back to libipp with 1114*7c478bd9Sstevel@tonic-gate * the command ioctl's return is the length of the first data buffer 1115*7c478bd9Sstevel@tonic-gate * in the array. We only expact to pass back data buffers if the 1116*7c478bd9Sstevel@tonic-gate * operation succeeds (NOTE: this does not mean the kernel call has 1117*7c478bd9Sstevel@tonic-gate * to succeed, merely that we successfully issued it and processed 1118*7c478bd9Sstevel@tonic-gate * the results). 1119*7c478bd9Sstevel@tonic-gate */ 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate if (rc == 0) 1122*7c478bd9Sstevel@tonic-gate *nextbuflenp = ippctl_array[0].buflen; 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate return (rc); 1125*7c478bd9Sstevel@tonic-gate } 1126*7c478bd9Sstevel@tonic-gate #undef __FN__ 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_create" 1129*7c478bd9Sstevel@tonic-gate static int 1130*7c478bd9Sstevel@tonic-gate ippctl_action_create( 1131*7c478bd9Sstevel@tonic-gate char *modname, 1132*7c478bd9Sstevel@tonic-gate char *aname, 1133*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 1134*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 1135*7c478bd9Sstevel@tonic-gate { 1136*7c478bd9Sstevel@tonic-gate int ipp_rc; 1137*7c478bd9Sstevel@tonic-gate int rc; 1138*7c478bd9Sstevel@tonic-gate ipp_mod_id_t mid; 1139*7c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate /* 1142*7c478bd9Sstevel@tonic-gate * Look up the module id from the name and create the new 1143*7c478bd9Sstevel@tonic-gate * action. 1144*7c478bd9Sstevel@tonic-gate */ 1145*7c478bd9Sstevel@tonic-gate 1146*7c478bd9Sstevel@tonic-gate mid = ipp_mod_lookup(modname); 1147*7c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_create(mid, aname, &nvlp, flags, &aid); 1150*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate /* 1153*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1154*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1155*7c478bd9Sstevel@tonic-gate */ 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) { 1158*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) { 1159*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1160*7c478bd9Sstevel@tonic-gate if (ipp_action_destroy(aid, 0) != 0) { 1161*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 1162*7c478bd9Sstevel@tonic-gate "ippctl: unrecoverable error (aid = %d)", 1163*7c478bd9Sstevel@tonic-gate aid); 1164*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate } 1167*7c478bd9Sstevel@tonic-gate return (rc); 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate 1170*7c478bd9Sstevel@tonic-gate /* 1171*7c478bd9Sstevel@tonic-gate * If the module passed back an nvlist, add this as 1172*7c478bd9Sstevel@tonic-gate * well. 1173*7c478bd9Sstevel@tonic-gate */ 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) { 1176*7c478bd9Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL); 1177*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1178*7c478bd9Sstevel@tonic-gate } else 1179*7c478bd9Sstevel@tonic-gate rc = 0; 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate return (rc); 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate #undef __FN__ 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_destroy" 1186*7c478bd9Sstevel@tonic-gate static int 1187*7c478bd9Sstevel@tonic-gate ippctl_action_destroy( 1188*7c478bd9Sstevel@tonic-gate char *aname, 1189*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 1190*7c478bd9Sstevel@tonic-gate { 1191*7c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 1192*7c478bd9Sstevel@tonic-gate int ipp_rc; 1193*7c478bd9Sstevel@tonic-gate int rc; 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate /* 1196*7c478bd9Sstevel@tonic-gate * Look up the action id and destroy the action. 1197*7c478bd9Sstevel@tonic-gate */ 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 1200*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_destroy(aid, flags); 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate /* 1205*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1206*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 1210*7c478bd9Sstevel@tonic-gate return (rc); 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate /* 1213*7c478bd9Sstevel@tonic-gate * There's no more information to pass back. 1214*7c478bd9Sstevel@tonic-gate */ 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate return (0); 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate #undef __FN__ 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_modify" 1221*7c478bd9Sstevel@tonic-gate static int 1222*7c478bd9Sstevel@tonic-gate ippctl_action_modify( 1223*7c478bd9Sstevel@tonic-gate char *aname, 1224*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 1225*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 1226*7c478bd9Sstevel@tonic-gate { 1227*7c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 1228*7c478bd9Sstevel@tonic-gate int ipp_rc; 1229*7c478bd9Sstevel@tonic-gate int rc; 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate /* 1232*7c478bd9Sstevel@tonic-gate * Look up the action id and modify the action. 1233*7c478bd9Sstevel@tonic-gate */ 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 1236*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_modify(aid, &nvlp, flags); 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate /* 1241*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1242*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1243*7c478bd9Sstevel@tonic-gate */ 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) { 1246*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) 1247*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1248*7c478bd9Sstevel@tonic-gate return (rc); 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate /* 1252*7c478bd9Sstevel@tonic-gate * If the module passed back an nvlist, add this as 1253*7c478bd9Sstevel@tonic-gate * well. 1254*7c478bd9Sstevel@tonic-gate */ 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) { 1257*7c478bd9Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL); 1258*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1259*7c478bd9Sstevel@tonic-gate } else 1260*7c478bd9Sstevel@tonic-gate rc = 0; 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate return (rc); 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate #undef __FN__ 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_info" 1267*7c478bd9Sstevel@tonic-gate static int 1268*7c478bd9Sstevel@tonic-gate ippctl_action_info( 1269*7c478bd9Sstevel@tonic-gate char *aname, 1270*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 1271*7c478bd9Sstevel@tonic-gate { 1272*7c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 1273*7c478bd9Sstevel@tonic-gate int ipp_rc; 1274*7c478bd9Sstevel@tonic-gate int rc; 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate /* 1277*7c478bd9Sstevel@tonic-gate * Look up the action and call the information retrieval 1278*7c478bd9Sstevel@tonic-gate * entry point. 1279*7c478bd9Sstevel@tonic-gate * 1280*7c478bd9Sstevel@tonic-gate * NOTE: The callback function that is passed in packs and 1281*7c478bd9Sstevel@tonic-gate * stores each of the nvlists it is called with in the array 1282*7c478bd9Sstevel@tonic-gate * that will be passed back to libipp. 1283*7c478bd9Sstevel@tonic-gate */ 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 1286*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_info(aid, ippctl_callback, NULL, flags); 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* 1291*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1292*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1293*7c478bd9Sstevel@tonic-gate */ 1294*7c478bd9Sstevel@tonic-gate 1295*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 1296*7c478bd9Sstevel@tonic-gate return (rc); 1297*7c478bd9Sstevel@tonic-gate 1298*7c478bd9Sstevel@tonic-gate /* 1299*7c478bd9Sstevel@tonic-gate * There's no more information to pass back. 1300*7c478bd9Sstevel@tonic-gate */ 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate return (0); 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate #undef __FN__ 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_mod" 1307*7c478bd9Sstevel@tonic-gate static int 1308*7c478bd9Sstevel@tonic-gate ippctl_action_mod( 1309*7c478bd9Sstevel@tonic-gate char *aname) 1310*7c478bd9Sstevel@tonic-gate { 1311*7c478bd9Sstevel@tonic-gate ipp_mod_id_t mid; 1312*7c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 1313*7c478bd9Sstevel@tonic-gate char *modname; 1314*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 1315*7c478bd9Sstevel@tonic-gate int ipp_rc; 1316*7c478bd9Sstevel@tonic-gate int rc; 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate /* 1319*7c478bd9Sstevel@tonic-gate * Look up the action id and get the id of the module that 1320*7c478bd9Sstevel@tonic-gate * implements the action. If that succeeds then look up the 1321*7c478bd9Sstevel@tonic-gate * name of the module. 1322*7c478bd9Sstevel@tonic-gate */ 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 1325*7c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 1326*7c478bd9Sstevel@tonic-gate 1327*7c478bd9Sstevel@tonic-gate if ((ipp_rc = ipp_action_mod(aid, &mid)) == 0) 1328*7c478bd9Sstevel@tonic-gate ipp_rc = ipp_mod_name(mid, &modname); 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate /* 1331*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1332*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1333*7c478bd9Sstevel@tonic-gate */ 1334*7c478bd9Sstevel@tonic-gate 1335*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 1336*7c478bd9Sstevel@tonic-gate return (rc); 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate /* 1339*7c478bd9Sstevel@tonic-gate * If everything succeeded add an nvlist containing the 1340*7c478bd9Sstevel@tonic-gate * module name to the set of nvlists to pass back to libipp. 1341*7c478bd9Sstevel@tonic-gate */ 1342*7c478bd9Sstevel@tonic-gate 1343*7c478bd9Sstevel@tonic-gate if (ipp_rc == 0) { 1344*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_SLEEP)) != 0) 1345*7c478bd9Sstevel@tonic-gate return (rc); 1346*7c478bd9Sstevel@tonic-gate 1347*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_attach_modname(nvlp, modname)) != 0) { 1348*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1349*7c478bd9Sstevel@tonic-gate return (rc); 1350*7c478bd9Sstevel@tonic-gate } 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL); 1355*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1356*7c478bd9Sstevel@tonic-gate } else 1357*7c478bd9Sstevel@tonic-gate rc = 0; 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate return (rc); 1360*7c478bd9Sstevel@tonic-gate } 1361*7c478bd9Sstevel@tonic-gate #undef __FN__ 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_list_mods" 1364*7c478bd9Sstevel@tonic-gate static int 1365*7c478bd9Sstevel@tonic-gate ippctl_list_mods( 1366*7c478bd9Sstevel@tonic-gate void) 1367*7c478bd9Sstevel@tonic-gate { 1368*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 1369*7c478bd9Sstevel@tonic-gate int ipp_rc; 1370*7c478bd9Sstevel@tonic-gate int rc = 0; 1371*7c478bd9Sstevel@tonic-gate ipp_mod_id_t *mid_array; 1372*7c478bd9Sstevel@tonic-gate char **modname_array = NULL; 1373*7c478bd9Sstevel@tonic-gate int nelt; 1374*7c478bd9Sstevel@tonic-gate int length; 1375*7c478bd9Sstevel@tonic-gate int i; 1376*7c478bd9Sstevel@tonic-gate 1377*7c478bd9Sstevel@tonic-gate /* 1378*7c478bd9Sstevel@tonic-gate * Get a list of all the module ids. If that succeeds, 1379*7c478bd9Sstevel@tonic-gate * translate the ids into names. 1380*7c478bd9Sstevel@tonic-gate * 1381*7c478bd9Sstevel@tonic-gate * NOTE: This translation may fail if a module is 1382*7c478bd9Sstevel@tonic-gate * unloaded during this operation. If this occurs, EAGAIN 1383*7c478bd9Sstevel@tonic-gate * will be passed back to libipp note that a transient 1384*7c478bd9Sstevel@tonic-gate * problem occured. 1385*7c478bd9Sstevel@tonic-gate */ 1386*7c478bd9Sstevel@tonic-gate 1387*7c478bd9Sstevel@tonic-gate if ((ipp_rc = ipp_list_mods(&mid_array, &nelt)) == 0) { 1388*7c478bd9Sstevel@tonic-gate 1389*7c478bd9Sstevel@tonic-gate /* 1390*7c478bd9Sstevel@tonic-gate * It is possible that there are no modules 1391*7c478bd9Sstevel@tonic-gate * registered. 1392*7c478bd9Sstevel@tonic-gate */ 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate if (nelt > 0) { 1395*7c478bd9Sstevel@tonic-gate length = nelt * sizeof (char *); 1396*7c478bd9Sstevel@tonic-gate modname_array = kmem_zalloc(length, KM_SLEEP); 1397*7c478bd9Sstevel@tonic-gate 1398*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelt; i++) { 1399*7c478bd9Sstevel@tonic-gate if (ipp_mod_name(mid_array[i], 1400*7c478bd9Sstevel@tonic-gate &modname_array[i]) != 0) { 1401*7c478bd9Sstevel@tonic-gate kmem_free(mid_array, nelt * 1402*7c478bd9Sstevel@tonic-gate sizeof (ipp_mod_id_t)); 1403*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 1404*7c478bd9Sstevel@tonic-gate ipp_rc = EAGAIN; 1405*7c478bd9Sstevel@tonic-gate goto done; 1406*7c478bd9Sstevel@tonic-gate } 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate kmem_free(mid_array, nelt * sizeof (ipp_mod_id_t)); 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 1412*7c478bd9Sstevel@tonic-gate KM_SLEEP)) != 0) { 1413*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 1414*7c478bd9Sstevel@tonic-gate return (rc); 1415*7c478bd9Sstevel@tonic-gate } 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_attach_modname_array(nvlp, 1418*7c478bd9Sstevel@tonic-gate modname_array, nelt)) != 0) { 1419*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 1420*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1421*7c478bd9Sstevel@tonic-gate return (rc); 1422*7c478bd9Sstevel@tonic-gate } 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_callback(nvlp, NULL)) != 0) { 1427*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1428*7c478bd9Sstevel@tonic-gate return (rc); 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate } 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate done: 1436*7c478bd9Sstevel@tonic-gate /* 1437*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1438*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1439*7c478bd9Sstevel@tonic-gate */ 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 1442*7c478bd9Sstevel@tonic-gate return (rc); 1443*7c478bd9Sstevel@tonic-gate 1444*7c478bd9Sstevel@tonic-gate return (0); 1445*7c478bd9Sstevel@tonic-gate } 1446*7c478bd9Sstevel@tonic-gate #undef __FN__ 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_mod_list_actions" 1449*7c478bd9Sstevel@tonic-gate static int 1450*7c478bd9Sstevel@tonic-gate ippctl_mod_list_actions( 1451*7c478bd9Sstevel@tonic-gate char *modname) 1452*7c478bd9Sstevel@tonic-gate { 1453*7c478bd9Sstevel@tonic-gate ipp_mod_id_t mid; 1454*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 1455*7c478bd9Sstevel@tonic-gate int ipp_rc; 1456*7c478bd9Sstevel@tonic-gate int rc = 0; 1457*7c478bd9Sstevel@tonic-gate ipp_action_id_t *aid_array; 1458*7c478bd9Sstevel@tonic-gate char **aname_array = NULL; 1459*7c478bd9Sstevel@tonic-gate int nelt; 1460*7c478bd9Sstevel@tonic-gate int length; 1461*7c478bd9Sstevel@tonic-gate int i; 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate /* 1464*7c478bd9Sstevel@tonic-gate * Get the module id. 1465*7c478bd9Sstevel@tonic-gate */ 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate mid = ipp_mod_lookup(modname); 1468*7c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 1469*7c478bd9Sstevel@tonic-gate 1470*7c478bd9Sstevel@tonic-gate /* 1471*7c478bd9Sstevel@tonic-gate * Get a list of all the action ids for the module. If that succeeds, 1472*7c478bd9Sstevel@tonic-gate * translate the ids into names. 1473*7c478bd9Sstevel@tonic-gate * 1474*7c478bd9Sstevel@tonic-gate * NOTE: This translation may fail if an action is 1475*7c478bd9Sstevel@tonic-gate * destroyed during this operation. If this occurs, EAGAIN 1476*7c478bd9Sstevel@tonic-gate * will be passed back to libipp note that a transient 1477*7c478bd9Sstevel@tonic-gate * problem occured. 1478*7c478bd9Sstevel@tonic-gate */ 1479*7c478bd9Sstevel@tonic-gate 1480*7c478bd9Sstevel@tonic-gate if ((ipp_rc = ipp_mod_list_actions(mid, &aid_array, &nelt)) == 0) { 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate /* 1483*7c478bd9Sstevel@tonic-gate * It is possible that there are no actions defined. 1484*7c478bd9Sstevel@tonic-gate * (This is unlikely though as the module would normally 1485*7c478bd9Sstevel@tonic-gate * be auto-unloaded fairly quickly) 1486*7c478bd9Sstevel@tonic-gate */ 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate if (nelt > 0) { 1489*7c478bd9Sstevel@tonic-gate length = nelt * sizeof (char *); 1490*7c478bd9Sstevel@tonic-gate aname_array = kmem_zalloc(length, KM_SLEEP); 1491*7c478bd9Sstevel@tonic-gate 1492*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelt; i++) { 1493*7c478bd9Sstevel@tonic-gate if (ipp_action_name(aid_array[i], 1494*7c478bd9Sstevel@tonic-gate &aname_array[i]) != 0) { 1495*7c478bd9Sstevel@tonic-gate kmem_free(aid_array, nelt * 1496*7c478bd9Sstevel@tonic-gate sizeof (ipp_action_id_t)); 1497*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 1498*7c478bd9Sstevel@tonic-gate ipp_rc = EAGAIN; 1499*7c478bd9Sstevel@tonic-gate goto done; 1500*7c478bd9Sstevel@tonic-gate } 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate kmem_free(aid_array, nelt * sizeof (ipp_action_id_t)); 1504*7c478bd9Sstevel@tonic-gate 1505*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 1506*7c478bd9Sstevel@tonic-gate KM_SLEEP)) != 0) { 1507*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 1508*7c478bd9Sstevel@tonic-gate return (rc); 1509*7c478bd9Sstevel@tonic-gate } 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_attach_aname_array(nvlp, aname_array, 1512*7c478bd9Sstevel@tonic-gate nelt)) != 0) { 1513*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 1514*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1515*7c478bd9Sstevel@tonic-gate return (rc); 1516*7c478bd9Sstevel@tonic-gate } 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_callback(nvlp, NULL)) != 0) { 1521*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1522*7c478bd9Sstevel@tonic-gate return (rc); 1523*7c478bd9Sstevel@tonic-gate } 1524*7c478bd9Sstevel@tonic-gate 1525*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1526*7c478bd9Sstevel@tonic-gate } 1527*7c478bd9Sstevel@tonic-gate } 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate done: 1530*7c478bd9Sstevel@tonic-gate /* 1531*7c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 1532*7c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 1533*7c478bd9Sstevel@tonic-gate */ 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 1536*7c478bd9Sstevel@tonic-gate return (rc); 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate return (0); 1539*7c478bd9Sstevel@tonic-gate } 1540*7c478bd9Sstevel@tonic-gate #undef __FN__ 1541*7c478bd9Sstevel@tonic-gate 1542*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_data" 1543*7c478bd9Sstevel@tonic-gate static int 1544*7c478bd9Sstevel@tonic-gate ippctl_data( 1545*7c478bd9Sstevel@tonic-gate char **dbufp, 1546*7c478bd9Sstevel@tonic-gate size_t *dbuflenp, 1547*7c478bd9Sstevel@tonic-gate size_t *nextbuflenp) 1548*7c478bd9Sstevel@tonic-gate { 1549*7c478bd9Sstevel@tonic-gate int i; 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "called\n"); 1552*7c478bd9Sstevel@tonic-gate 1553*7c478bd9Sstevel@tonic-gate /* 1554*7c478bd9Sstevel@tonic-gate * Get the next data buffer from the array by looking at the 1555*7c478bd9Sstevel@tonic-gate * 'read index'. If this is the same as the 'write index' then 1556*7c478bd9Sstevel@tonic-gate * there's no more buffers in the array. 1557*7c478bd9Sstevel@tonic-gate */ 1558*7c478bd9Sstevel@tonic-gate 1559*7c478bd9Sstevel@tonic-gate i = ippctl_rindex; 1560*7c478bd9Sstevel@tonic-gate if (i == ippctl_windex) 1561*7c478bd9Sstevel@tonic-gate return (ENOENT); 1562*7c478bd9Sstevel@tonic-gate 1563*7c478bd9Sstevel@tonic-gate /* 1564*7c478bd9Sstevel@tonic-gate * Extract the buffer details. It is a pre-packed nvlist. 1565*7c478bd9Sstevel@tonic-gate */ 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate *dbufp = ippctl_array[i].buf; 1568*7c478bd9Sstevel@tonic-gate *dbuflenp = ippctl_array[i].buflen; 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate DBG2(DBG_CBOPS, "accessing nvlist[%d], length %lu\n", i, *dbuflenp); 1571*7c478bd9Sstevel@tonic-gate ASSERT(*dbufp != NULL); 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate /* 1574*7c478bd9Sstevel@tonic-gate * Advance the 'read index' and check if there's another buffer. 1575*7c478bd9Sstevel@tonic-gate * If there is then we need to pass back its length to libipp so that 1576*7c478bd9Sstevel@tonic-gate * another data ioctl will be issued. 1577*7c478bd9Sstevel@tonic-gate */ 1578*7c478bd9Sstevel@tonic-gate 1579*7c478bd9Sstevel@tonic-gate i++; 1580*7c478bd9Sstevel@tonic-gate if (i < ippctl_windex) 1581*7c478bd9Sstevel@tonic-gate *nextbuflenp = ippctl_array[i].buflen; 1582*7c478bd9Sstevel@tonic-gate else 1583*7c478bd9Sstevel@tonic-gate *nextbuflenp = 0; 1584*7c478bd9Sstevel@tonic-gate 1585*7c478bd9Sstevel@tonic-gate ippctl_rindex = i; 1586*7c478bd9Sstevel@tonic-gate return (0); 1587*7c478bd9Sstevel@tonic-gate } 1588*7c478bd9Sstevel@tonic-gate #undef __FN__ 1589*7c478bd9Sstevel@tonic-gate 1590*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_flush" 1591*7c478bd9Sstevel@tonic-gate static void 1592*7c478bd9Sstevel@tonic-gate ippctl_flush( 1593*7c478bd9Sstevel@tonic-gate void) 1594*7c478bd9Sstevel@tonic-gate { 1595*7c478bd9Sstevel@tonic-gate int i; 1596*7c478bd9Sstevel@tonic-gate char *buf; 1597*7c478bd9Sstevel@tonic-gate size_t buflen; 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate /* 1600*7c478bd9Sstevel@tonic-gate * Free any buffers left in the array. 1601*7c478bd9Sstevel@tonic-gate */ 1602*7c478bd9Sstevel@tonic-gate 1603*7c478bd9Sstevel@tonic-gate for (i = 0; i < ippctl_limit; i++) { 1604*7c478bd9Sstevel@tonic-gate if ((buflen = ippctl_array[i].buflen) > 0) { 1605*7c478bd9Sstevel@tonic-gate buf = ippctl_array[i].buf; 1606*7c478bd9Sstevel@tonic-gate ASSERT(buf != NULL); 1607*7c478bd9Sstevel@tonic-gate kmem_free(buf, buflen); 1608*7c478bd9Sstevel@tonic-gate } 1609*7c478bd9Sstevel@tonic-gate } 1610*7c478bd9Sstevel@tonic-gate 1611*7c478bd9Sstevel@tonic-gate /* 1612*7c478bd9Sstevel@tonic-gate * NULL all the entries. 1613*7c478bd9Sstevel@tonic-gate */ 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate bzero(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t)); 1616*7c478bd9Sstevel@tonic-gate 1617*7c478bd9Sstevel@tonic-gate /* 1618*7c478bd9Sstevel@tonic-gate * Reset the indexes. 1619*7c478bd9Sstevel@tonic-gate */ 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate ippctl_rindex = 0; 1622*7c478bd9Sstevel@tonic-gate ippctl_windex = 1; 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate #undef __FN__ 1625*7c478bd9Sstevel@tonic-gate 1626*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_add_nvlist" 1627*7c478bd9Sstevel@tonic-gate static int 1628*7c478bd9Sstevel@tonic-gate ippctl_add_nvlist( 1629*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 1630*7c478bd9Sstevel@tonic-gate int i) 1631*7c478bd9Sstevel@tonic-gate { 1632*7c478bd9Sstevel@tonic-gate char *buf; 1633*7c478bd9Sstevel@tonic-gate size_t buflen; 1634*7c478bd9Sstevel@tonic-gate int rc; 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate /* 1637*7c478bd9Sstevel@tonic-gate * NULL the buffer pointer so that a buffer is automatically 1638*7c478bd9Sstevel@tonic-gate * allocated for us. 1639*7c478bd9Sstevel@tonic-gate */ 1640*7c478bd9Sstevel@tonic-gate 1641*7c478bd9Sstevel@tonic-gate buf = NULL; 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate /* 1644*7c478bd9Sstevel@tonic-gate * Pack the nvlist and get back the buffer pointer and length. 1645*7c478bd9Sstevel@tonic-gate */ 1646*7c478bd9Sstevel@tonic-gate 1647*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_pack(nvlp, &buf, &buflen, NV_ENCODE_NATIVE, 1648*7c478bd9Sstevel@tonic-gate KM_SLEEP)) != 0) { 1649*7c478bd9Sstevel@tonic-gate ippctl_array[i].buf = NULL; 1650*7c478bd9Sstevel@tonic-gate ippctl_array[i].buflen = 0; 1651*7c478bd9Sstevel@tonic-gate return (rc); 1652*7c478bd9Sstevel@tonic-gate } 1653*7c478bd9Sstevel@tonic-gate 1654*7c478bd9Sstevel@tonic-gate DBG2(DBG_CBOPS, "added nvlist[%d]: length %lu\n", i, buflen); 1655*7c478bd9Sstevel@tonic-gate 1656*7c478bd9Sstevel@tonic-gate /* 1657*7c478bd9Sstevel@tonic-gate * Store the pointer an length in the array at the given index. 1658*7c478bd9Sstevel@tonic-gate */ 1659*7c478bd9Sstevel@tonic-gate 1660*7c478bd9Sstevel@tonic-gate ippctl_array[i].buf = buf; 1661*7c478bd9Sstevel@tonic-gate ippctl_array[i].buflen = buflen; 1662*7c478bd9Sstevel@tonic-gate 1663*7c478bd9Sstevel@tonic-gate return (0); 1664*7c478bd9Sstevel@tonic-gate } 1665*7c478bd9Sstevel@tonic-gate #undef __FN__ 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_callback" 1668*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1669*7c478bd9Sstevel@tonic-gate static int 1670*7c478bd9Sstevel@tonic-gate ippctl_callback( 1671*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 1672*7c478bd9Sstevel@tonic-gate void *arg) 1673*7c478bd9Sstevel@tonic-gate { 1674*7c478bd9Sstevel@tonic-gate int i; 1675*7c478bd9Sstevel@tonic-gate int rc; 1676*7c478bd9Sstevel@tonic-gate 1677*7c478bd9Sstevel@tonic-gate /* 1678*7c478bd9Sstevel@tonic-gate * Check the 'write index' to see if there's space in the array for 1679*7c478bd9Sstevel@tonic-gate * a new entry. 1680*7c478bd9Sstevel@tonic-gate */ 1681*7c478bd9Sstevel@tonic-gate 1682*7c478bd9Sstevel@tonic-gate i = ippctl_windex; 1683*7c478bd9Sstevel@tonic-gate ASSERT(i != 0); 1684*7c478bd9Sstevel@tonic-gate 1685*7c478bd9Sstevel@tonic-gate /* 1686*7c478bd9Sstevel@tonic-gate * If there's no space, re-allocate the array (see comments in 1687*7c478bd9Sstevel@tonic-gate * ippctl_realloc() for details). 1688*7c478bd9Sstevel@tonic-gate */ 1689*7c478bd9Sstevel@tonic-gate 1690*7c478bd9Sstevel@tonic-gate if (i == ippctl_limit) 1691*7c478bd9Sstevel@tonic-gate ippctl_realloc(); 1692*7c478bd9Sstevel@tonic-gate 1693*7c478bd9Sstevel@tonic-gate /* 1694*7c478bd9Sstevel@tonic-gate * Add the nvlist to the array. 1695*7c478bd9Sstevel@tonic-gate */ 1696*7c478bd9Sstevel@tonic-gate 1697*7c478bd9Sstevel@tonic-gate if ((rc = ippctl_add_nvlist(nvlp, i)) == 0) 1698*7c478bd9Sstevel@tonic-gate ippctl_windex++; 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate return (rc); 1701*7c478bd9Sstevel@tonic-gate } 1702*7c478bd9Sstevel@tonic-gate #undef __FN__ 1703*7c478bd9Sstevel@tonic-gate 1704*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_set_rc" 1705*7c478bd9Sstevel@tonic-gate static int 1706*7c478bd9Sstevel@tonic-gate ippctl_set_rc( 1707*7c478bd9Sstevel@tonic-gate int val) 1708*7c478bd9Sstevel@tonic-gate { 1709*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 1710*7c478bd9Sstevel@tonic-gate int rc; 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate /* 1713*7c478bd9Sstevel@tonic-gate * Create an nvlist to store the return code, 1714*7c478bd9Sstevel@tonic-gate */ 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_SLEEP)) != 0) 1717*7c478bd9Sstevel@tonic-gate return (ENOMEM); 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_int32(nvlp, IPPCTL_RC, val)) != 0) { 1720*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1721*7c478bd9Sstevel@tonic-gate return (rc); 1722*7c478bd9Sstevel@tonic-gate } 1723*7c478bd9Sstevel@tonic-gate 1724*7c478bd9Sstevel@tonic-gate /* 1725*7c478bd9Sstevel@tonic-gate * Add it at the beginning of the array. 1726*7c478bd9Sstevel@tonic-gate */ 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate rc = ippctl_add_nvlist(nvlp, 0); 1729*7c478bd9Sstevel@tonic-gate 1730*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 1731*7c478bd9Sstevel@tonic-gate return (rc); 1732*7c478bd9Sstevel@tonic-gate } 1733*7c478bd9Sstevel@tonic-gate #undef __FN__ 1734*7c478bd9Sstevel@tonic-gate 1735*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_alloc" 1736*7c478bd9Sstevel@tonic-gate static void 1737*7c478bd9Sstevel@tonic-gate ippctl_alloc( 1738*7c478bd9Sstevel@tonic-gate int limit) 1739*7c478bd9Sstevel@tonic-gate { 1740*7c478bd9Sstevel@tonic-gate /* 1741*7c478bd9Sstevel@tonic-gate * Allocate the data buffer array and initialize the indexes. 1742*7c478bd9Sstevel@tonic-gate */ 1743*7c478bd9Sstevel@tonic-gate 1744*7c478bd9Sstevel@tonic-gate ippctl_array = kmem_zalloc(limit * sizeof (ippctl_buf_t), KM_SLEEP); 1745*7c478bd9Sstevel@tonic-gate ippctl_limit = limit; 1746*7c478bd9Sstevel@tonic-gate ippctl_rindex = 0; 1747*7c478bd9Sstevel@tonic-gate ippctl_windex = 1; 1748*7c478bd9Sstevel@tonic-gate } 1749*7c478bd9Sstevel@tonic-gate #undef __FN__ 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_realloc" 1752*7c478bd9Sstevel@tonic-gate static void 1753*7c478bd9Sstevel@tonic-gate ippctl_realloc( 1754*7c478bd9Sstevel@tonic-gate void) 1755*7c478bd9Sstevel@tonic-gate { 1756*7c478bd9Sstevel@tonic-gate ippctl_buf_t *array; 1757*7c478bd9Sstevel@tonic-gate int limit; 1758*7c478bd9Sstevel@tonic-gate int i; 1759*7c478bd9Sstevel@tonic-gate 1760*7c478bd9Sstevel@tonic-gate /* 1761*7c478bd9Sstevel@tonic-gate * Allocate a new array twice the size of the old one. 1762*7c478bd9Sstevel@tonic-gate */ 1763*7c478bd9Sstevel@tonic-gate 1764*7c478bd9Sstevel@tonic-gate limit = ippctl_limit << 1; 1765*7c478bd9Sstevel@tonic-gate array = kmem_zalloc(limit * sizeof (ippctl_buf_t), KM_SLEEP); 1766*7c478bd9Sstevel@tonic-gate 1767*7c478bd9Sstevel@tonic-gate /* 1768*7c478bd9Sstevel@tonic-gate * Copy across the information from the old array into the new one. 1769*7c478bd9Sstevel@tonic-gate */ 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate for (i = 0; i < ippctl_limit; i++) 1772*7c478bd9Sstevel@tonic-gate array[i] = ippctl_array[i]; 1773*7c478bd9Sstevel@tonic-gate 1774*7c478bd9Sstevel@tonic-gate /* 1775*7c478bd9Sstevel@tonic-gate * Free the old array. 1776*7c478bd9Sstevel@tonic-gate */ 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate kmem_free(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t)); 1779*7c478bd9Sstevel@tonic-gate 1780*7c478bd9Sstevel@tonic-gate ippctl_array = array; 1781*7c478bd9Sstevel@tonic-gate ippctl_limit = limit; 1782*7c478bd9Sstevel@tonic-gate } 1783*7c478bd9Sstevel@tonic-gate #undef __FN__ 1784*7c478bd9Sstevel@tonic-gate 1785*7c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_free" 1786*7c478bd9Sstevel@tonic-gate static void 1787*7c478bd9Sstevel@tonic-gate ippctl_free( 1788*7c478bd9Sstevel@tonic-gate void) 1789*7c478bd9Sstevel@tonic-gate { 1790*7c478bd9Sstevel@tonic-gate /* 1791*7c478bd9Sstevel@tonic-gate * Flush the array prior to freeing it to make sure no buffers are 1792*7c478bd9Sstevel@tonic-gate * leaked. 1793*7c478bd9Sstevel@tonic-gate */ 1794*7c478bd9Sstevel@tonic-gate 1795*7c478bd9Sstevel@tonic-gate ippctl_flush(); 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate /* 1798*7c478bd9Sstevel@tonic-gate * Free the array. 1799*7c478bd9Sstevel@tonic-gate */ 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate kmem_free(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t)); 1802*7c478bd9Sstevel@tonic-gate ippctl_array = NULL; 1803*7c478bd9Sstevel@tonic-gate ippctl_limit = -1; 1804*7c478bd9Sstevel@tonic-gate ippctl_rindex = -1; 1805*7c478bd9Sstevel@tonic-gate ippctl_windex = -1; 1806*7c478bd9Sstevel@tonic-gate } 1807*7c478bd9Sstevel@tonic-gate #undef __FN__ 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate #ifdef IPPCTL_DEBUG 1810*7c478bd9Sstevel@tonic-gate static void 1811*7c478bd9Sstevel@tonic-gate ippctl_debug( 1812*7c478bd9Sstevel@tonic-gate uint64_t type, 1813*7c478bd9Sstevel@tonic-gate char *fn, 1814*7c478bd9Sstevel@tonic-gate char *fmt, 1815*7c478bd9Sstevel@tonic-gate ...) 1816*7c478bd9Sstevel@tonic-gate { 1817*7c478bd9Sstevel@tonic-gate char buf[255]; 1818*7c478bd9Sstevel@tonic-gate va_list adx; 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate if ((type & ippctl_debug_flags) == 0) 1821*7c478bd9Sstevel@tonic-gate return; 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate mutex_enter(debug_mutex); 1824*7c478bd9Sstevel@tonic-gate va_start(adx, fmt); 1825*7c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, 255, fmt, adx); 1826*7c478bd9Sstevel@tonic-gate va_end(adx); 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate printf("%s: %s", fn, buf); 1829*7c478bd9Sstevel@tonic-gate mutex_exit(debug_mutex); 1830*7c478bd9Sstevel@tonic-gate } 1831*7c478bd9Sstevel@tonic-gate #endif /* IPPCTL_DBG */ 1832