1*6e91bba0SGirish Moodalbail /* 2*6e91bba0SGirish Moodalbail * CDDL HEADER START 3*6e91bba0SGirish Moodalbail * 4*6e91bba0SGirish Moodalbail * The contents of this file are subject to the terms of the 5*6e91bba0SGirish Moodalbail * Common Development and Distribution License (the "License"). 6*6e91bba0SGirish Moodalbail * You may not use this file except in compliance with the License. 7*6e91bba0SGirish Moodalbail * 8*6e91bba0SGirish Moodalbail * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6e91bba0SGirish Moodalbail * or http://www.opensolaris.org/os/licensing. 10*6e91bba0SGirish Moodalbail * See the License for the specific language governing permissions 11*6e91bba0SGirish Moodalbail * and limitations under the License. 12*6e91bba0SGirish Moodalbail * 13*6e91bba0SGirish Moodalbail * When distributing Covered Code, include this CDDL HEADER in each 14*6e91bba0SGirish Moodalbail * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6e91bba0SGirish Moodalbail * If applicable, add the following below this CDDL HEADER, with the 16*6e91bba0SGirish Moodalbail * fields enclosed by brackets "[]" replaced with your own identifying 17*6e91bba0SGirish Moodalbail * information: Portions Copyright [yyyy] [name of copyright owner] 18*6e91bba0SGirish Moodalbail * 19*6e91bba0SGirish Moodalbail * CDDL HEADER END 20*6e91bba0SGirish Moodalbail */ 21*6e91bba0SGirish Moodalbail /* 22*6e91bba0SGirish Moodalbail * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23*6e91bba0SGirish Moodalbail * Use is subject to license terms. 24*6e91bba0SGirish Moodalbail */ 25*6e91bba0SGirish Moodalbail 26*6e91bba0SGirish Moodalbail #include <inet/tunables.h> 27*6e91bba0SGirish Moodalbail #include <sys/md5.h> 28*6e91bba0SGirish Moodalbail #include <inet/common.h> 29*6e91bba0SGirish Moodalbail #include <inet/ip.h> 30*6e91bba0SGirish Moodalbail #include <inet/ip6.h> 31*6e91bba0SGirish Moodalbail #include <netinet/icmp6.h> 32*6e91bba0SGirish Moodalbail #include <inet/ip_stack.h> 33*6e91bba0SGirish Moodalbail #include <inet/rawip_impl.h> 34*6e91bba0SGirish Moodalbail #include <inet/tcp_stack.h> 35*6e91bba0SGirish Moodalbail #include <inet/tcp_impl.h> 36*6e91bba0SGirish Moodalbail #include <inet/udp_impl.h> 37*6e91bba0SGirish Moodalbail #include <inet/sctp/sctp_stack.h> 38*6e91bba0SGirish Moodalbail #include <inet/sctp/sctp_impl.h> 39*6e91bba0SGirish Moodalbail #include <inet/tunables.h> 40*6e91bba0SGirish Moodalbail 41*6e91bba0SGirish Moodalbail static int 42*6e91bba0SGirish Moodalbail prop_perm2const(mod_prop_info_t *pinfo) 43*6e91bba0SGirish Moodalbail { 44*6e91bba0SGirish Moodalbail if (pinfo->mpi_setf == NULL) 45*6e91bba0SGirish Moodalbail return (MOD_PROP_PERM_READ); 46*6e91bba0SGirish Moodalbail if (pinfo->mpi_getf == NULL) 47*6e91bba0SGirish Moodalbail return (MOD_PROP_PERM_WRITE); 48*6e91bba0SGirish Moodalbail return (MOD_PROP_PERM_RW); 49*6e91bba0SGirish Moodalbail } 50*6e91bba0SGirish Moodalbail 51*6e91bba0SGirish Moodalbail /* 52*6e91bba0SGirish Moodalbail * Modifies the value of the property to default value or to the `pval' 53*6e91bba0SGirish Moodalbail * specified by the user. 54*6e91bba0SGirish Moodalbail */ 55*6e91bba0SGirish Moodalbail /* ARGSUSED */ 56*6e91bba0SGirish Moodalbail int 57*6e91bba0SGirish Moodalbail mod_set_boolean(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, 58*6e91bba0SGirish Moodalbail const char *ifname, const void* pval, uint_t flags) 59*6e91bba0SGirish Moodalbail { 60*6e91bba0SGirish Moodalbail char *end; 61*6e91bba0SGirish Moodalbail unsigned long new_value; 62*6e91bba0SGirish Moodalbail 63*6e91bba0SGirish Moodalbail if (flags & MOD_PROP_DEFAULT) { 64*6e91bba0SGirish Moodalbail pinfo->prop_cur_bval = pinfo->prop_def_bval; 65*6e91bba0SGirish Moodalbail return (0); 66*6e91bba0SGirish Moodalbail } 67*6e91bba0SGirish Moodalbail 68*6e91bba0SGirish Moodalbail if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0') 69*6e91bba0SGirish Moodalbail return (EINVAL); 70*6e91bba0SGirish Moodalbail if (new_value != B_TRUE && new_value != B_FALSE) 71*6e91bba0SGirish Moodalbail return (EINVAL); 72*6e91bba0SGirish Moodalbail pinfo->prop_cur_bval = new_value; 73*6e91bba0SGirish Moodalbail return (0); 74*6e91bba0SGirish Moodalbail } 75*6e91bba0SGirish Moodalbail 76*6e91bba0SGirish Moodalbail /* 77*6e91bba0SGirish Moodalbail * Retrieves property permission, default value, current value or possible 78*6e91bba0SGirish Moodalbail * values for those properties whose value type is boolean_t. 79*6e91bba0SGirish Moodalbail */ 80*6e91bba0SGirish Moodalbail /* ARGSUSED */ 81*6e91bba0SGirish Moodalbail int 82*6e91bba0SGirish Moodalbail mod_get_boolean(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, 83*6e91bba0SGirish Moodalbail void *pval, uint_t psize, uint_t flags) 84*6e91bba0SGirish Moodalbail { 85*6e91bba0SGirish Moodalbail boolean_t get_def = (flags & MOD_PROP_DEFAULT); 86*6e91bba0SGirish Moodalbail boolean_t get_perm = (flags & MOD_PROP_PERM); 87*6e91bba0SGirish Moodalbail boolean_t get_range = (flags & MOD_PROP_POSSIBLE); 88*6e91bba0SGirish Moodalbail size_t nbytes; 89*6e91bba0SGirish Moodalbail 90*6e91bba0SGirish Moodalbail bzero(pval, psize); 91*6e91bba0SGirish Moodalbail if (get_perm) 92*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo)); 93*6e91bba0SGirish Moodalbail else if (get_range) 94*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u,%u", B_FALSE, B_TRUE); 95*6e91bba0SGirish Moodalbail else if (get_def) 96*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_bval); 97*6e91bba0SGirish Moodalbail else 98*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_bval); 99*6e91bba0SGirish Moodalbail if (nbytes >= psize) 100*6e91bba0SGirish Moodalbail return (ENOBUFS); 101*6e91bba0SGirish Moodalbail return (0); 102*6e91bba0SGirish Moodalbail } 103*6e91bba0SGirish Moodalbail 104*6e91bba0SGirish Moodalbail /* 105*6e91bba0SGirish Moodalbail * Modifies the value of the property to default value or to the `pval' 106*6e91bba0SGirish Moodalbail * specified by the user. 107*6e91bba0SGirish Moodalbail */ 108*6e91bba0SGirish Moodalbail /* ARGSUSED */ 109*6e91bba0SGirish Moodalbail int 110*6e91bba0SGirish Moodalbail mod_set_uint32(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, 111*6e91bba0SGirish Moodalbail const char *ifname, const void* pval, uint_t flags) 112*6e91bba0SGirish Moodalbail { 113*6e91bba0SGirish Moodalbail char *end; 114*6e91bba0SGirish Moodalbail unsigned long new_value; 115*6e91bba0SGirish Moodalbail 116*6e91bba0SGirish Moodalbail if (flags & MOD_PROP_DEFAULT) { 117*6e91bba0SGirish Moodalbail pinfo->prop_cur_uval = pinfo->prop_def_uval; 118*6e91bba0SGirish Moodalbail return (0); 119*6e91bba0SGirish Moodalbail } 120*6e91bba0SGirish Moodalbail 121*6e91bba0SGirish Moodalbail if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0') 122*6e91bba0SGirish Moodalbail return (EINVAL); 123*6e91bba0SGirish Moodalbail if (new_value < pinfo->prop_min_uval || 124*6e91bba0SGirish Moodalbail new_value > pinfo->prop_max_uval) { 125*6e91bba0SGirish Moodalbail return (ERANGE); 126*6e91bba0SGirish Moodalbail } 127*6e91bba0SGirish Moodalbail pinfo->prop_cur_uval = (uint32_t)new_value; 128*6e91bba0SGirish Moodalbail return (0); 129*6e91bba0SGirish Moodalbail } 130*6e91bba0SGirish Moodalbail 131*6e91bba0SGirish Moodalbail /* 132*6e91bba0SGirish Moodalbail * Rounds up the value to make it multiple of 8. 133*6e91bba0SGirish Moodalbail */ 134*6e91bba0SGirish Moodalbail /* ARGSUSED */ 135*6e91bba0SGirish Moodalbail int 136*6e91bba0SGirish Moodalbail mod_set_aligned(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, 137*6e91bba0SGirish Moodalbail const char *ifname, const void* pval, uint_t flags) 138*6e91bba0SGirish Moodalbail { 139*6e91bba0SGirish Moodalbail int err; 140*6e91bba0SGirish Moodalbail 141*6e91bba0SGirish Moodalbail if ((err = mod_set_uint32(cbarg, cr, pinfo, ifname, pval, flags)) != 0) 142*6e91bba0SGirish Moodalbail return (err); 143*6e91bba0SGirish Moodalbail 144*6e91bba0SGirish Moodalbail /* if required, align the value to multiple of 8 */ 145*6e91bba0SGirish Moodalbail if (pinfo->prop_cur_uval & 0x7) { 146*6e91bba0SGirish Moodalbail pinfo->prop_cur_uval &= ~0x7; 147*6e91bba0SGirish Moodalbail pinfo->prop_cur_uval += 0x8; 148*6e91bba0SGirish Moodalbail } 149*6e91bba0SGirish Moodalbail 150*6e91bba0SGirish Moodalbail return (0); 151*6e91bba0SGirish Moodalbail } 152*6e91bba0SGirish Moodalbail 153*6e91bba0SGirish Moodalbail /* 154*6e91bba0SGirish Moodalbail * Retrieves property permission, default value, current value or possible 155*6e91bba0SGirish Moodalbail * values for those properties whose value type is uint32_t. 156*6e91bba0SGirish Moodalbail */ 157*6e91bba0SGirish Moodalbail /* ARGSUSED */ 158*6e91bba0SGirish Moodalbail int 159*6e91bba0SGirish Moodalbail mod_get_uint32(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, 160*6e91bba0SGirish Moodalbail void *pval, uint_t psize, uint_t flags) 161*6e91bba0SGirish Moodalbail { 162*6e91bba0SGirish Moodalbail boolean_t get_def = (flags & MOD_PROP_DEFAULT); 163*6e91bba0SGirish Moodalbail boolean_t get_perm = (flags & MOD_PROP_PERM); 164*6e91bba0SGirish Moodalbail boolean_t get_range = (flags & MOD_PROP_POSSIBLE); 165*6e91bba0SGirish Moodalbail size_t nbytes; 166*6e91bba0SGirish Moodalbail 167*6e91bba0SGirish Moodalbail bzero(pval, psize); 168*6e91bba0SGirish Moodalbail if (get_perm) 169*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo)); 170*6e91bba0SGirish Moodalbail else if (get_range) 171*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u-%u", 172*6e91bba0SGirish Moodalbail pinfo->prop_min_uval, pinfo->prop_max_uval); 173*6e91bba0SGirish Moodalbail else if (get_def) 174*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_uval); 175*6e91bba0SGirish Moodalbail else 176*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_uval); 177*6e91bba0SGirish Moodalbail if (nbytes >= psize) 178*6e91bba0SGirish Moodalbail return (ENOBUFS); 179*6e91bba0SGirish Moodalbail return (0); 180*6e91bba0SGirish Moodalbail } 181*6e91bba0SGirish Moodalbail 182*6e91bba0SGirish Moodalbail /* 183*6e91bba0SGirish Moodalbail * Implements /sbin/ndd -get /dev/ip ?, for all the modules. Needed for 184*6e91bba0SGirish Moodalbail * backward compatibility with /sbin/ndd. 185*6e91bba0SGirish Moodalbail */ 186*6e91bba0SGirish Moodalbail /* ARGSUSED */ 187*6e91bba0SGirish Moodalbail int 188*6e91bba0SGirish Moodalbail mod_get_allprop(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, 189*6e91bba0SGirish Moodalbail void *val, uint_t psize, uint_t flags) 190*6e91bba0SGirish Moodalbail { 191*6e91bba0SGirish Moodalbail char *pval = val; 192*6e91bba0SGirish Moodalbail mod_prop_info_t *ptbl, *prop; 193*6e91bba0SGirish Moodalbail ip_stack_t *ipst; 194*6e91bba0SGirish Moodalbail tcp_stack_t *tcps; 195*6e91bba0SGirish Moodalbail sctp_stack_t *sctps; 196*6e91bba0SGirish Moodalbail udp_stack_t *us; 197*6e91bba0SGirish Moodalbail icmp_stack_t *is; 198*6e91bba0SGirish Moodalbail uint_t size; 199*6e91bba0SGirish Moodalbail size_t nbytes = 0, tbytes = 0; 200*6e91bba0SGirish Moodalbail 201*6e91bba0SGirish Moodalbail bzero(pval, psize); 202*6e91bba0SGirish Moodalbail size = psize; 203*6e91bba0SGirish Moodalbail 204*6e91bba0SGirish Moodalbail switch (pinfo->mpi_proto) { 205*6e91bba0SGirish Moodalbail case MOD_PROTO_IP: 206*6e91bba0SGirish Moodalbail case MOD_PROTO_IPV4: 207*6e91bba0SGirish Moodalbail case MOD_PROTO_IPV6: 208*6e91bba0SGirish Moodalbail ipst = (ip_stack_t *)cbarg; 209*6e91bba0SGirish Moodalbail ptbl = ipst->ips_propinfo_tbl; 210*6e91bba0SGirish Moodalbail break; 211*6e91bba0SGirish Moodalbail case MOD_PROTO_RAWIP: 212*6e91bba0SGirish Moodalbail is = (icmp_stack_t *)cbarg; 213*6e91bba0SGirish Moodalbail ptbl = is->is_propinfo_tbl; 214*6e91bba0SGirish Moodalbail break; 215*6e91bba0SGirish Moodalbail case MOD_PROTO_TCP: 216*6e91bba0SGirish Moodalbail tcps = (tcp_stack_t *)cbarg; 217*6e91bba0SGirish Moodalbail ptbl = tcps->tcps_propinfo_tbl; 218*6e91bba0SGirish Moodalbail break; 219*6e91bba0SGirish Moodalbail case MOD_PROTO_UDP: 220*6e91bba0SGirish Moodalbail us = (udp_stack_t *)cbarg; 221*6e91bba0SGirish Moodalbail ptbl = us->us_propinfo_tbl; 222*6e91bba0SGirish Moodalbail break; 223*6e91bba0SGirish Moodalbail case MOD_PROTO_SCTP: 224*6e91bba0SGirish Moodalbail sctps = (sctp_stack_t *)cbarg; 225*6e91bba0SGirish Moodalbail ptbl = sctps->sctps_propinfo_tbl; 226*6e91bba0SGirish Moodalbail break; 227*6e91bba0SGirish Moodalbail default: 228*6e91bba0SGirish Moodalbail return (EINVAL); 229*6e91bba0SGirish Moodalbail } 230*6e91bba0SGirish Moodalbail 231*6e91bba0SGirish Moodalbail for (prop = ptbl; prop->mpi_name != NULL; prop++) { 232*6e91bba0SGirish Moodalbail if (prop->mpi_name[0] == '\0' || 233*6e91bba0SGirish Moodalbail strcmp(prop->mpi_name, "mtu") == 0 || 234*6e91bba0SGirish Moodalbail strcmp(prop->mpi_name, "?") == 0) 235*6e91bba0SGirish Moodalbail continue; 236*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, size, "%s %d %d", prop->mpi_name, 237*6e91bba0SGirish Moodalbail prop->mpi_proto, prop_perm2const(prop)); 238*6e91bba0SGirish Moodalbail size -= nbytes + 1; 239*6e91bba0SGirish Moodalbail pval += nbytes + 1; 240*6e91bba0SGirish Moodalbail tbytes += nbytes + 1; 241*6e91bba0SGirish Moodalbail if (tbytes >= psize) { 242*6e91bba0SGirish Moodalbail /* Buffer overflow, stop copying information */ 243*6e91bba0SGirish Moodalbail return (ENOBUFS); 244*6e91bba0SGirish Moodalbail } 245*6e91bba0SGirish Moodalbail } 246*6e91bba0SGirish Moodalbail return (0); 247*6e91bba0SGirish Moodalbail } 248*6e91bba0SGirish Moodalbail 249*6e91bba0SGirish Moodalbail /* 250*6e91bba0SGirish Moodalbail * Hold a lock while changing *_epriv_ports to prevent multiple 251*6e91bba0SGirish Moodalbail * threads from changing it at the same time. 252*6e91bba0SGirish Moodalbail */ 253*6e91bba0SGirish Moodalbail /* ARGSUSED */ 254*6e91bba0SGirish Moodalbail int 255*6e91bba0SGirish Moodalbail mod_set_extra_privports(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, 256*6e91bba0SGirish Moodalbail const char *ifname, const void* val, uint_t flags) 257*6e91bba0SGirish Moodalbail { 258*6e91bba0SGirish Moodalbail uint_t proto = pinfo->mpi_proto; 259*6e91bba0SGirish Moodalbail tcp_stack_t *tcps; 260*6e91bba0SGirish Moodalbail sctp_stack_t *sctps; 261*6e91bba0SGirish Moodalbail udp_stack_t *us; 262*6e91bba0SGirish Moodalbail unsigned long new_value; 263*6e91bba0SGirish Moodalbail char *end; 264*6e91bba0SGirish Moodalbail kmutex_t *lock; 265*6e91bba0SGirish Moodalbail uint_t i, nports; 266*6e91bba0SGirish Moodalbail in_port_t *ports; 267*6e91bba0SGirish Moodalbail boolean_t def = (flags & MOD_PROP_DEFAULT); 268*6e91bba0SGirish Moodalbail const char *pval = val; 269*6e91bba0SGirish Moodalbail 270*6e91bba0SGirish Moodalbail if (!def) { 271*6e91bba0SGirish Moodalbail if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || 272*6e91bba0SGirish Moodalbail *end != '\0') { 273*6e91bba0SGirish Moodalbail return (EINVAL); 274*6e91bba0SGirish Moodalbail } 275*6e91bba0SGirish Moodalbail 276*6e91bba0SGirish Moodalbail if (new_value < pinfo->prop_min_uval || 277*6e91bba0SGirish Moodalbail new_value > pinfo->prop_max_uval) { 278*6e91bba0SGirish Moodalbail return (ERANGE); 279*6e91bba0SGirish Moodalbail } 280*6e91bba0SGirish Moodalbail } 281*6e91bba0SGirish Moodalbail 282*6e91bba0SGirish Moodalbail switch (proto) { 283*6e91bba0SGirish Moodalbail case MOD_PROTO_TCP: 284*6e91bba0SGirish Moodalbail tcps = (tcp_stack_t *)cbarg; 285*6e91bba0SGirish Moodalbail lock = &tcps->tcps_epriv_port_lock; 286*6e91bba0SGirish Moodalbail ports = tcps->tcps_g_epriv_ports; 287*6e91bba0SGirish Moodalbail nports = tcps->tcps_g_num_epriv_ports; 288*6e91bba0SGirish Moodalbail break; 289*6e91bba0SGirish Moodalbail case MOD_PROTO_UDP: 290*6e91bba0SGirish Moodalbail us = (udp_stack_t *)cbarg; 291*6e91bba0SGirish Moodalbail lock = &us->us_epriv_port_lock; 292*6e91bba0SGirish Moodalbail ports = us->us_epriv_ports; 293*6e91bba0SGirish Moodalbail nports = us->us_num_epriv_ports; 294*6e91bba0SGirish Moodalbail break; 295*6e91bba0SGirish Moodalbail case MOD_PROTO_SCTP: 296*6e91bba0SGirish Moodalbail sctps = (sctp_stack_t *)cbarg; 297*6e91bba0SGirish Moodalbail lock = &sctps->sctps_epriv_port_lock; 298*6e91bba0SGirish Moodalbail ports = sctps->sctps_g_epriv_ports; 299*6e91bba0SGirish Moodalbail nports = sctps->sctps_g_num_epriv_ports; 300*6e91bba0SGirish Moodalbail break; 301*6e91bba0SGirish Moodalbail default: 302*6e91bba0SGirish Moodalbail return (ENOTSUP); 303*6e91bba0SGirish Moodalbail } 304*6e91bba0SGirish Moodalbail 305*6e91bba0SGirish Moodalbail mutex_enter(lock); 306*6e91bba0SGirish Moodalbail 307*6e91bba0SGirish Moodalbail /* if MOD_PROP_DEFAULT is set then reset the ports list to default */ 308*6e91bba0SGirish Moodalbail if (def) { 309*6e91bba0SGirish Moodalbail for (i = 0; i < nports; i++) 310*6e91bba0SGirish Moodalbail ports[i] = 0; 311*6e91bba0SGirish Moodalbail ports[0] = ULP_DEF_EPRIV_PORT1; 312*6e91bba0SGirish Moodalbail ports[1] = ULP_DEF_EPRIV_PORT2; 313*6e91bba0SGirish Moodalbail mutex_exit(lock); 314*6e91bba0SGirish Moodalbail return (0); 315*6e91bba0SGirish Moodalbail } 316*6e91bba0SGirish Moodalbail 317*6e91bba0SGirish Moodalbail /* Check if the value is already in the list */ 318*6e91bba0SGirish Moodalbail for (i = 0; i < nports; i++) { 319*6e91bba0SGirish Moodalbail if (new_value == ports[i]) 320*6e91bba0SGirish Moodalbail break; 321*6e91bba0SGirish Moodalbail } 322*6e91bba0SGirish Moodalbail 323*6e91bba0SGirish Moodalbail if (flags & MOD_PROP_REMOVE) { 324*6e91bba0SGirish Moodalbail if (i == nports) { 325*6e91bba0SGirish Moodalbail mutex_exit(lock); 326*6e91bba0SGirish Moodalbail return (ESRCH); 327*6e91bba0SGirish Moodalbail } 328*6e91bba0SGirish Moodalbail /* Clear the value */ 329*6e91bba0SGirish Moodalbail ports[i] = 0; 330*6e91bba0SGirish Moodalbail } else if (flags & MOD_PROP_APPEND) { 331*6e91bba0SGirish Moodalbail if (i != nports) { 332*6e91bba0SGirish Moodalbail mutex_exit(lock); 333*6e91bba0SGirish Moodalbail return (EEXIST); 334*6e91bba0SGirish Moodalbail } 335*6e91bba0SGirish Moodalbail 336*6e91bba0SGirish Moodalbail /* Find an empty slot */ 337*6e91bba0SGirish Moodalbail for (i = 0; i < nports; i++) { 338*6e91bba0SGirish Moodalbail if (ports[i] == 0) 339*6e91bba0SGirish Moodalbail break; 340*6e91bba0SGirish Moodalbail } 341*6e91bba0SGirish Moodalbail if (i == nports) { 342*6e91bba0SGirish Moodalbail mutex_exit(lock); 343*6e91bba0SGirish Moodalbail return (EOVERFLOW); 344*6e91bba0SGirish Moodalbail } 345*6e91bba0SGirish Moodalbail /* Set the new value */ 346*6e91bba0SGirish Moodalbail ports[i] = (in_port_t)new_value; 347*6e91bba0SGirish Moodalbail } else { 348*6e91bba0SGirish Moodalbail /* 349*6e91bba0SGirish Moodalbail * If the user used 'assignment' modifier. 350*6e91bba0SGirish Moodalbail * For eg: 351*6e91bba0SGirish Moodalbail * # ipadm set-prop -p extra_priv_ports=3001 tcp 352*6e91bba0SGirish Moodalbail * 353*6e91bba0SGirish Moodalbail * We clear all the ports and then just add 3001. 354*6e91bba0SGirish Moodalbail */ 355*6e91bba0SGirish Moodalbail ASSERT(flags == MOD_PROP_ACTIVE); 356*6e91bba0SGirish Moodalbail for (i = 0; i < nports; i++) 357*6e91bba0SGirish Moodalbail ports[i] = 0; 358*6e91bba0SGirish Moodalbail ports[0] = (in_port_t)new_value; 359*6e91bba0SGirish Moodalbail } 360*6e91bba0SGirish Moodalbail 361*6e91bba0SGirish Moodalbail mutex_exit(lock); 362*6e91bba0SGirish Moodalbail return (0); 363*6e91bba0SGirish Moodalbail } 364*6e91bba0SGirish Moodalbail 365*6e91bba0SGirish Moodalbail /* 366*6e91bba0SGirish Moodalbail * Note: No locks are held when inspecting *_epriv_ports 367*6e91bba0SGirish Moodalbail * but instead the code relies on: 368*6e91bba0SGirish Moodalbail * - the fact that the address of the array and its size never changes 369*6e91bba0SGirish Moodalbail * - the atomic assignment of the elements of the array 370*6e91bba0SGirish Moodalbail */ 371*6e91bba0SGirish Moodalbail /* ARGSUSED */ 372*6e91bba0SGirish Moodalbail int 373*6e91bba0SGirish Moodalbail mod_get_extra_privports(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, 374*6e91bba0SGirish Moodalbail void *val, uint_t psize, uint_t flags) 375*6e91bba0SGirish Moodalbail { 376*6e91bba0SGirish Moodalbail uint_t proto = pinfo->mpi_proto; 377*6e91bba0SGirish Moodalbail tcp_stack_t *tcps; 378*6e91bba0SGirish Moodalbail sctp_stack_t *sctps; 379*6e91bba0SGirish Moodalbail udp_stack_t *us; 380*6e91bba0SGirish Moodalbail uint_t i, nports, size; 381*6e91bba0SGirish Moodalbail in_port_t *ports; 382*6e91bba0SGirish Moodalbail char *pval = val; 383*6e91bba0SGirish Moodalbail size_t nbytes = 0, tbytes = 0; 384*6e91bba0SGirish Moodalbail boolean_t get_def = (flags & MOD_PROP_DEFAULT); 385*6e91bba0SGirish Moodalbail boolean_t get_perm = (flags & MOD_PROP_PERM); 386*6e91bba0SGirish Moodalbail boolean_t get_range = (flags & MOD_PROP_POSSIBLE); 387*6e91bba0SGirish Moodalbail 388*6e91bba0SGirish Moodalbail bzero(pval, psize); 389*6e91bba0SGirish Moodalbail size = psize; 390*6e91bba0SGirish Moodalbail 391*6e91bba0SGirish Moodalbail if (get_def) { 392*6e91bba0SGirish Moodalbail tbytes = snprintf(pval, psize, "%u,%u", ULP_DEF_EPRIV_PORT1, 393*6e91bba0SGirish Moodalbail ULP_DEF_EPRIV_PORT2); 394*6e91bba0SGirish Moodalbail goto ret; 395*6e91bba0SGirish Moodalbail } else if (get_perm) { 396*6e91bba0SGirish Moodalbail tbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW); 397*6e91bba0SGirish Moodalbail goto ret; 398*6e91bba0SGirish Moodalbail } 399*6e91bba0SGirish Moodalbail 400*6e91bba0SGirish Moodalbail switch (proto) { 401*6e91bba0SGirish Moodalbail case MOD_PROTO_TCP: 402*6e91bba0SGirish Moodalbail tcps = (tcp_stack_t *)cbarg; 403*6e91bba0SGirish Moodalbail ports = tcps->tcps_g_epriv_ports; 404*6e91bba0SGirish Moodalbail nports = tcps->tcps_g_num_epriv_ports; 405*6e91bba0SGirish Moodalbail break; 406*6e91bba0SGirish Moodalbail case MOD_PROTO_UDP: 407*6e91bba0SGirish Moodalbail us = (udp_stack_t *)cbarg; 408*6e91bba0SGirish Moodalbail ports = us->us_epriv_ports; 409*6e91bba0SGirish Moodalbail nports = us->us_num_epriv_ports; 410*6e91bba0SGirish Moodalbail break; 411*6e91bba0SGirish Moodalbail case MOD_PROTO_SCTP: 412*6e91bba0SGirish Moodalbail sctps = (sctp_stack_t *)cbarg; 413*6e91bba0SGirish Moodalbail ports = sctps->sctps_g_epriv_ports; 414*6e91bba0SGirish Moodalbail nports = sctps->sctps_g_num_epriv_ports; 415*6e91bba0SGirish Moodalbail break; 416*6e91bba0SGirish Moodalbail default: 417*6e91bba0SGirish Moodalbail return (ENOTSUP); 418*6e91bba0SGirish Moodalbail } 419*6e91bba0SGirish Moodalbail 420*6e91bba0SGirish Moodalbail if (get_range) { 421*6e91bba0SGirish Moodalbail tbytes = snprintf(pval, psize, "%u-%u", pinfo->prop_min_uval, 422*6e91bba0SGirish Moodalbail pinfo->prop_max_uval); 423*6e91bba0SGirish Moodalbail goto ret; 424*6e91bba0SGirish Moodalbail } 425*6e91bba0SGirish Moodalbail 426*6e91bba0SGirish Moodalbail for (i = 0; i < nports; i++) { 427*6e91bba0SGirish Moodalbail if (ports[i] != 0) { 428*6e91bba0SGirish Moodalbail if (psize == size) 429*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, size, "%u", ports[i]); 430*6e91bba0SGirish Moodalbail else 431*6e91bba0SGirish Moodalbail nbytes = snprintf(pval, size, ",%u", ports[i]); 432*6e91bba0SGirish Moodalbail size -= nbytes; 433*6e91bba0SGirish Moodalbail pval += nbytes; 434*6e91bba0SGirish Moodalbail tbytes += nbytes; 435*6e91bba0SGirish Moodalbail if (tbytes >= psize) 436*6e91bba0SGirish Moodalbail return (ENOBUFS); 437*6e91bba0SGirish Moodalbail } 438*6e91bba0SGirish Moodalbail } 439*6e91bba0SGirish Moodalbail return (0); 440*6e91bba0SGirish Moodalbail ret: 441*6e91bba0SGirish Moodalbail if (tbytes >= psize) 442*6e91bba0SGirish Moodalbail return (ENOBUFS); 443*6e91bba0SGirish Moodalbail return (0); 444*6e91bba0SGirish Moodalbail } 445