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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 1993-2003 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 32 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.5 */ 33 34 /* 35 * t_rcvudata.c and t_rcvvudata.c are very similar and contain common code. 36 * Any changes to either of them should be reviewed to see whether they 37 * are applicable to the other file. 38 */ 39 #include "mt.h" 40 #include <rpc/trace.h> 41 #include <string.h> 42 #include <stdlib.h> 43 #include <errno.h> 44 #include <stropts.h> 45 #include <sys/stream.h> 46 #define _SUN_TPI_VERSION 2 47 #include <sys/tihdr.h> 48 #include <sys/timod.h> 49 #include <xti.h> 50 #include <syslog.h> 51 #include "tx.h" 52 53 54 int 55 _tx_rcvudata( 56 int fd, 57 struct t_unitdata *unitdata, 58 int *flags, 59 int api_semantics 60 ) 61 { 62 struct strbuf ctlbuf; 63 int retval; 64 union T_primitives *pptr; 65 struct _ti_user *tiptr; 66 int sv_errno; 67 int didalloc; 68 int flg = 0; 69 70 trace2(TR_t_rcvudata, 0, fd); 71 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) { 72 sv_errno = errno; 73 trace2(TR_t_rcvudata, 1, fd); 74 errno = sv_errno; 75 return (-1); 76 } 77 sig_mutex_lock(&tiptr->ti_lock); 78 79 if (tiptr->ti_servtype != T_CLTS) { 80 t_errno = TNOTSUPPORT; 81 sig_mutex_unlock(&tiptr->ti_lock); 82 trace2(TR_t_rcvudata, 1, fd); 83 return (-1); 84 } 85 86 if (_T_IS_XTI(api_semantics)) { 87 /* 88 * User level state verification only done for XTI 89 * because doing for TLI may break existing applications 90 */ 91 if (tiptr->ti_state != T_IDLE) { 92 t_errno = TOUTSTATE; 93 sig_mutex_unlock(&tiptr->ti_lock); 94 trace2(TR_t_rcvudata, 1, fd); 95 return (-1); 96 } 97 } 98 99 100 /* 101 * check if there is something in look buffer 102 */ 103 if (tiptr->ti_lookcnt > 0) { 104 sig_mutex_unlock(&tiptr->ti_lock); 105 trace2(TR_t_rcvudata, 1, fd); 106 t_errno = TLOOK; 107 return (-1); 108 } 109 110 /* 111 * Acquire ctlbuf for use in sending/receiving control part 112 * of the message. 113 */ 114 if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) { 115 sv_errno = errno; 116 sig_mutex_unlock(&tiptr->ti_lock); 117 trace2(TR_t_rcvudata, 1, fd); 118 errno = sv_errno; 119 return (-1); 120 } 121 122 *flags = 0; 123 124 /* 125 * This is a call that may block indefinitely so we drop the 126 * lock and allow signals in MT case here and reacquire it. 127 * Error case should roll back state changes done above 128 * (happens to be no state change here) 129 */ 130 sig_mutex_unlock(&tiptr->ti_lock); 131 if ((retval = getmsg(fd, &ctlbuf, (struct strbuf *)&unitdata->udata, 132 &flg)) < 0) { 133 if (errno == EAGAIN) 134 t_errno = TNODATA; 135 else 136 t_errno = TSYSERR; 137 sv_errno = errno; 138 sig_mutex_lock(&tiptr->ti_lock); 139 errno = sv_errno; 140 goto err_out; 141 } 142 sig_mutex_lock(&tiptr->ti_lock); 143 144 if (unitdata->udata.len == -1) unitdata->udata.len = 0; 145 146 /* 147 * is there control piece with data? 148 */ 149 if (ctlbuf.len > 0) { 150 if (ctlbuf.len < (int)sizeof (t_scalar_t)) { 151 unitdata->udata.len = 0; 152 t_errno = TSYSERR; 153 errno = EPROTO; 154 goto err_out; 155 } 156 157 pptr = (union T_primitives *)ctlbuf.buf; 158 159 switch (pptr->type) { 160 161 case T_UNITDATA_IND: 162 if ((ctlbuf.len < 163 (int)sizeof (struct T_unitdata_ind)) || 164 (pptr->unitdata_ind.OPT_length && 165 (ctlbuf.len < (int)(pptr->unitdata_ind.OPT_length 166 + pptr->unitdata_ind.OPT_offset)))) { 167 t_errno = TSYSERR; 168 unitdata->udata.len = 0; 169 errno = EPROTO; 170 goto err_out; 171 } 172 173 if (_T_IS_TLI(api_semantics) || 174 unitdata->addr.maxlen > 0) { 175 if (TLEN_GT_NLEN(pptr->unitdata_ind.SRC_length, 176 unitdata->addr.maxlen)) { 177 t_errno = TBUFOVFLW; 178 unitdata->udata.len = 0; 179 goto err_out; 180 } 181 (void) memcpy(unitdata->addr.buf, 182 ctlbuf.buf + pptr->unitdata_ind.SRC_offset, 183 (size_t)pptr->unitdata_ind.SRC_length); 184 unitdata->addr.len = 185 pptr->unitdata_ind.SRC_length; 186 } 187 if (_T_IS_TLI(api_semantics) || 188 unitdata->opt.maxlen > 0) { 189 if (TLEN_GT_NLEN(pptr->unitdata_ind.OPT_length, 190 unitdata->opt.maxlen)) { 191 t_errno = TBUFOVFLW; 192 unitdata->udata.len = 0; 193 goto err_out; 194 } 195 (void) memcpy(unitdata->opt.buf, ctlbuf.buf + 196 pptr->unitdata_ind.OPT_offset, 197 (size_t)pptr->unitdata_ind.OPT_length); 198 unitdata->opt.len = 199 pptr->unitdata_ind.OPT_length; 200 } 201 if (retval & MOREDATA) 202 *flags |= T_MORE; 203 /* 204 * No state changes happens on T_RCVUDATA 205 * event (NOOP). We do it only to log errors. 206 */ 207 _T_TX_NEXTSTATE(T_RCVUDATA, tiptr, 208 "t_rcvudata: invalid state event T_RCVUDATA"); 209 210 if (didalloc) 211 free(ctlbuf.buf); 212 else 213 tiptr->ti_ctlbuf = ctlbuf.buf; 214 215 sig_mutex_unlock(&tiptr->ti_lock); 216 trace2(TR_t_rcvudata, 1, fd); 217 return (0); 218 219 case T_UDERROR_IND: 220 if (_t_register_lookevent(tiptr, 0, 0, ctlbuf.buf, 221 ctlbuf.len) < 0) { 222 t_errno = TSYSERR; 223 errno = ENOMEM; 224 goto err_out; 225 } 226 unitdata->udata.len = 0; 227 t_errno = TLOOK; 228 goto err_out; 229 230 default: 231 break; 232 } 233 234 t_errno = TSYSERR; 235 errno = EPROTO; 236 goto err_out; 237 238 } else { /* else part of "if (ctlbuf.len > 0)" */ 239 unitdata->addr.len = 0; 240 unitdata->opt.len = 0; 241 /* 242 * only data in message no control piece 243 */ 244 if (retval & MOREDATA) 245 *flags = T_MORE; 246 /* 247 * No state transition occurs on 248 * event T_RCVUDATA. We do it only to 249 * log errors. 250 */ 251 _T_TX_NEXTSTATE(T_RCVUDATA, tiptr, 252 "t_rcvudata: invalid state event T_RCVUDATA"); 253 if (didalloc) 254 free(ctlbuf.buf); 255 else 256 tiptr->ti_ctlbuf = ctlbuf.buf; 257 sig_mutex_unlock(&tiptr->ti_lock); 258 trace2(TR_t_rcvudata, 1, fd); 259 return (0); 260 } 261 /* NOTREACHED */ 262 err_out: 263 sv_errno = errno; 264 if (didalloc) 265 free(ctlbuf.buf); 266 else 267 tiptr->ti_ctlbuf = ctlbuf.buf; 268 sig_mutex_unlock(&tiptr->ti_lock); 269 trace2(TR_t_rcvudata, 1, fd); 270 errno = sv_errno; 271 return (-1); 272 } 273