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