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