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 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include <sys/param.h>
35 #include <sys/types.h>
40 #include <sys/stream.h>
41 #define _SUN_TPI_VERSION 2
42 #include <sys/tihdr.h>
43 #include <sys/timod.h>
51 * Snd_conn_req - send connect request message to transport provider.
52 * All signals for the caller are blocked during the call to simplify design.
53 * (This is OK for a bounded amount of time this routine is expected to
54 * execute). Also, assumes tiptr->ti_lock is held.
58 struct _ti_user
*tiptr
,
59 const struct t_call
*call
,
60 struct strbuf
*ctlbufp
)
62 struct T_conn_req
*creq
;
66 assert(MUTEX_HELD(&tiptr
->ti_lock
));
69 if (tiptr
->ti_servtype
== T_CLTS
) {
70 t_errno
= TNOTSUPPORT
;
74 if (_t_is_event(fd
, tiptr
) < 0)
77 /* LINTED pointer cast */
78 creq
= (struct T_conn_req
*)ctlbufp
->buf
;
79 creq
->PRIM_type
= T_CONN_REQ
;
80 creq
->DEST_length
= call
->addr
.len
;
81 creq
->DEST_offset
= 0;
82 creq
->OPT_length
= call
->opt
.len
;
84 size
= (int)sizeof (struct T_conn_req
); /* size without any buffers */
87 if (_t_aligned_copy(ctlbufp
, call
->addr
.len
, size
,
88 call
->addr
.buf
, &creq
->DEST_offset
) < 0) {
90 * Aligned copy will overflow buffer allocated based
91 * based on transport maximum address size.
97 size
= creq
->DEST_offset
+ creq
->DEST_length
;
100 if (_t_aligned_copy(ctlbufp
, call
->opt
.len
, size
,
101 call
->opt
.buf
, &creq
->OPT_offset
) < 0) {
103 * Aligned copy will overflow buffer allocated based
104 * on maximum option size in transport.
110 size
= creq
->OPT_offset
+ creq
->OPT_length
;
112 if (call
->udata
.len
) {
113 if ((tiptr
->ti_cdatasize
== T_INVALID
/* -2 */) ||
114 ((tiptr
->ti_cdatasize
!= T_INFINITE
/* -1 */) &&
115 (call
->udata
.len
> (uint32_t)tiptr
->ti_cdatasize
))) {
117 * user data not valid with connect or it
118 * exceeds the limits specified by the transport
129 * Assumes signals are blocked so putmsg() will not block
132 if (putmsg(fd
, ctlbufp
,
133 (struct strbuf
*)(call
->udata
.len
? &call
->udata
: NULL
), 0) < 0) {
138 if (_t_is_ok(fd
, tiptr
, T_CONN_REQ
) < 0)
146 * Rcv_conn_con - get connection confirmation off
149 * - called holding the tiptr->ti_lock
153 struct _ti_user
*tiptr
,
155 struct strbuf
*ctlbufp
,
158 struct strbuf databuf
;
159 union T_primitives
*pptr
;
160 int retval
, fd
, sv_errno
;
167 if (tiptr
->ti_servtype
== T_CLTS
) {
168 t_errno
= TNOTSUPPORT
;
173 * see if there is something in look buffer
175 if (tiptr
->ti_lookcnt
> 0) {
182 * Acquire databuf for use in sending/receiving data part
184 if (_t_acquire_databuf(tiptr
, &databuf
, &didralloc
) < 0)
188 * This is a call that may block indefinitely so we drop the
189 * lock and allow signals in MT case here and reacquire it.
190 * Error case should roll back state changes done above
191 * (happens to be no state change here)
193 sig_mutex_unlock(&tiptr
->ti_lock
);
194 if ((retval
= getmsg(fd
, ctlbufp
, &databuf
, &flg
)) < 0) {
200 sig_mutex_lock(&tiptr
->ti_lock
);
204 sig_mutex_lock(&tiptr
->ti_lock
);
206 if (databuf
.len
== -1) databuf
.len
= 0;
209 * did we get entire message
218 * is cntl part large enough to determine message type?
220 if (ctlbufp
->len
< (int)sizeof (t_scalar_t
)) {
226 /* LINTED pointer cast */
227 pptr
= (union T_primitives
*)ctlbufp
->buf
;
229 switch (pptr
->type
) {
233 if ((ctlbufp
->len
< (int)sizeof (struct T_conn_con
)) ||
234 (pptr
->conn_con
.OPT_length
!= 0 &&
235 (ctlbufp
->len
< (int)(pptr
->conn_con
.OPT_length
+
236 pptr
->conn_con
.OPT_offset
)))) {
244 * Note: Buffer overflow is an error in XTI
245 * only if netbuf.maxlen > 0
247 if (_T_IS_TLI(api_semantics
) || call
->addr
.maxlen
> 0) {
248 if (TLEN_GT_NLEN(pptr
->conn_con
.RES_length
,
249 call
->addr
.maxlen
)) {
253 (void) memcpy(call
->addr
.buf
,
254 ctlbufp
->buf
+ pptr
->conn_con
.RES_offset
,
255 (size_t)pptr
->conn_con
.RES_length
);
256 call
->addr
.len
= pptr
->conn_con
.RES_length
;
258 if (_T_IS_TLI(api_semantics
) || call
->opt
.maxlen
> 0) {
259 if (TLEN_GT_NLEN(pptr
->conn_con
.OPT_length
,
264 (void) memcpy(call
->opt
.buf
,
265 ctlbufp
->buf
+ pptr
->conn_con
.OPT_offset
,
266 (size_t)pptr
->conn_con
.OPT_length
);
267 call
->opt
.len
= pptr
->conn_con
.OPT_length
;
269 if (_T_IS_TLI(api_semantics
) ||
270 call
->udata
.maxlen
> 0) {
271 if (databuf
.len
> (int)call
->udata
.maxlen
) {
275 (void) memcpy(call
->udata
.buf
, databuf
.buf
,
276 (size_t)databuf
.len
);
277 call
->udata
.len
= databuf
.len
;
280 * since a confirmation seq number
283 call
->sequence
= (int)-1;
288 tiptr
->ti_rcvbuf
= databuf
.buf
;
294 * if disconnect indication then append it to
295 * the "look bufffer" list.
296 * This may result in MT case for the process
297 * signal mask to be temporarily masked to
298 * ensure safe memory allocation.
301 if (_t_register_lookevent(tiptr
, databuf
.buf
, databuf
.len
,
302 ctlbufp
->buf
, ctlbufp
->len
) < 0) {
320 tiptr
->ti_rcvbuf
= databuf
.buf
;