import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / nsl / t_rcvvudata.c
blobf1a1e5402f96e0351ec2dd303a9a068c51dc5e2c
1 /*
2 * CDDL HEADER START
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.
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]
20 * CDDL HEADER END
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * t_rcvudata.c and t_rcvvudata.c are very similar and contain common code.
30 * Any changes to either of them should be reviewed to see whether they
31 * are applicable to the other file.
33 #include "mt.h"
34 #include <string.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <stropts.h>
38 #include <sys/stream.h>
39 #define _SUN_TPI_VERSION 2
40 #include <sys/tihdr.h>
41 #include <sys/timod.h>
42 #include <xti.h>
43 #include <syslog.h>
44 #include <assert.h>
45 #include "tx.h"
48 int
49 _tx_rcvvudata(
50 int fd,
51 struct t_unitdata *unitdata,
52 struct t_iovec *tiov,
53 unsigned int tiovcount,
54 int *flags,
55 int api_semantics
58 struct strbuf ctlbuf;
59 struct strbuf databuf;
60 char *dataptr;
61 int retval;
62 union T_primitives *pptr;
63 struct _ti_user *tiptr;
64 int sv_errno;
65 int didalloc;
66 int flg = 0;
67 unsigned int nbytes;
69 assert(api_semantics == TX_XTI_XNS5_API);
71 if (tiovcount == 0 || tiovcount > T_IOV_MAX) {
72 t_errno = TBADDATA;
73 return (-1);
76 if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL)
77 return (-1);
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 return (-1);
86 if (tiptr->ti_state != T_IDLE) {
87 t_errno = TOUTSTATE;
88 sig_mutex_unlock(&tiptr->ti_lock);
89 return (-1);
93 * check if there is something in look buffer
95 if (tiptr->ti_lookcnt > 0) {
96 sig_mutex_unlock(&tiptr->ti_lock);
97 t_errno = TLOOK;
98 return (-1);
102 * Acquire ctlbuf for use in sending/receiving control part
103 * of the message.
105 if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) {
106 sv_errno = errno;
107 sig_mutex_unlock(&tiptr->ti_lock);
108 errno = sv_errno;
109 return (-1);
112 *flags = 0;
114 nbytes = _t_bytecount_upto_intmax(tiov, tiovcount);
115 dataptr = NULL;
116 if (nbytes != 0 && ((dataptr = malloc(nbytes)) == NULL)) {
117 t_errno = TSYSERR;
118 goto err_out;
121 databuf.maxlen = nbytes;
122 databuf.len = 0;
123 databuf.buf = dataptr;
126 * This is a call that may block indefinitely so we drop the
127 * lock and allow signals in MT case here and reacquire it.
128 * Error case should roll back state changes done above
129 * (happens to be no state change here)
131 sig_mutex_unlock(&tiptr->ti_lock);
132 if ((retval = getmsg(fd, &ctlbuf, &databuf, &flg)) < 0) {
133 if (errno == EAGAIN)
134 t_errno = TNODATA;
135 else
136 t_errno = TSYSERR;
137 sv_errno = errno;
138 sig_mutex_lock(&tiptr->ti_lock);
139 errno = sv_errno;
140 goto err_out;
142 sig_mutex_lock(&tiptr->ti_lock);
145 * is there control piece with data?
147 if (ctlbuf.len > 0) {
148 if (ctlbuf.len < (int)sizeof (t_scalar_t)) {
149 t_errno = TSYSERR;
150 errno = EPROTO;
151 goto err_out;
154 /* LINTED pointer cast */
155 pptr = (union T_primitives *)ctlbuf.buf;
157 switch (pptr->type) {
159 case T_UNITDATA_IND:
160 if ((ctlbuf.len <
161 (int)sizeof (struct T_unitdata_ind)) ||
162 (pptr->unitdata_ind.OPT_length &&
163 (ctlbuf.len < (int)(pptr->unitdata_ind.OPT_length
164 + pptr->unitdata_ind.OPT_offset)))) {
165 t_errno = TSYSERR;
166 errno = EPROTO;
167 goto err_out;
170 if (unitdata->addr.maxlen > 0) {
171 if (TLEN_GT_NLEN(pptr->unitdata_ind.SRC_length,
172 unitdata->addr.maxlen)) {
173 t_errno = TBUFOVFLW;
174 goto err_out;
176 (void) memcpy(unitdata->addr.buf,
177 ctlbuf.buf + pptr->unitdata_ind.SRC_offset,
178 (size_t)pptr->unitdata_ind.SRC_length);
179 unitdata->addr.len =
180 pptr->unitdata_ind.SRC_length;
182 if (unitdata->opt.maxlen > 0) {
183 if (TLEN_GT_NLEN(pptr->unitdata_ind.OPT_length,
184 unitdata->opt.maxlen)) {
185 t_errno = TBUFOVFLW;
186 goto err_out;
188 (void) memcpy(unitdata->opt.buf, ctlbuf.buf +
189 pptr->unitdata_ind.OPT_offset,
190 (size_t)pptr->unitdata_ind.OPT_length);
191 unitdata->opt.len =
192 pptr->unitdata_ind.OPT_length;
194 if (retval & MOREDATA)
195 *flags |= T_MORE;
197 * No state changes happens on T_RCVUDATA
198 * event (NOOP). We do it only to log errors.
200 _T_TX_NEXTSTATE(T_RCVUDATA, tiptr,
201 "t_rcvvudata: invalid state event T_RCVUDATA");
203 if (didalloc)
204 free(ctlbuf.buf);
205 else
206 tiptr->ti_ctlbuf = ctlbuf.buf;
207 _t_scatter(&databuf, tiov, tiovcount);
208 free(dataptr);
209 sig_mutex_unlock(&tiptr->ti_lock);
210 return (databuf.len);
212 case T_UDERROR_IND:
213 if (_t_register_lookevent(tiptr, 0, 0, ctlbuf.buf,
214 ctlbuf.len) < 0) {
215 t_errno = TSYSERR;
216 errno = ENOMEM;
217 goto err_out;
219 t_errno = TLOOK;
220 goto err_out;
222 default:
223 break;
226 t_errno = TSYSERR;
227 errno = EPROTO;
228 goto err_out;
230 } else { /* else part of "if (ctlbuf.len > 0)" */
231 unitdata->addr.len = 0;
232 unitdata->opt.len = 0;
234 * only data in message no control piece
236 if (retval & MOREDATA)
237 *flags = T_MORE;
239 * No state transition occurs on
240 * event T_RCVUDATA. We do it only to
241 * log errors.
243 _T_TX_NEXTSTATE(T_RCVUDATA, tiptr,
244 "t_rcvvudata: invalid state event T_RCVUDATA");
245 if (didalloc)
246 free(ctlbuf.buf);
247 else
248 tiptr->ti_ctlbuf = ctlbuf.buf;
249 _t_scatter(&databuf, tiov, tiovcount);
250 free(dataptr);
251 sig_mutex_unlock(&tiptr->ti_lock);
252 return (databuf.len);
254 /* NOTREACHED */
255 err_out:
256 sv_errno = errno;
257 if (didalloc)
258 free(ctlbuf.buf);
259 else
260 tiptr->ti_ctlbuf = ctlbuf.buf;
261 free(dataptr);
262 sig_mutex_unlock(&tiptr->ti_lock);
263 errno = sv_errno;
264 return (-1);