xref: /onnv-gate/usr/src/lib/libnsl/nsl/t_sndvudata.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1998-2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * t_sndudata.c and t_sndvudata.c are very similar and contain common code.
31*0Sstevel@tonic-gate  * Any changes to either of them should be reviewed to see whether they
32*0Sstevel@tonic-gate  * are applicable to the other file.
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate #include "mt.h"
35*0Sstevel@tonic-gate #include <rpc/trace.h>
36*0Sstevel@tonic-gate #include <stdlib.h>
37*0Sstevel@tonic-gate #include <errno.h>
38*0Sstevel@tonic-gate #include <stropts.h>
39*0Sstevel@tonic-gate #include <sys/stream.h>
40*0Sstevel@tonic-gate #define	_SUN_TPI_VERSION 2
41*0Sstevel@tonic-gate #include <sys/tihdr.h>
42*0Sstevel@tonic-gate #include <sys/timod.h>
43*0Sstevel@tonic-gate #include <xti.h>
44*0Sstevel@tonic-gate #include <syslog.h>
45*0Sstevel@tonic-gate #include <assert.h>
46*0Sstevel@tonic-gate #include "tx.h"
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate int
49*0Sstevel@tonic-gate _tx_sndvudata(int fd, const struct t_unitdata *unitdata, struct t_iovec *tiov,
50*0Sstevel@tonic-gate     unsigned int tiovcount, int api_semantics)
51*0Sstevel@tonic-gate {
52*0Sstevel@tonic-gate 	struct T_unitdata_req *udreq;
53*0Sstevel@tonic-gate 	struct strbuf ctlbuf;
54*0Sstevel@tonic-gate 	struct strbuf databuf;
55*0Sstevel@tonic-gate 	int size;
56*0Sstevel@tonic-gate 	struct _ti_user *tiptr;
57*0Sstevel@tonic-gate 	int sv_errno;
58*0Sstevel@tonic-gate 	int didalloc;
59*0Sstevel@tonic-gate 	char *dataptr;
60*0Sstevel@tonic-gate 	unsigned int nbytes;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	trace2(TR_t_sndvudata, 0, fd);
63*0Sstevel@tonic-gate 	assert(api_semantics == TX_XTI_XNS5_API);
64*0Sstevel@tonic-gate 	if ((tiptr = _t_checkfd(fd, 0, api_semantics)) == NULL) {
65*0Sstevel@tonic-gate 		sv_errno = errno;
66*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
67*0Sstevel@tonic-gate 		errno = sv_errno;
68*0Sstevel@tonic-gate 		return (-1);
69*0Sstevel@tonic-gate 	}
70*0Sstevel@tonic-gate 	sig_mutex_lock(&tiptr->ti_lock);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	if (tiptr->ti_servtype != T_CLTS) {
73*0Sstevel@tonic-gate 		t_errno = TNOTSUPPORT;
74*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
75*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
76*0Sstevel@tonic-gate 		return (-1);
77*0Sstevel@tonic-gate 	}
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	if (tiovcount == 0 || tiovcount > T_IOV_MAX) {
80*0Sstevel@tonic-gate 		t_errno = TBADDATA;
81*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
82*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
83*0Sstevel@tonic-gate 		return (-1);
84*0Sstevel@tonic-gate 	}
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	if (tiptr->ti_state != T_IDLE) {
87*0Sstevel@tonic-gate 		t_errno = TOUTSTATE;
88*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
89*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
90*0Sstevel@tonic-gate 		return (-1);
91*0Sstevel@tonic-gate 	}
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	nbytes = _t_bytecount_upto_intmax(tiov, tiovcount);
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 	if ((nbytes == 0) &&
96*0Sstevel@tonic-gate 	    !(tiptr->ti_prov_flag & (SENDZERO|OLD_SENDZERO))) {
97*0Sstevel@tonic-gate 		t_errno = TBADDATA;
98*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
99*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
100*0Sstevel@tonic-gate 		return (-1);
101*0Sstevel@tonic-gate 	}
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 	if ((tiptr->ti_maxpsz > 0) && (nbytes > (uint32_t)tiptr->ti_maxpsz)) {
104*0Sstevel@tonic-gate 		t_errno = TBADDATA;
105*0Sstevel@tonic-gate 		sv_errno = errno;
106*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
107*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
108*0Sstevel@tonic-gate 		errno = sv_errno;
109*0Sstevel@tonic-gate 		return (-1);
110*0Sstevel@tonic-gate 	}
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	/*
113*0Sstevel@tonic-gate 	 * Acquire ctlbuf for use in sending/receiving control part
114*0Sstevel@tonic-gate 	 * of the message.
115*0Sstevel@tonic-gate 	 */
116*0Sstevel@tonic-gate 	if (_t_acquire_ctlbuf(tiptr, &ctlbuf, &didalloc) < 0) {
117*0Sstevel@tonic-gate 		sv_errno = errno;
118*0Sstevel@tonic-gate 		sig_mutex_unlock(&tiptr->ti_lock);
119*0Sstevel@tonic-gate 		trace2(TR_t_sndvudata, 1, fd);
120*0Sstevel@tonic-gate 		errno = sv_errno;
121*0Sstevel@tonic-gate 		return (-1);
122*0Sstevel@tonic-gate 	}
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	udreq = (struct T_unitdata_req *)ctlbuf.buf;
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	udreq->PRIM_type = T_UNITDATA_REQ;
127*0Sstevel@tonic-gate 	udreq->DEST_length = unitdata->addr.len;
128*0Sstevel@tonic-gate 	udreq->DEST_offset = 0;
129*0Sstevel@tonic-gate 	udreq->OPT_length = unitdata->opt.len;
130*0Sstevel@tonic-gate 	udreq->OPT_offset = 0;
131*0Sstevel@tonic-gate 	size = (int)sizeof (struct T_unitdata_req);
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	if (unitdata->addr.len) {
134*0Sstevel@tonic-gate 		if (_t_aligned_copy(&ctlbuf, unitdata->addr.len, size,
135*0Sstevel@tonic-gate 		    unitdata->addr.buf, &udreq->DEST_offset) < 0) {
136*0Sstevel@tonic-gate 			/*
137*0Sstevel@tonic-gate 			 * Aligned copy based will overflow buffer
138*0Sstevel@tonic-gate 			 * allocated based on maximum transport address
139*0Sstevel@tonic-gate 			 * size information
140*0Sstevel@tonic-gate 			 */
141*0Sstevel@tonic-gate 			t_errno = TSYSERR;
142*0Sstevel@tonic-gate 			errno = EPROTO;
143*0Sstevel@tonic-gate 			goto err_out;
144*0Sstevel@tonic-gate 		}
145*0Sstevel@tonic-gate 		size = udreq->DEST_offset + udreq->DEST_length;
146*0Sstevel@tonic-gate 	}
147*0Sstevel@tonic-gate 	if (unitdata->opt.len) {
148*0Sstevel@tonic-gate 		if (_t_aligned_copy(&ctlbuf, unitdata->opt.len, size,
149*0Sstevel@tonic-gate 		    unitdata->opt.buf, &udreq->OPT_offset) < 0) {
150*0Sstevel@tonic-gate 			/*
151*0Sstevel@tonic-gate 			 * Aligned copy based will overflow buffer
152*0Sstevel@tonic-gate 			 * allocated based on maximum transport option
153*0Sstevel@tonic-gate 			 * size information
154*0Sstevel@tonic-gate 			 */
155*0Sstevel@tonic-gate 			t_errno = TSYSERR;
156*0Sstevel@tonic-gate 			errno = EPROTO;
157*0Sstevel@tonic-gate 			goto err_out;
158*0Sstevel@tonic-gate 		}
159*0Sstevel@tonic-gate 		size = udreq->OPT_offset + udreq->OPT_length;
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	if (size > (int)ctlbuf.maxlen) {
163*0Sstevel@tonic-gate 		t_errno = TSYSERR;
164*0Sstevel@tonic-gate 		errno = EIO;
165*0Sstevel@tonic-gate 		goto err_out;
166*0Sstevel@tonic-gate 	}
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	ctlbuf.len = size;
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	dataptr = NULL;
171*0Sstevel@tonic-gate 	if (nbytes != 0) {
172*0Sstevel@tonic-gate 		if ((dataptr = malloc((size_t)nbytes)) == NULL) {
173*0Sstevel@tonic-gate 			t_errno = TSYSERR;
174*0Sstevel@tonic-gate 			goto err_out;
175*0Sstevel@tonic-gate 		}
176*0Sstevel@tonic-gate 		_t_gather(dataptr, tiov, tiovcount);
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 	databuf.buf = dataptr;
179*0Sstevel@tonic-gate 	databuf.len = nbytes;
180*0Sstevel@tonic-gate 	databuf.maxlen = nbytes;
181*0Sstevel@tonic-gate 	/*
182*0Sstevel@tonic-gate 	 * Calls to send data (write or putmsg) can potentially
183*0Sstevel@tonic-gate 	 * block, for MT case, we drop the lock and enable signals here
184*0Sstevel@tonic-gate 	 * and acquire it back
185*0Sstevel@tonic-gate 	 */
186*0Sstevel@tonic-gate 	sig_mutex_unlock(&tiptr->ti_lock);
187*0Sstevel@tonic-gate 	if (putmsg(fd, &ctlbuf, &databuf, 0) < 0) {
188*0Sstevel@tonic-gate 		if (errno == EAGAIN)
189*0Sstevel@tonic-gate 			t_errno = TFLOW;
190*0Sstevel@tonic-gate 		else
191*0Sstevel@tonic-gate 			t_errno = TSYSERR;
192*0Sstevel@tonic-gate 		sv_errno = errno;
193*0Sstevel@tonic-gate 		sig_mutex_lock(&tiptr->ti_lock);
194*0Sstevel@tonic-gate 		errno = sv_errno;
195*0Sstevel@tonic-gate 		goto err_out;
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 	sig_mutex_lock(&tiptr->ti_lock);
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	_T_TX_NEXTSTATE(T_SNDUDATA, tiptr,
200*0Sstevel@tonic-gate 			"t_sndvudata: invalid state event T_SNDUDATA");
201*0Sstevel@tonic-gate 	if (didalloc)
202*0Sstevel@tonic-gate 		free(ctlbuf.buf);
203*0Sstevel@tonic-gate 	else
204*0Sstevel@tonic-gate 		tiptr->ti_ctlbuf = ctlbuf.buf;
205*0Sstevel@tonic-gate 	if (dataptr != NULL)
206*0Sstevel@tonic-gate 		free(dataptr);
207*0Sstevel@tonic-gate 	sig_mutex_unlock(&tiptr->ti_lock);
208*0Sstevel@tonic-gate 	trace2(TR_t_sndvudata, 0, fd);
209*0Sstevel@tonic-gate 	return (0);
210*0Sstevel@tonic-gate err_out:
211*0Sstevel@tonic-gate 	sv_errno = errno;
212*0Sstevel@tonic-gate 	if (didalloc)
213*0Sstevel@tonic-gate 		free(ctlbuf.buf);
214*0Sstevel@tonic-gate 	else
215*0Sstevel@tonic-gate 		tiptr->ti_ctlbuf = ctlbuf.buf;
216*0Sstevel@tonic-gate 	if (dataptr != NULL)
217*0Sstevel@tonic-gate 		free(dataptr);
218*0Sstevel@tonic-gate 	sig_mutex_unlock(&tiptr->ti_lock);
219*0Sstevel@tonic-gate 	trace2(TR_t_sndvudata, 1, fd);
220*0Sstevel@tonic-gate 	errno = sv_errno;
221*0Sstevel@tonic-gate 	return (-1);
222*0Sstevel@tonic-gate }
223