1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1990 Mentat Inc. */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 32*7c478bd9Sstevel@tonic-gate #include <inet/common.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 35*7c478bd9Sstevel@tonic-gate #include <inet/mi.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 39*7c478bd9Sstevel@tonic-gate #include <inet/nd.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* Free the table pointed to by 'ndp' */ 42*7c478bd9Sstevel@tonic-gate void 43*7c478bd9Sstevel@tonic-gate nd_free(caddr_t *nd_pparam) 44*7c478bd9Sstevel@tonic-gate { 45*7c478bd9Sstevel@tonic-gate ND *nd; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate if ((nd = (ND *)(*nd_pparam)) != NULL) { 48*7c478bd9Sstevel@tonic-gate if (nd->nd_tbl) 49*7c478bd9Sstevel@tonic-gate mi_free((char *)nd->nd_tbl); 50*7c478bd9Sstevel@tonic-gate mi_free((char *)nd); 51*7c478bd9Sstevel@tonic-gate *nd_pparam = NULL; 52*7c478bd9Sstevel@tonic-gate } 53*7c478bd9Sstevel@tonic-gate } 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate int 56*7c478bd9Sstevel@tonic-gate nd_getset(queue_t *q, caddr_t nd_param, MBLKP mp) 57*7c478bd9Sstevel@tonic-gate { 58*7c478bd9Sstevel@tonic-gate int err; 59*7c478bd9Sstevel@tonic-gate IOCP iocp; 60*7c478bd9Sstevel@tonic-gate MBLKP mp1; 61*7c478bd9Sstevel@tonic-gate ND *nd; 62*7c478bd9Sstevel@tonic-gate NDE *nde; 63*7c478bd9Sstevel@tonic-gate char *valp; 64*7c478bd9Sstevel@tonic-gate long avail; 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate if (!nd_param) 67*7c478bd9Sstevel@tonic-gate return (B_FALSE); 68*7c478bd9Sstevel@tonic-gate nd = (ND *)nd_param; 69*7c478bd9Sstevel@tonic-gate iocp = (IOCP)mp->b_rptr; 70*7c478bd9Sstevel@tonic-gate if (iocp->ioc_count == 0 || !(mp1 = mp->b_cont)) { 71*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 72*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 73*7c478bd9Sstevel@tonic-gate iocp->ioc_error = EINVAL; 74*7c478bd9Sstevel@tonic-gate return (B_TRUE); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * NOTE - logic throughout nd_xxx assumes single data block for ioctl. 78*7c478bd9Sstevel@tonic-gate * However, existing code sends in some big buffers. 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate avail = iocp->ioc_count; 81*7c478bd9Sstevel@tonic-gate if (mp1->b_cont) { 82*7c478bd9Sstevel@tonic-gate freemsg(mp1->b_cont); 83*7c478bd9Sstevel@tonic-gate mp1->b_cont = NULL; 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate mp1->b_datap->db_lim[-1] = '\0'; /* Force null termination */ 87*7c478bd9Sstevel@tonic-gate valp = (char *)mp1->b_rptr; 88*7c478bd9Sstevel@tonic-gate for (nde = nd->nd_tbl; ; nde++) { 89*7c478bd9Sstevel@tonic-gate if (!nde->nde_name) 90*7c478bd9Sstevel@tonic-gate return (B_FALSE); 91*7c478bd9Sstevel@tonic-gate if (mi_strcmp(nde->nde_name, valp) == 0) 92*7c478bd9Sstevel@tonic-gate break; 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate err = EINVAL; 95*7c478bd9Sstevel@tonic-gate while (*valp++) 96*7c478bd9Sstevel@tonic-gate noop; 97*7c478bd9Sstevel@tonic-gate if (!*valp || valp >= (char *)mp1->b_wptr) 98*7c478bd9Sstevel@tonic-gate valp = NULL; 99*7c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) { 100*7c478bd9Sstevel@tonic-gate case ND_GET: 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * (temporary) hack: "*valp" is size of user buffer for 103*7c478bd9Sstevel@tonic-gate * copyout. If result of action routine is too big, free 104*7c478bd9Sstevel@tonic-gate * excess and return ioc_rval as buffer size needed. Return 105*7c478bd9Sstevel@tonic-gate * as many mblocks as will fit, free the rest. For backward 106*7c478bd9Sstevel@tonic-gate * compatibility, assume size of original ioctl buffer if 107*7c478bd9Sstevel@tonic-gate * "*valp" bad or not given. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate if (valp) 110*7c478bd9Sstevel@tonic-gate (void) ddi_strtol(valp, NULL, 10, &avail); 111*7c478bd9Sstevel@tonic-gate /* We overwrite the name/value with the reply data */ 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate mblk_t *mp2 = mp1; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate while (mp2) { 116*7c478bd9Sstevel@tonic-gate mp2->b_wptr = mp2->b_rptr; 117*7c478bd9Sstevel@tonic-gate mp2 = mp2->b_cont; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate err = (*nde->nde_get_pfi)(q, mp1, nde->nde_data, iocp->ioc_cr); 121*7c478bd9Sstevel@tonic-gate if (!err) { 122*7c478bd9Sstevel@tonic-gate int size_out; 123*7c478bd9Sstevel@tonic-gate int excess; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* Tack on the null */ 128*7c478bd9Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp1, '\0'); 129*7c478bd9Sstevel@tonic-gate size_out = msgdsize(mp1); 130*7c478bd9Sstevel@tonic-gate excess = size_out - avail; 131*7c478bd9Sstevel@tonic-gate if (excess > 0) { 132*7c478bd9Sstevel@tonic-gate iocp->ioc_rval = size_out; 133*7c478bd9Sstevel@tonic-gate size_out -= excess; 134*7c478bd9Sstevel@tonic-gate (void) adjmsg(mp1, -(excess + 1)); 135*7c478bd9Sstevel@tonic-gate (void) mi_mpprintf_putc((char *)mp1, '\0'); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate iocp->ioc_count = size_out; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate break; 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate case ND_SET: 142*7c478bd9Sstevel@tonic-gate if (valp) { 143*7c478bd9Sstevel@tonic-gate if ((iocp->ioc_cr != NULL) && 144*7c478bd9Sstevel@tonic-gate ((err = secpolicy_net_config(iocp->ioc_cr, B_FALSE)) 145*7c478bd9Sstevel@tonic-gate == 0)) { 146*7c478bd9Sstevel@tonic-gate err = (*nde->nde_set_pfi)(q, mp1, valp, 147*7c478bd9Sstevel@tonic-gate nde->nde_data, iocp->ioc_cr); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate iocp->ioc_count = 0; 150*7c478bd9Sstevel@tonic-gate freemsg(mp1); 151*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate break; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate default: 156*7c478bd9Sstevel@tonic-gate break; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate iocp->ioc_error = err; 159*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK; 160*7c478bd9Sstevel@tonic-gate return (B_TRUE); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 164*7c478bd9Sstevel@tonic-gate int 165*7c478bd9Sstevel@tonic-gate nd_get_default(queue_t *q, MBLKP mp, caddr_t data, cred_t *ioc_cr) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate return (EACCES); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * This routine may be used as the get dispatch routine in nd tables 172*7c478bd9Sstevel@tonic-gate * for long variables. To use this routine instead of a module 173*7c478bd9Sstevel@tonic-gate * specific routine, call nd_load as 174*7c478bd9Sstevel@tonic-gate * nd_load(&nd_ptr, "name", nd_get_long, set_pfi, &long_variable) 175*7c478bd9Sstevel@tonic-gate * The name of the variable followed by a space and the value of the 176*7c478bd9Sstevel@tonic-gate * variable will be printed in response to a get_status call. 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 179*7c478bd9Sstevel@tonic-gate int 180*7c478bd9Sstevel@tonic-gate nd_get_long(queue_t *q, MBLKP mp, caddr_t data, cred_t *ioc_cr) 181*7c478bd9Sstevel@tonic-gate { 182*7c478bd9Sstevel@tonic-gate ulong_t *lp; 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate lp = (ulong_t *)data; 185*7c478bd9Sstevel@tonic-gate (void) mi_mpprintf(mp, "%ld", *lp); 186*7c478bd9Sstevel@tonic-gate return (0); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 190*7c478bd9Sstevel@tonic-gate int 191*7c478bd9Sstevel@tonic-gate nd_get_names(queue_t *q, MBLKP mp, caddr_t nd_param, cred_t *ioc_cr) 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate ND *nd; 194*7c478bd9Sstevel@tonic-gate NDE *nde; 195*7c478bd9Sstevel@tonic-gate char *rwtag; 196*7c478bd9Sstevel@tonic-gate boolean_t get_ok, set_ok; 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate nd = (ND *)nd_param; 199*7c478bd9Sstevel@tonic-gate if (!nd) 200*7c478bd9Sstevel@tonic-gate return (ENOENT); 201*7c478bd9Sstevel@tonic-gate for (nde = nd->nd_tbl; nde->nde_name; nde++) { 202*7c478bd9Sstevel@tonic-gate get_ok = nde->nde_get_pfi != nd_get_default; 203*7c478bd9Sstevel@tonic-gate set_ok = nde->nde_set_pfi != nd_set_default; 204*7c478bd9Sstevel@tonic-gate if (get_ok) { 205*7c478bd9Sstevel@tonic-gate if (set_ok) 206*7c478bd9Sstevel@tonic-gate rwtag = "read and write"; 207*7c478bd9Sstevel@tonic-gate else 208*7c478bd9Sstevel@tonic-gate rwtag = "read only"; 209*7c478bd9Sstevel@tonic-gate } else if (set_ok) 210*7c478bd9Sstevel@tonic-gate rwtag = "write only"; 211*7c478bd9Sstevel@tonic-gate else 212*7c478bd9Sstevel@tonic-gate rwtag = "no read or write"; 213*7c478bd9Sstevel@tonic-gate (void) mi_mpprintf(mp, "%s (%s)", nde->nde_name, rwtag); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate return (0); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * Load 'name' into the named dispatch table pointed to by 'ndp'. 220*7c478bd9Sstevel@tonic-gate * 'ndp' should be the address of a char pointer cell. If the table 221*7c478bd9Sstevel@tonic-gate * does not exist (*ndp == 0), a new table is allocated and 'ndp' 222*7c478bd9Sstevel@tonic-gate * is stuffed. If there is not enough space in the table for a new 223*7c478bd9Sstevel@tonic-gate * entry, more space is allocated. 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate boolean_t 226*7c478bd9Sstevel@tonic-gate nd_load(caddr_t *nd_pparam, char *name, ndgetf_t get_pfi, ndsetf_t set_pfi, 227*7c478bd9Sstevel@tonic-gate caddr_t data) 228*7c478bd9Sstevel@tonic-gate { 229*7c478bd9Sstevel@tonic-gate ND *nd; 230*7c478bd9Sstevel@tonic-gate NDE *nde; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if (!nd_pparam) 233*7c478bd9Sstevel@tonic-gate return (B_FALSE); 234*7c478bd9Sstevel@tonic-gate if ((nd = (ND *)(*nd_pparam)) == NULL) { 235*7c478bd9Sstevel@tonic-gate if ((nd = (ND *)mi_alloc(sizeof (ND), BPRI_MED)) == NULL) 236*7c478bd9Sstevel@tonic-gate return (B_FALSE); 237*7c478bd9Sstevel@tonic-gate bzero((caddr_t)nd, sizeof (ND)); 238*7c478bd9Sstevel@tonic-gate *nd_pparam = (caddr_t)nd; 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate if (nd->nd_tbl) { 241*7c478bd9Sstevel@tonic-gate for (nde = nd->nd_tbl; nde->nde_name; nde++) { 242*7c478bd9Sstevel@tonic-gate if (mi_strcmp(name, nde->nde_name) == 0) 243*7c478bd9Sstevel@tonic-gate goto fill_it; 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate if (nd->nd_free_count <= 1) { 247*7c478bd9Sstevel@tonic-gate if ((nde = (NDE *)mi_alloc(nd->nd_size + 248*7c478bd9Sstevel@tonic-gate NDE_ALLOC_SIZE, BPRI_MED)) == NULL) 249*7c478bd9Sstevel@tonic-gate return (B_FALSE); 250*7c478bd9Sstevel@tonic-gate bzero((char *)nde, nd->nd_size + NDE_ALLOC_SIZE); 251*7c478bd9Sstevel@tonic-gate nd->nd_free_count += NDE_ALLOC_COUNT; 252*7c478bd9Sstevel@tonic-gate if (nd->nd_tbl) { 253*7c478bd9Sstevel@tonic-gate bcopy((char *)nd->nd_tbl, (char *)nde, nd->nd_size); 254*7c478bd9Sstevel@tonic-gate mi_free((char *)nd->nd_tbl); 255*7c478bd9Sstevel@tonic-gate } else { 256*7c478bd9Sstevel@tonic-gate nd->nd_free_count--; 257*7c478bd9Sstevel@tonic-gate nde->nde_name = "?"; 258*7c478bd9Sstevel@tonic-gate nde->nde_get_pfi = nd_get_names; 259*7c478bd9Sstevel@tonic-gate nde->nde_set_pfi = nd_set_default; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate nde->nde_data = (caddr_t)nd; 262*7c478bd9Sstevel@tonic-gate nd->nd_tbl = nde; 263*7c478bd9Sstevel@tonic-gate nd->nd_size += NDE_ALLOC_SIZE; 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate for (nde = nd->nd_tbl; nde->nde_name; nde++) 266*7c478bd9Sstevel@tonic-gate noop; 267*7c478bd9Sstevel@tonic-gate nd->nd_free_count--; 268*7c478bd9Sstevel@tonic-gate fill_it: 269*7c478bd9Sstevel@tonic-gate nde->nde_name = name; 270*7c478bd9Sstevel@tonic-gate nde->nde_get_pfi = get_pfi ? get_pfi : nd_get_default; 271*7c478bd9Sstevel@tonic-gate nde->nde_set_pfi = set_pfi ? set_pfi : nd_set_default; 272*7c478bd9Sstevel@tonic-gate nde->nde_data = data; 273*7c478bd9Sstevel@tonic-gate return (B_TRUE); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * Unload 'name' from the named dispatch table. If the table does not 278*7c478bd9Sstevel@tonic-gate * exist, I return. I do not free up space, but I do raise the 279*7c478bd9Sstevel@tonic-gate * free count so future nd_load()s don't take as much memory. 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate void 283*7c478bd9Sstevel@tonic-gate nd_unload(caddr_t *nd_pparam, char *name) 284*7c478bd9Sstevel@tonic-gate { 285*7c478bd9Sstevel@tonic-gate ND *nd; 286*7c478bd9Sstevel@tonic-gate NDE *nde; 287*7c478bd9Sstevel@tonic-gate boolean_t foundit = B_FALSE; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* My apologies for the in-boolean assignment. */ 290*7c478bd9Sstevel@tonic-gate if (nd_pparam == NULL || (nd = (ND *)(*nd_pparam)) == NULL || 291*7c478bd9Sstevel@tonic-gate nd->nd_tbl == NULL) 292*7c478bd9Sstevel@tonic-gate return; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate for (nde = nd->nd_tbl; nde->nde_name != NULL; nde++) { 295*7c478bd9Sstevel@tonic-gate if (foundit) 296*7c478bd9Sstevel@tonic-gate *(nde - 1) = *nde; 297*7c478bd9Sstevel@tonic-gate if (mi_strcmp(name, nde->nde_name) == 0) 298*7c478bd9Sstevel@tonic-gate foundit = B_TRUE; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate if (foundit) 301*7c478bd9Sstevel@tonic-gate bzero(nde - 1, sizeof (NDE)); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 305*7c478bd9Sstevel@tonic-gate int 306*7c478bd9Sstevel@tonic-gate nd_set_default(queue_t *q, MBLKP mp, char *value, caddr_t data, cred_t *ioc_cr) 307*7c478bd9Sstevel@tonic-gate { 308*7c478bd9Sstevel@tonic-gate return (EACCES); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 312*7c478bd9Sstevel@tonic-gate int 313*7c478bd9Sstevel@tonic-gate nd_set_long(queue_t *q, MBLKP mp, char *value, caddr_t data, cred_t *ioc_cr) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate ulong_t *lp; 316*7c478bd9Sstevel@tonic-gate long new_value; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (ddi_strtol(value, NULL, 10, &new_value) != 0) 319*7c478bd9Sstevel@tonic-gate return (EINVAL); 320*7c478bd9Sstevel@tonic-gate lp = (ulong_t *)data; 321*7c478bd9Sstevel@tonic-gate *lp = new_value; 322*7c478bd9Sstevel@tonic-gate return (0); 323*7c478bd9Sstevel@tonic-gate } 324