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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/ib/clients/rds/rds.h> 27 #include <inet/proto_set.h> 28 29 #define rds_max_buf 2097152 30 opdes_t rds_opt_arr[] = { 31 32 { SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, 33 { SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, 34 { SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0 }, 35 }; 36 37 /* ARGSUSED */ 38 int 39 rds_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 40 { 41 /* no default value processed by protocol specific code currently */ 42 return (-1); 43 } 44 45 /* 46 * This routine retrieves the current status of socket options. 47 * It returns the size of the option retrieved. 48 */ 49 int 50 rds_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) 51 { 52 int *i1 = (int *)(uintptr_t)ptr; 53 54 switch (level) { 55 case SOL_SOCKET: 56 switch (name) { 57 case SO_TYPE: 58 *i1 = SOCK_DGRAM; 59 break; /* goto sizeof (int) option return */ 60 61 case SO_SNDBUF: 62 *i1 = q->q_hiwat; 63 break; /* goto sizeof (int) option return */ 64 case SO_RCVBUF: 65 *i1 = RD(q)->q_hiwat; 66 break; /* goto sizeof (int) option return */ 67 default: 68 return (-1); 69 } 70 break; 71 default: 72 return (-1); 73 } 74 return (sizeof (int)); 75 } 76 77 /* This routine sets socket options. */ 78 /* ARGSUSED */ 79 int 80 rds_opt_set(queue_t *q, uint_t optset_context, int level, 81 int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp, 82 uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk) 83 { 84 int *i1 = (int *)(uintptr_t)invalp; 85 boolean_t checkonly; 86 87 switch (optset_context) { 88 case SETFN_OPTCOM_CHECKONLY: 89 checkonly = B_TRUE; 90 /* 91 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ 92 * inlen != 0 implies value supplied and 93 * we have to "pretend" to set it. 94 * inlen == 0 implies that there is no 95 * value part in T_CHECK request and just validation 96 * done elsewhere should be enough, we just return here. 97 */ 98 if (inlen == 0) { 99 *outlenp = 0; 100 return (0); 101 } 102 break; 103 case SETFN_OPTCOM_NEGOTIATE: 104 checkonly = B_FALSE; 105 break; 106 default: 107 /* 108 * We should never get here 109 */ 110 *outlenp = 0; 111 return (EINVAL); 112 } 113 114 ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) || 115 (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0)); 116 117 /* 118 * For fixed length options, no sanity check 119 * of passed in length is done. It is assumed *_optcom_req() 120 * routines do the right thing. 121 */ 122 123 switch (level) { 124 case SOL_SOCKET: 125 switch (name) { 126 127 case SO_SNDBUF: 128 if (*i1 > rds_max_buf) { 129 *outlenp = 0; 130 return (ENOBUFS); 131 } 132 if (!checkonly) { 133 q->q_hiwat = *i1; 134 q->q_next->q_hiwat = *i1; 135 } 136 break; 137 case SO_RCVBUF: 138 if (*i1 > rds_max_buf) { 139 *outlenp = 0; 140 return (ENOBUFS); 141 } 142 if (!checkonly) { 143 RD(q)->q_hiwat = *i1; 144 (void) proto_set_rx_hiwat(RD(q), NULL, *i1); 145 } 146 break; 147 default: 148 *outlenp = 0; 149 return (EINVAL); 150 } 151 break; 152 default: 153 *outlenp = 0; 154 return (EINVAL); 155 } 156 /* 157 * Common case of OK return with outval same as inval. 158 */ 159 if (invalp != outvalp) { 160 /* don't trust bcopy for identical src/dst */ 161 (void) bcopy(invalp, outvalp, inlen); 162 } 163 *outlenp = inlen; 164 return (0); 165 } 166 167 uint_t rds_max_optsize; /* initialized when RDS driver is loaded */ 168 169 #define RDS_VALID_LEVELS_CNT A_CNT(rds_valid_levels_arr) 170 171 #define RDS_OPT_ARR_CNT A_CNT(rds_opt_arr) 172 173 174 optlevel_t rds_valid_levels_arr[] = { 175 SOL_SOCKET, 176 }; 177 178 /* 179 * Initialize option database object for RDS 180 * 181 * This object represents database of options to search passed to 182 * {sock,tpi}optcom_req() interface routine to take care of option 183 * management and associated methods. 184 */ 185 186 optdb_obj_t rds_opt_obj = { 187 rds_opt_default, /* RDS default value function pointer */ 188 rds_opt_get, /* RDS get function pointer */ 189 rds_opt_set, /* RDS set function pointer */ 190 B_TRUE, /* RDS is tpi provider */ 191 RDS_OPT_ARR_CNT, /* RDS option database count of entries */ 192 rds_opt_arr, /* RDS option database */ 193 RDS_VALID_LEVELS_CNT, /* RDS valid level count of entries */ 194 rds_valid_levels_arr /* RDS valid level array */ 195 }; 196