17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*19397407SSherry Moore * Common Development and Distribution License (the "License"). 6*19397407SSherry Moore * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*19397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * IP Policy Framework config driver 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 337c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 347c478bd9Sstevel@tonic-gate #include <sys/errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 367c478bd9Sstevel@tonic-gate #include <sys/open.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/conf.h> 397c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 407c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 417c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 427c478bd9Sstevel@tonic-gate #include <sys/stream.h> 437c478bd9Sstevel@tonic-gate #include <ipp/ipp.h> 447c478bd9Sstevel@tonic-gate #include <ipp/ippctl.h> 457c478bd9Sstevel@tonic-gate #include <sys/nvpair.h> 467c478bd9Sstevel@tonic-gate #include <sys/policy.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * Debug switch. 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #if defined(DEBUG) 537c478bd9Sstevel@tonic-gate #define IPPCTL_DEBUG 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * Debug macros. 587c478bd9Sstevel@tonic-gate */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #ifdef IPPCTL_DEBUG 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate #define DBG_MODLINK 0x00000001ull 637c478bd9Sstevel@tonic-gate #define DBG_DEVOPS 0x00000002ull 647c478bd9Sstevel@tonic-gate #define DBG_CBOPS 0x00000004ull 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static uint64_t ippctl_debug_flags = 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * DBG_MODLINK | 697c478bd9Sstevel@tonic-gate * DBG_DEVOPS | 707c478bd9Sstevel@tonic-gate * DBG_CBOPS | 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate 0; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static kmutex_t debug_mutex[1]; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 777c478bd9Sstevel@tonic-gate static void ippctl_debug(uint64_t, char *, char *, ...) 787c478bd9Sstevel@tonic-gate __PRINTFLIKE(3); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #define DBG0(_type, _fmt) \ 817c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt)); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1) \ 847c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1)); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2) \ 877c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2)); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3) \ 907c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 917c478bd9Sstevel@tonic-gate (_a3)); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \ 947c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 957c478bd9Sstevel@tonic-gate (_a3), (_a4)); 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \ 987c478bd9Sstevel@tonic-gate ippctl_debug((_type), __FN__, (_fmt), (_a1), (_a2), \ 997c478bd9Sstevel@tonic-gate (_a3), (_a4), (_a5)); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate #else /* IPPCTL_DBG */ 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate #define DBG0(_type, _fmt) 1047c478bd9Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1) 1057c478bd9Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2) 1067c478bd9Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3) 1077c478bd9Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) 1087c478bd9Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate #endif /* IPPCTL_DBG */ 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * cb_ops 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate static int ippctl_open(dev_t *, int, int, cred_t *); 1177c478bd9Sstevel@tonic-gate static int ippctl_close(dev_t, int, int, cred_t *); 1187c478bd9Sstevel@tonic-gate static int ippctl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static struct cb_ops ippctl_cb_ops = { 1217c478bd9Sstevel@tonic-gate ippctl_open, /* cb_open */ 1227c478bd9Sstevel@tonic-gate ippctl_close, /* cb_close */ 1237c478bd9Sstevel@tonic-gate nodev, /* cb_strategy */ 1247c478bd9Sstevel@tonic-gate nodev, /* cb_print */ 1257c478bd9Sstevel@tonic-gate nodev, /* cb_dump */ 1267c478bd9Sstevel@tonic-gate nodev, /* cb_read */ 1277c478bd9Sstevel@tonic-gate nodev, /* cb_write */ 1287c478bd9Sstevel@tonic-gate ippctl_ioctl, /* cb_ioctl */ 1297c478bd9Sstevel@tonic-gate nodev, /* cb_devmap */ 1307c478bd9Sstevel@tonic-gate nodev, /* cb_mmap */ 1317c478bd9Sstevel@tonic-gate nodev, /* cb_segmap */ 1327c478bd9Sstevel@tonic-gate nochpoll, /* cb_chpoll */ 1337c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 1347c478bd9Sstevel@tonic-gate 0, /* cb_str */ 1357c478bd9Sstevel@tonic-gate D_NEW | D_MP, /* cb_flag */ 1367c478bd9Sstevel@tonic-gate CB_REV, /* cb_rev */ 1377c478bd9Sstevel@tonic-gate nodev, /* cb_aread */ 1387c478bd9Sstevel@tonic-gate nodev /* cb_awrite */ 1397c478bd9Sstevel@tonic-gate }; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * dev_ops 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate static int ippctl_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 1467c478bd9Sstevel@tonic-gate static int ippctl_attach(dev_info_t *, ddi_attach_cmd_t); 1477c478bd9Sstevel@tonic-gate static int ippctl_detach(dev_info_t *, ddi_detach_cmd_t); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate static struct dev_ops ippctl_dev_ops = { 1507c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 1517c478bd9Sstevel@tonic-gate 0, /* devo_refcnt */ 1527c478bd9Sstevel@tonic-gate ippctl_info, /* devo_getinfo */ 1537c478bd9Sstevel@tonic-gate nulldev, /* devo_identify */ 1547c478bd9Sstevel@tonic-gate nulldev, /* devo_probe */ 1557c478bd9Sstevel@tonic-gate ippctl_attach, /* devo_attach */ 1567c478bd9Sstevel@tonic-gate ippctl_detach, /* devo_detach */ 1577c478bd9Sstevel@tonic-gate nodev, /* devo_reset */ 1587c478bd9Sstevel@tonic-gate &ippctl_cb_ops, /* devo_cb_ops */ 159*19397407SSherry Moore (struct bus_ops *)0, /* devo_bus_ops */ 160*19397407SSherry Moore NULL, /* devo_power */ 161*19397407SSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */ 1627c478bd9Sstevel@tonic-gate }; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 1657c478bd9Sstevel@tonic-gate &mod_driverops, 166*19397407SSherry Moore "IP Policy Configuration Driver", 1677c478bd9Sstevel@tonic-gate &ippctl_dev_ops, 1687c478bd9Sstevel@tonic-gate }; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1717c478bd9Sstevel@tonic-gate MODREV_1, 1727c478bd9Sstevel@tonic-gate &modldrv, 1737c478bd9Sstevel@tonic-gate NULL 1747c478bd9Sstevel@tonic-gate }; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* 1777c478bd9Sstevel@tonic-gate * Local definitions, types and prototypes. 1787c478bd9Sstevel@tonic-gate */ 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate #define MAXUBUFLEN (1 << 16) 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate #define FREE_TEXT(_string) \ 1837c478bd9Sstevel@tonic-gate kmem_free((_string), strlen(_string) + 1) 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate #define FREE_TEXT_ARRAY(_array, _nelt) \ 1867c478bd9Sstevel@tonic-gate { \ 1877c478bd9Sstevel@tonic-gate int j; \ 1887c478bd9Sstevel@tonic-gate \ 1897c478bd9Sstevel@tonic-gate for (j = 0; j < (_nelt); j++) \ 1907c478bd9Sstevel@tonic-gate if ((_array)[j] != NULL) \ 1917c478bd9Sstevel@tonic-gate FREE_TEXT((_array)[j]); \ 1927c478bd9Sstevel@tonic-gate kmem_free((_array), (_nelt) * sizeof (char *)); \ 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate typedef struct ippctl_buf ippctl_buf_t; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate struct ippctl_buf { 1987c478bd9Sstevel@tonic-gate char *buf; 1997c478bd9Sstevel@tonic-gate size_t buflen; 2007c478bd9Sstevel@tonic-gate }; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate static int ippctl_copyin(caddr_t, int, char **, size_t *); 2037c478bd9Sstevel@tonic-gate static int ippctl_copyout(caddr_t, int, char *, size_t); 2047c478bd9Sstevel@tonic-gate static int ippctl_extract_op(nvlist_t *, uint8_t *); 2057c478bd9Sstevel@tonic-gate static int ippctl_extract_aname(nvlist_t *, char **); 2067c478bd9Sstevel@tonic-gate static int ippctl_extract_modname(nvlist_t *, char **); 2077c478bd9Sstevel@tonic-gate static int ippctl_attach_modname(nvlist_t *nvlp, char *val); 2087c478bd9Sstevel@tonic-gate static int ippctl_attach_modname_array(nvlist_t *nvlp, char **val, int); 2097c478bd9Sstevel@tonic-gate static int ippctl_attach_aname_array(nvlist_t *nvlp, char **val, int); 2107c478bd9Sstevel@tonic-gate static int ippctl_extract_flags(nvlist_t *, ipp_flags_t *); 2117c478bd9Sstevel@tonic-gate static int ippctl_cmd(char *, size_t, size_t *); 2127c478bd9Sstevel@tonic-gate static int ippctl_action_create(char *, char *, nvlist_t *, ipp_flags_t); 2137c478bd9Sstevel@tonic-gate static int ippctl_action_destroy(char *, ipp_flags_t); 2147c478bd9Sstevel@tonic-gate static int ippctl_action_modify(char *, nvlist_t *, ipp_flags_t); 2157c478bd9Sstevel@tonic-gate static int ippctl_action_info(char *, ipp_flags_t); 2167c478bd9Sstevel@tonic-gate static int ippctl_action_mod(char *); 2177c478bd9Sstevel@tonic-gate static int ippctl_list_mods(void); 2187c478bd9Sstevel@tonic-gate static int ippctl_mod_list_actions(char *); 2197c478bd9Sstevel@tonic-gate static int ippctl_data(char **, size_t *, size_t *); 2207c478bd9Sstevel@tonic-gate static void ippctl_flush(void); 2217c478bd9Sstevel@tonic-gate static int ippctl_add_nvlist(nvlist_t *, int); 2227c478bd9Sstevel@tonic-gate static int ippctl_callback(nvlist_t *, void *); 2237c478bd9Sstevel@tonic-gate static int ippctl_set_rc(int); 2247c478bd9Sstevel@tonic-gate static void ippctl_alloc(int); 2257c478bd9Sstevel@tonic-gate static void ippctl_realloc(void); 2267c478bd9Sstevel@tonic-gate static void ippctl_free(void); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * Global data 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate static dev_info_t *ippctl_dip = NULL; 2337c478bd9Sstevel@tonic-gate static kmutex_t ippctl_lock; 2347c478bd9Sstevel@tonic-gate static boolean_t ippctl_busy; 2357c478bd9Sstevel@tonic-gate static ippctl_buf_t *ippctl_array = NULL; 2367c478bd9Sstevel@tonic-gate static int ippctl_limit = -1; 2377c478bd9Sstevel@tonic-gate static int ippctl_rindex = -1; 2387c478bd9Sstevel@tonic-gate static int ippctl_windex = -1; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * Module linkage functions 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate #define __FN__ "_init" 2457c478bd9Sstevel@tonic-gate int 2467c478bd9Sstevel@tonic-gate _init( 2477c478bd9Sstevel@tonic-gate void) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate int rc; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if ((rc = mod_install(&modlinkage)) != 0) { 2527c478bd9Sstevel@tonic-gate DBG0(DBG_MODLINK, "mod_install failed\n"); 2537c478bd9Sstevel@tonic-gate return (rc); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate return (rc); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate #undef __FN__ 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate #define __FN__ "_fini" 2617c478bd9Sstevel@tonic-gate int 2627c478bd9Sstevel@tonic-gate _fini( 2637c478bd9Sstevel@tonic-gate void) 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate int rc; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if ((rc = mod_remove(&modlinkage)) == 0) { 2687c478bd9Sstevel@tonic-gate return (rc); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate DBG0(DBG_MODLINK, "mod_remove failed\n"); 2727c478bd9Sstevel@tonic-gate return (rc); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate #undef __FN__ 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate #define __FN__ "_info" 2777c478bd9Sstevel@tonic-gate int 2787c478bd9Sstevel@tonic-gate _info( 2797c478bd9Sstevel@tonic-gate struct modinfo *modinfop) 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate DBG0(DBG_MODLINK, "calling mod_info\n"); 2827c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate #undef __FN__ 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * Driver interface functions (dev_ops and cb_ops) 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_info" 2917c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2927c478bd9Sstevel@tonic-gate static int 2937c478bd9Sstevel@tonic-gate ippctl_info( 2947c478bd9Sstevel@tonic-gate dev_info_t *dip, 2957c478bd9Sstevel@tonic-gate ddi_info_cmd_t cmd, 2967c478bd9Sstevel@tonic-gate void *arg, 2977c478bd9Sstevel@tonic-gate void **result) 2987c478bd9Sstevel@tonic-gate { 2997c478bd9Sstevel@tonic-gate int rc = DDI_FAILURE; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate switch (cmd) { 3027c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 3037c478bd9Sstevel@tonic-gate *result = (void *)0; /* Single instance driver */ 3047c478bd9Sstevel@tonic-gate rc = DDI_SUCCESS; 3057c478bd9Sstevel@tonic-gate break; 3067c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 3077c478bd9Sstevel@tonic-gate *result = (void *)ippctl_dip; 3087c478bd9Sstevel@tonic-gate rc = DDI_SUCCESS; 3097c478bd9Sstevel@tonic-gate break; 3107c478bd9Sstevel@tonic-gate default: 3117c478bd9Sstevel@tonic-gate break; 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate return (rc); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate #undef __FN__ 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach" 3197c478bd9Sstevel@tonic-gate static int 3207c478bd9Sstevel@tonic-gate ippctl_attach( 3217c478bd9Sstevel@tonic-gate dev_info_t *dip, 3227c478bd9Sstevel@tonic-gate ddi_attach_cmd_t cmd) 3237c478bd9Sstevel@tonic-gate { 3247c478bd9Sstevel@tonic-gate switch (cmd) { 3257c478bd9Sstevel@tonic-gate case DDI_ATTACH: 3267c478bd9Sstevel@tonic-gate break; 3277c478bd9Sstevel@tonic-gate case DDI_PM_RESUME: 3287c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3297c478bd9Sstevel@tonic-gate case DDI_RESUME: 3307c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3317c478bd9Sstevel@tonic-gate default: 3327c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate DBG0(DBG_DEVOPS, "DDI_ATTACH\n"); 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * This is strictly a single instance driver. 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate if (ippctl_dip != NULL) 3427c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * Create minor node. 3467c478bd9Sstevel@tonic-gate */ 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, "ctl", S_IFCHR, 0, 3497c478bd9Sstevel@tonic-gate DDI_PSEUDO, 0) != DDI_SUCCESS) 3507c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * No need for per-instance structure, just store vital data in 3547c478bd9Sstevel@tonic-gate * globals. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate ippctl_dip = dip; 3587c478bd9Sstevel@tonic-gate mutex_init(&ippctl_lock, NULL, MUTEX_DRIVER, NULL); 3597c478bd9Sstevel@tonic-gate ippctl_busy = B_FALSE; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate #undef __FN__ 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_detach" 3667c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3677c478bd9Sstevel@tonic-gate static int 3687c478bd9Sstevel@tonic-gate ippctl_detach( 3697c478bd9Sstevel@tonic-gate dev_info_t *dip, 3707c478bd9Sstevel@tonic-gate ddi_detach_cmd_t cmd) 3717c478bd9Sstevel@tonic-gate { 3727c478bd9Sstevel@tonic-gate switch (cmd) { 3737c478bd9Sstevel@tonic-gate case DDI_DETACH: 3747c478bd9Sstevel@tonic-gate break; 3757c478bd9Sstevel@tonic-gate case DDI_PM_SUSPEND: 3767c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3777c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 3787c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3797c478bd9Sstevel@tonic-gate default: 3807c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate DBG0(DBG_DEVOPS, "DDI_DETACH\n"); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate ASSERT(dip == ippctl_dip); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3887c478bd9Sstevel@tonic-gate mutex_destroy(&ippctl_lock); 3897c478bd9Sstevel@tonic-gate ippctl_dip = NULL; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate #undef __FN__ 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_open" 3967c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3977c478bd9Sstevel@tonic-gate static int 3987c478bd9Sstevel@tonic-gate ippctl_open( 3997c478bd9Sstevel@tonic-gate dev_t *devp, 4007c478bd9Sstevel@tonic-gate int flag, 4017c478bd9Sstevel@tonic-gate int otyp, 4027c478bd9Sstevel@tonic-gate cred_t *credp) 4037c478bd9Sstevel@tonic-gate { 4047c478bd9Sstevel@tonic-gate minor_t minor = getminor(*devp); 4057c478bd9Sstevel@tonic-gate #define LIMIT 4 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "open\n"); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate /* 4107c478bd9Sstevel@tonic-gate * Only allow privileged users to open our device. 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (secpolicy_net_config(credp, B_FALSE) != 0) { 4147c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "not privileged user\n"); 4157c478bd9Sstevel@tonic-gate return (EPERM); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * Sanity check other arguments. 4207c478bd9Sstevel@tonic-gate */ 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate if (minor != 0) { 4237c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad minor\n"); 4247c478bd9Sstevel@tonic-gate return (ENXIO); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if (otyp != OTYP_CHR) { 4287c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad device type\n"); 4297c478bd9Sstevel@tonic-gate return (EINVAL); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * This is also a single dev_t driver. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate mutex_enter(&ippctl_lock); 4377c478bd9Sstevel@tonic-gate if (ippctl_busy) { 4387c478bd9Sstevel@tonic-gate mutex_exit(&ippctl_lock); 4397c478bd9Sstevel@tonic-gate return (EBUSY); 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate ippctl_busy = B_TRUE; 4427c478bd9Sstevel@tonic-gate mutex_exit(&ippctl_lock); 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * Allocate data buffer array (starting with length LIMIT, defined 4467c478bd9Sstevel@tonic-gate * at the start of this function). 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate ippctl_alloc(LIMIT); 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "success\n"); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate return (0); 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate #undef LIMIT 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate #undef __FN__ 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_close" 4607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4617c478bd9Sstevel@tonic-gate static int 4627c478bd9Sstevel@tonic-gate ippctl_close( 4637c478bd9Sstevel@tonic-gate dev_t dev, 4647c478bd9Sstevel@tonic-gate int flag, 4657c478bd9Sstevel@tonic-gate int otyp, 4667c478bd9Sstevel@tonic-gate cred_t *credp) 4677c478bd9Sstevel@tonic-gate { 4687c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "close\n"); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate ASSERT(minor == 0); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * Free the data buffer array. 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate ippctl_free(); 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate mutex_enter(&ippctl_lock); 4817c478bd9Sstevel@tonic-gate ippctl_busy = B_FALSE; 4827c478bd9Sstevel@tonic-gate mutex_exit(&ippctl_lock); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "success\n"); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate return (0); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate #undef __FN__ 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_ioctl" 4917c478bd9Sstevel@tonic-gate static int 4927c478bd9Sstevel@tonic-gate ippctl_ioctl( 4937c478bd9Sstevel@tonic-gate dev_t dev, 4947c478bd9Sstevel@tonic-gate int cmd, 4957c478bd9Sstevel@tonic-gate intptr_t arg, 4967c478bd9Sstevel@tonic-gate int mode, 4977c478bd9Sstevel@tonic-gate cred_t *credp, 4987c478bd9Sstevel@tonic-gate int *rvalp) 4997c478bd9Sstevel@tonic-gate { 5007c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev); 5017c478bd9Sstevel@tonic-gate char *cbuf; 5027c478bd9Sstevel@tonic-gate char *dbuf; 5037c478bd9Sstevel@tonic-gate size_t cbuflen; 5047c478bd9Sstevel@tonic-gate size_t dbuflen; 5057c478bd9Sstevel@tonic-gate size_t nextbuflen; 5067c478bd9Sstevel@tonic-gate int rc; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * Paranoia check. 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (secpolicy_net_config(credp, B_FALSE) != 0) { 5137c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "not privileged user\n"); 5147c478bd9Sstevel@tonic-gate return (EPERM); 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate if (minor != 0) { 5187c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "bad minor\n"); 5197c478bd9Sstevel@tonic-gate return (ENXIO); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate switch (cmd) { 5237c478bd9Sstevel@tonic-gate case IPPCTL_CMD: 5247c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "command\n"); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* 5277c478bd9Sstevel@tonic-gate * Copy in the command buffer from user space. 5287c478bd9Sstevel@tonic-gate */ 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if ((rc = ippctl_copyin((caddr_t)arg, mode, &cbuf, 5317c478bd9Sstevel@tonic-gate &cbuflen)) != 0) 5327c478bd9Sstevel@tonic-gate break; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate /* 5357c478bd9Sstevel@tonic-gate * Execute the command. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate rc = ippctl_cmd(cbuf, cbuflen, &nextbuflen); 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* 5417c478bd9Sstevel@tonic-gate * Pass back the length of the first data buffer. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "nextbuflen = %lu\n", nextbuflen); 5457c478bd9Sstevel@tonic-gate *rvalp = nextbuflen; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate /* 5487c478bd9Sstevel@tonic-gate * Free the kernel copy of the command buffer. 5497c478bd9Sstevel@tonic-gate */ 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate kmem_free(cbuf, cbuflen); 5527c478bd9Sstevel@tonic-gate break; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate case IPPCTL_DATA: 5557c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "data\n"); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate /* 5587c478bd9Sstevel@tonic-gate * Grab the next data buffer from the array of pending 5597c478bd9Sstevel@tonic-gate * buffers. 5607c478bd9Sstevel@tonic-gate */ 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if ((rc = ippctl_data(&dbuf, &dbuflen, &nextbuflen)) != 0) 5637c478bd9Sstevel@tonic-gate break; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * Copy it out to user space. 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate rc = ippctl_copyout((caddr_t)arg, mode, dbuf, dbuflen); 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* 5727c478bd9Sstevel@tonic-gate * Pass back the length of the next data buffer. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "nextbuflen = %lu\n", nextbuflen); 5767c478bd9Sstevel@tonic-gate *rvalp = nextbuflen; 5777c478bd9Sstevel@tonic-gate break; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate default: 5807c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "unrecognized ioctl\n"); 5817c478bd9Sstevel@tonic-gate rc = EINVAL; 5827c478bd9Sstevel@tonic-gate break; 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "rc = %d\n", rc); 5867c478bd9Sstevel@tonic-gate return (rc); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate #undef __FN__ 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* 5917c478bd9Sstevel@tonic-gate * Local functions 5927c478bd9Sstevel@tonic-gate */ 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_copyin" 5957c478bd9Sstevel@tonic-gate static int 5967c478bd9Sstevel@tonic-gate ippctl_copyin( 5977c478bd9Sstevel@tonic-gate caddr_t arg, 5987c478bd9Sstevel@tonic-gate int mode, 5997c478bd9Sstevel@tonic-gate char **kbufp, 6007c478bd9Sstevel@tonic-gate size_t *kbuflenp) 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate ippctl_ioctl_t iioc; 6037c478bd9Sstevel@tonic-gate caddr_t ubuf; 6047c478bd9Sstevel@tonic-gate char *kbuf; 6057c478bd9Sstevel@tonic-gate size_t ubuflen; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying in ioctl structure\n"); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate /* 6107c478bd9Sstevel@tonic-gate * Copy in the ioctl structure from user-space, converting from 32-bit 6117c478bd9Sstevel@tonic-gate * as necessary. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 6157c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 6167c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 6177c478bd9Sstevel@tonic-gate { 6187c478bd9Sstevel@tonic-gate ippctl_ioctl32_t iioc32; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "converting from 32-bit\n"); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc32, 6237c478bd9Sstevel@tonic-gate sizeof (ippctl_ioctl32_t), mode) != 0) 6247c478bd9Sstevel@tonic-gate return (EFAULT); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate ubuf = (caddr_t)(uintptr_t)iioc32.ii32_buf; 6277c478bd9Sstevel@tonic-gate ubuflen = (size_t)iioc32.ii32_buflen; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate break; 6307c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 6317c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 6327c478bd9Sstevel@tonic-gate mode) != 0) 6337c478bd9Sstevel@tonic-gate return (EFAULT); 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 6367c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 6377c478bd9Sstevel@tonic-gate break; 6387c478bd9Sstevel@tonic-gate default: 6397c478bd9Sstevel@tonic-gate return (EFAULT); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate #else /* _MULTI_DATAMODEL */ 6427c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 6437c478bd9Sstevel@tonic-gate mode) != 0) 6447c478bd9Sstevel@tonic-gate return (EFAULT); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 6477c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 6487c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuf = 0x%p\n", (void *)ubuf); 6517c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuflen = %lu\n", ubuflen); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* 6547c478bd9Sstevel@tonic-gate * Sanity check the command buffer information. 6557c478bd9Sstevel@tonic-gate */ 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if (ubuflen == 0 || ubuf == NULL) 6587c478bd9Sstevel@tonic-gate return (EINVAL); 6597c478bd9Sstevel@tonic-gate if (ubuflen > MAXUBUFLEN) 6607c478bd9Sstevel@tonic-gate return (E2BIG); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * Allocate some memory for the command buffer and copy it in. 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate kbuf = kmem_zalloc(ubuflen, KM_SLEEP); 6677c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying in nvlist\n"); 6687c478bd9Sstevel@tonic-gate if (ddi_copyin(ubuf, (caddr_t)kbuf, ubuflen, mode) != 0) { 6697c478bd9Sstevel@tonic-gate kmem_free(kbuf, ubuflen); 6707c478bd9Sstevel@tonic-gate return (EFAULT); 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate *kbufp = kbuf; 6747c478bd9Sstevel@tonic-gate *kbuflenp = ubuflen; 6757c478bd9Sstevel@tonic-gate return (0); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate #undef __FN__ 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_copyout" 6807c478bd9Sstevel@tonic-gate static int 6817c478bd9Sstevel@tonic-gate ippctl_copyout( 6827c478bd9Sstevel@tonic-gate caddr_t arg, 6837c478bd9Sstevel@tonic-gate int mode, 6847c478bd9Sstevel@tonic-gate char *kbuf, 6857c478bd9Sstevel@tonic-gate size_t kbuflen) 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate ippctl_ioctl_t iioc; 6887c478bd9Sstevel@tonic-gate caddr_t ubuf; 6897c478bd9Sstevel@tonic-gate int ubuflen; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying out ioctl structure\n"); 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* 6947c478bd9Sstevel@tonic-gate * Copy in the ioctl structure from user-space, converting from 32-bit 6957c478bd9Sstevel@tonic-gate * as necessary. 6967c478bd9Sstevel@tonic-gate */ 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 6997c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 7007c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 7017c478bd9Sstevel@tonic-gate { 7027c478bd9Sstevel@tonic-gate ippctl_ioctl32_t iioc32; 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc32, 7057c478bd9Sstevel@tonic-gate sizeof (ippctl_ioctl32_t), mode) != 0) 7067c478bd9Sstevel@tonic-gate return (EFAULT); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate ubuf = (caddr_t)(uintptr_t)iioc32.ii32_buf; 7097c478bd9Sstevel@tonic-gate ubuflen = iioc32.ii32_buflen; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate break; 7127c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 7137c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 7147c478bd9Sstevel@tonic-gate mode) != 0) 7157c478bd9Sstevel@tonic-gate return (EFAULT); 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 7187c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 7197c478bd9Sstevel@tonic-gate break; 7207c478bd9Sstevel@tonic-gate default: 7217c478bd9Sstevel@tonic-gate return (EFAULT); 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate #else /* _MULTI_DATAMODEL */ 7247c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, (caddr_t)&iioc, sizeof (ippctl_ioctl_t), 7257c478bd9Sstevel@tonic-gate mode) != 0) 7267c478bd9Sstevel@tonic-gate return (EFAULT); 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate ubuf = iioc.ii_buf; 7297c478bd9Sstevel@tonic-gate ubuflen = iioc.ii_buflen; 7307c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuf = 0x%p\n", (void *)ubuf); 7337c478bd9Sstevel@tonic-gate DBG1(DBG_CBOPS, "ubuflen = %d\n", ubuflen); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* 7367c478bd9Sstevel@tonic-gate * Sanity check the data buffer details. 7377c478bd9Sstevel@tonic-gate */ 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate if (ubuflen == 0 || ubuf == NULL) 7407c478bd9Sstevel@tonic-gate return (EINVAL); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate if (ubuflen < kbuflen) 7437c478bd9Sstevel@tonic-gate return (ENOSPC); 7447c478bd9Sstevel@tonic-gate if (ubuflen > MAXUBUFLEN) 7457c478bd9Sstevel@tonic-gate return (E2BIG); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate /* 7487c478bd9Sstevel@tonic-gate * Copy out the data buffer to user space. 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "copying out nvlist\n"); 7527c478bd9Sstevel@tonic-gate if (ddi_copyout((caddr_t)kbuf, ubuf, kbuflen, mode) != 0) 7537c478bd9Sstevel@tonic-gate return (EFAULT); 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate return (0); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate #undef __FN__ 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_op" 7607c478bd9Sstevel@tonic-gate static int 7617c478bd9Sstevel@tonic-gate ippctl_extract_op( 7627c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 7637c478bd9Sstevel@tonic-gate uint8_t *valp) 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate int rc; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate /* 7687c478bd9Sstevel@tonic-gate * Look-up and remove the opcode passed from libipp from the 7697c478bd9Sstevel@tonic-gate * nvlist. 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_byte(nvlp, IPPCTL_OP, valp)) != 0) 7737c478bd9Sstevel@tonic-gate return (rc); 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_OP); 7767c478bd9Sstevel@tonic-gate return (0); 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate #undef __FN__ 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_aname" 7817c478bd9Sstevel@tonic-gate static int 7827c478bd9Sstevel@tonic-gate ippctl_extract_aname( 7837c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 7847c478bd9Sstevel@tonic-gate char **valp) 7857c478bd9Sstevel@tonic-gate { 7867c478bd9Sstevel@tonic-gate int rc; 7877c478bd9Sstevel@tonic-gate char *ptr; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate /* 7907c478bd9Sstevel@tonic-gate * Look-up and remove the action name passed from libipp from the 7917c478bd9Sstevel@tonic-gate * nvlist. 7927c478bd9Sstevel@tonic-gate */ 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_ANAME, &ptr)) != 0) 7957c478bd9Sstevel@tonic-gate return (rc); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate *valp = kmem_alloc(strlen(ptr) + 1, KM_SLEEP); 7987c478bd9Sstevel@tonic-gate (void) strcpy(*valp, ptr); 7997c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_ANAME); 8007c478bd9Sstevel@tonic-gate return (0); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate #undef __FN__ 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_modname" 8057c478bd9Sstevel@tonic-gate static int 8067c478bd9Sstevel@tonic-gate ippctl_extract_modname( 8077c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 8087c478bd9Sstevel@tonic-gate char **valp) 8097c478bd9Sstevel@tonic-gate { 8107c478bd9Sstevel@tonic-gate int rc; 8117c478bd9Sstevel@tonic-gate char *ptr; 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* 8147c478bd9Sstevel@tonic-gate * Look-up and remove the module name passed from libipp from the 8157c478bd9Sstevel@tonic-gate * nvlist. 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_string(nvlp, IPPCTL_MODNAME, &ptr)) != 0) 8197c478bd9Sstevel@tonic-gate return (rc); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate *valp = kmem_alloc(strlen(ptr) + 1, KM_SLEEP); 8227c478bd9Sstevel@tonic-gate (void) strcpy(*valp, ptr); 8237c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_MODNAME); 8247c478bd9Sstevel@tonic-gate return (0); 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate #undef __FN__ 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach_modname" 8297c478bd9Sstevel@tonic-gate static int 8307c478bd9Sstevel@tonic-gate ippctl_attach_modname( 8317c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 8327c478bd9Sstevel@tonic-gate char *modname) 8337c478bd9Sstevel@tonic-gate { 8347c478bd9Sstevel@tonic-gate /* 8357c478bd9Sstevel@tonic-gate * Add a module name to an nvlist for passing back to user 8367c478bd9Sstevel@tonic-gate * space. 8377c478bd9Sstevel@tonic-gate */ 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate return (nvlist_add_string(nvlp, IPPCTL_MODNAME, modname)); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate #undef __FN__ 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach_modname_array" 8447c478bd9Sstevel@tonic-gate static int 8457c478bd9Sstevel@tonic-gate ippctl_attach_modname_array( 8467c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 8477c478bd9Sstevel@tonic-gate char **modname_array, 8487c478bd9Sstevel@tonic-gate int nelt) 8497c478bd9Sstevel@tonic-gate { 8507c478bd9Sstevel@tonic-gate /* 8517c478bd9Sstevel@tonic-gate * Add a module name array to an nvlist for passing back to user 8527c478bd9Sstevel@tonic-gate * space. 8537c478bd9Sstevel@tonic-gate */ 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate return (nvlist_add_string_array(nvlp, IPPCTL_MODNAME_ARRAY, 8567c478bd9Sstevel@tonic-gate modname_array, nelt)); 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate #undef __FN__ 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_attach_aname_array" 8617c478bd9Sstevel@tonic-gate static int 8627c478bd9Sstevel@tonic-gate ippctl_attach_aname_array( 8637c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 8647c478bd9Sstevel@tonic-gate char **aname_array, 8657c478bd9Sstevel@tonic-gate int nelt) 8667c478bd9Sstevel@tonic-gate { 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * Add an action name array to an nvlist for passing back to user 8697c478bd9Sstevel@tonic-gate * space. 8707c478bd9Sstevel@tonic-gate */ 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate return (nvlist_add_string_array(nvlp, IPPCTL_ANAME_ARRAY, 8737c478bd9Sstevel@tonic-gate aname_array, nelt)); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate #undef __FN__ 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_extract_flags" 8787c478bd9Sstevel@tonic-gate static int 8797c478bd9Sstevel@tonic-gate ippctl_extract_flags( 8807c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 8817c478bd9Sstevel@tonic-gate ipp_flags_t *valp) 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate int rc; 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate /* 8867c478bd9Sstevel@tonic-gate * Look-up and remove the flags passed from libipp from the 8877c478bd9Sstevel@tonic-gate * nvlist. 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate if ((rc = nvlist_lookup_uint32(nvlp, IPPCTL_FLAGS, 8917c478bd9Sstevel@tonic-gate (uint32_t *)valp)) != 0) 8927c478bd9Sstevel@tonic-gate return (rc); 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate (void) nvlist_remove_all(nvlp, IPPCTL_FLAGS); 8957c478bd9Sstevel@tonic-gate return (0); 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate #undef __FN__ 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_cmd" 9007c478bd9Sstevel@tonic-gate static int 9017c478bd9Sstevel@tonic-gate ippctl_cmd( 9027c478bd9Sstevel@tonic-gate char *cbuf, 9037c478bd9Sstevel@tonic-gate size_t cbuflen, 9047c478bd9Sstevel@tonic-gate size_t *nextbuflenp) 9057c478bd9Sstevel@tonic-gate { 9067c478bd9Sstevel@tonic-gate nvlist_t *nvlp = NULL; 9077c478bd9Sstevel@tonic-gate int rc; 9087c478bd9Sstevel@tonic-gate char *aname = NULL; 9097c478bd9Sstevel@tonic-gate char *modname = NULL; 9107c478bd9Sstevel@tonic-gate ipp_flags_t flags; 9117c478bd9Sstevel@tonic-gate uint8_t op; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * Start a new command cycle by flushing any previous data buffers. 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate ippctl_flush(); 9187c478bd9Sstevel@tonic-gate *nextbuflenp = 0; 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * Unpack the nvlist from the command buffer. 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate if ((rc = nvlist_unpack(cbuf, cbuflen, &nvlp, KM_SLEEP)) != 0) 9257c478bd9Sstevel@tonic-gate return (rc); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* 9287c478bd9Sstevel@tonic-gate * Extract the opcode to find out what we should do. 9297c478bd9Sstevel@tonic-gate */ 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_op(nvlp, &op)) != 0) { 9327c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 9337c478bd9Sstevel@tonic-gate return (rc); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate switch (op) { 9377c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_CREATE: 9387c478bd9Sstevel@tonic-gate /* 9397c478bd9Sstevel@tonic-gate * Create a new action. 9407c478bd9Sstevel@tonic-gate */ 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_CREATE\n"); 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate /* 9457c478bd9Sstevel@tonic-gate * Extract the module name, action name and flags from the 9467c478bd9Sstevel@tonic-gate * nvlist. 9477c478bd9Sstevel@tonic-gate */ 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_modname(nvlp, &modname)) != 0) { 9507c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 9517c478bd9Sstevel@tonic-gate return (rc); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 9557c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 9567c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 9577c478bd9Sstevel@tonic-gate return (rc); 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 9617c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 9627c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 9637c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 9647c478bd9Sstevel@tonic-gate return (rc); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate rc = ippctl_action_create(modname, aname, nvlp, flags); 9697c478bd9Sstevel@tonic-gate break; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_MODIFY: 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate /* 9747c478bd9Sstevel@tonic-gate * Modify an existing action. 9757c478bd9Sstevel@tonic-gate */ 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_MODIFY\n"); 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate /* 9807c478bd9Sstevel@tonic-gate * Extract the action name and flags from the nvlist. 9817c478bd9Sstevel@tonic-gate */ 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 9847c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 9857c478bd9Sstevel@tonic-gate return (rc); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 9897c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 9907c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 9917c478bd9Sstevel@tonic-gate return (rc); 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate rc = ippctl_action_modify(aname, nvlp, flags); 9957c478bd9Sstevel@tonic-gate break; 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_DESTROY: 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* 10007c478bd9Sstevel@tonic-gate * Destroy an action. 10017c478bd9Sstevel@tonic-gate */ 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_DESTROY\n"); 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Extract the action name and flags from the nvlist. 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 10107c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10117c478bd9Sstevel@tonic-gate return (rc); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 10157c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 10167c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10177c478bd9Sstevel@tonic-gate return (rc); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10217c478bd9Sstevel@tonic-gate rc = ippctl_action_destroy(aname, flags); 10227c478bd9Sstevel@tonic-gate break; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_INFO: 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* 10277c478bd9Sstevel@tonic-gate * Retrive the configuration of an action. 10287c478bd9Sstevel@tonic-gate */ 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_INFO\n"); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 10337c478bd9Sstevel@tonic-gate * Extract the action name and flags from the nvlist. 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 10377c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10387c478bd9Sstevel@tonic-gate return (rc); 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_flags(nvlp, &flags)) != 0) { 10427c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10437c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 10447c478bd9Sstevel@tonic-gate return (rc); 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10487c478bd9Sstevel@tonic-gate rc = ippctl_action_info(aname, flags); 10497c478bd9Sstevel@tonic-gate break; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate case IPPCTL_OP_ACTION_MOD: 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* 10547c478bd9Sstevel@tonic-gate * Find the module that implements a given action. 10557c478bd9Sstevel@tonic-gate */ 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_ACTION_MOD\n"); 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate /* 10607c478bd9Sstevel@tonic-gate * Extract the action name from the nvlist. 10617c478bd9Sstevel@tonic-gate */ 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_aname(nvlp, &aname)) != 0) { 10647c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10657c478bd9Sstevel@tonic-gate return (rc); 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10697c478bd9Sstevel@tonic-gate rc = ippctl_action_mod(aname); 10707c478bd9Sstevel@tonic-gate break; 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate case IPPCTL_OP_LIST_MODS: 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate /* 10757c478bd9Sstevel@tonic-gate * List all the modules. 10767c478bd9Sstevel@tonic-gate */ 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_LIST_MODS\n"); 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10817c478bd9Sstevel@tonic-gate rc = ippctl_list_mods(); 10827c478bd9Sstevel@tonic-gate break; 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate case IPPCTL_OP_MOD_LIST_ACTIONS: 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate /* 10877c478bd9Sstevel@tonic-gate * List all the actions for a given module. 10887c478bd9Sstevel@tonic-gate */ 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "op = IPPCTL_OP_LIST_MODS\n"); 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate if ((rc = ippctl_extract_modname(nvlp, &modname)) != 0) { 10937c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10947c478bd9Sstevel@tonic-gate return (rc); 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 10987c478bd9Sstevel@tonic-gate rc = ippctl_mod_list_actions(modname); 10997c478bd9Sstevel@tonic-gate break; 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate default: 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate /* 11047c478bd9Sstevel@tonic-gate * Unrecognized opcode. 11057c478bd9Sstevel@tonic-gate */ 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 11087c478bd9Sstevel@tonic-gate rc = EINVAL; 11097c478bd9Sstevel@tonic-gate break; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate /* 11137c478bd9Sstevel@tonic-gate * The length of buffer that we need to notify back to libipp with 11147c478bd9Sstevel@tonic-gate * the command ioctl's return is the length of the first data buffer 11157c478bd9Sstevel@tonic-gate * in the array. We only expact to pass back data buffers if the 11167c478bd9Sstevel@tonic-gate * operation succeeds (NOTE: this does not mean the kernel call has 11177c478bd9Sstevel@tonic-gate * to succeed, merely that we successfully issued it and processed 11187c478bd9Sstevel@tonic-gate * the results). 11197c478bd9Sstevel@tonic-gate */ 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate if (rc == 0) 11227c478bd9Sstevel@tonic-gate *nextbuflenp = ippctl_array[0].buflen; 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate return (rc); 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate #undef __FN__ 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_create" 11297c478bd9Sstevel@tonic-gate static int 11307c478bd9Sstevel@tonic-gate ippctl_action_create( 11317c478bd9Sstevel@tonic-gate char *modname, 11327c478bd9Sstevel@tonic-gate char *aname, 11337c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 11347c478bd9Sstevel@tonic-gate ipp_flags_t flags) 11357c478bd9Sstevel@tonic-gate { 11367c478bd9Sstevel@tonic-gate int ipp_rc; 11377c478bd9Sstevel@tonic-gate int rc; 11387c478bd9Sstevel@tonic-gate ipp_mod_id_t mid; 11397c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate /* 11427c478bd9Sstevel@tonic-gate * Look up the module id from the name and create the new 11437c478bd9Sstevel@tonic-gate * action. 11447c478bd9Sstevel@tonic-gate */ 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate mid = ipp_mod_lookup(modname); 11477c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_create(mid, aname, &nvlp, flags, &aid); 11507c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate /* 11537c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 11547c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 11557c478bd9Sstevel@tonic-gate */ 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) { 11587c478bd9Sstevel@tonic-gate if (nvlp != NULL) { 11597c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 11607c478bd9Sstevel@tonic-gate if (ipp_action_destroy(aid, 0) != 0) { 11617c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 11627c478bd9Sstevel@tonic-gate "ippctl: unrecoverable error (aid = %d)", 11637c478bd9Sstevel@tonic-gate aid); 11647c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate return (rc); 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate /* 11717c478bd9Sstevel@tonic-gate * If the module passed back an nvlist, add this as 11727c478bd9Sstevel@tonic-gate * well. 11737c478bd9Sstevel@tonic-gate */ 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate if (nvlp != NULL) { 11767c478bd9Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL); 11777c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 11787c478bd9Sstevel@tonic-gate } else 11797c478bd9Sstevel@tonic-gate rc = 0; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate return (rc); 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate #undef __FN__ 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_destroy" 11867c478bd9Sstevel@tonic-gate static int 11877c478bd9Sstevel@tonic-gate ippctl_action_destroy( 11887c478bd9Sstevel@tonic-gate char *aname, 11897c478bd9Sstevel@tonic-gate ipp_flags_t flags) 11907c478bd9Sstevel@tonic-gate { 11917c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 11927c478bd9Sstevel@tonic-gate int ipp_rc; 11937c478bd9Sstevel@tonic-gate int rc; 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate /* 11967c478bd9Sstevel@tonic-gate * Look up the action id and destroy the action. 11977c478bd9Sstevel@tonic-gate */ 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 12007c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_destroy(aid, flags); 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate /* 12057c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 12067c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 12077c478bd9Sstevel@tonic-gate */ 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 12107c478bd9Sstevel@tonic-gate return (rc); 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate /* 12137c478bd9Sstevel@tonic-gate * There's no more information to pass back. 12147c478bd9Sstevel@tonic-gate */ 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate return (0); 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate #undef __FN__ 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_modify" 12217c478bd9Sstevel@tonic-gate static int 12227c478bd9Sstevel@tonic-gate ippctl_action_modify( 12237c478bd9Sstevel@tonic-gate char *aname, 12247c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 12257c478bd9Sstevel@tonic-gate ipp_flags_t flags) 12267c478bd9Sstevel@tonic-gate { 12277c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 12287c478bd9Sstevel@tonic-gate int ipp_rc; 12297c478bd9Sstevel@tonic-gate int rc; 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate /* 12327c478bd9Sstevel@tonic-gate * Look up the action id and modify the action. 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 12367c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_modify(aid, &nvlp, flags); 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate /* 12417c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 12427c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 12437c478bd9Sstevel@tonic-gate */ 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) { 12467c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 12477c478bd9Sstevel@tonic-gate return (rc); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* 12517c478bd9Sstevel@tonic-gate * If the module passed back an nvlist, add this as 12527c478bd9Sstevel@tonic-gate * well. 12537c478bd9Sstevel@tonic-gate */ 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate if (nvlp != NULL) { 12567c478bd9Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL); 12577c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 12587c478bd9Sstevel@tonic-gate } else 12597c478bd9Sstevel@tonic-gate rc = 0; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate return (rc); 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate #undef __FN__ 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_info" 12667c478bd9Sstevel@tonic-gate static int 12677c478bd9Sstevel@tonic-gate ippctl_action_info( 12687c478bd9Sstevel@tonic-gate char *aname, 12697c478bd9Sstevel@tonic-gate ipp_flags_t flags) 12707c478bd9Sstevel@tonic-gate { 12717c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 12727c478bd9Sstevel@tonic-gate int ipp_rc; 12737c478bd9Sstevel@tonic-gate int rc; 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate /* 12767c478bd9Sstevel@tonic-gate * Look up the action and call the information retrieval 12777c478bd9Sstevel@tonic-gate * entry point. 12787c478bd9Sstevel@tonic-gate * 12797c478bd9Sstevel@tonic-gate * NOTE: The callback function that is passed in packs and 12807c478bd9Sstevel@tonic-gate * stores each of the nvlists it is called with in the array 12817c478bd9Sstevel@tonic-gate * that will be passed back to libipp. 12827c478bd9Sstevel@tonic-gate */ 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 12857c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate ipp_rc = ipp_action_info(aid, ippctl_callback, NULL, flags); 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate /* 12907c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 12917c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 12927c478bd9Sstevel@tonic-gate */ 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 12957c478bd9Sstevel@tonic-gate return (rc); 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate /* 12987c478bd9Sstevel@tonic-gate * There's no more information to pass back. 12997c478bd9Sstevel@tonic-gate */ 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate return (0); 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate #undef __FN__ 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_action_mod" 13067c478bd9Sstevel@tonic-gate static int 13077c478bd9Sstevel@tonic-gate ippctl_action_mod( 13087c478bd9Sstevel@tonic-gate char *aname) 13097c478bd9Sstevel@tonic-gate { 13107c478bd9Sstevel@tonic-gate ipp_mod_id_t mid; 13117c478bd9Sstevel@tonic-gate ipp_action_id_t aid; 13127c478bd9Sstevel@tonic-gate char *modname; 13137c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 13147c478bd9Sstevel@tonic-gate int ipp_rc; 13157c478bd9Sstevel@tonic-gate int rc; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate /* 13187c478bd9Sstevel@tonic-gate * Look up the action id and get the id of the module that 13197c478bd9Sstevel@tonic-gate * implements the action. If that succeeds then look up the 13207c478bd9Sstevel@tonic-gate * name of the module. 13217c478bd9Sstevel@tonic-gate */ 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate aid = ipp_action_lookup(aname); 13247c478bd9Sstevel@tonic-gate FREE_TEXT(aname); 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate if ((ipp_rc = ipp_action_mod(aid, &mid)) == 0) 13277c478bd9Sstevel@tonic-gate ipp_rc = ipp_mod_name(mid, &modname); 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate /* 13307c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 13317c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 13327c478bd9Sstevel@tonic-gate */ 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 13357c478bd9Sstevel@tonic-gate return (rc); 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate /* 13387c478bd9Sstevel@tonic-gate * If everything succeeded add an nvlist containing the 13397c478bd9Sstevel@tonic-gate * module name to the set of nvlists to pass back to libipp. 13407c478bd9Sstevel@tonic-gate */ 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate if (ipp_rc == 0) { 13437c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_SLEEP)) != 0) 13447c478bd9Sstevel@tonic-gate return (rc); 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate if ((rc = ippctl_attach_modname(nvlp, modname)) != 0) { 13477c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 13487c478bd9Sstevel@tonic-gate return (rc); 13497c478bd9Sstevel@tonic-gate } 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate rc = ippctl_callback(nvlp, NULL); 13547c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 13557c478bd9Sstevel@tonic-gate } else 13567c478bd9Sstevel@tonic-gate rc = 0; 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate return (rc); 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate #undef __FN__ 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_list_mods" 13637c478bd9Sstevel@tonic-gate static int 13647c478bd9Sstevel@tonic-gate ippctl_list_mods( 13657c478bd9Sstevel@tonic-gate void) 13667c478bd9Sstevel@tonic-gate { 13677c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 13687c478bd9Sstevel@tonic-gate int ipp_rc; 13697c478bd9Sstevel@tonic-gate int rc = 0; 13707c478bd9Sstevel@tonic-gate ipp_mod_id_t *mid_array; 13717c478bd9Sstevel@tonic-gate char **modname_array = NULL; 13727c478bd9Sstevel@tonic-gate int nelt; 13737c478bd9Sstevel@tonic-gate int length; 13747c478bd9Sstevel@tonic-gate int i; 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate /* 13777c478bd9Sstevel@tonic-gate * Get a list of all the module ids. If that succeeds, 13787c478bd9Sstevel@tonic-gate * translate the ids into names. 13797c478bd9Sstevel@tonic-gate * 13807c478bd9Sstevel@tonic-gate * NOTE: This translation may fail if a module is 13817c478bd9Sstevel@tonic-gate * unloaded during this operation. If this occurs, EAGAIN 13827c478bd9Sstevel@tonic-gate * will be passed back to libipp note that a transient 13837c478bd9Sstevel@tonic-gate * problem occured. 13847c478bd9Sstevel@tonic-gate */ 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate if ((ipp_rc = ipp_list_mods(&mid_array, &nelt)) == 0) { 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* 13897c478bd9Sstevel@tonic-gate * It is possible that there are no modules 13907c478bd9Sstevel@tonic-gate * registered. 13917c478bd9Sstevel@tonic-gate */ 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate if (nelt > 0) { 13947c478bd9Sstevel@tonic-gate length = nelt * sizeof (char *); 13957c478bd9Sstevel@tonic-gate modname_array = kmem_zalloc(length, KM_SLEEP); 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate for (i = 0; i < nelt; i++) { 13987c478bd9Sstevel@tonic-gate if (ipp_mod_name(mid_array[i], 13997c478bd9Sstevel@tonic-gate &modname_array[i]) != 0) { 14007c478bd9Sstevel@tonic-gate kmem_free(mid_array, nelt * 14017c478bd9Sstevel@tonic-gate sizeof (ipp_mod_id_t)); 14027c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 14037c478bd9Sstevel@tonic-gate ipp_rc = EAGAIN; 14047c478bd9Sstevel@tonic-gate goto done; 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate kmem_free(mid_array, nelt * sizeof (ipp_mod_id_t)); 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 14117c478bd9Sstevel@tonic-gate KM_SLEEP)) != 0) { 14127c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 14137c478bd9Sstevel@tonic-gate return (rc); 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if ((rc = ippctl_attach_modname_array(nvlp, 14177c478bd9Sstevel@tonic-gate modname_array, nelt)) != 0) { 14187c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 14197c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 14207c478bd9Sstevel@tonic-gate return (rc); 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(modname_array, nelt); 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if ((rc = ippctl_callback(nvlp, NULL)) != 0) { 14267c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 14277c478bd9Sstevel@tonic-gate return (rc); 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate done: 14357c478bd9Sstevel@tonic-gate /* 14367c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 14377c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 14387c478bd9Sstevel@tonic-gate */ 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 14417c478bd9Sstevel@tonic-gate return (rc); 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate return (0); 14447c478bd9Sstevel@tonic-gate } 14457c478bd9Sstevel@tonic-gate #undef __FN__ 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_mod_list_actions" 14487c478bd9Sstevel@tonic-gate static int 14497c478bd9Sstevel@tonic-gate ippctl_mod_list_actions( 14507c478bd9Sstevel@tonic-gate char *modname) 14517c478bd9Sstevel@tonic-gate { 14527c478bd9Sstevel@tonic-gate ipp_mod_id_t mid; 14537c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 14547c478bd9Sstevel@tonic-gate int ipp_rc; 14557c478bd9Sstevel@tonic-gate int rc = 0; 14567c478bd9Sstevel@tonic-gate ipp_action_id_t *aid_array; 14577c478bd9Sstevel@tonic-gate char **aname_array = NULL; 14587c478bd9Sstevel@tonic-gate int nelt; 14597c478bd9Sstevel@tonic-gate int length; 14607c478bd9Sstevel@tonic-gate int i; 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* 14637c478bd9Sstevel@tonic-gate * Get the module id. 14647c478bd9Sstevel@tonic-gate */ 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate mid = ipp_mod_lookup(modname); 14677c478bd9Sstevel@tonic-gate FREE_TEXT(modname); 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate /* 14707c478bd9Sstevel@tonic-gate * Get a list of all the action ids for the module. If that succeeds, 14717c478bd9Sstevel@tonic-gate * translate the ids into names. 14727c478bd9Sstevel@tonic-gate * 14737c478bd9Sstevel@tonic-gate * NOTE: This translation may fail if an action is 14747c478bd9Sstevel@tonic-gate * destroyed during this operation. If this occurs, EAGAIN 14757c478bd9Sstevel@tonic-gate * will be passed back to libipp note that a transient 14767c478bd9Sstevel@tonic-gate * problem occured. 14777c478bd9Sstevel@tonic-gate */ 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate if ((ipp_rc = ipp_mod_list_actions(mid, &aid_array, &nelt)) == 0) { 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate /* 14827c478bd9Sstevel@tonic-gate * It is possible that there are no actions defined. 14837c478bd9Sstevel@tonic-gate * (This is unlikely though as the module would normally 14847c478bd9Sstevel@tonic-gate * be auto-unloaded fairly quickly) 14857c478bd9Sstevel@tonic-gate */ 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate if (nelt > 0) { 14887c478bd9Sstevel@tonic-gate length = nelt * sizeof (char *); 14897c478bd9Sstevel@tonic-gate aname_array = kmem_zalloc(length, KM_SLEEP); 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate for (i = 0; i < nelt; i++) { 14927c478bd9Sstevel@tonic-gate if (ipp_action_name(aid_array[i], 14937c478bd9Sstevel@tonic-gate &aname_array[i]) != 0) { 14947c478bd9Sstevel@tonic-gate kmem_free(aid_array, nelt * 14957c478bd9Sstevel@tonic-gate sizeof (ipp_action_id_t)); 14967c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 14977c478bd9Sstevel@tonic-gate ipp_rc = EAGAIN; 14987c478bd9Sstevel@tonic-gate goto done; 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate kmem_free(aid_array, nelt * sizeof (ipp_action_id_t)); 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 15057c478bd9Sstevel@tonic-gate KM_SLEEP)) != 0) { 15067c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 15077c478bd9Sstevel@tonic-gate return (rc); 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate if ((rc = ippctl_attach_aname_array(nvlp, aname_array, 15117c478bd9Sstevel@tonic-gate nelt)) != 0) { 15127c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 15137c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 15147c478bd9Sstevel@tonic-gate return (rc); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate FREE_TEXT_ARRAY(aname_array, nelt); 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate if ((rc = ippctl_callback(nvlp, NULL)) != 0) { 15207c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 15217c478bd9Sstevel@tonic-gate return (rc); 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate } 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate done: 15297c478bd9Sstevel@tonic-gate /* 15307c478bd9Sstevel@tonic-gate * Add an nvlist containing the kernel return code to the 15317c478bd9Sstevel@tonic-gate * set of nvlists to pass back to libipp. 15327c478bd9Sstevel@tonic-gate */ 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate if ((rc = ippctl_set_rc(ipp_rc)) != 0) 15357c478bd9Sstevel@tonic-gate return (rc); 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate return (0); 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate #undef __FN__ 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_data" 15427c478bd9Sstevel@tonic-gate static int 15437c478bd9Sstevel@tonic-gate ippctl_data( 15447c478bd9Sstevel@tonic-gate char **dbufp, 15457c478bd9Sstevel@tonic-gate size_t *dbuflenp, 15467c478bd9Sstevel@tonic-gate size_t *nextbuflenp) 15477c478bd9Sstevel@tonic-gate { 15487c478bd9Sstevel@tonic-gate int i; 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate DBG0(DBG_CBOPS, "called\n"); 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate /* 15537c478bd9Sstevel@tonic-gate * Get the next data buffer from the array by looking at the 15547c478bd9Sstevel@tonic-gate * 'read index'. If this is the same as the 'write index' then 15557c478bd9Sstevel@tonic-gate * there's no more buffers in the array. 15567c478bd9Sstevel@tonic-gate */ 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate i = ippctl_rindex; 15597c478bd9Sstevel@tonic-gate if (i == ippctl_windex) 15607c478bd9Sstevel@tonic-gate return (ENOENT); 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate /* 15637c478bd9Sstevel@tonic-gate * Extract the buffer details. It is a pre-packed nvlist. 15647c478bd9Sstevel@tonic-gate */ 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate *dbufp = ippctl_array[i].buf; 15677c478bd9Sstevel@tonic-gate *dbuflenp = ippctl_array[i].buflen; 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate DBG2(DBG_CBOPS, "accessing nvlist[%d], length %lu\n", i, *dbuflenp); 15707c478bd9Sstevel@tonic-gate ASSERT(*dbufp != NULL); 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate /* 15737c478bd9Sstevel@tonic-gate * Advance the 'read index' and check if there's another buffer. 15747c478bd9Sstevel@tonic-gate * If there is then we need to pass back its length to libipp so that 15757c478bd9Sstevel@tonic-gate * another data ioctl will be issued. 15767c478bd9Sstevel@tonic-gate */ 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate i++; 15797c478bd9Sstevel@tonic-gate if (i < ippctl_windex) 15807c478bd9Sstevel@tonic-gate *nextbuflenp = ippctl_array[i].buflen; 15817c478bd9Sstevel@tonic-gate else 15827c478bd9Sstevel@tonic-gate *nextbuflenp = 0; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate ippctl_rindex = i; 15857c478bd9Sstevel@tonic-gate return (0); 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate #undef __FN__ 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_flush" 15907c478bd9Sstevel@tonic-gate static void 15917c478bd9Sstevel@tonic-gate ippctl_flush( 15927c478bd9Sstevel@tonic-gate void) 15937c478bd9Sstevel@tonic-gate { 15947c478bd9Sstevel@tonic-gate int i; 15957c478bd9Sstevel@tonic-gate char *buf; 15967c478bd9Sstevel@tonic-gate size_t buflen; 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate /* 15997c478bd9Sstevel@tonic-gate * Free any buffers left in the array. 16007c478bd9Sstevel@tonic-gate */ 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate for (i = 0; i < ippctl_limit; i++) { 16037c478bd9Sstevel@tonic-gate if ((buflen = ippctl_array[i].buflen) > 0) { 16047c478bd9Sstevel@tonic-gate buf = ippctl_array[i].buf; 16057c478bd9Sstevel@tonic-gate ASSERT(buf != NULL); 16067c478bd9Sstevel@tonic-gate kmem_free(buf, buflen); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate /* 16117c478bd9Sstevel@tonic-gate * NULL all the entries. 16127c478bd9Sstevel@tonic-gate */ 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate bzero(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t)); 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate /* 16177c478bd9Sstevel@tonic-gate * Reset the indexes. 16187c478bd9Sstevel@tonic-gate */ 16197c478bd9Sstevel@tonic-gate 16207c478bd9Sstevel@tonic-gate ippctl_rindex = 0; 16217c478bd9Sstevel@tonic-gate ippctl_windex = 1; 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate #undef __FN__ 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_add_nvlist" 16267c478bd9Sstevel@tonic-gate static int 16277c478bd9Sstevel@tonic-gate ippctl_add_nvlist( 16287c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 16297c478bd9Sstevel@tonic-gate int i) 16307c478bd9Sstevel@tonic-gate { 16317c478bd9Sstevel@tonic-gate char *buf; 16327c478bd9Sstevel@tonic-gate size_t buflen; 16337c478bd9Sstevel@tonic-gate int rc; 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate /* 16367c478bd9Sstevel@tonic-gate * NULL the buffer pointer so that a buffer is automatically 16377c478bd9Sstevel@tonic-gate * allocated for us. 16387c478bd9Sstevel@tonic-gate */ 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate buf = NULL; 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate /* 16437c478bd9Sstevel@tonic-gate * Pack the nvlist and get back the buffer pointer and length. 16447c478bd9Sstevel@tonic-gate */ 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate if ((rc = nvlist_pack(nvlp, &buf, &buflen, NV_ENCODE_NATIVE, 16477c478bd9Sstevel@tonic-gate KM_SLEEP)) != 0) { 16487c478bd9Sstevel@tonic-gate ippctl_array[i].buf = NULL; 16497c478bd9Sstevel@tonic-gate ippctl_array[i].buflen = 0; 16507c478bd9Sstevel@tonic-gate return (rc); 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate DBG2(DBG_CBOPS, "added nvlist[%d]: length %lu\n", i, buflen); 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate /* 16567c478bd9Sstevel@tonic-gate * Store the pointer an length in the array at the given index. 16577c478bd9Sstevel@tonic-gate */ 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate ippctl_array[i].buf = buf; 16607c478bd9Sstevel@tonic-gate ippctl_array[i].buflen = buflen; 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate return (0); 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate #undef __FN__ 16657c478bd9Sstevel@tonic-gate 16667c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_callback" 16677c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 16687c478bd9Sstevel@tonic-gate static int 16697c478bd9Sstevel@tonic-gate ippctl_callback( 16707c478bd9Sstevel@tonic-gate nvlist_t *nvlp, 16717c478bd9Sstevel@tonic-gate void *arg) 16727c478bd9Sstevel@tonic-gate { 16737c478bd9Sstevel@tonic-gate int i; 16747c478bd9Sstevel@tonic-gate int rc; 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate /* 16777c478bd9Sstevel@tonic-gate * Check the 'write index' to see if there's space in the array for 16787c478bd9Sstevel@tonic-gate * a new entry. 16797c478bd9Sstevel@tonic-gate */ 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate i = ippctl_windex; 16827c478bd9Sstevel@tonic-gate ASSERT(i != 0); 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate /* 16857c478bd9Sstevel@tonic-gate * If there's no space, re-allocate the array (see comments in 16867c478bd9Sstevel@tonic-gate * ippctl_realloc() for details). 16877c478bd9Sstevel@tonic-gate */ 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate if (i == ippctl_limit) 16907c478bd9Sstevel@tonic-gate ippctl_realloc(); 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate /* 16937c478bd9Sstevel@tonic-gate * Add the nvlist to the array. 16947c478bd9Sstevel@tonic-gate */ 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate if ((rc = ippctl_add_nvlist(nvlp, i)) == 0) 16977c478bd9Sstevel@tonic-gate ippctl_windex++; 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate return (rc); 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate #undef __FN__ 17027c478bd9Sstevel@tonic-gate 17037c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_set_rc" 17047c478bd9Sstevel@tonic-gate static int 17057c478bd9Sstevel@tonic-gate ippctl_set_rc( 17067c478bd9Sstevel@tonic-gate int val) 17077c478bd9Sstevel@tonic-gate { 17087c478bd9Sstevel@tonic-gate nvlist_t *nvlp; 17097c478bd9Sstevel@tonic-gate int rc; 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate /* 17127c478bd9Sstevel@tonic-gate * Create an nvlist to store the return code, 17137c478bd9Sstevel@tonic-gate */ 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, KM_SLEEP)) != 0) 17167c478bd9Sstevel@tonic-gate return (ENOMEM); 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate if ((rc = nvlist_add_int32(nvlp, IPPCTL_RC, val)) != 0) { 17197c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 17207c478bd9Sstevel@tonic-gate return (rc); 17217c478bd9Sstevel@tonic-gate } 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate /* 17247c478bd9Sstevel@tonic-gate * Add it at the beginning of the array. 17257c478bd9Sstevel@tonic-gate */ 17267c478bd9Sstevel@tonic-gate 17277c478bd9Sstevel@tonic-gate rc = ippctl_add_nvlist(nvlp, 0); 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate nvlist_free(nvlp); 17307c478bd9Sstevel@tonic-gate return (rc); 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate #undef __FN__ 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_alloc" 17357c478bd9Sstevel@tonic-gate static void 17367c478bd9Sstevel@tonic-gate ippctl_alloc( 17377c478bd9Sstevel@tonic-gate int limit) 17387c478bd9Sstevel@tonic-gate { 17397c478bd9Sstevel@tonic-gate /* 17407c478bd9Sstevel@tonic-gate * Allocate the data buffer array and initialize the indexes. 17417c478bd9Sstevel@tonic-gate */ 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate ippctl_array = kmem_zalloc(limit * sizeof (ippctl_buf_t), KM_SLEEP); 17447c478bd9Sstevel@tonic-gate ippctl_limit = limit; 17457c478bd9Sstevel@tonic-gate ippctl_rindex = 0; 17467c478bd9Sstevel@tonic-gate ippctl_windex = 1; 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate #undef __FN__ 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_realloc" 17517c478bd9Sstevel@tonic-gate static void 17527c478bd9Sstevel@tonic-gate ippctl_realloc( 17537c478bd9Sstevel@tonic-gate void) 17547c478bd9Sstevel@tonic-gate { 17557c478bd9Sstevel@tonic-gate ippctl_buf_t *array; 17567c478bd9Sstevel@tonic-gate int limit; 17577c478bd9Sstevel@tonic-gate int i; 17587c478bd9Sstevel@tonic-gate 17597c478bd9Sstevel@tonic-gate /* 17607c478bd9Sstevel@tonic-gate * Allocate a new array twice the size of the old one. 17617c478bd9Sstevel@tonic-gate */ 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate limit = ippctl_limit << 1; 17647c478bd9Sstevel@tonic-gate array = kmem_zalloc(limit * sizeof (ippctl_buf_t), KM_SLEEP); 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate /* 17677c478bd9Sstevel@tonic-gate * Copy across the information from the old array into the new one. 17687c478bd9Sstevel@tonic-gate */ 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate for (i = 0; i < ippctl_limit; i++) 17717c478bd9Sstevel@tonic-gate array[i] = ippctl_array[i]; 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate /* 17747c478bd9Sstevel@tonic-gate * Free the old array. 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate kmem_free(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t)); 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate ippctl_array = array; 17807c478bd9Sstevel@tonic-gate ippctl_limit = limit; 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate #undef __FN__ 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate #define __FN__ "ippctl_free" 17857c478bd9Sstevel@tonic-gate static void 17867c478bd9Sstevel@tonic-gate ippctl_free( 17877c478bd9Sstevel@tonic-gate void) 17887c478bd9Sstevel@tonic-gate { 17897c478bd9Sstevel@tonic-gate /* 17907c478bd9Sstevel@tonic-gate * Flush the array prior to freeing it to make sure no buffers are 17917c478bd9Sstevel@tonic-gate * leaked. 17927c478bd9Sstevel@tonic-gate */ 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate ippctl_flush(); 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate /* 17977c478bd9Sstevel@tonic-gate * Free the array. 17987c478bd9Sstevel@tonic-gate */ 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate kmem_free(ippctl_array, ippctl_limit * sizeof (ippctl_buf_t)); 18017c478bd9Sstevel@tonic-gate ippctl_array = NULL; 18027c478bd9Sstevel@tonic-gate ippctl_limit = -1; 18037c478bd9Sstevel@tonic-gate ippctl_rindex = -1; 18047c478bd9Sstevel@tonic-gate ippctl_windex = -1; 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate #undef __FN__ 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate #ifdef IPPCTL_DEBUG 18097c478bd9Sstevel@tonic-gate static void 18107c478bd9Sstevel@tonic-gate ippctl_debug( 18117c478bd9Sstevel@tonic-gate uint64_t type, 18127c478bd9Sstevel@tonic-gate char *fn, 18137c478bd9Sstevel@tonic-gate char *fmt, 18147c478bd9Sstevel@tonic-gate ...) 18157c478bd9Sstevel@tonic-gate { 18167c478bd9Sstevel@tonic-gate char buf[255]; 18177c478bd9Sstevel@tonic-gate va_list adx; 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate if ((type & ippctl_debug_flags) == 0) 18207c478bd9Sstevel@tonic-gate return; 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate mutex_enter(debug_mutex); 18237c478bd9Sstevel@tonic-gate va_start(adx, fmt); 18247c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, 255, fmt, adx); 18257c478bd9Sstevel@tonic-gate va_end(adx); 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate printf("%s: %s", fn, buf); 18287c478bd9Sstevel@tonic-gate mutex_exit(debug_mutex); 18297c478bd9Sstevel@tonic-gate } 18307c478bd9Sstevel@tonic-gate #endif /* IPPCTL_DBG */ 1831