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 2001-2002 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 #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 33*7c478bd9Sstevel@tonic-gate #include <unistd.h> 34*7c478bd9Sstevel@tonic-gate #include <errno.h> 35*7c478bd9Sstevel@tonic-gate #include <strings.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 38*7c478bd9Sstevel@tonic-gate #include <assert.h> 39*7c478bd9Sstevel@tonic-gate #include <libipp.h> 40*7c478bd9Sstevel@tonic-gate #include <libnvpair.h> 41*7c478bd9Sstevel@tonic-gate #include <ipp/ippctl.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * Debug macros 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) && !defined(lint) 48*7c478bd9Sstevel@tonic-gate uint32_t ipp_debug_flags = 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * DBG_IO | 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate DBG_ERR | 53*7c478bd9Sstevel@tonic-gate 0; 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #define DBG0(flags, fmt) \ 56*7c478bd9Sstevel@tonic-gate do { \ 57*7c478bd9Sstevel@tonic-gate if (flags & ipp_debug_flags) \ 58*7c478bd9Sstevel@tonic-gate fprintf(stderr, "libipp: " __FN__ ": " fmt); \ 59*7c478bd9Sstevel@tonic-gate } while (0) 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #define DBG1(flags, fmt, a) \ 62*7c478bd9Sstevel@tonic-gate do { \ 63*7c478bd9Sstevel@tonic-gate if (flags & ipp_debug_flags) \ 64*7c478bd9Sstevel@tonic-gate fprintf(stderr, "libipp: " __FN__ ": " fmt, a); \ 65*7c478bd9Sstevel@tonic-gate } while (0) 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate #define DBG2(flags, fmt, a, b) \ 68*7c478bd9Sstevel@tonic-gate do { \ 69*7c478bd9Sstevel@tonic-gate if (flags & ipp_debug_flags) \ 70*7c478bd9Sstevel@tonic-gate fprintf(stderr, "libipp: " __FN__ ": " fmt, a, \ 71*7c478bd9Sstevel@tonic-gate b); \ 72*7c478bd9Sstevel@tonic-gate } while (0) 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #define DBG3(flags, fmt, a, b, c) \ 75*7c478bd9Sstevel@tonic-gate do { \ 76*7c478bd9Sstevel@tonic-gate if (flags & ipp_debug_flags) \ 77*7c478bd9Sstevel@tonic-gate fprintf(stderr, "libipp: " __FN__ ": " fmt, a, \ 78*7c478bd9Sstevel@tonic-gate b, c); \ 79*7c478bd9Sstevel@tonic-gate } while (0) 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #else /* defined(DEBUG) && !defined(lint) */ 82*7c478bd9Sstevel@tonic-gate #define DBG0(flags, fmt) 83*7c478bd9Sstevel@tonic-gate #define DBG1(flags, fmt, a) 84*7c478bd9Sstevel@tonic-gate #define DBG2(flags, fmt, a, b) 85*7c478bd9Sstevel@tonic-gate #define DBG3(flags, fmt, a, b, c) 86*7c478bd9Sstevel@tonic-gate #endif /* defined(DEBUG) && !defined(lint) */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate /* 89*7c478bd9Sstevel@tonic-gate * Control device node 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate #define IPPCTL_DEVICE "/devices/pseudo/ippctl@0:ctl" 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 95*7c478bd9Sstevel@tonic-gate * Structures. 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate typedef struct array_desc_t { 99*7c478bd9Sstevel@tonic-gate char *name; 100*7c478bd9Sstevel@tonic-gate char **array; 101*7c478bd9Sstevel@tonic-gate int nelt; 102*7c478bd9Sstevel@tonic-gate } array_desc_t; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * Prototypes 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate static int nvlist_callback(nvlist_t *, void *); 109*7c478bd9Sstevel@tonic-gate static int string_callback(nvlist_t *, void *); 110*7c478bd9Sstevel@tonic-gate static int string_array_callback(nvlist_t *, void *); 111*7c478bd9Sstevel@tonic-gate static int dispatch(nvlist_t **, int (*)(nvlist_t *, void *), void *); 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * API functions 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_create" 117*7c478bd9Sstevel@tonic-gate int 118*7c478bd9Sstevel@tonic-gate ipp_action_create( 119*7c478bd9Sstevel@tonic-gate const char *modname, 120*7c478bd9Sstevel@tonic-gate const char *aname, 121*7c478bd9Sstevel@tonic-gate nvlist_t **nvlpp, 122*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 125*7c478bd9Sstevel@tonic-gate int rc; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate if (nvlpp == NULL || modname == NULL || aname == NULL) { 132*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument\n"); 133*7c478bd9Sstevel@tonic-gate errno = EINVAL; 134*7c478bd9Sstevel@tonic-gate return (-1); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* 138*7c478bd9Sstevel@tonic-gate * Add our data to the nvlist. (This information will be removed for 139*7c478bd9Sstevel@tonic-gate * use by ippctl). 140*7c478bd9Sstevel@tonic-gate */ 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate nvlp = *nvlpp; 143*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 144*7c478bd9Sstevel@tonic-gate IPPCTL_OP_ACTION_CREATE)) != 0) { 145*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 146*7c478bd9Sstevel@tonic-gate goto failed; 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_MODNAME, 150*7c478bd9Sstevel@tonic-gate (char *)modname)) != 0) { 151*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", 152*7c478bd9Sstevel@tonic-gate IPPCTL_MODNAME); 153*7c478bd9Sstevel@tonic-gate goto failed; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) { 157*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME); 158*7c478bd9Sstevel@tonic-gate goto failed; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) { 162*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS); 163*7c478bd9Sstevel@tonic-gate goto failed; 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 168*7c478bd9Sstevel@tonic-gate */ 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate return (dispatch(nvlpp, nvlist_callback, (void *)nvlpp)); 171*7c478bd9Sstevel@tonic-gate failed: 172*7c478bd9Sstevel@tonic-gate errno = rc; 173*7c478bd9Sstevel@tonic-gate return (-1); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate #undef __FN__ 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_destroy" 178*7c478bd9Sstevel@tonic-gate int 179*7c478bd9Sstevel@tonic-gate ipp_action_destroy( 180*7c478bd9Sstevel@tonic-gate const char *aname, 181*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 184*7c478bd9Sstevel@tonic-gate int rc; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (aname == NULL) { 191*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument\n"); 192*7c478bd9Sstevel@tonic-gate errno = EINVAL; 193*7c478bd9Sstevel@tonic-gate return (-1); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * Create an nvlist for our data as none is passed into the function. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) { 201*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to allocate nvlist\n"); 202*7c478bd9Sstevel@tonic-gate nvlp = NULL; 203*7c478bd9Sstevel@tonic-gate goto failed; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 207*7c478bd9Sstevel@tonic-gate IPPCTL_OP_ACTION_DESTROY)) != 0) { 208*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 209*7c478bd9Sstevel@tonic-gate goto failed; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) { 213*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME); 214*7c478bd9Sstevel@tonic-gate goto failed; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) { 218*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS); 219*7c478bd9Sstevel@tonic-gate goto failed; 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate return (dispatch(&nvlp, NULL, NULL)); 227*7c478bd9Sstevel@tonic-gate failed: 228*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) 229*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 230*7c478bd9Sstevel@tonic-gate errno = rc; 231*7c478bd9Sstevel@tonic-gate return (-1); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate #undef __FN__ 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_modify" 236*7c478bd9Sstevel@tonic-gate int 237*7c478bd9Sstevel@tonic-gate ipp_action_modify( 238*7c478bd9Sstevel@tonic-gate const char *aname, 239*7c478bd9Sstevel@tonic-gate nvlist_t **nvlpp, 240*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 241*7c478bd9Sstevel@tonic-gate { 242*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 243*7c478bd9Sstevel@tonic-gate int rc; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* 246*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (nvlpp == NULL || aname == NULL) { 250*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument\n"); 251*7c478bd9Sstevel@tonic-gate errno = EINVAL; 252*7c478bd9Sstevel@tonic-gate return (-1); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* 256*7c478bd9Sstevel@tonic-gate * Add our data to the nvlist. 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate nvlp = *nvlpp; 260*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 261*7c478bd9Sstevel@tonic-gate IPPCTL_OP_ACTION_MODIFY)) != 0) { 262*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 263*7c478bd9Sstevel@tonic-gate goto failed; 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) { 267*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME); 268*7c478bd9Sstevel@tonic-gate goto failed; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) { 272*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS); 273*7c478bd9Sstevel@tonic-gate goto failed; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate return (dispatch(nvlpp, nvlist_callback, (void *)nvlpp)); 281*7c478bd9Sstevel@tonic-gate failed: 282*7c478bd9Sstevel@tonic-gate errno = rc; 283*7c478bd9Sstevel@tonic-gate return (-1); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate #undef __FN__ 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_info" 288*7c478bd9Sstevel@tonic-gate int 289*7c478bd9Sstevel@tonic-gate ipp_action_info( 290*7c478bd9Sstevel@tonic-gate const char *aname, 291*7c478bd9Sstevel@tonic-gate int (*fn)(nvlist_t *, void *), 292*7c478bd9Sstevel@tonic-gate void *arg, 293*7c478bd9Sstevel@tonic-gate ipp_flags_t flags) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 296*7c478bd9Sstevel@tonic-gate int rc; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if (aname == NULL || fn == NULL) { 303*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument\n"); 304*7c478bd9Sstevel@tonic-gate errno = EINVAL; 305*7c478bd9Sstevel@tonic-gate return (-1); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * Create an nvlist for our data. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) { 313*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to allocate nvlist\n"); 314*7c478bd9Sstevel@tonic-gate nvlp = NULL; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 318*7c478bd9Sstevel@tonic-gate IPPCTL_OP_ACTION_INFO)) != 0) { 319*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 320*7c478bd9Sstevel@tonic-gate goto failed; 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) { 324*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME); 325*7c478bd9Sstevel@tonic-gate goto failed; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) { 329*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS); 330*7c478bd9Sstevel@tonic-gate goto failed; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate return (dispatch(&nvlp, fn, arg)); 338*7c478bd9Sstevel@tonic-gate failed: 339*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) 340*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 341*7c478bd9Sstevel@tonic-gate errno = rc; 342*7c478bd9Sstevel@tonic-gate return (-1); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate #undef __FN__ 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_mod" 347*7c478bd9Sstevel@tonic-gate int 348*7c478bd9Sstevel@tonic-gate ipp_action_mod( 349*7c478bd9Sstevel@tonic-gate const char *aname, 350*7c478bd9Sstevel@tonic-gate char **modnamep) 351*7c478bd9Sstevel@tonic-gate { 352*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 353*7c478bd9Sstevel@tonic-gate int rc; 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* 356*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 357*7c478bd9Sstevel@tonic-gate */ 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate if (aname == NULL || modnamep == NULL) { 360*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument\n"); 361*7c478bd9Sstevel@tonic-gate errno = EINVAL; 362*7c478bd9Sstevel@tonic-gate return (-1); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Create an nvlist for our data. 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) { 370*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to allocate nvlist\n"); 371*7c478bd9Sstevel@tonic-gate nvlp = NULL; 372*7c478bd9Sstevel@tonic-gate goto failed; 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 376*7c478bd9Sstevel@tonic-gate IPPCTL_OP_ACTION_MOD)) != 0) { 377*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 378*7c478bd9Sstevel@tonic-gate goto failed; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) { 382*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME); 383*7c478bd9Sstevel@tonic-gate goto failed; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* 387*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate return (dispatch(&nvlp, string_callback, (void *)modnamep)); 391*7c478bd9Sstevel@tonic-gate failed: 392*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) 393*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 394*7c478bd9Sstevel@tonic-gate errno = rc; 395*7c478bd9Sstevel@tonic-gate return (-1); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate #undef __FN__ 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_list_mods" 400*7c478bd9Sstevel@tonic-gate int 401*7c478bd9Sstevel@tonic-gate ipp_list_mods( 402*7c478bd9Sstevel@tonic-gate char ***modname_arrayp, 403*7c478bd9Sstevel@tonic-gate int *neltp) 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 406*7c478bd9Sstevel@tonic-gate array_desc_t ad; 407*7c478bd9Sstevel@tonic-gate int rc; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (modname_arrayp == NULL || neltp == NULL) { 414*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument"); 415*7c478bd9Sstevel@tonic-gate errno = EINVAL; 416*7c478bd9Sstevel@tonic-gate return (-1); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * Create an nvlist for our data. 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) { 424*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to allocate nvlist\n"); 425*7c478bd9Sstevel@tonic-gate nvlp = NULL; 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 429*7c478bd9Sstevel@tonic-gate IPPCTL_OP_LIST_MODS)) != 0) { 430*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 431*7c478bd9Sstevel@tonic-gate goto failed; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate ad.name = IPPCTL_MODNAME_ARRAY; 439*7c478bd9Sstevel@tonic-gate ad.array = NULL; 440*7c478bd9Sstevel@tonic-gate ad.nelt = 0; 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if ((rc = dispatch(&nvlp, string_array_callback, (void *)&ad)) == 0) { 443*7c478bd9Sstevel@tonic-gate *modname_arrayp = ad.array; 444*7c478bd9Sstevel@tonic-gate *neltp = ad.nelt; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate return (rc); 448*7c478bd9Sstevel@tonic-gate failed: 449*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) 450*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 451*7c478bd9Sstevel@tonic-gate errno = rc; 452*7c478bd9Sstevel@tonic-gate return (-1); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate #undef __FN__ 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_mod_list_actions" 457*7c478bd9Sstevel@tonic-gate int 458*7c478bd9Sstevel@tonic-gate ipp_mod_list_actions( 459*7c478bd9Sstevel@tonic-gate const char *modname, 460*7c478bd9Sstevel@tonic-gate char ***aname_arrayp, 461*7c478bd9Sstevel@tonic-gate int *neltp) 462*7c478bd9Sstevel@tonic-gate { 463*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 464*7c478bd9Sstevel@tonic-gate array_desc_t ad; 465*7c478bd9Sstevel@tonic-gate int rc; 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * Sanity check the arguments. 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate if (modname == NULL || aname_arrayp == NULL || neltp == NULL) { 472*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "bad argument"); 473*7c478bd9Sstevel@tonic-gate errno = EINVAL; 474*7c478bd9Sstevel@tonic-gate return (-1); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * Create an nvlist for our data. 479*7c478bd9Sstevel@tonic-gate */ 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) { 482*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to allocate nvlist\n"); 483*7c478bd9Sstevel@tonic-gate nvlp = NULL; 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP, 487*7c478bd9Sstevel@tonic-gate IPPCTL_OP_MOD_LIST_ACTIONS)) != 0) { 488*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP); 489*7c478bd9Sstevel@tonic-gate goto failed; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_string(nvlp, IPPCTL_MODNAME, 493*7c478bd9Sstevel@tonic-gate (char *)modname)) != 0) { 494*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_MODNAME); 495*7c478bd9Sstevel@tonic-gate goto failed; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate /* 499*7c478bd9Sstevel@tonic-gate * Talk to the kernel. 500*7c478bd9Sstevel@tonic-gate */ 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate ad.name = IPPCTL_ANAME_ARRAY; 503*7c478bd9Sstevel@tonic-gate ad.array = NULL; 504*7c478bd9Sstevel@tonic-gate ad.nelt = 0; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if ((rc = dispatch(&nvlp, string_array_callback, (void *)&ad)) == 0) { 507*7c478bd9Sstevel@tonic-gate *aname_arrayp = ad.array; 508*7c478bd9Sstevel@tonic-gate *neltp = ad.nelt; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate return (rc); 512*7c478bd9Sstevel@tonic-gate failed: 513*7c478bd9Sstevel@tonic-gate if (nvlp != NULL) 514*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 515*7c478bd9Sstevel@tonic-gate errno = rc; 516*7c478bd9Sstevel@tonic-gate return (-1); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate #undef __FN__ 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_free" 521*7c478bd9Sstevel@tonic-gate void 522*7c478bd9Sstevel@tonic-gate ipp_free( 523*7c478bd9Sstevel@tonic-gate char *buf) 524*7c478bd9Sstevel@tonic-gate { 525*7c478bd9Sstevel@tonic-gate free(buf); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate #undef __FN__ 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate #define __FN__ "ipp_free_array" 530*7c478bd9Sstevel@tonic-gate void 531*7c478bd9Sstevel@tonic-gate ipp_free_array( 532*7c478bd9Sstevel@tonic-gate char **array, 533*7c478bd9Sstevel@tonic-gate int nelt) 534*7c478bd9Sstevel@tonic-gate { 535*7c478bd9Sstevel@tonic-gate int i; 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate assert(array[nelt] == NULL); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelt; i++) 540*7c478bd9Sstevel@tonic-gate free(array[i]); 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate free(array); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate #undef __FN__ 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate #define __FN__ "nvlist_callback" 547*7c478bd9Sstevel@tonic-gate static int 548*7c478bd9Sstevel@tonic-gate nvlist_callback( 549*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 550*7c478bd9Sstevel@tonic-gate void *arg) 551*7c478bd9Sstevel@tonic-gate { 552*7c478bd9Sstevel@tonic-gate nvlist_t **nvlpp = (nvlist_t **)arg; 553*7c478bd9Sstevel@tonic-gate int rc; 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate /* 556*7c478bd9Sstevel@tonic-gate * Callback function used by ipp_action_create() and 557*7c478bd9Sstevel@tonic-gate * ipp_action_modify() 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate DBG0(DBG_IO, "called\n"); 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate assert(nvlpp != NULL); 563*7c478bd9Sstevel@tonic-gate assert(*nvlpp == NULL); 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * Duplicate the nvlist and set the given pointer to point at the new 567*7c478bd9Sstevel@tonic-gate * copy. 568*7c478bd9Sstevel@tonic-gate */ 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_dup(nvlp, nvlpp, 0)) != 0) { 571*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to dup nvlist\n"); 572*7c478bd9Sstevel@tonic-gate errno = rc; 573*7c478bd9Sstevel@tonic-gate return (-1); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate return (0); 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate #undef __FN__ 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate #define __FN__ "string_callback" 581*7c478bd9Sstevel@tonic-gate static int 582*7c478bd9Sstevel@tonic-gate string_callback( 583*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 584*7c478bd9Sstevel@tonic-gate void *arg) 585*7c478bd9Sstevel@tonic-gate { 586*7c478bd9Sstevel@tonic-gate char **namep = (char **)arg; 587*7c478bd9Sstevel@tonic-gate char *name; 588*7c478bd9Sstevel@tonic-gate char *ptr; 589*7c478bd9Sstevel@tonic-gate int rc; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* 592*7c478bd9Sstevel@tonic-gate * Callback function used by ipp_action_mod() 593*7c478bd9Sstevel@tonic-gate */ 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate DBG0(DBG_IO, "called\n"); 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate assert(namep != NULL); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate /* 600*7c478bd9Sstevel@tonic-gate * Look up the module name from the nvlist. 601*7c478bd9Sstevel@tonic-gate */ 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_MODNAME, &ptr)) != 0) { 604*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to find string\n"); 605*7c478bd9Sstevel@tonic-gate errno = rc; 606*7c478bd9Sstevel@tonic-gate return (-1); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate /* 610*7c478bd9Sstevel@tonic-gate * Allocate a duplicate string. 611*7c478bd9Sstevel@tonic-gate */ 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate if ((name = strdup(ptr)) == NULL) { 614*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to duplicate string\n"); 615*7c478bd9Sstevel@tonic-gate return (-1); 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate * Set the given pointer to point at the string. 620*7c478bd9Sstevel@tonic-gate */ 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate *namep = name; 623*7c478bd9Sstevel@tonic-gate return (0); 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate #undef __FN__ 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate #define __FN__ "string_array_callback" 628*7c478bd9Sstevel@tonic-gate static int 629*7c478bd9Sstevel@tonic-gate string_array_callback( 630*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 631*7c478bd9Sstevel@tonic-gate void *arg) 632*7c478bd9Sstevel@tonic-gate { 633*7c478bd9Sstevel@tonic-gate array_desc_t *adp = (array_desc_t *)arg; 634*7c478bd9Sstevel@tonic-gate char **dst; 635*7c478bd9Sstevel@tonic-gate char **src; 636*7c478bd9Sstevel@tonic-gate uint_t nelt; 637*7c478bd9Sstevel@tonic-gate int i; 638*7c478bd9Sstevel@tonic-gate int rc; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * Callback function used by ipp_list_mods() 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate DBG0(DBG_IO, "called\n"); 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate assert(adp != NULL); 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate /* 649*7c478bd9Sstevel@tonic-gate * Look up the module name from the nvlist. 650*7c478bd9Sstevel@tonic-gate */ 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_string_array(nvlp, adp->name, &src, 653*7c478bd9Sstevel@tonic-gate &nelt)) != 0) { 654*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to find array\n"); 655*7c478bd9Sstevel@tonic-gate errno = rc; 656*7c478bd9Sstevel@tonic-gate return (-1); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate /* 660*7c478bd9Sstevel@tonic-gate * Allocate an array. 661*7c478bd9Sstevel@tonic-gate */ 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate if ((dst = malloc((nelt + 1) * sizeof (char *))) == NULL) { 664*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to allocate new array\n"); 665*7c478bd9Sstevel@tonic-gate return (-1); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate /* 669*7c478bd9Sstevel@tonic-gate * For each string in the array, allocate a new buffer and copy 670*7c478bd9Sstevel@tonic-gate * the string into it. 671*7c478bd9Sstevel@tonic-gate */ 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelt; i++) { 674*7c478bd9Sstevel@tonic-gate if ((dst[i] = strdup(src[i])) == NULL) { 675*7c478bd9Sstevel@tonic-gate while (--i >= 0) { 676*7c478bd9Sstevel@tonic-gate free(dst[i]); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate free(dst); 679*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to duplicate array\n"); 680*7c478bd9Sstevel@tonic-gate return (-1); 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate dst[nelt] = NULL; 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * Set the information to be passed back. 687*7c478bd9Sstevel@tonic-gate */ 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate adp->array = dst; 690*7c478bd9Sstevel@tonic-gate adp->nelt = nelt; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate return (0); 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate #undef __FN__ 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate #define __FN__ "dispatch" 697*7c478bd9Sstevel@tonic-gate static int 698*7c478bd9Sstevel@tonic-gate dispatch( 699*7c478bd9Sstevel@tonic-gate nvlist_t **nvlpp, 700*7c478bd9Sstevel@tonic-gate int (*fn)(nvlist_t *, void *), 701*7c478bd9Sstevel@tonic-gate void *arg) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate char *cbuf = NULL; 704*7c478bd9Sstevel@tonic-gate char *dbuf = NULL; 705*7c478bd9Sstevel@tonic-gate size_t cbuflen = 0; 706*7c478bd9Sstevel@tonic-gate size_t dbuflen = 0; 707*7c478bd9Sstevel@tonic-gate size_t thisbuflen = 0; 708*7c478bd9Sstevel@tonic-gate size_t nextbuflen = 0; 709*7c478bd9Sstevel@tonic-gate int rc; 710*7c478bd9Sstevel@tonic-gate ippctl_ioctl_t iioc; 711*7c478bd9Sstevel@tonic-gate int fd; 712*7c478bd9Sstevel@tonic-gate nvlist_t *cnvlp; 713*7c478bd9Sstevel@tonic-gate nvlist_t *dnvlp = NULL; 714*7c478bd9Sstevel@tonic-gate int count; 715*7c478bd9Sstevel@tonic-gate int rval; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate /* 718*7c478bd9Sstevel@tonic-gate * Sanity check the 'command' nvlist. 719*7c478bd9Sstevel@tonic-gate */ 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate cnvlp = *nvlpp; 722*7c478bd9Sstevel@tonic-gate if (cnvlp == NULL) { 723*7c478bd9Sstevel@tonic-gate rc = EINVAL; 724*7c478bd9Sstevel@tonic-gate return (-1); 725*7c478bd9Sstevel@tonic-gate } 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate /* 728*7c478bd9Sstevel@tonic-gate * Pack the nvlist and then free the original. 729*7c478bd9Sstevel@tonic-gate */ 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_pack(cnvlp, &cbuf, &cbuflen, NV_ENCODE_NATIVE, 732*7c478bd9Sstevel@tonic-gate 0)) != 0) { 733*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to pack nvlist\n"); 734*7c478bd9Sstevel@tonic-gate nvlist_free(cnvlp); 735*7c478bd9Sstevel@tonic-gate errno = rc; 736*7c478bd9Sstevel@tonic-gate return (-1); 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate nvlist_free(cnvlp); 739*7c478bd9Sstevel@tonic-gate *nvlpp = NULL; 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate /* 742*7c478bd9Sstevel@tonic-gate * Open the control device node. 743*7c478bd9Sstevel@tonic-gate */ 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate DBG1(DBG_IO, "opening %s\n", IPPCTL_DEVICE); 746*7c478bd9Sstevel@tonic-gate if ((fd = open(IPPCTL_DEVICE, O_RDWR | O_NOCTTY)) == -1) { 747*7c478bd9Sstevel@tonic-gate DBG1(DBG_ERR, "failed to open %s\n", IPPCTL_DEVICE); 748*7c478bd9Sstevel@tonic-gate goto command_failed; 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate /* 752*7c478bd9Sstevel@tonic-gate * Set up an ioctl structure to point at the packed nvlist. 753*7c478bd9Sstevel@tonic-gate */ 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate iioc.ii_buf = cbuf; 756*7c478bd9Sstevel@tonic-gate iioc.ii_buflen = cbuflen; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate /* 759*7c478bd9Sstevel@tonic-gate * Issue a command ioctl, passing the ioctl structure. 760*7c478bd9Sstevel@tonic-gate */ 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate DBG0(DBG_IO, "command\n"); 763*7c478bd9Sstevel@tonic-gate if ((rc = ioctl(fd, IPPCTL_CMD, &iioc)) < 0) { 764*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "command ioctl failed\n"); 765*7c478bd9Sstevel@tonic-gate goto command_failed; 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate /* 769*7c478bd9Sstevel@tonic-gate * Get back the length of the first data buffer. 770*7c478bd9Sstevel@tonic-gate */ 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate if ((nextbuflen = (size_t)rc) == 0) { 773*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "no data buffer\n"); 774*7c478bd9Sstevel@tonic-gate errno = EPROTO; 775*7c478bd9Sstevel@tonic-gate goto command_failed; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate /* 779*7c478bd9Sstevel@tonic-gate * Try to re-use the command buffer as the first data buffer. 780*7c478bd9Sstevel@tonic-gate */ 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate dbuf = cbuf; 783*7c478bd9Sstevel@tonic-gate thisbuflen = cbuflen; 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate count = 0; 786*7c478bd9Sstevel@tonic-gate while (nextbuflen != 0) { 787*7c478bd9Sstevel@tonic-gate dbuflen = nextbuflen; 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate /* 790*7c478bd9Sstevel@tonic-gate * Check whether the buffer we have is long enough for the 791*7c478bd9Sstevel@tonic-gate * next lot of data. If it isn't, allocate a new one of 792*7c478bd9Sstevel@tonic-gate * the appropriate length. 793*7c478bd9Sstevel@tonic-gate */ 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate if (nextbuflen > thisbuflen) { 796*7c478bd9Sstevel@tonic-gate if ((dbuf = realloc(dbuf, nextbuflen)) == NULL) { 797*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, 798*7c478bd9Sstevel@tonic-gate "failed to allocate data buffer\n"); 799*7c478bd9Sstevel@tonic-gate goto data_failed; 800*7c478bd9Sstevel@tonic-gate } 801*7c478bd9Sstevel@tonic-gate thisbuflen = nextbuflen; 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* 805*7c478bd9Sstevel@tonic-gate * Set up an ioctl structure to point at the data buffer. 806*7c478bd9Sstevel@tonic-gate */ 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate iioc.ii_buf = dbuf; 809*7c478bd9Sstevel@tonic-gate iioc.ii_buflen = dbuflen; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate /* 812*7c478bd9Sstevel@tonic-gate * Issue a data ioctl, passing the ioctl structure. 813*7c478bd9Sstevel@tonic-gate */ 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate DBG2(DBG_IO, "data[%d]: length = %d\n", count, dbuflen); 816*7c478bd9Sstevel@tonic-gate if ((rc = ioctl(fd, IPPCTL_DATA, &iioc)) < 0) { 817*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "data ioctl failed\n"); 818*7c478bd9Sstevel@tonic-gate goto data_failed; 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Get the length of the *next* data buffer, if there is 823*7c478bd9Sstevel@tonic-gate * one. 824*7c478bd9Sstevel@tonic-gate */ 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate nextbuflen = (size_t)rc; 827*7c478bd9Sstevel@tonic-gate DBG1(DBG_IO, "nextbuflen = %d\n", nextbuflen); 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate /* 830*7c478bd9Sstevel@tonic-gate * Unpack the nvlist that the current data buffer should 831*7c478bd9Sstevel@tonic-gate * now contain. 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_unpack(dbuf, dbuflen, &dnvlp, 0)) != 0) { 835*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to unpack nvlist\n"); 836*7c478bd9Sstevel@tonic-gate errno = rc; 837*7c478bd9Sstevel@tonic-gate goto data_failed; 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* 841*7c478bd9Sstevel@tonic-gate * The first data buffer should contain the kernel function's 842*7c478bd9Sstevel@tonic-gate * return code. Subsequent buffers contain nvlists which 843*7c478bd9Sstevel@tonic-gate * should be passed to the given callback function. 844*7c478bd9Sstevel@tonic-gate */ 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate if (count == 0) { 847*7c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_int32(dnvlp, IPPCTL_RC, 848*7c478bd9Sstevel@tonic-gate &rval)) != 0) { 849*7c478bd9Sstevel@tonic-gate DBG0(DBG_ERR, "failed to find return code\n"); 850*7c478bd9Sstevel@tonic-gate nvlist_free(dnvlp); 851*7c478bd9Sstevel@tonic-gate errno = rc; 852*7c478bd9Sstevel@tonic-gate goto data_failed; 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate } else { 855*7c478bd9Sstevel@tonic-gate if (fn != NULL) 856*7c478bd9Sstevel@tonic-gate if (fn(dnvlp, arg) != 0) { 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate /* 859*7c478bd9Sstevel@tonic-gate * The callback function returned 860*7c478bd9Sstevel@tonic-gate * a non-zero value. Abort any further 861*7c478bd9Sstevel@tonic-gate * data collection. 862*7c478bd9Sstevel@tonic-gate */ 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate nvlist_free(dnvlp); 865*7c478bd9Sstevel@tonic-gate free(dbuf); 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Free the nvlist now that we have extracted the return 871*7c478bd9Sstevel@tonic-gate * code or called the callback function. 872*7c478bd9Sstevel@tonic-gate */ 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate nvlist_free(dnvlp); 875*7c478bd9Sstevel@tonic-gate dnvlp = NULL; 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate count++; 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate /* 881*7c478bd9Sstevel@tonic-gate * Free the data buffer as data collection is now complete. 882*7c478bd9Sstevel@tonic-gate */ 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate free(dbuf); 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* 887*7c478bd9Sstevel@tonic-gate * Close the control device. 888*7c478bd9Sstevel@tonic-gate */ 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate (void) close(fd); 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate /* 893*7c478bd9Sstevel@tonic-gate * If the kernel returned an error, we should return an error. 894*7c478bd9Sstevel@tonic-gate * and set errno. 895*7c478bd9Sstevel@tonic-gate */ 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate if (rval != 0) { 898*7c478bd9Sstevel@tonic-gate DBG1(DBG_IO, "kernel return code = %d\n", rval); 899*7c478bd9Sstevel@tonic-gate errno = rval; 900*7c478bd9Sstevel@tonic-gate return (-1); 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate return (0); 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate command_failed: 906*7c478bd9Sstevel@tonic-gate free(cbuf); 907*7c478bd9Sstevel@tonic-gate if (fd != -1) 908*7c478bd9Sstevel@tonic-gate (void) close(fd); 909*7c478bd9Sstevel@tonic-gate return (-1); 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate data_failed: 912*7c478bd9Sstevel@tonic-gate if (dbuf != NULL) 913*7c478bd9Sstevel@tonic-gate free(dbuf); 914*7c478bd9Sstevel@tonic-gate (void) close(fd); 915*7c478bd9Sstevel@tonic-gate return (-1); 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate #undef __FN__ 918