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.7.3.1 */ 33 34 /* 35 * t_rcvrel.c and t_rcvreldata.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 <rpc/trace.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 <signal.h> 51 #include <syslog.h> 52 #include "tx.h" 53 54 int 55 _tx_rcvrel(int fd, int api_semantics) 56 { 57 struct strbuf ctlbuf; 58 struct strbuf databuf; 59 int retval; 60 union T_primitives *pptr; 61 struct _ti_user *tiptr; 62 int sv_errno; 63 int didalloc, didralloc; 64 65 int flg = 0; 66 67 68 trace2(TR_t_rcvrel, 0, fd); 69 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == 0) { 70 sv_errno = errno; 71 trace2(TR_t_rcvrel, 1, fd); 72 errno = sv_errno; 73 return (-1); 74 } 75 sig_mutex_lock(&tiptr->ti_lock); 76 77 if (tiptr->ti_servtype != T_COTS_ORD) { 78 t_errno = TNOTSUPPORT; 79 sig_mutex_unlock(&tiptr->ti_lock); 80 trace2(TR_t_rcvrel, 1, fd); 81 return (-1); 82 } 83 84 if (_T_IS_XTI(api_semantics)) { 85 /* 86 * User level state verification only done for XTI 87 * because doing for TLI may break existing applications 88 */ 89 if (! (tiptr->ti_state == T_DATAXFER || 90 tiptr->ti_state == T_OUTREL)) { 91 t_errno = TOUTSTATE; 92 sig_mutex_unlock(&tiptr->ti_lock); 93 trace2(TR_t_rcvrel, 1, fd); 94 return (-1); 95 } 96 } 97 98 if ((retval = _t_look_locked(fd, tiptr, 0, api_semantics)) < 0) { 99 sv_errno = errno; 100 sig_mutex_unlock(&tiptr->ti_lock); 101 trace2(TR_t_rcvrel, 1, fd); 102 errno = sv_errno; 103 return (-1); 104 } 105 106 if (retval == T_DISCONNECT) { 107 /* 108 * This ensures preference to T_DISCON_IND which is 109 * the design model for TPI 110 */ 111 t_errno = TLOOK; 112 sig_mutex_unlock(&tiptr->ti_lock); 113 trace2(TR_t_rcvrel, 1, fd); 114 return (-1); 115 } 116 117 if ((tiptr->ti_lookcnt > 0) && 118 (*((t_scalar_t *)tiptr->ti_lookbufs.tl_lookcbuf) == T_ORDREL_IND)) { 119 /* 120 * Current look buffer event is T_ORDREL_IND. 121 * Remove it from look buffer event list. 122 */ 123 _t_free_looklist_head(tiptr); 124 _T_TX_NEXTSTATE(T_RCVREL, tiptr, 125 "t_rcv: invalid state event T_RCVREL"); 126 sig_mutex_unlock(&tiptr->ti_lock); 127 trace2(TR_t_rcvrel, 1, fd); 128 return (0); 129 } else { 130 if (retval != T_ORDREL) { 131 t_errno = TNOREL; 132 sig_mutex_unlock(&tiptr->ti_lock); 133 trace2(TR_t_rcvrel, 1, fd); 134 return (-1); 135 } 136 } 137 138 /* 139 * get ordrel off read queue. 140 * use ctl and rcv buffers 141 * 142 * Acquire ctlbuf for use in sending/receiving control part 143 * of the message. 144 */ 145 if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) { 146 sv_errno = errno; 147 sig_mutex_unlock(&tiptr->ti_lock); 148 trace2(TR_t_rcvrel, 1, fd); 149 errno = sv_errno; 150 return (-1); 151 } 152 153 /* 154 * Acquire databuf for use in sending/receiving data part 155 */ 156 if (_t_acquire_databuf(tiptr, &databuf, &didralloc) < 0) { 157 sv_errno = errno; 158 if (didalloc) 159 free(ctlbuf.buf); 160 else 161 tiptr->ti_ctlbuf = ctlbuf.buf; 162 sig_mutex_unlock(&tiptr->ti_lock); 163 trace2(TR_t_rcvrel, 1, fd); 164 errno = sv_errno; 165 return (-1); 166 } 167 168 /* 169 * Since we have verified above that an orderly release event 170 * is pending on this endpoint, we assume that this getmsg() 171 * cannot block forever. 172 */ 173 do { 174 retval = getmsg(fd, &ctlbuf, &databuf, &flg); 175 } while (retval < 0 && errno == EINTR); 176 177 if (retval < 0) { 178 t_errno = TSYSERR; 179 goto err_out; 180 } 181 182 /* 183 * did I get entire message? 184 */ 185 if (retval > 0) { 186 t_errno = TSYSERR; 187 errno = EIO; 188 goto err_out; 189 } 190 pptr = (union T_primitives *)ctlbuf.buf; 191 192 if (ctlbuf.len < (int)sizeof (struct T_ordrel_ind)) { 193 t_errno = TSYSERR; 194 errno = EPROTO; 195 goto err_out; 196 } 197 if (pptr->type != T_ORDREL_IND) { 198 if (pptr->type == T_DISCON_IND) { 199 /* 200 * T_DISCON_IND gets priority following 201 * TPI design philosphy. 202 * 203 * Add it to the events in the "look buffer" 204 * list of events. This routine may defer signals. 205 */ 206 if (_t_register_lookevent(tiptr, databuf.buf, 207 databuf.len, ctlbuf.buf, 208 ctlbuf.len) < 0) { 209 t_errno = TSYSERR; 210 errno = ENOMEM; 211 goto err_out; 212 } 213 t_errno = TLOOK; 214 goto err_out; 215 } else { 216 t_errno = TSYSERR; 217 errno = EPROTO; 218 goto err_out; 219 } 220 } 221 222 _T_TX_NEXTSTATE(T_RCVREL, tiptr, 223 "t_rcvrel: invalid state event T_RCVREL"); 224 225 if (didalloc) 226 free(ctlbuf.buf); 227 else 228 tiptr->ti_ctlbuf = ctlbuf.buf; 229 if (didralloc) 230 free(databuf.buf); 231 else 232 tiptr->ti_rcvbuf = databuf.buf; 233 sig_mutex_unlock(&tiptr->ti_lock); 234 trace2(TR_t_rcvrel, 1, fd); 235 return (0); 236 237 err_out: 238 sv_errno = errno; 239 240 if (didalloc) 241 free(ctlbuf.buf); 242 else 243 tiptr->ti_ctlbuf = ctlbuf.buf; 244 if (didralloc) 245 free(databuf.buf); 246 else 247 tiptr->ti_rcvbuf = databuf.buf; 248 sig_mutex_unlock(&tiptr->ti_lock); 249 trace2(TR_t_rcvrel, 1, fd); 250 errno = sv_errno; 251 return (-1); 252 } 253