13302Sagiri /*
23302Sagiri * CDDL HEADER START
33302Sagiri *
43302Sagiri * The contents of this file are subject to the terms of the
53302Sagiri * Common Development and Distribution License (the "License").
63302Sagiri * You may not use this file except in compliance with the License.
73302Sagiri *
83302Sagiri * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93302Sagiri * or http://www.opensolaris.org/os/licensing.
103302Sagiri * See the License for the specific language governing permissions
113302Sagiri * and limitations under the License.
123302Sagiri *
133302Sagiri * When distributing Covered Code, include this CDDL HEADER in each
143302Sagiri * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153302Sagiri * If applicable, add the following below this CDDL HEADER, with the
163302Sagiri * fields enclosed by brackets "[]" replaced with your own identifying
173302Sagiri * information: Portions Copyright [yyyy] [name of copyright owner]
183302Sagiri *
193302Sagiri * CDDL HEADER END
203302Sagiri */
213302Sagiri /*
22*12599SRavichandra.Nallan@Sun.COM * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23*12599SRavichandra.Nallan@Sun.COM * Copyright (c) 1990 Mentat Inc.
243302Sagiri */
253302Sagiri
263302Sagiri #include <sys/ib/clients/rds/rds.h>
278348SEric.Yu@Sun.COM #include <inet/proto_set.h>
283302Sagiri
293302Sagiri #define rds_max_buf 2097152
303302Sagiri opdes_t rds_opt_arr[] = {
313302Sagiri
3211042SErik.Nordmark@Sun.COM { SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
3311042SErik.Nordmark@Sun.COM { SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
3411042SErik.Nordmark@Sun.COM { SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
353302Sagiri };
363302Sagiri
373302Sagiri /* ARGSUSED */
383302Sagiri int
rds_opt_default(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr)393302Sagiri rds_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
403302Sagiri {
413302Sagiri /* no default value processed by protocol specific code currently */
423302Sagiri return (-1);
433302Sagiri }
443302Sagiri
453302Sagiri /*
463302Sagiri * This routine retrieves the current status of socket options.
473302Sagiri * It returns the size of the option retrieved.
483302Sagiri */
493302Sagiri int
rds_opt_get(queue_t * q,t_scalar_t level,t_scalar_t name,uchar_t * ptr)503302Sagiri rds_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
513302Sagiri {
523302Sagiri int *i1 = (int *)(uintptr_t)ptr;
533302Sagiri
543302Sagiri switch (level) {
553302Sagiri case SOL_SOCKET:
563302Sagiri switch (name) {
573302Sagiri case SO_TYPE:
583302Sagiri *i1 = SOCK_DGRAM;
593302Sagiri break; /* goto sizeof (int) option return */
603302Sagiri
613302Sagiri case SO_SNDBUF:
623302Sagiri *i1 = q->q_hiwat;
633302Sagiri break; /* goto sizeof (int) option return */
643302Sagiri case SO_RCVBUF:
653302Sagiri *i1 = RD(q)->q_hiwat;
663302Sagiri break; /* goto sizeof (int) option return */
673302Sagiri default:
683302Sagiri return (-1);
693302Sagiri }
703302Sagiri break;
713302Sagiri default:
723302Sagiri return (-1);
733302Sagiri }
743302Sagiri return (sizeof (int));
753302Sagiri }
763302Sagiri
773302Sagiri /* This routine sets socket options. */
783302Sagiri /* ARGSUSED */
793302Sagiri int
rds_opt_set(queue_t * q,uint_t optset_context,int level,int name,uint_t inlen,uchar_t * invalp,uint_t * outlenp,uchar_t * outvalp,void * thisdg_attrs,cred_t * cr)803302Sagiri rds_opt_set(queue_t *q, uint_t optset_context, int level,
813302Sagiri int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
8211042SErik.Nordmark@Sun.COM uchar_t *outvalp, void *thisdg_attrs, cred_t *cr)
833302Sagiri {
843302Sagiri int *i1 = (int *)(uintptr_t)invalp;
853302Sagiri boolean_t checkonly;
863302Sagiri
873302Sagiri switch (optset_context) {
883302Sagiri case SETFN_OPTCOM_CHECKONLY:
893302Sagiri checkonly = B_TRUE;
903302Sagiri /*
913302Sagiri * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
923302Sagiri * inlen != 0 implies value supplied and
933302Sagiri * we have to "pretend" to set it.
943302Sagiri * inlen == 0 implies that there is no
953302Sagiri * value part in T_CHECK request and just validation
963302Sagiri * done elsewhere should be enough, we just return here.
973302Sagiri */
983302Sagiri if (inlen == 0) {
993302Sagiri *outlenp = 0;
1003302Sagiri return (0);
1013302Sagiri }
1023302Sagiri break;
1033302Sagiri case SETFN_OPTCOM_NEGOTIATE:
1043302Sagiri checkonly = B_FALSE;
1053302Sagiri break;
1063302Sagiri default:
1073302Sagiri /*
1083302Sagiri * We should never get here
1093302Sagiri */
1103302Sagiri *outlenp = 0;
1113302Sagiri return (EINVAL);
1123302Sagiri }
1133302Sagiri
1143302Sagiri ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
1153302Sagiri (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
1163302Sagiri
1173302Sagiri /*
1183302Sagiri * For fixed length options, no sanity check
1193302Sagiri * of passed in length is done. It is assumed *_optcom_req()
1203302Sagiri * routines do the right thing.
1213302Sagiri */
1223302Sagiri
1233302Sagiri switch (level) {
1243302Sagiri case SOL_SOCKET:
1253302Sagiri switch (name) {
1263302Sagiri
1273302Sagiri case SO_SNDBUF:
1283302Sagiri if (*i1 > rds_max_buf) {
1293302Sagiri *outlenp = 0;
1303302Sagiri return (ENOBUFS);
1313302Sagiri }
1323302Sagiri if (!checkonly) {
1333302Sagiri q->q_hiwat = *i1;
1343302Sagiri }
1353302Sagiri break;
1363302Sagiri case SO_RCVBUF:
1373302Sagiri if (*i1 > rds_max_buf) {
1383302Sagiri *outlenp = 0;
1393302Sagiri return (ENOBUFS);
1403302Sagiri }
1413302Sagiri if (!checkonly) {
1423302Sagiri RD(q)->q_hiwat = *i1;
1438348SEric.Yu@Sun.COM (void) proto_set_rx_hiwat(RD(q), NULL, *i1);
1443302Sagiri }
1453302Sagiri break;
1463302Sagiri default:
1473302Sagiri *outlenp = 0;
1483302Sagiri return (EINVAL);
1493302Sagiri }
1503302Sagiri break;
1513302Sagiri default:
1523302Sagiri *outlenp = 0;
1533302Sagiri return (EINVAL);
1543302Sagiri }
1553302Sagiri /*
1563302Sagiri * Common case of OK return with outval same as inval.
1573302Sagiri */
1583302Sagiri if (invalp != outvalp) {
1593302Sagiri /* don't trust bcopy for identical src/dst */
1603302Sagiri (void) bcopy(invalp, outvalp, inlen);
1613302Sagiri }
1623302Sagiri *outlenp = inlen;
1633302Sagiri return (0);
1643302Sagiri }
1653302Sagiri
1663302Sagiri uint_t rds_max_optsize; /* initialized when RDS driver is loaded */
1673302Sagiri
1683302Sagiri #define RDS_VALID_LEVELS_CNT A_CNT(rds_valid_levels_arr)
1693302Sagiri
1703302Sagiri #define RDS_OPT_ARR_CNT A_CNT(rds_opt_arr)
1713302Sagiri
1723302Sagiri
1733302Sagiri optlevel_t rds_valid_levels_arr[] = {
1743302Sagiri SOL_SOCKET,
1753302Sagiri };
1763302Sagiri
1773302Sagiri /*
1783302Sagiri * Initialize option database object for RDS
1793302Sagiri *
1803302Sagiri * This object represents database of options to search passed to
1813302Sagiri * {sock,tpi}optcom_req() interface routine to take care of option
1823302Sagiri * management and associated methods.
1833302Sagiri */
1843302Sagiri
1853302Sagiri optdb_obj_t rds_opt_obj = {
1863302Sagiri rds_opt_default, /* RDS default value function pointer */
1873302Sagiri rds_opt_get, /* RDS get function pointer */
1883302Sagiri rds_opt_set, /* RDS set function pointer */
1893302Sagiri RDS_OPT_ARR_CNT, /* RDS option database count of entries */
1903302Sagiri rds_opt_arr, /* RDS option database */
1913302Sagiri RDS_VALID_LEVELS_CNT, /* RDS valid level count of entries */
1923302Sagiri rds_valid_levels_arr /* RDS valid level array */
1933302Sagiri };
194