xref: /titanic_44/usr/src/uts/common/io/strsun.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Solaris DDI STREAMS utility routines (PSARC/2003/648).
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * Please see the appropriate section 9F manpage for documentation.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate void
44*7c478bd9Sstevel@tonic-gate merror(queue_t *wq, mblk_t *mp, int error)
45*7c478bd9Sstevel@tonic-gate {
46*7c478bd9Sstevel@tonic-gate 	if ((mp = mexchange(wq, mp, 1, M_ERROR, -1)) == NULL)
47*7c478bd9Sstevel@tonic-gate 		return;
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate 	*mp->b_rptr = (uchar_t)error;
50*7c478bd9Sstevel@tonic-gate 	qreply(wq, mp);
51*7c478bd9Sstevel@tonic-gate }
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate void
54*7c478bd9Sstevel@tonic-gate mioc2ack(mblk_t *mp, mblk_t *dp, size_t count, int rval)
55*7c478bd9Sstevel@tonic-gate {
56*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
57*7c478bd9Sstevel@tonic-gate 	mblk_t *odp = mp->b_cont;  	/* allows freemsg() to be a tail call */
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate 	DB_TYPE(mp) = M_IOCACK;
60*7c478bd9Sstevel@tonic-gate 	iocp->ioc_count = count;
61*7c478bd9Sstevel@tonic-gate 	iocp->ioc_error = 0;
62*7c478bd9Sstevel@tonic-gate 	iocp->ioc_rval = rval;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	mp->b_cont = dp;
65*7c478bd9Sstevel@tonic-gate 	if (dp != NULL)
66*7c478bd9Sstevel@tonic-gate 		dp->b_wptr = dp->b_rptr + count;
67*7c478bd9Sstevel@tonic-gate 	freemsg(odp);
68*7c478bd9Sstevel@tonic-gate }
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate void
71*7c478bd9Sstevel@tonic-gate miocack(queue_t *wq, mblk_t *mp, int count, int rval)
72*7c478bd9Sstevel@tonic-gate {
73*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 	DB_TYPE(mp) = M_IOCACK;
76*7c478bd9Sstevel@tonic-gate 	iocp->ioc_count = count;
77*7c478bd9Sstevel@tonic-gate 	iocp->ioc_error = 0;
78*7c478bd9Sstevel@tonic-gate 	iocp->ioc_rval = rval;
79*7c478bd9Sstevel@tonic-gate 	qreply(wq, mp);
80*7c478bd9Sstevel@tonic-gate }
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate void
83*7c478bd9Sstevel@tonic-gate miocnak(queue_t *wq, mblk_t *mp, int count, int error)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	DB_TYPE(mp) = M_IOCNAK;
88*7c478bd9Sstevel@tonic-gate 	iocp->ioc_count = count;
89*7c478bd9Sstevel@tonic-gate 	iocp->ioc_error = error;
90*7c478bd9Sstevel@tonic-gate 	qreply(wq, mp);
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate mblk_t *
94*7c478bd9Sstevel@tonic-gate mexchange(queue_t *wq, mblk_t *mp, size_t size, uchar_t type, int32_t primtype)
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate 	if (mp == NULL || MBLKSIZE(mp) < size || DB_REF(mp) > 1) {
97*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
98*7c478bd9Sstevel@tonic-gate 		if ((mp = allocb(size, BPRI_LO)) == NULL) {
99*7c478bd9Sstevel@tonic-gate 			if (wq != NULL) {
100*7c478bd9Sstevel@tonic-gate 				if ((mp = allocb(1, BPRI_HI)) != NULL)
101*7c478bd9Sstevel@tonic-gate 					merror(wq, mp, ENOSR);
102*7c478bd9Sstevel@tonic-gate 			}
103*7c478bd9Sstevel@tonic-gate 			return (NULL);
104*7c478bd9Sstevel@tonic-gate 		}
105*7c478bd9Sstevel@tonic-gate 	}
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	DB_TYPE(mp) = type;
108*7c478bd9Sstevel@tonic-gate 	mp->b_rptr = DB_BASE(mp);
109*7c478bd9Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + size;
110*7c478bd9Sstevel@tonic-gate 	if (primtype >= 0)
111*7c478bd9Sstevel@tonic-gate 		*(int32_t *)mp->b_rptr = primtype;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	return (mp);
114*7c478bd9Sstevel@tonic-gate }
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate size_t
117*7c478bd9Sstevel@tonic-gate msgsize(mblk_t *mp)
118*7c478bd9Sstevel@tonic-gate {
119*7c478bd9Sstevel@tonic-gate 	size_t	n = 0;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	for (; mp != NULL; mp = mp->b_cont)
122*7c478bd9Sstevel@tonic-gate 		n += MBLKL(mp);
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	return (n);
125*7c478bd9Sstevel@tonic-gate }
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate void
128*7c478bd9Sstevel@tonic-gate mcopymsg(mblk_t *mp, void *bufp)
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	caddr_t	dest = bufp;
131*7c478bd9Sstevel@tonic-gate 	mblk_t	*bp;
132*7c478bd9Sstevel@tonic-gate 	size_t	n;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
135*7c478bd9Sstevel@tonic-gate 		n = MBLKL(bp);
136*7c478bd9Sstevel@tonic-gate 		bcopy(bp->b_rptr, dest, n);
137*7c478bd9Sstevel@tonic-gate 		dest += n;
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 	freemsg(mp);
141*7c478bd9Sstevel@tonic-gate }
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate void
144*7c478bd9Sstevel@tonic-gate mcopyin(mblk_t *mp, void *private, size_t size, void *useraddr)
145*7c478bd9Sstevel@tonic-gate {
146*7c478bd9Sstevel@tonic-gate 	struct copyreq *cp = (struct copyreq *)mp->b_rptr;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if (useraddr != NULL) {
149*7c478bd9Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)useraddr;
150*7c478bd9Sstevel@tonic-gate 	} else {
151*7c478bd9Sstevel@tonic-gate 		ASSERT(DB_TYPE(mp) == M_IOCTL);
152*7c478bd9Sstevel@tonic-gate 		ASSERT(mp->b_cont != NULL);
153*7c478bd9Sstevel@tonic-gate 		ASSERT(((struct iocblk *)mp->b_rptr)->ioc_count == TRANSPARENT);
154*7c478bd9Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)*(uintptr_t *)mp->b_cont->b_rptr;
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	cp->cq_flag = 0;
158*7c478bd9Sstevel@tonic-gate 	cp->cq_size = size;
159*7c478bd9Sstevel@tonic-gate 	cp->cq_private = (mblk_t *)private;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	DB_TYPE(mp) = M_COPYIN;
162*7c478bd9Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	if (mp->b_cont != NULL) {
165*7c478bd9Sstevel@tonic-gate 		freemsg(mp->b_cont);
166*7c478bd9Sstevel@tonic-gate 		mp->b_cont = NULL;
167*7c478bd9Sstevel@tonic-gate 	}
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate void
171*7c478bd9Sstevel@tonic-gate mcopyout(mblk_t *mp, void *private, size_t size, void *useraddr, mblk_t *dp)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	struct copyreq *cp = (struct copyreq *)mp->b_rptr;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	if (useraddr != NULL)
176*7c478bd9Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)useraddr;
177*7c478bd9Sstevel@tonic-gate 	else {
178*7c478bd9Sstevel@tonic-gate 		ASSERT(DB_TYPE(mp) == M_IOCTL);
179*7c478bd9Sstevel@tonic-gate 		ASSERT(mp->b_cont != NULL);
180*7c478bd9Sstevel@tonic-gate 		ASSERT(((struct iocblk *)mp->b_rptr)->ioc_count == TRANSPARENT);
181*7c478bd9Sstevel@tonic-gate 		cp->cq_addr = (caddr_t)*(uintptr_t *)mp->b_cont->b_rptr;
182*7c478bd9Sstevel@tonic-gate 	}
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	cp->cq_flag = 0;
185*7c478bd9Sstevel@tonic-gate 	cp->cq_size = size;
186*7c478bd9Sstevel@tonic-gate 	cp->cq_private = (mblk_t *)private;
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 	DB_TYPE(mp) = M_COPYOUT;
189*7c478bd9Sstevel@tonic-gate 	mp->b_wptr = mp->b_rptr + sizeof (struct copyreq);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	if (dp != NULL) {
192*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
193*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
194*7c478bd9Sstevel@tonic-gate 		mp->b_cont = dp;
195*7c478bd9Sstevel@tonic-gate 		mp->b_cont->b_wptr = mp->b_cont->b_rptr + size;
196*7c478bd9Sstevel@tonic-gate 	}
197*7c478bd9Sstevel@tonic-gate }
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate int
200*7c478bd9Sstevel@tonic-gate miocpullup(mblk_t *iocmp, size_t size)
201*7c478bd9Sstevel@tonic-gate {
202*7c478bd9Sstevel@tonic-gate 	struct iocblk	*iocp = (struct iocblk *)iocmp->b_rptr;
203*7c478bd9Sstevel@tonic-gate 	mblk_t		*datamp = iocmp->b_cont;
204*7c478bd9Sstevel@tonic-gate 	mblk_t		*newdatamp;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	/*
207*7c478bd9Sstevel@tonic-gate 	 * We'd like to be sure that DB_TYPE(iocmp) == M_IOCTL, but some
208*7c478bd9Sstevel@tonic-gate 	 * nitwit routines like ttycommon_ioctl() always reset the type of
209*7c478bd9Sstevel@tonic-gate 	 * legitimate M_IOCTL messages to M_IOCACK as a "courtesy" to the
210*7c478bd9Sstevel@tonic-gate 	 * caller, even when the routine does not understand the M_IOCTL.
211*7c478bd9Sstevel@tonic-gate 	 * The ttycommon_ioctl() routine does us the additional favor of
212*7c478bd9Sstevel@tonic-gate 	 * clearing ioc_count, so we cannot rely on it having a correct
213*7c478bd9Sstevel@tonic-gate 	 * size either (blissfully, ttycommon_ioctl() does not screw with
214*7c478bd9Sstevel@tonic-gate 	 * TRANSPARENT messages, so we can still sanity check for that).
215*7c478bd9Sstevel@tonic-gate 	 */
216*7c478bd9Sstevel@tonic-gate 	ASSERT(MBLKL(iocmp) == sizeof (struct iocblk));
217*7c478bd9Sstevel@tonic-gate 	if (MBLKL(iocmp) != sizeof (struct iocblk)) {
218*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "miocpullup: passed mblk_t %p is not an ioctl"
219*7c478bd9Sstevel@tonic-gate 		    " mblk_t", (void *)iocmp);
220*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	if (iocp->ioc_count == TRANSPARENT)
224*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	if (size == 0)
227*7c478bd9Sstevel@tonic-gate 		return (0);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	if (datamp == NULL)
230*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 	if (MBLKL(datamp) >= size)
233*7c478bd9Sstevel@tonic-gate 		return (0);
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	newdatamp = msgpullup(datamp, size);
236*7c478bd9Sstevel@tonic-gate 	if (newdatamp == NULL) {
237*7c478bd9Sstevel@tonic-gate 		if (msgdsize(datamp) < size)
238*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
239*7c478bd9Sstevel@tonic-gate 		return (ENOMEM);
240*7c478bd9Sstevel@tonic-gate 	}
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	iocmp->b_cont = newdatamp;
243*7c478bd9Sstevel@tonic-gate 	freemsg(datamp);
244*7c478bd9Sstevel@tonic-gate 	return (0);
245*7c478bd9Sstevel@tonic-gate }
246