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 2014 Gary Mills
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
41 * Kernel TLI-like function to read a datagram off of a
42 * transport endpoints stream head.
45 * 0 On success or positive error code.
46 * On sucess, type is set to:
47 * T_DATA If normal data has been received
48 * T_UDERR If an error indication has been received,
49 * in which case uderr contains the unitdata
53 #include <sys/param.h>
54 #include <sys/types.h>
57 #include <sys/errno.h>
58 #include <sys/stream.h>
59 #include <sys/strsubr.h>
60 #include <sys/vnode.h>
61 #include <sys/ioctl.h>
62 #include <sys/stropts.h>
63 #include <sys/tihdr.h>
64 #include <sys/timod.h>
65 #include <sys/tiuser.h>
66 #include <sys/t_kuser.h>
67 #include <sys/sysmacros.h>
68 #include <sys/strsun.h>
72 t_krcvudata(TIUSER
*tiptr
, struct t_kunitdata
*unitdata
, int *type
, int *uderr
)
76 union T_primitives
*pptr
;
87 if (type
== NULL
|| uderr
== NULL
)
91 unitdata
->udata
.buf
= NULL
;
93 if (unitdata
->udata
.udata_mp
) {
94 KTLILOG(2, "t_krcvudata: freeing existing message block\n", 0);
95 freemsg(unitdata
->udata
.udata_mp
);
96 unitdata
->udata
.udata_mp
= NULL
;
100 * XXX Grabbing a mutex to do an atomic operation seems pointless
102 mutex_enter(&fp
->f_tlock
);
104 mutex_exit(&fp
->f_tlock
);
106 if ((error
= tli_recv(tiptr
, &bp
, flag
)) != 0)
112 switch (bp
->b_datap
->db_type
) {
114 /* LINTED pointer alignment */
115 pptr
= (union T_primitives
*)bp
->b_rptr
;
116 switch (pptr
->type
) {
118 KTLILOG(2, "t_krcvudata: Got T_UNITDATA_IND\n", 0);
122 * check everything for consistency
124 if (hdrsz
< TUNITDATAINDSZ
||
125 hdrsz
< (pptr
->unitdata_ind
.OPT_length
+
126 pptr
->unitdata_ind
.OPT_offset
) ||
127 hdrsz
< (pptr
->unitdata_ind
.SRC_length
+
128 pptr
->unitdata_ind
.SRC_offset
)) {
135 * okay, so now we copy them
137 len
= MIN(pptr
->unitdata_ind
.SRC_length
,
138 unitdata
->addr
.maxlen
);
139 bcopy(bp
->b_rptr
+ pptr
->unitdata_ind
.SRC_offset
,
140 unitdata
->addr
.buf
, len
);
141 unitdata
->addr
.len
= len
;
143 len
= MIN(pptr
->unitdata_ind
.OPT_length
,
144 unitdata
->opt
.maxlen
);
145 bcopy(bp
->b_rptr
+ pptr
->unitdata_ind
.OPT_offset
,
146 unitdata
->opt
.buf
, len
);
147 unitdata
->opt
.len
= len
;
152 * we assume that the client knows how to deal
153 * with a set of linked mblks, so all we do is
154 * make a pass and remove any that are zero
160 if (bp
->b_wptr
== bp
->b_rptr
) {
162 "t_krcvudata: zero length block\n",
183 struct datab
*dbp
= tp
->b_datap
;
184 frtn_t
*frp
= dbp
->db_frtnp
;
186 KTLILOG(2, "t_krcvudata: bp %x, ", tp
);
187 KTLILOG(2, "db_size %x, ", dbp
->db_lim
- dbp
->db_base
);
188 KTLILOG(2, "db_ref %x", dbp
->db_ref
);
191 KTLILOG(2, ", func: %x", frp
->free_func
);
192 KTLILOG(2, ", arg %x\n", frp
->free_arg
);
198 #endif /* KTLIDEBUG */
200 * now just point the users mblk
201 * pointer to what we received.
204 KTLILOG(2, "t_krcvudata: No data\n", 0);
208 if (bp
->b_wptr
!= bp
->b_rptr
) {
209 if (!IS_P2ALIGNED(bp
->b_rptr
, sizeof (uint32_t)))
210 if (!pullupmsg(bp
, MBLKL(bp
))) {
212 "t_krcvudata: pullupmsg failed\n", 0);
217 unitdata
->udata
.buf
= (char *)bp
->b_rptr
;
218 unitdata
->udata
.len
= (uint_t
)MBLKL(bp
);
220 KTLILOG(2, "t_krcvudata: got %d bytes\n",
221 unitdata
->udata
.len
);
222 unitdata
->udata
.udata_mp
= bp
;
225 "t_krcvudata: 0 length data message\n", 0);
227 unitdata
->udata
.len
= 0;
233 KTLILOG(2, "t_krcvudata: Got T_UDERROR_IND\n", 0);
237 * check everything for consistency
239 if (hdrsz
< TUDERRORINDSZ
||
240 hdrsz
< (pptr
->uderror_ind
.OPT_length
+
241 pptr
->uderror_ind
.OPT_offset
) ||
242 hdrsz
< (pptr
->uderror_ind
.DEST_length
+
243 pptr
->uderror_ind
.DEST_offset
)) {
249 if (pptr
->uderror_ind
.DEST_length
>
250 (int)unitdata
->addr
.maxlen
||
251 pptr
->uderror_ind
.OPT_length
>
252 (int)unitdata
->opt
.maxlen
) {
259 * okay, so now we copy them
261 bcopy(bp
->b_rptr
+ pptr
->uderror_ind
.DEST_offset
,
263 (size_t)pptr
->uderror_ind
.DEST_length
);
264 unitdata
->addr
.len
= pptr
->uderror_ind
.DEST_length
;
266 bcopy(bp
->b_rptr
+ pptr
->uderror_ind
.OPT_offset
,
268 (size_t)pptr
->uderror_ind
.OPT_length
);
269 unitdata
->opt
.len
= pptr
->uderror_ind
.OPT_length
;
271 *uderr
= pptr
->uderror_ind
.ERROR_type
;
273 unitdata
->udata
.buf
= NULL
;
274 unitdata
->udata
.udata_mp
= NULL
;
275 unitdata
->udata
.len
= 0;
284 "t_krcvudata: Unknown transport primitive %d\n",
293 KTLILOG(1, "t_krcvudata: tli_recv returned M_FLUSH\n", 0);
299 KTLILOG(1, "t_krcvudata: unknown message type %x\n",
300 bp
->b_datap
->db_type
);