xref: /titanic_52/usr/src/uts/common/io/strredirm.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Redirection STREAMS module.
31  *
32  * This module is intended for use in conjunction with instantiations of the
33  * redirection driver.  Its purpose in life is to detect when the stream that
34  * it's pushed on is closed, thereupon calling back into the redirection
35  * driver so that the driver can cancel redirection to the stream.
36  */
37 
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/errno.h>
41 #include <sys/kmem.h>
42 
43 #include <sys/stream.h>
44 #include <sys/stropts.h>
45 
46 #include <sys/debug.h>
47 
48 #include <sys/strredir.h>
49 #include <sys/thread.h>
50 
51 #include <sys/conf.h>
52 #include <sys/ddi.h>
53 #include <sys/sunddi.h>
54 #include <sys/modctl.h>
55 
56 /*
57  * Forward declarations for private routines.
58  */
59 static int	wcmopen(queue_t	*, dev_t *, int, int, cred_t *);
60 static int	wcmclose(queue_t *, int, cred_t *);
61 static int	wcmput(queue_t *, mblk_t *);
62 
63 static struct module_info	wcminfo = {
64 	_STRREDIR_MODID,
65 	"redirmod",
66 	0,
67 	INFPSZ,
68 	5120,
69 	1024
70 };
71 
72 static struct qinit	wcmrinit = {
73 	wcmput,		/* put */
74 	NULL,		/* service */
75 	wcmopen,	/* open */
76 	wcmclose,	/* close */
77 	NULL,		/* qadmin */
78 	&wcminfo,
79 	NULL		/* mstat */
80 };
81 
82 static struct qinit	wcmwinit = {
83 	wcmput,		/* put */
84 	NULL,		/* service */
85 	wcmopen,	/* open */
86 	wcmclose,	/* close */
87 	NULL,		/* qadmin */
88 	&wcminfo,
89 	NULL		/* mstat */
90 };
91 
92 static struct streamtab	redirminfo = {
93 	&wcmrinit,
94 	&wcmwinit,
95 	NULL,
96 	NULL
97 };
98 
99 static struct fmodsw fsw = {
100 	"redirmod",
101 	&redirminfo,
102 	D_NEW | D_MP
103 };
104 
105 static struct modlstrmod modlstrmod = {
106 	&mod_strmodops,
107 	"redirection module",
108 	&fsw
109 };
110 
111 static struct modlinkage modlinkage = {
112 	MODREV_1, &modlstrmod, NULL
113 };
114 
115 int
116 _init()
117 {
118 	return (mod_install(&modlinkage));
119 }
120 
121 int
122 _fini()
123 {
124 	return (EBUSY);
125 }
126 
127 int
128 _info(struct modinfo *modinfop)
129 {
130 	return (mod_info(&modlinkage, modinfop));
131 }
132 
133 /* ARGSUSED */
134 static int
135 wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
136 {
137 	extern kthread_t	*iwscn_thread;
138 	extern wcm_data_t	*iwscn_wcm_data;
139 
140 	if (sflag != MODOPEN)
141 		return (EINVAL);
142 
143 	/*
144 	 * There's nothing to do if we're already open.
145 	 */
146 	if (q->q_ptr == NULL) {
147 		/*
148 		 * Attach the per open instance state structure.
149 		 * Its fields were * initialized elsewhere (from the
150 		 * SRIOCSREDIR case of of the redirection driver's ioctl
151 		 * routine).
152 		 * To prevent other threads from getting this, check thread_id.
153 		 */
154 		if (curthread != iwscn_thread)
155 			return (EINVAL);
156 		q->q_ptr = WR(q)->q_ptr = iwscn_wcm_data;
157 	}
158 	qprocson(q);
159 	return (0);
160 }
161 
162 /* ARGSUSED */
163 static int
164 wcmclose(queue_t *q, int flag, cred_t *cred)
165 {
166 	wcm_data_t	*mdp = (wcm_data_t *)q->q_ptr;
167 
168 	qprocsoff(q);
169 	srpop(mdp, flag, cred);
170 	WR(q)->q_ptr = q->q_ptr = NULL;
171 	kmem_free(mdp, sizeof (*mdp));
172 
173 	return (0);
174 }
175 
176 /*
177  * This module's only purpose in life is to intercept closes on the stream
178  * it's pushed on.  It passes all messages on unchanged, in both directions.
179  */
180 static int
181 wcmput(queue_t *q, mblk_t *mp)
182 {
183 	putnext(q, mp);
184 	return (0);
185 }
186