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