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