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
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.
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]
23 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
24 /* All Rights Reserved */
27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.5.2.1 */
38 #include <sys/stream.h>
39 #define _SUN_TPI_VERSION 2
40 #include <sys/tihdr.h>
41 #include <sys/timod.h>
52 const struct t_call
*call
,
56 struct T_conn_res
*cres
;
57 struct strfdinsert strfdinsert
;
58 int size
, retval
, sv_errno
;
59 struct _ti_user
*tiptr
;
60 struct _ti_user
*restiptr
;
64 t_scalar_t conn_res_prim
;
66 if ((tiptr
= _t_checkfd(fd
, 0, api_semantics
)) == NULL
)
68 if ((restiptr
= _t_checkfd(resfd
, 0, api_semantics
)) == NULL
)
72 * We need to block signals to perform the I_FDINSERT operation
73 * (sending T_CONN_RES downstream) which is non-idempotent.
74 * Note that sig_mutex_lock() only defers signals, it does not
75 * block them, so interruptible syscalls could still get EINTR.
77 (void) thr_sigsetmask(SIG_SETMASK
, &fillset
, &mask
);
78 sig_mutex_lock(&tiptr
->ti_lock
);
80 if (tiptr
->ti_servtype
== T_CLTS
) {
81 t_errno
= TNOTSUPPORT
;
82 sig_mutex_unlock(&tiptr
->ti_lock
);
83 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
87 if (_T_IS_XTI(api_semantics
)) {
89 * User level state verification only done for XTI
90 * because doing for TLI may break existing applications
92 * For fd == resfd, state should be T_INCON
94 * fd state should be T_INCON
95 * resfd state should be T_IDLE (bound endpoint) or
96 * it can be T_UNBND. The T_UNBND case is not (yet?)
97 * allowed in the published XTI spec but fixed by the
100 if ((fd
== resfd
&& tiptr
->ti_state
!= T_INCON
) ||
102 ((tiptr
->ti_state
!= T_INCON
) ||
103 !(restiptr
->ti_state
== T_IDLE
||
104 restiptr
->ti_state
== T_UNBND
)))) {
106 sig_mutex_unlock(&tiptr
->ti_lock
);
107 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
113 * If fd != resfd, and a resfd bound to a protocol address is
114 * passed, then it better not have a qlen > 0.
115 * That is, an endpoint bound as if it will be a listener
116 * cannot be used as an acceptor.
118 if (fd
!= resfd
&& restiptr
->ti_state
== T_IDLE
&&
119 restiptr
->ti_qlen
> 0) {
121 sig_mutex_unlock(&tiptr
->ti_lock
);
122 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
126 if (fd
== resfd
&& tiptr
->ti_ocnt
> 1) {
128 sig_mutex_unlock(&tiptr
->ti_lock
);
129 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
134 * Note: TRESADDR error is specified by XTI. It happens
135 * when resfd is bound and fd and resfd are not BOUND to
136 * the same protocol address. TCP obviously does allow
137 * two endpoints to bind to the same address. Why is the
138 * need for this error considering there is an address switch
139 * that can be done for the endpoint at accept time ? Go
140 * figure and ask the XTI folks.
141 * We interpret this to be a transport specific error condition
142 * to be be coveyed by the transport provider in T_ERROR_ACK
143 * to T_CONN_RES on transports that allow two endpoints to
144 * be bound to the same address and have trouble with the
145 * idea of accepting connections on a resfd that has a qlen > 0
150 if ((retval
= ioctl(resfd
, I_NREAD
, &size
)) < 0) {
154 sig_mutex_unlock(&tiptr
->ti_lock
);
155 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
161 sig_mutex_unlock(&tiptr
->ti_lock
);
162 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
168 * Acquire ctlbuf for use in sending/receiving control part
171 if (_t_acquire_ctlbuf(tiptr
, &ctlbuf
, &didalloc
) < 0) {
173 sig_mutex_unlock(&tiptr
->ti_lock
);
174 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
180 * In Unix98 t_accept() need not return [TLOOK] if connect/disconnect
181 * indications are present. TLI and Unix95 need to return error.
183 if (_T_API_VER_LT(api_semantics
, TX_XTI_XNS5_API
)) {
184 if (_t_is_event(fd
, tiptr
) < 0)
188 /* LINTED pointer cast */
189 cres
= (struct T_conn_res
*)ctlbuf
.buf
;
190 cres
->OPT_length
= call
->opt
.len
;
191 cres
->OPT_offset
= 0;
192 cres
->SEQ_number
= call
->sequence
;
193 if ((restiptr
->ti_flags
& V_ACCEPTOR_ID
) != 0) {
194 cres
->ACCEPTOR_id
= restiptr
->acceptor_id
;
195 cres
->PRIM_type
= conn_res_prim
= T_CONN_RES
;
197 /* I_FDINSERT should use O_T_CONN_RES. */
198 cres
->ACCEPTOR_id
= 0;
199 cres
->PRIM_type
= conn_res_prim
= O_T_CONN_RES
;
202 size
= (int)sizeof (struct T_conn_res
);
205 if (_t_aligned_copy(&ctlbuf
, call
->opt
.len
, size
,
206 call
->opt
.buf
, &cres
->OPT_offset
) < 0) {
208 * Aligned copy will overflow buffer allocated based
209 * transport maximum options length.
215 size
= cres
->OPT_offset
+ cres
->OPT_length
;
218 if (call
->udata
.len
) {
219 if ((tiptr
->ti_cdatasize
== T_INVALID
/* -2 */) ||
220 ((tiptr
->ti_cdatasize
!= T_INFINITE
/* -1 */) &&
221 (call
->udata
.len
> (uint32_t)tiptr
->ti_cdatasize
))) {
223 * user data not valid with connect or it
224 * exceeds the limits specified by the transport
236 * Assumes signals are blocked so putmsg() will not block
239 if ((restiptr
->ti_flags
& V_ACCEPTOR_ID
) != 0) {
241 * Assumes signals are blocked so putmsg() will not block
244 if (putmsg(fd
, &ctlbuf
,
245 (struct strbuf
*)(call
->udata
.len
? &call
->udata
: NULL
), 0) <
254 strfdinsert
.ctlbuf
.maxlen
= ctlbuf
.maxlen
;
255 strfdinsert
.ctlbuf
.len
= ctlbuf
.len
;
256 strfdinsert
.ctlbuf
.buf
= ctlbuf
.buf
;
258 strfdinsert
.databuf
.maxlen
= call
->udata
.maxlen
;
259 strfdinsert
.databuf
.len
=
260 (call
->udata
.len
? call
->udata
.len
: -1);
261 strfdinsert
.databuf
.buf
= call
->udata
.buf
;
262 strfdinsert
.fildes
= resfd
;
263 strfdinsert
.offset
= (int)sizeof (t_scalar_t
);
264 strfdinsert
.flags
= 0; /* could be EXPEDITED also */
266 if (ioctl(fd
, I_FDINSERT
, &strfdinsert
) < 0) {
275 if (_t_is_ok(fd
, tiptr
, conn_res_prim
) < 0) {
277 * At the TPI level, the error returned in a T_ERROR_ACK
278 * received in response to a T_CONN_RES for a listener and
279 * acceptor endpoints not being the same kind of endpoints
280 * has changed to a new t_errno code introduced with
281 * XTI (TPROVMISMATCH). We need to adjust TLI error code
282 * to be same as before.
284 if (_T_IS_TLI(api_semantics
) && t_errno
== TPROVMISMATCH
) {
291 if (tiptr
->ti_ocnt
== 1) {
293 _T_TX_NEXTSTATE(T_ACCEPT1
, tiptr
,
294 "t_accept: invalid state event T_ACCEPT1");
296 _T_TX_NEXTSTATE(T_ACCEPT2
, tiptr
,
297 "t_accept: invalid state event T_ACCEPT2");
299 * XXX Here we lock the resfd lock also. This
300 * is an instance of holding two locks without
301 * any enforcement of a locking hiararchy.
302 * There is potential for deadlock in incorrect
303 * or buggy programs here but this is the safer
304 * choice in this case. Correct programs will not
307 sig_mutex_lock(&restiptr
->ti_lock
);
308 _T_TX_NEXTSTATE(T_PASSCON
, restiptr
,
309 "t_accept: invalid state event T_PASSCON");
310 sig_mutex_unlock(&restiptr
->ti_lock
);
313 _T_TX_NEXTSTATE(T_ACCEPT3
, tiptr
,
314 "t_accept: invalid state event T_ACCEPT3");
316 sig_mutex_lock(&restiptr
->ti_lock
);
317 _T_TX_NEXTSTATE(T_PASSCON
, restiptr
,
318 "t_accept: invalid state event T_PASSCON");
320 sig_mutex_unlock(&restiptr
->ti_lock
);
324 tiptr
->ti_flags
&= ~TX_TQFULL_NOTIFIED
;
327 * Update attributes which may have been negotiated during
328 * connection establishment for protocols where we suspect
329 * such negotiation is likely (e.g. OSI). We do not do it for
330 * all endpoints for performance reasons. Also, this code is
331 * deliberately done after user level state changes so even
332 * the (unlikely) failure case reflects a connected endpoint.
334 if (restiptr
->ti_tsdusize
!= 0) {
335 if (_t_do_postconn_sync(resfd
, restiptr
) < 0)
342 tiptr
->ti_ctlbuf
= ctlbuf
.buf
;
343 sig_mutex_unlock(&tiptr
->ti_lock
);
344 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);
352 tiptr
->ti_ctlbuf
= ctlbuf
.buf
;
353 sig_mutex_unlock(&tiptr
->ti_lock
);
354 (void) thr_sigsetmask(SIG_SETMASK
, &mask
, NULL
);