112016SGirish.Moodalbail@Sun.COM /*
212016SGirish.Moodalbail@Sun.COM * CDDL HEADER START
312016SGirish.Moodalbail@Sun.COM *
412016SGirish.Moodalbail@Sun.COM * The contents of this file are subject to the terms of the
512016SGirish.Moodalbail@Sun.COM * Common Development and Distribution License (the "License").
612016SGirish.Moodalbail@Sun.COM * You may not use this file except in compliance with the License.
712016SGirish.Moodalbail@Sun.COM *
812016SGirish.Moodalbail@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912016SGirish.Moodalbail@Sun.COM * or http://www.opensolaris.org/os/licensing.
1012016SGirish.Moodalbail@Sun.COM * See the License for the specific language governing permissions
1112016SGirish.Moodalbail@Sun.COM * and limitations under the License.
1212016SGirish.Moodalbail@Sun.COM *
1312016SGirish.Moodalbail@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1412016SGirish.Moodalbail@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512016SGirish.Moodalbail@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1612016SGirish.Moodalbail@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1712016SGirish.Moodalbail@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1812016SGirish.Moodalbail@Sun.COM *
1912016SGirish.Moodalbail@Sun.COM * CDDL HEADER END
2012016SGirish.Moodalbail@Sun.COM */
2112016SGirish.Moodalbail@Sun.COM /*
2212313SSowmini.Varadhan@Sun.COM * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
2312313SSowmini.Varadhan@Sun.COM * Copyright (c) 1990 Mentat Inc.
2412016SGirish.Moodalbail@Sun.COM */
2512016SGirish.Moodalbail@Sun.COM
2612016SGirish.Moodalbail@Sun.COM #include <inet/tunables.h>
2712016SGirish.Moodalbail@Sun.COM #include <sys/md5.h>
2812016SGirish.Moodalbail@Sun.COM #include <inet/common.h>
2912016SGirish.Moodalbail@Sun.COM #include <inet/ip.h>
3012016SGirish.Moodalbail@Sun.COM #include <inet/ip6.h>
3112016SGirish.Moodalbail@Sun.COM #include <netinet/icmp6.h>
3212016SGirish.Moodalbail@Sun.COM #include <inet/ip_stack.h>
3312016SGirish.Moodalbail@Sun.COM #include <inet/rawip_impl.h>
3412016SGirish.Moodalbail@Sun.COM #include <inet/tcp_stack.h>
3512016SGirish.Moodalbail@Sun.COM #include <inet/tcp_impl.h>
3612016SGirish.Moodalbail@Sun.COM #include <inet/udp_impl.h>
3712016SGirish.Moodalbail@Sun.COM #include <inet/sctp/sctp_stack.h>
3812016SGirish.Moodalbail@Sun.COM #include <inet/sctp/sctp_impl.h>
3912016SGirish.Moodalbail@Sun.COM #include <inet/tunables.h>
4012016SGirish.Moodalbail@Sun.COM
4112016SGirish.Moodalbail@Sun.COM static int
prop_perm2const(mod_prop_info_t * pinfo)4212016SGirish.Moodalbail@Sun.COM prop_perm2const(mod_prop_info_t *pinfo)
4312016SGirish.Moodalbail@Sun.COM {
4412016SGirish.Moodalbail@Sun.COM if (pinfo->mpi_setf == NULL)
4512016SGirish.Moodalbail@Sun.COM return (MOD_PROP_PERM_READ);
4612016SGirish.Moodalbail@Sun.COM if (pinfo->mpi_getf == NULL)
4712016SGirish.Moodalbail@Sun.COM return (MOD_PROP_PERM_WRITE);
4812016SGirish.Moodalbail@Sun.COM return (MOD_PROP_PERM_RW);
4912016SGirish.Moodalbail@Sun.COM }
5012016SGirish.Moodalbail@Sun.COM
5112016SGirish.Moodalbail@Sun.COM /*
5212016SGirish.Moodalbail@Sun.COM * Modifies the value of the property to default value or to the `pval'
5312016SGirish.Moodalbail@Sun.COM * specified by the user.
5412016SGirish.Moodalbail@Sun.COM */
5512016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
5612016SGirish.Moodalbail@Sun.COM int
mod_set_boolean(void * cbarg,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)5712016SGirish.Moodalbail@Sun.COM mod_set_boolean(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
5812016SGirish.Moodalbail@Sun.COM const char *ifname, const void* pval, uint_t flags)
5912016SGirish.Moodalbail@Sun.COM {
6012016SGirish.Moodalbail@Sun.COM char *end;
6112016SGirish.Moodalbail@Sun.COM unsigned long new_value;
6212016SGirish.Moodalbail@Sun.COM
6312016SGirish.Moodalbail@Sun.COM if (flags & MOD_PROP_DEFAULT) {
6412016SGirish.Moodalbail@Sun.COM pinfo->prop_cur_bval = pinfo->prop_def_bval;
6512016SGirish.Moodalbail@Sun.COM return (0);
6612016SGirish.Moodalbail@Sun.COM }
6712016SGirish.Moodalbail@Sun.COM
6812016SGirish.Moodalbail@Sun.COM if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0')
6912016SGirish.Moodalbail@Sun.COM return (EINVAL);
7012016SGirish.Moodalbail@Sun.COM if (new_value != B_TRUE && new_value != B_FALSE)
7112016SGirish.Moodalbail@Sun.COM return (EINVAL);
7212016SGirish.Moodalbail@Sun.COM pinfo->prop_cur_bval = new_value;
7312016SGirish.Moodalbail@Sun.COM return (0);
7412016SGirish.Moodalbail@Sun.COM }
7512016SGirish.Moodalbail@Sun.COM
7612016SGirish.Moodalbail@Sun.COM /*
7712016SGirish.Moodalbail@Sun.COM * Retrieves property permission, default value, current value or possible
7812016SGirish.Moodalbail@Sun.COM * values for those properties whose value type is boolean_t.
7912016SGirish.Moodalbail@Sun.COM */
8012016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
8112016SGirish.Moodalbail@Sun.COM int
mod_get_boolean(void * cbarg,mod_prop_info_t * pinfo,const char * ifname,void * pval,uint_t psize,uint_t flags)8212016SGirish.Moodalbail@Sun.COM mod_get_boolean(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
8312016SGirish.Moodalbail@Sun.COM void *pval, uint_t psize, uint_t flags)
8412016SGirish.Moodalbail@Sun.COM {
8512016SGirish.Moodalbail@Sun.COM boolean_t get_def = (flags & MOD_PROP_DEFAULT);
8612016SGirish.Moodalbail@Sun.COM boolean_t get_perm = (flags & MOD_PROP_PERM);
8712016SGirish.Moodalbail@Sun.COM boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
8812016SGirish.Moodalbail@Sun.COM size_t nbytes;
8912016SGirish.Moodalbail@Sun.COM
9012016SGirish.Moodalbail@Sun.COM bzero(pval, psize);
9112016SGirish.Moodalbail@Sun.COM if (get_perm)
9212016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo));
9312016SGirish.Moodalbail@Sun.COM else if (get_range)
9412016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u,%u", B_FALSE, B_TRUE);
9512016SGirish.Moodalbail@Sun.COM else if (get_def)
9612016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_bval);
9712016SGirish.Moodalbail@Sun.COM else
9812016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_bval);
9912016SGirish.Moodalbail@Sun.COM if (nbytes >= psize)
10012016SGirish.Moodalbail@Sun.COM return (ENOBUFS);
10112016SGirish.Moodalbail@Sun.COM return (0);
10212016SGirish.Moodalbail@Sun.COM }
10312016SGirish.Moodalbail@Sun.COM
10412313SSowmini.Varadhan@Sun.COM int
mod_uint32_value(const void * pval,mod_prop_info_t * pinfo,uint_t flags,ulong_t * new_value)10512313SSowmini.Varadhan@Sun.COM mod_uint32_value(const void *pval, mod_prop_info_t *pinfo, uint_t flags,
10612313SSowmini.Varadhan@Sun.COM ulong_t *new_value)
10712313SSowmini.Varadhan@Sun.COM {
10812313SSowmini.Varadhan@Sun.COM char *end;
10912313SSowmini.Varadhan@Sun.COM
11012313SSowmini.Varadhan@Sun.COM if (flags & MOD_PROP_DEFAULT) {
11112313SSowmini.Varadhan@Sun.COM *new_value = pinfo->prop_def_uval;
11212313SSowmini.Varadhan@Sun.COM return (0);
11312313SSowmini.Varadhan@Sun.COM }
11412313SSowmini.Varadhan@Sun.COM
11512313SSowmini.Varadhan@Sun.COM if (ddi_strtoul(pval, &end, 10, (ulong_t *)new_value) != 0 ||
11612313SSowmini.Varadhan@Sun.COM *end != '\0')
11712313SSowmini.Varadhan@Sun.COM return (EINVAL);
11812313SSowmini.Varadhan@Sun.COM if (*new_value < pinfo->prop_min_uval ||
11912313SSowmini.Varadhan@Sun.COM *new_value > pinfo->prop_max_uval) {
12012313SSowmini.Varadhan@Sun.COM return (ERANGE);
12112313SSowmini.Varadhan@Sun.COM }
12212313SSowmini.Varadhan@Sun.COM return (0);
12312313SSowmini.Varadhan@Sun.COM }
12412313SSowmini.Varadhan@Sun.COM
12512016SGirish.Moodalbail@Sun.COM /*
12612016SGirish.Moodalbail@Sun.COM * Modifies the value of the property to default value or to the `pval'
12712016SGirish.Moodalbail@Sun.COM * specified by the user.
12812016SGirish.Moodalbail@Sun.COM */
12912016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
13012016SGirish.Moodalbail@Sun.COM int
mod_set_uint32(void * cbarg,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)13112016SGirish.Moodalbail@Sun.COM mod_set_uint32(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
13212313SSowmini.Varadhan@Sun.COM const char *ifname, const void *pval, uint_t flags)
13312016SGirish.Moodalbail@Sun.COM {
13412313SSowmini.Varadhan@Sun.COM unsigned long new_value;
13512313SSowmini.Varadhan@Sun.COM int err;
13612016SGirish.Moodalbail@Sun.COM
13712313SSowmini.Varadhan@Sun.COM if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
13812313SSowmini.Varadhan@Sun.COM return (err);
13912016SGirish.Moodalbail@Sun.COM pinfo->prop_cur_uval = (uint32_t)new_value;
14012016SGirish.Moodalbail@Sun.COM return (0);
14112016SGirish.Moodalbail@Sun.COM }
14212016SGirish.Moodalbail@Sun.COM
14312016SGirish.Moodalbail@Sun.COM /*
14412016SGirish.Moodalbail@Sun.COM * Rounds up the value to make it multiple of 8.
14512016SGirish.Moodalbail@Sun.COM */
14612016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
14712016SGirish.Moodalbail@Sun.COM int
mod_set_aligned(void * cbarg,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)14812016SGirish.Moodalbail@Sun.COM mod_set_aligned(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
14912016SGirish.Moodalbail@Sun.COM const char *ifname, const void* pval, uint_t flags)
15012016SGirish.Moodalbail@Sun.COM {
15112016SGirish.Moodalbail@Sun.COM int err;
15212016SGirish.Moodalbail@Sun.COM
15312016SGirish.Moodalbail@Sun.COM if ((err = mod_set_uint32(cbarg, cr, pinfo, ifname, pval, flags)) != 0)
15412016SGirish.Moodalbail@Sun.COM return (err);
15512016SGirish.Moodalbail@Sun.COM
15612016SGirish.Moodalbail@Sun.COM /* if required, align the value to multiple of 8 */
15712016SGirish.Moodalbail@Sun.COM if (pinfo->prop_cur_uval & 0x7) {
15812016SGirish.Moodalbail@Sun.COM pinfo->prop_cur_uval &= ~0x7;
15912016SGirish.Moodalbail@Sun.COM pinfo->prop_cur_uval += 0x8;
16012016SGirish.Moodalbail@Sun.COM }
16112016SGirish.Moodalbail@Sun.COM
16212016SGirish.Moodalbail@Sun.COM return (0);
16312016SGirish.Moodalbail@Sun.COM }
16412016SGirish.Moodalbail@Sun.COM
16512016SGirish.Moodalbail@Sun.COM /*
16612016SGirish.Moodalbail@Sun.COM * Retrieves property permission, default value, current value or possible
16712016SGirish.Moodalbail@Sun.COM * values for those properties whose value type is uint32_t.
16812016SGirish.Moodalbail@Sun.COM */
16912016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
17012016SGirish.Moodalbail@Sun.COM int
mod_get_uint32(void * cbarg,mod_prop_info_t * pinfo,const char * ifname,void * pval,uint_t psize,uint_t flags)17112016SGirish.Moodalbail@Sun.COM mod_get_uint32(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
17212016SGirish.Moodalbail@Sun.COM void *pval, uint_t psize, uint_t flags)
17312016SGirish.Moodalbail@Sun.COM {
17412016SGirish.Moodalbail@Sun.COM boolean_t get_def = (flags & MOD_PROP_DEFAULT);
17512016SGirish.Moodalbail@Sun.COM boolean_t get_perm = (flags & MOD_PROP_PERM);
17612016SGirish.Moodalbail@Sun.COM boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
17712016SGirish.Moodalbail@Sun.COM size_t nbytes;
17812016SGirish.Moodalbail@Sun.COM
17912016SGirish.Moodalbail@Sun.COM bzero(pval, psize);
18012016SGirish.Moodalbail@Sun.COM if (get_perm)
18112016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo));
18212016SGirish.Moodalbail@Sun.COM else if (get_range)
18312016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u-%u",
18412016SGirish.Moodalbail@Sun.COM pinfo->prop_min_uval, pinfo->prop_max_uval);
18512016SGirish.Moodalbail@Sun.COM else if (get_def)
18612016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_uval);
18712016SGirish.Moodalbail@Sun.COM else
18812016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_uval);
18912016SGirish.Moodalbail@Sun.COM if (nbytes >= psize)
19012016SGirish.Moodalbail@Sun.COM return (ENOBUFS);
19112016SGirish.Moodalbail@Sun.COM return (0);
19212016SGirish.Moodalbail@Sun.COM }
19312016SGirish.Moodalbail@Sun.COM
19412016SGirish.Moodalbail@Sun.COM /*
19512016SGirish.Moodalbail@Sun.COM * Implements /sbin/ndd -get /dev/ip ?, for all the modules. Needed for
19612016SGirish.Moodalbail@Sun.COM * backward compatibility with /sbin/ndd.
19712016SGirish.Moodalbail@Sun.COM */
19812016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
19912016SGirish.Moodalbail@Sun.COM int
mod_get_allprop(void * cbarg,mod_prop_info_t * pinfo,const char * ifname,void * val,uint_t psize,uint_t flags)20012016SGirish.Moodalbail@Sun.COM mod_get_allprop(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
20112016SGirish.Moodalbail@Sun.COM void *val, uint_t psize, uint_t flags)
20212016SGirish.Moodalbail@Sun.COM {
20312016SGirish.Moodalbail@Sun.COM char *pval = val;
20412016SGirish.Moodalbail@Sun.COM mod_prop_info_t *ptbl, *prop;
20512016SGirish.Moodalbail@Sun.COM ip_stack_t *ipst;
20612016SGirish.Moodalbail@Sun.COM tcp_stack_t *tcps;
20712016SGirish.Moodalbail@Sun.COM sctp_stack_t *sctps;
20812016SGirish.Moodalbail@Sun.COM udp_stack_t *us;
20912016SGirish.Moodalbail@Sun.COM icmp_stack_t *is;
21012016SGirish.Moodalbail@Sun.COM uint_t size;
21112016SGirish.Moodalbail@Sun.COM size_t nbytes = 0, tbytes = 0;
21212016SGirish.Moodalbail@Sun.COM
21312016SGirish.Moodalbail@Sun.COM bzero(pval, psize);
21412016SGirish.Moodalbail@Sun.COM size = psize;
21512016SGirish.Moodalbail@Sun.COM
21612016SGirish.Moodalbail@Sun.COM switch (pinfo->mpi_proto) {
21712016SGirish.Moodalbail@Sun.COM case MOD_PROTO_IP:
21812016SGirish.Moodalbail@Sun.COM case MOD_PROTO_IPV4:
21912016SGirish.Moodalbail@Sun.COM case MOD_PROTO_IPV6:
22012016SGirish.Moodalbail@Sun.COM ipst = (ip_stack_t *)cbarg;
22112016SGirish.Moodalbail@Sun.COM ptbl = ipst->ips_propinfo_tbl;
22212016SGirish.Moodalbail@Sun.COM break;
22312016SGirish.Moodalbail@Sun.COM case MOD_PROTO_RAWIP:
22412016SGirish.Moodalbail@Sun.COM is = (icmp_stack_t *)cbarg;
22512016SGirish.Moodalbail@Sun.COM ptbl = is->is_propinfo_tbl;
22612016SGirish.Moodalbail@Sun.COM break;
22712016SGirish.Moodalbail@Sun.COM case MOD_PROTO_TCP:
22812016SGirish.Moodalbail@Sun.COM tcps = (tcp_stack_t *)cbarg;
22912016SGirish.Moodalbail@Sun.COM ptbl = tcps->tcps_propinfo_tbl;
23012016SGirish.Moodalbail@Sun.COM break;
23112016SGirish.Moodalbail@Sun.COM case MOD_PROTO_UDP:
23212016SGirish.Moodalbail@Sun.COM us = (udp_stack_t *)cbarg;
23312016SGirish.Moodalbail@Sun.COM ptbl = us->us_propinfo_tbl;
23412016SGirish.Moodalbail@Sun.COM break;
23512016SGirish.Moodalbail@Sun.COM case MOD_PROTO_SCTP:
23612016SGirish.Moodalbail@Sun.COM sctps = (sctp_stack_t *)cbarg;
23712016SGirish.Moodalbail@Sun.COM ptbl = sctps->sctps_propinfo_tbl;
23812016SGirish.Moodalbail@Sun.COM break;
23912016SGirish.Moodalbail@Sun.COM default:
24012016SGirish.Moodalbail@Sun.COM return (EINVAL);
24112016SGirish.Moodalbail@Sun.COM }
24212016SGirish.Moodalbail@Sun.COM
24312016SGirish.Moodalbail@Sun.COM for (prop = ptbl; prop->mpi_name != NULL; prop++) {
24412016SGirish.Moodalbail@Sun.COM if (prop->mpi_name[0] == '\0' ||
245*13125SGirish.Moodalbail@oracle.COM strcmp(prop->mpi_name, "?") == 0) {
24612016SGirish.Moodalbail@Sun.COM continue;
247*13125SGirish.Moodalbail@oracle.COM }
24812016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, size, "%s %d %d", prop->mpi_name,
24912016SGirish.Moodalbail@Sun.COM prop->mpi_proto, prop_perm2const(prop));
25012016SGirish.Moodalbail@Sun.COM size -= nbytes + 1;
25112016SGirish.Moodalbail@Sun.COM pval += nbytes + 1;
25212016SGirish.Moodalbail@Sun.COM tbytes += nbytes + 1;
25312016SGirish.Moodalbail@Sun.COM if (tbytes >= psize) {
25412016SGirish.Moodalbail@Sun.COM /* Buffer overflow, stop copying information */
25512016SGirish.Moodalbail@Sun.COM return (ENOBUFS);
25612016SGirish.Moodalbail@Sun.COM }
25712016SGirish.Moodalbail@Sun.COM }
25812016SGirish.Moodalbail@Sun.COM return (0);
25912016SGirish.Moodalbail@Sun.COM }
26012016SGirish.Moodalbail@Sun.COM
26112016SGirish.Moodalbail@Sun.COM /*
26212016SGirish.Moodalbail@Sun.COM * Hold a lock while changing *_epriv_ports to prevent multiple
26312016SGirish.Moodalbail@Sun.COM * threads from changing it at the same time.
26412016SGirish.Moodalbail@Sun.COM */
26512016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
26612016SGirish.Moodalbail@Sun.COM int
mod_set_extra_privports(void * cbarg,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * val,uint_t flags)26712016SGirish.Moodalbail@Sun.COM mod_set_extra_privports(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
26812016SGirish.Moodalbail@Sun.COM const char *ifname, const void* val, uint_t flags)
26912016SGirish.Moodalbail@Sun.COM {
27012016SGirish.Moodalbail@Sun.COM uint_t proto = pinfo->mpi_proto;
27112016SGirish.Moodalbail@Sun.COM tcp_stack_t *tcps;
27212016SGirish.Moodalbail@Sun.COM sctp_stack_t *sctps;
27312016SGirish.Moodalbail@Sun.COM udp_stack_t *us;
27412016SGirish.Moodalbail@Sun.COM unsigned long new_value;
27512016SGirish.Moodalbail@Sun.COM char *end;
27612016SGirish.Moodalbail@Sun.COM kmutex_t *lock;
27712016SGirish.Moodalbail@Sun.COM uint_t i, nports;
27812016SGirish.Moodalbail@Sun.COM in_port_t *ports;
27912016SGirish.Moodalbail@Sun.COM boolean_t def = (flags & MOD_PROP_DEFAULT);
28012016SGirish.Moodalbail@Sun.COM const char *pval = val;
28112016SGirish.Moodalbail@Sun.COM
28212016SGirish.Moodalbail@Sun.COM if (!def) {
28312016SGirish.Moodalbail@Sun.COM if (ddi_strtoul(pval, &end, 10, &new_value) != 0 ||
28412016SGirish.Moodalbail@Sun.COM *end != '\0') {
28512016SGirish.Moodalbail@Sun.COM return (EINVAL);
28612016SGirish.Moodalbail@Sun.COM }
28712016SGirish.Moodalbail@Sun.COM
28812016SGirish.Moodalbail@Sun.COM if (new_value < pinfo->prop_min_uval ||
28912016SGirish.Moodalbail@Sun.COM new_value > pinfo->prop_max_uval) {
29012016SGirish.Moodalbail@Sun.COM return (ERANGE);
29112016SGirish.Moodalbail@Sun.COM }
29212016SGirish.Moodalbail@Sun.COM }
29312016SGirish.Moodalbail@Sun.COM
29412016SGirish.Moodalbail@Sun.COM switch (proto) {
29512016SGirish.Moodalbail@Sun.COM case MOD_PROTO_TCP:
29612016SGirish.Moodalbail@Sun.COM tcps = (tcp_stack_t *)cbarg;
29712016SGirish.Moodalbail@Sun.COM lock = &tcps->tcps_epriv_port_lock;
29812016SGirish.Moodalbail@Sun.COM ports = tcps->tcps_g_epriv_ports;
29912016SGirish.Moodalbail@Sun.COM nports = tcps->tcps_g_num_epriv_ports;
30012016SGirish.Moodalbail@Sun.COM break;
30112016SGirish.Moodalbail@Sun.COM case MOD_PROTO_UDP:
30212016SGirish.Moodalbail@Sun.COM us = (udp_stack_t *)cbarg;
30312016SGirish.Moodalbail@Sun.COM lock = &us->us_epriv_port_lock;
30412016SGirish.Moodalbail@Sun.COM ports = us->us_epriv_ports;
30512016SGirish.Moodalbail@Sun.COM nports = us->us_num_epriv_ports;
30612016SGirish.Moodalbail@Sun.COM break;
30712016SGirish.Moodalbail@Sun.COM case MOD_PROTO_SCTP:
30812016SGirish.Moodalbail@Sun.COM sctps = (sctp_stack_t *)cbarg;
30912016SGirish.Moodalbail@Sun.COM lock = &sctps->sctps_epriv_port_lock;
31012016SGirish.Moodalbail@Sun.COM ports = sctps->sctps_g_epriv_ports;
31112016SGirish.Moodalbail@Sun.COM nports = sctps->sctps_g_num_epriv_ports;
31212016SGirish.Moodalbail@Sun.COM break;
31312016SGirish.Moodalbail@Sun.COM default:
31412016SGirish.Moodalbail@Sun.COM return (ENOTSUP);
31512016SGirish.Moodalbail@Sun.COM }
31612016SGirish.Moodalbail@Sun.COM
31712016SGirish.Moodalbail@Sun.COM mutex_enter(lock);
31812016SGirish.Moodalbail@Sun.COM
31912016SGirish.Moodalbail@Sun.COM /* if MOD_PROP_DEFAULT is set then reset the ports list to default */
32012016SGirish.Moodalbail@Sun.COM if (def) {
32112016SGirish.Moodalbail@Sun.COM for (i = 0; i < nports; i++)
32212016SGirish.Moodalbail@Sun.COM ports[i] = 0;
32312016SGirish.Moodalbail@Sun.COM ports[0] = ULP_DEF_EPRIV_PORT1;
32412016SGirish.Moodalbail@Sun.COM ports[1] = ULP_DEF_EPRIV_PORT2;
32512016SGirish.Moodalbail@Sun.COM mutex_exit(lock);
32612016SGirish.Moodalbail@Sun.COM return (0);
32712016SGirish.Moodalbail@Sun.COM }
32812016SGirish.Moodalbail@Sun.COM
32912016SGirish.Moodalbail@Sun.COM /* Check if the value is already in the list */
33012016SGirish.Moodalbail@Sun.COM for (i = 0; i < nports; i++) {
33112016SGirish.Moodalbail@Sun.COM if (new_value == ports[i])
33212016SGirish.Moodalbail@Sun.COM break;
33312016SGirish.Moodalbail@Sun.COM }
33412016SGirish.Moodalbail@Sun.COM
33512016SGirish.Moodalbail@Sun.COM if (flags & MOD_PROP_REMOVE) {
33612016SGirish.Moodalbail@Sun.COM if (i == nports) {
33712016SGirish.Moodalbail@Sun.COM mutex_exit(lock);
33812016SGirish.Moodalbail@Sun.COM return (ESRCH);
33912016SGirish.Moodalbail@Sun.COM }
34012016SGirish.Moodalbail@Sun.COM /* Clear the value */
34112016SGirish.Moodalbail@Sun.COM ports[i] = 0;
34212016SGirish.Moodalbail@Sun.COM } else if (flags & MOD_PROP_APPEND) {
34312016SGirish.Moodalbail@Sun.COM if (i != nports) {
34412016SGirish.Moodalbail@Sun.COM mutex_exit(lock);
34512016SGirish.Moodalbail@Sun.COM return (EEXIST);
34612016SGirish.Moodalbail@Sun.COM }
34712016SGirish.Moodalbail@Sun.COM
34812016SGirish.Moodalbail@Sun.COM /* Find an empty slot */
34912016SGirish.Moodalbail@Sun.COM for (i = 0; i < nports; i++) {
35012016SGirish.Moodalbail@Sun.COM if (ports[i] == 0)
35112016SGirish.Moodalbail@Sun.COM break;
35212016SGirish.Moodalbail@Sun.COM }
35312016SGirish.Moodalbail@Sun.COM if (i == nports) {
35412016SGirish.Moodalbail@Sun.COM mutex_exit(lock);
35512016SGirish.Moodalbail@Sun.COM return (EOVERFLOW);
35612016SGirish.Moodalbail@Sun.COM }
35712016SGirish.Moodalbail@Sun.COM /* Set the new value */
35812016SGirish.Moodalbail@Sun.COM ports[i] = (in_port_t)new_value;
35912016SGirish.Moodalbail@Sun.COM } else {
36012016SGirish.Moodalbail@Sun.COM /*
36112016SGirish.Moodalbail@Sun.COM * If the user used 'assignment' modifier.
36212016SGirish.Moodalbail@Sun.COM * For eg:
36312016SGirish.Moodalbail@Sun.COM * # ipadm set-prop -p extra_priv_ports=3001 tcp
36412016SGirish.Moodalbail@Sun.COM *
36512016SGirish.Moodalbail@Sun.COM * We clear all the ports and then just add 3001.
36612016SGirish.Moodalbail@Sun.COM */
36712016SGirish.Moodalbail@Sun.COM ASSERT(flags == MOD_PROP_ACTIVE);
36812016SGirish.Moodalbail@Sun.COM for (i = 0; i < nports; i++)
36912016SGirish.Moodalbail@Sun.COM ports[i] = 0;
37012016SGirish.Moodalbail@Sun.COM ports[0] = (in_port_t)new_value;
37112016SGirish.Moodalbail@Sun.COM }
37212016SGirish.Moodalbail@Sun.COM
37312016SGirish.Moodalbail@Sun.COM mutex_exit(lock);
37412016SGirish.Moodalbail@Sun.COM return (0);
37512016SGirish.Moodalbail@Sun.COM }
37612016SGirish.Moodalbail@Sun.COM
37712016SGirish.Moodalbail@Sun.COM /*
37812016SGirish.Moodalbail@Sun.COM * Note: No locks are held when inspecting *_epriv_ports
37912016SGirish.Moodalbail@Sun.COM * but instead the code relies on:
38012016SGirish.Moodalbail@Sun.COM * - the fact that the address of the array and its size never changes
38112016SGirish.Moodalbail@Sun.COM * - the atomic assignment of the elements of the array
38212016SGirish.Moodalbail@Sun.COM */
38312016SGirish.Moodalbail@Sun.COM /* ARGSUSED */
38412016SGirish.Moodalbail@Sun.COM int
mod_get_extra_privports(void * cbarg,mod_prop_info_t * pinfo,const char * ifname,void * val,uint_t psize,uint_t flags)38512016SGirish.Moodalbail@Sun.COM mod_get_extra_privports(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
38612016SGirish.Moodalbail@Sun.COM void *val, uint_t psize, uint_t flags)
38712016SGirish.Moodalbail@Sun.COM {
38812016SGirish.Moodalbail@Sun.COM uint_t proto = pinfo->mpi_proto;
38912016SGirish.Moodalbail@Sun.COM tcp_stack_t *tcps;
39012016SGirish.Moodalbail@Sun.COM sctp_stack_t *sctps;
39112016SGirish.Moodalbail@Sun.COM udp_stack_t *us;
39212016SGirish.Moodalbail@Sun.COM uint_t i, nports, size;
39312016SGirish.Moodalbail@Sun.COM in_port_t *ports;
39412016SGirish.Moodalbail@Sun.COM char *pval = val;
39512016SGirish.Moodalbail@Sun.COM size_t nbytes = 0, tbytes = 0;
39612016SGirish.Moodalbail@Sun.COM boolean_t get_def = (flags & MOD_PROP_DEFAULT);
39712016SGirish.Moodalbail@Sun.COM boolean_t get_perm = (flags & MOD_PROP_PERM);
39812016SGirish.Moodalbail@Sun.COM boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
39912016SGirish.Moodalbail@Sun.COM
40012016SGirish.Moodalbail@Sun.COM bzero(pval, psize);
40112016SGirish.Moodalbail@Sun.COM size = psize;
40212016SGirish.Moodalbail@Sun.COM
40312016SGirish.Moodalbail@Sun.COM if (get_def) {
40412016SGirish.Moodalbail@Sun.COM tbytes = snprintf(pval, psize, "%u,%u", ULP_DEF_EPRIV_PORT1,
40512016SGirish.Moodalbail@Sun.COM ULP_DEF_EPRIV_PORT2);
40612016SGirish.Moodalbail@Sun.COM goto ret;
40712016SGirish.Moodalbail@Sun.COM } else if (get_perm) {
40812016SGirish.Moodalbail@Sun.COM tbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW);
40912016SGirish.Moodalbail@Sun.COM goto ret;
41012016SGirish.Moodalbail@Sun.COM }
41112016SGirish.Moodalbail@Sun.COM
41212016SGirish.Moodalbail@Sun.COM switch (proto) {
41312016SGirish.Moodalbail@Sun.COM case MOD_PROTO_TCP:
41412016SGirish.Moodalbail@Sun.COM tcps = (tcp_stack_t *)cbarg;
41512016SGirish.Moodalbail@Sun.COM ports = tcps->tcps_g_epriv_ports;
41612016SGirish.Moodalbail@Sun.COM nports = tcps->tcps_g_num_epriv_ports;
41712016SGirish.Moodalbail@Sun.COM break;
41812016SGirish.Moodalbail@Sun.COM case MOD_PROTO_UDP:
41912016SGirish.Moodalbail@Sun.COM us = (udp_stack_t *)cbarg;
42012016SGirish.Moodalbail@Sun.COM ports = us->us_epriv_ports;
42112016SGirish.Moodalbail@Sun.COM nports = us->us_num_epriv_ports;
42212016SGirish.Moodalbail@Sun.COM break;
42312016SGirish.Moodalbail@Sun.COM case MOD_PROTO_SCTP:
42412016SGirish.Moodalbail@Sun.COM sctps = (sctp_stack_t *)cbarg;
42512016SGirish.Moodalbail@Sun.COM ports = sctps->sctps_g_epriv_ports;
42612016SGirish.Moodalbail@Sun.COM nports = sctps->sctps_g_num_epriv_ports;
42712016SGirish.Moodalbail@Sun.COM break;
42812016SGirish.Moodalbail@Sun.COM default:
42912016SGirish.Moodalbail@Sun.COM return (ENOTSUP);
43012016SGirish.Moodalbail@Sun.COM }
43112016SGirish.Moodalbail@Sun.COM
43212016SGirish.Moodalbail@Sun.COM if (get_range) {
43312016SGirish.Moodalbail@Sun.COM tbytes = snprintf(pval, psize, "%u-%u", pinfo->prop_min_uval,
43412016SGirish.Moodalbail@Sun.COM pinfo->prop_max_uval);
43512016SGirish.Moodalbail@Sun.COM goto ret;
43612016SGirish.Moodalbail@Sun.COM }
43712016SGirish.Moodalbail@Sun.COM
43812016SGirish.Moodalbail@Sun.COM for (i = 0; i < nports; i++) {
43912016SGirish.Moodalbail@Sun.COM if (ports[i] != 0) {
44012016SGirish.Moodalbail@Sun.COM if (psize == size)
44112016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, size, "%u", ports[i]);
44212016SGirish.Moodalbail@Sun.COM else
44312016SGirish.Moodalbail@Sun.COM nbytes = snprintf(pval, size, ",%u", ports[i]);
44412016SGirish.Moodalbail@Sun.COM size -= nbytes;
44512016SGirish.Moodalbail@Sun.COM pval += nbytes;
44612016SGirish.Moodalbail@Sun.COM tbytes += nbytes;
44712016SGirish.Moodalbail@Sun.COM if (tbytes >= psize)
44812016SGirish.Moodalbail@Sun.COM return (ENOBUFS);
44912016SGirish.Moodalbail@Sun.COM }
45012016SGirish.Moodalbail@Sun.COM }
45112016SGirish.Moodalbail@Sun.COM return (0);
45212016SGirish.Moodalbail@Sun.COM ret:
45312016SGirish.Moodalbail@Sun.COM if (tbytes >= psize)
45412016SGirish.Moodalbail@Sun.COM return (ENOBUFS);
45512016SGirish.Moodalbail@Sun.COM return (0);
45612016SGirish.Moodalbail@Sun.COM }
457