1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/ib/clients/rds/rds.h> 29 #include <inet/mi.h> 30 31 #define rds_max_buf 2097152 32 opdes_t rds_opt_arr[] = { 33 34 { SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, 35 { SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, 36 { SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, 37 }; 38 39 /* ARGSUSED */ 40 int 41 rds_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 42 { 43 /* no default value processed by protocol specific code currently */ 44 return (-1); 45 } 46 47 /* 48 * This routine retrieves the current status of socket options. 49 * It returns the size of the option retrieved. 50 */ 51 int 52 rds_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 53 { 54 int *i1 = (int *)(uintptr_t)ptr; 55 56 switch (level) { 57 case SOL_SOCKET: 58 switch (name) { 59 case SO_TYPE: 60 *i1 = SOCK_DGRAM; 61 break; /* goto sizeof (int) option return */ 62 63 case SO_SNDBUF: 64 *i1 = q->q_hiwat; 65 break; /* goto sizeof (int) option return */ 66 case SO_RCVBUF: 67 *i1 = RD(q)->q_hiwat; 68 break; /* goto sizeof (int) option return */ 69 default: 70 return (-1); 71 } 72 break; 73 default: 74 return (-1); 75 } 76 return (sizeof (int)); 77 } 78 79 /* This routine sets socket options. */ 80 /* ARGSUSED */ 81 int 82 rds_opt_set(queue_t *q, uint_t optset_context, int level, 83 int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp, 84 uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk) 85 { 86 int *i1 = (int *)(uintptr_t)invalp; 87 boolean_t checkonly; 88 89 switch (optset_context) { 90 case SETFN_OPTCOM_CHECKONLY: 91 checkonly = B_TRUE; 92 /* 93 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ 94 * inlen != 0 implies value supplied and 95 * we have to "pretend" to set it. 96 * inlen == 0 implies that there is no 97 * value part in T_CHECK request and just validation 98 * done elsewhere should be enough, we just return here. 99 */ 100 if (inlen == 0) { 101 *outlenp = 0; 102 return (0); 103 } 104 break; 105 case SETFN_OPTCOM_NEGOTIATE: 106 checkonly = B_FALSE; 107 break; 108 default: 109 /* 110 * We should never get here 111 */ 112 *outlenp = 0; 113 return (EINVAL); 114 } 115 116 ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) || 117 (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0)); 118 119 /* 120 * For fixed length options, no sanity check 121 * of passed in length is done. It is assumed *_optcom_req() 122 * routines do the right thing. 123 */ 124 125 switch (level) { 126 case SOL_SOCKET: 127 switch (name) { 128 129 case SO_SNDBUF: 130 if (*i1 > rds_max_buf) { 131 *outlenp = 0; 132 return (ENOBUFS); 133 } 134 if (!checkonly) { 135 q->q_hiwat = *i1; 136 q->q_next->q_hiwat = *i1; 137 } 138 break; 139 case SO_RCVBUF: 140 if (*i1 > rds_max_buf) { 141 *outlenp = 0; 142 return (ENOBUFS); 143 } 144 if (!checkonly) { 145 RD(q)->q_hiwat = *i1; 146 (void) mi_set_sth_hiwat(RD(q), *i1); 147 } 148 break; 149 default: 150 *outlenp = 0; 151 return (EINVAL); 152 } 153 break; 154 default: 155 *outlenp = 0; 156 return (EINVAL); 157 } 158 /* 159 * Common case of OK return with outval same as inval. 160 */ 161 if (invalp != outvalp) { 162 /* don't trust bcopy for identical src/dst */ 163 (void) bcopy(invalp, outvalp, inlen); 164 } 165 *outlenp = inlen; 166 return (0); 167 } 168 169 uint_t rds_max_optsize; /* initialized when RDS driver is loaded */ 170 171 #define RDS_VALID_LEVELS_CNT A_CNT(rds_valid_levels_arr) 172 173 #define RDS_OPT_ARR_CNT A_CNT(rds_opt_arr) 174 175 176 optlevel_t rds_valid_levels_arr[] = { 177 SOL_SOCKET, 178 }; 179 180 /* 181 * Initialize option database object for RDS 182 * 183 * This object represents database of options to search passed to 184 * {sock,tpi}optcom_req() interface routine to take care of option 185 * management and associated methods. 186 */ 187 188 optdb_obj_t rds_opt_obj = { 189 rds_opt_default, /* RDS default value function pointer */ 190 rds_opt_get, /* RDS get function pointer */ 191 rds_opt_set, /* RDS set function pointer */ 192 B_TRUE, /* RDS is tpi provider */ 193 RDS_OPT_ARR_CNT, /* RDS option database count of entries */ 194 rds_opt_arr, /* RDS option database */ 195 RDS_VALID_LEVELS_CNT, /* RDS valid level count of entries */ 196 rds_valid_levels_arr /* RDS valid level array */ 197 }; 198