xref: /onnv-gate/usr/src/uts/common/io/strsun.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 2005 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  * Solaris DDI STREAMS utility routines (PSARC/2003/648).
31*0Sstevel@tonic-gate  *
32*0Sstevel@tonic-gate  * Please see the appropriate section 9F manpage for documentation.
33*0Sstevel@tonic-gate  */
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <sys/types.h>
36*0Sstevel@tonic-gate #include <sys/systm.h>
37*0Sstevel@tonic-gate #include <sys/errno.h>
38*0Sstevel@tonic-gate #include <sys/stream.h>
39*0Sstevel@tonic-gate #include <sys/stropts.h>
40*0Sstevel@tonic-gate #include <sys/strsun.h>
41*0Sstevel@tonic-gate #include <sys/cmn_err.h>
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate void
44*0Sstevel@tonic-gate merror(queue_t *wq, mblk_t *mp, int error)
45*0Sstevel@tonic-gate {
46*0Sstevel@tonic-gate 	if ((mp = mexchange(wq, mp, 1, M_ERROR, -1)) == NULL)
47*0Sstevel@tonic-gate 		return;
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate 	*mp->b_rptr = (uchar_t)error;
50*0Sstevel@tonic-gate 	qreply(wq, mp);
51*0Sstevel@tonic-gate }
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate void
54*0Sstevel@tonic-gate mioc2ack(mblk_t *mp, mblk_t *dp, size_t count, int rval)
55*0Sstevel@tonic-gate {
56*0Sstevel@tonic-gate 	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
57*0Sstevel@tonic-gate 	mblk_t *odp = mp->b_cont;  	/* allows freemsg() to be a tail call */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	DB_TYPE(mp) = M_IOCACK;
60*0Sstevel@tonic-gate 	iocp->ioc_count = count;
61*0Sstevel@tonic-gate 	iocp->ioc_error = 0;
62*0Sstevel@tonic-gate 	iocp->ioc_rval = rval;
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	mp->b_cont = dp;
65*0Sstevel@tonic-gate 	if (dp != NULL)
66*0Sstevel@tonic-gate 		dp->b_wptr = dp->b_rptr + count;
67*0Sstevel@tonic-gate 	freemsg(odp);
68*0Sstevel@tonic-gate }
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate void
71*0Sstevel@tonic-gate miocack(queue_t *wq, mblk_t *mp, int count, int rval)
72*0Sstevel@tonic-gate {
73*0Sstevel@tonic-gate 	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	DB_TYPE(mp) = M_IOCACK;
76*0Sstevel@tonic-gate 	iocp->ioc_count = count;
77*0Sstevel@tonic-gate 	iocp->ioc_error = 0;
78*0Sstevel@tonic-gate 	iocp->ioc_rval = rval;
79*0Sstevel@tonic-gate 	qreply(wq, mp);
80*0Sstevel@tonic-gate }
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate void
83*0Sstevel@tonic-gate miocnak(queue_t *wq, mblk_t *mp, int count, int error)
84*0Sstevel@tonic-gate {
85*0Sstevel@tonic-gate 	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 	DB_TYPE(mp) = M_IOCNAK;
88*0Sstevel@tonic-gate 	iocp->ioc_count = count;
89*0Sstevel@tonic-gate 	iocp->ioc_error = error;
90*0Sstevel@tonic-gate 	qreply(wq, mp);
91*0Sstevel@tonic-gate }
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate mblk_t *
94*0Sstevel@tonic-gate mexchange(queue_t *wq, mblk_t *mp, size_t size, uchar_t type, int32_t primtype)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate 	if (mp == NULL || MBLKSIZE(mp) < size || DB_REF(mp) > 1) {
97*0Sstevel@tonic-gate 		freemsg(mp);
98*0Sstevel@tonic-gate 		if ((mp = allocb(size, BPRI_LO)) == NULL) {
99*0Sstevel@tonic-gate 			if (wq != NULL) {
100*0Sstevel@tonic-gate 				if ((mp = allocb(1, BPRI_HI)) != NULL)
101*0Sstevel@tonic-gate 					merror(wq, mp, ENOSR);
102*0Sstevel@tonic-gate 			}
103*0Sstevel@tonic-gate 			return (NULL);
104*0Sstevel@tonic-gate 		}
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	DB_TYPE(mp) = type;
108*0Sstevel@tonic-gate 	mp->b_rptr = DB_BASE(mp);
109*0Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + size;
110*0Sstevel@tonic-gate 	if (primtype >= 0)
111*0Sstevel@tonic-gate 		*(int32_t *)mp->b_rptr = primtype;
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	return (mp);
114*0Sstevel@tonic-gate }
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate size_t
117*0Sstevel@tonic-gate msgsize(mblk_t *mp)
118*0Sstevel@tonic-gate {
119*0Sstevel@tonic-gate 	size_t	n = 0;
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	for (; mp != NULL; mp = mp->b_cont)
122*0Sstevel@tonic-gate 		n += MBLKL(mp);
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	return (n);
125*0Sstevel@tonic-gate }
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate void
128*0Sstevel@tonic-gate mcopymsg(mblk_t *mp, void *bufp)
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate 	caddr_t	dest = bufp;
131*0Sstevel@tonic-gate 	mblk_t	*bp;
132*0Sstevel@tonic-gate 	size_t	n;
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
135*0Sstevel@tonic-gate 		n = MBLKL(bp);
136*0Sstevel@tonic-gate 		bcopy(bp->b_rptr, dest, n);
137*0Sstevel@tonic-gate 		dest += n;
138*0Sstevel@tonic-gate 	}
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	freemsg(mp);
141*0Sstevel@tonic-gate }
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate void
144*0Sstevel@tonic-gate mcopyin(mblk_t *mp, void *private, size_t size, void *useraddr)
145*0Sstevel@tonic-gate {
146*0Sstevel@tonic-gate 	struct copyreq *cp = (struct copyreq *)mp->b_rptr;
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	if (useraddr != NULL) {
149*0Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)useraddr;
150*0Sstevel@tonic-gate 	} else {
151*0Sstevel@tonic-gate 		ASSERT(DB_TYPE(mp) == M_IOCTL);
152*0Sstevel@tonic-gate 		ASSERT(mp->b_cont != NULL);
153*0Sstevel@tonic-gate 		ASSERT(((struct iocblk *)mp->b_rptr)->ioc_count == TRANSPARENT);
154*0Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)*(uintptr_t *)mp->b_cont->b_rptr;
155*0Sstevel@tonic-gate 	}
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	cp->cq_flag = 0;
158*0Sstevel@tonic-gate 	cp->cq_size = size;
159*0Sstevel@tonic-gate 	cp->cq_private = (mblk_t *)private;
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 	DB_TYPE(mp) = M_COPYIN;
162*0Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	if (mp->b_cont != NULL) {
165*0Sstevel@tonic-gate 		freemsg(mp->b_cont);
166*0Sstevel@tonic-gate 		mp->b_cont = NULL;
167*0Sstevel@tonic-gate 	}
168*0Sstevel@tonic-gate }
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate void
171*0Sstevel@tonic-gate mcopyout(mblk_t *mp, void *private, size_t size, void *useraddr, mblk_t *dp)
172*0Sstevel@tonic-gate {
173*0Sstevel@tonic-gate 	struct copyreq *cp = (struct copyreq *)mp->b_rptr;
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	if (useraddr != NULL)
176*0Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)useraddr;
177*0Sstevel@tonic-gate 	else {
178*0Sstevel@tonic-gate 		ASSERT(DB_TYPE(mp) == M_IOCTL);
179*0Sstevel@tonic-gate 		ASSERT(mp->b_cont != NULL);
180*0Sstevel@tonic-gate 		ASSERT(((struct iocblk *)mp->b_rptr)->ioc_count == TRANSPARENT);
181*0Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)*(uintptr_t *)mp->b_cont->b_rptr;
182*0Sstevel@tonic-gate 	}
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	cp->cq_flag = 0;
185*0Sstevel@tonic-gate 	cp->cq_size = size;
186*0Sstevel@tonic-gate 	cp->cq_private = (mblk_t *)private;
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	DB_TYPE(mp) = M_COPYOUT;
189*0Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	if (dp != NULL) {
192*0Sstevel@tonic-gate 		if (mp->b_cont != NULL)
193*0Sstevel@tonic-gate 			freemsg(mp->b_cont);
194*0Sstevel@tonic-gate 		mp->b_cont = dp;
195*0Sstevel@tonic-gate 		mp->b_cont->b_wptr = mp->b_cont->b_rptr + size;
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate }
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate int
200*0Sstevel@tonic-gate miocpullup(mblk_t *iocmp, size_t size)
201*0Sstevel@tonic-gate {
202*0Sstevel@tonic-gate 	struct iocblk	*iocp = (struct iocblk *)iocmp->b_rptr;
203*0Sstevel@tonic-gate 	mblk_t		*datamp = iocmp->b_cont;
204*0Sstevel@tonic-gate 	mblk_t		*newdatamp;
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 	/*
207*0Sstevel@tonic-gate 	 * We'd like to be sure that DB_TYPE(iocmp) == M_IOCTL, but some
208*0Sstevel@tonic-gate 	 * nitwit routines like ttycommon_ioctl() always reset the type of
209*0Sstevel@tonic-gate 	 * legitimate M_IOCTL messages to M_IOCACK as a "courtesy" to the
210*0Sstevel@tonic-gate 	 * caller, even when the routine does not understand the M_IOCTL.
211*0Sstevel@tonic-gate 	 * The ttycommon_ioctl() routine does us the additional favor of
212*0Sstevel@tonic-gate 	 * clearing ioc_count, so we cannot rely on it having a correct
213*0Sstevel@tonic-gate 	 * size either (blissfully, ttycommon_ioctl() does not screw with
214*0Sstevel@tonic-gate 	 * TRANSPARENT messages, so we can still sanity check for that).
215*0Sstevel@tonic-gate 	 */
216*0Sstevel@tonic-gate 	ASSERT(MBLKL(iocmp) == sizeof (struct iocblk));
217*0Sstevel@tonic-gate 	if (MBLKL(iocmp) != sizeof (struct iocblk)) {
218*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "miocpullup: passed mblk_t %p is not an ioctl"
219*0Sstevel@tonic-gate 		    " mblk_t", (void *)iocmp);
220*0Sstevel@tonic-gate 		return (EINVAL);
221*0Sstevel@tonic-gate 	}
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	if (iocp->ioc_count == TRANSPARENT)
224*0Sstevel@tonic-gate 		return (EINVAL);
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	if (size == 0)
227*0Sstevel@tonic-gate 		return (0);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	if (datamp == NULL)
230*0Sstevel@tonic-gate 		return (EINVAL);
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	if (MBLKL(datamp) >= size)
233*0Sstevel@tonic-gate 		return (0);
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	newdatamp = msgpullup(datamp, size);
236*0Sstevel@tonic-gate 	if (newdatamp == NULL) {
237*0Sstevel@tonic-gate 		if (msgdsize(datamp) < size)
238*0Sstevel@tonic-gate 			return (EINVAL);
239*0Sstevel@tonic-gate 		return (ENOMEM);
240*0Sstevel@tonic-gate 	}
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	iocmp->b_cont = newdatamp;
243*0Sstevel@tonic-gate 	freemsg(datamp);
244*0Sstevel@tonic-gate 	return (0);
245*0Sstevel@tonic-gate }
246