4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
40 * Kernel TLI-like function to allow a trasnport endpoint to initiate a
41 * connection to another transport endpoint. This function will wait for
42 * an ack and a T_CONN_CON before returning.
45 * 0 on success, and if rcvcall is non-NULL it shall be
46 * filled with the connection confirm data.
47 * Otherwise a positive error code.
50 #include <sys/param.h>
51 #include <sys/types.h>
54 #include <sys/vnode.h>
55 #include <sys/errno.h>
56 #include <sys/stream.h>
57 #include <sys/ioctl.h>
58 #include <sys/stropts.h>
59 #include <sys/tihdr.h>
60 #include <sys/timod.h>
61 #include <sys/tiuser.h>
62 #include <sys/t_kuser.h>
63 #include <sys/strsubr.h>
64 #include <sys/sysmacros.h>
65 #include <sys/strsun.h>
69 t_kconnect(TIUSER
*tiptr
, struct t_call
*sndcall
, struct t_call
*rcvcall
)
74 struct T_conn_req
*creq
;
75 union T_primitives
*pptr
;
85 msgsz
= (int)TCONNREQSZ
;
87 * Usually connect()s are performed with the credential of the caller;
88 * in this particular case we specifically use the credential of
89 * the opener as this call is typically done in the context of a user
90 * process but on behalf of the kernel, e.g., a client connection
91 * to a server which is later shared by different users.
92 * At open time, we make sure to set fp->f_cred to kcred if such is
95 * Note: if the receiver uses SCM_UCRED/getpeerucred the pid will
98 while (!(bp
= allocb_cred(msgsz
+ sndcall
->addr
.len
+ sndcall
->opt
.len
,
99 fp
->f_cred
, NOPID
))) {
100 if (strwaitbuf(msgsz
+ sndcall
->addr
.len
+ sndcall
->opt
.len
,
105 /* LINTED pointer alignment */
106 creq
= (struct T_conn_req
*)bp
->b_wptr
;
107 creq
->PRIM_type
= T_CONN_REQ
;
108 creq
->DEST_length
= (t_scalar_t
)sndcall
->addr
.len
;
109 creq
->OPT_length
= (t_scalar_t
)sndcall
->opt
.len
;
111 if (sndcall
->addr
.len
) {
112 bcopy(sndcall
->addr
.buf
, (bp
->b_wptr
+msgsz
), sndcall
->addr
.len
);
113 creq
->DEST_offset
= (t_scalar_t
)msgsz
;
114 msgsz
+= sndcall
->addr
.len
;
116 creq
->DEST_offset
= (t_scalar_t
)0;
118 if (sndcall
->opt
.len
) {
119 bcopy(sndcall
->opt
.buf
, (bp
->b_wptr
+msgsz
), sndcall
->opt
.len
);
120 creq
->OPT_offset
= (t_scalar_t
)msgsz
;
121 msgsz
+= sndcall
->opt
.len
;
123 creq
->OPT_offset
= (t_scalar_t
)0;
125 bp
->b_datap
->db_type
= M_PROTO
;
129 * copy the users data, if any.
131 if (sndcall
->udata
.len
) {
133 * if CO then we would allocate a data block and
134 * put the users connect data into it.
137 "Attempt to send connectionless data on T_CONN_REQ\n", 0);
147 if ((error
= tli_send(tiptr
, bp
, flag
)) != 0)
151 * wait for acknowledgment
153 if ((error
= get_ok_ack(tiptr
, T_CONN_REQ
, flag
)) != 0)
160 if ((error
= tli_recv(tiptr
, &bp
, flag
)) != 0)
163 if (bp
->b_datap
->db_type
!= M_PROTO
) {
168 /* LINTED pointer alignment */
169 pptr
= (union T_primitives
*)bp
->b_rptr
;
170 switch (pptr
->type
) {
175 * check everything for consistency
177 if (hdrsz
< TCONNCONSZ
||
178 hdrsz
< (pptr
->conn_con
.OPT_length
+
179 pptr
->conn_con
.OPT_offset
) ||
180 hdrsz
< (pptr
->conn_con
.RES_length
+
181 pptr
->conn_con
.RES_offset
)) {
187 if (rcvcall
!= NULL
) {
189 * okay, so now we copy them
191 len
= MIN(pptr
->conn_con
.RES_length
,
192 rcvcall
->addr
.maxlen
);
193 bcopy(bp
->b_rptr
+ pptr
->conn_con
.RES_offset
,
194 rcvcall
->addr
.buf
, len
);
195 rcvcall
->addr
.len
= len
;
197 len
= MIN(pptr
->conn_con
.OPT_length
,
198 rcvcall
->opt
.maxlen
);
199 bcopy(bp
->b_rptr
+ pptr
->conn_con
.OPT_offset
,
200 rcvcall
->opt
.buf
, len
);
201 rcvcall
->opt
.len
= len
;
206 msgsz
= (int)MBLKL(bp
);
207 len
= MIN(msgsz
, rcvcall
->udata
.maxlen
);
208 bcopy(bp
->b_rptr
, rcvcall
->udata
.buf
, len
);
209 rcvcall
->udata
.len
= len
;
219 * TCP puts the errno here, i.e.
220 * ETIMEDOUT, ECONNREFUSED
222 error
= pptr
->discon_ind
.DISCON_reason
;