xref: /illumos-gate/usr/src/uts/common/io/connld.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4 1.8	*/
32 
33 /*
34  * This module establishes a unique connection on
35  * a STREAMS-based pipe.
36  */
37 #include <sys/types.h>
38 #include <sys/sysmacros.h>
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/errno.h>
42 #include <sys/signal.h>
43 #include <sys/user.h>
44 #include <sys/fstyp.h>
45 #include <sys/stropts.h>
46 #include <sys/stream.h>
47 #include <sys/strsubr.h>
48 #include <sys/vnode.h>
49 #include <sys/file.h>
50 #include <sys/fs/fifonode.h>
51 #include <sys/debug.h>
52 #include <sys/ddi.h>
53 
54 /*
55  * This is the loadable module wrapper.
56  */
57 #include <sys/conf.h>
58 #include <sys/modctl.h>
59 
60 extern struct streamtab conninfo;
61 
62 static struct fmodsw fsw = {
63 	"connld",
64 	&conninfo,
65 	D_NEW | D_MP
66 };
67 
68 /*
69  * Module linkage information for the kernel.
70  */
71 
72 static struct modlstrmod modlstrmod = {
73 	&mod_strmodops, "Streams-based pipes", &fsw
74 };
75 
76 static struct modlinkage modlinkage = {
77 	MODREV_1, (void *)&modlstrmod, NULL
78 };
79 
80 int
81 _init()
82 {
83 	return (mod_install(&modlinkage));
84 }
85 
86 int
87 _fini()
88 {
89 	return (mod_remove(&modlinkage));
90 }
91 
92 int
93 _info(struct modinfo *modinfop)
94 {
95 	return (mod_info(&modlinkage, modinfop));
96 }
97 
98 /*
99  * Define local and external routines.
100  */
101 int connopen(queue_t *, dev_t *, int, int, cred_t *);
102 int connclose(queue_t *, int, cred_t *);
103 int connput(queue_t *, mblk_t *);
104 
105 /*
106  * Define STREAMS header information.
107  */
108 static struct module_info conn_info = {
109 	1003,
110 	"connld",
111 	0,
112 	INFPSZ,
113 	STRHIGH,
114 	STRLOW
115 };
116 static struct qinit connrinit = {
117 	connput,
118 	NULL,
119 	connopen,
120 	connclose,
121 	NULL,
122 	&conn_info,
123 	NULL
124 };
125 static struct qinit connwinit = {
126 	connput,
127 	NULL,
128 	NULL,
129 	NULL,
130 	NULL,
131 	&conn_info,
132 	NULL
133 };
134 struct streamtab conninfo = {
135 	&connrinit,
136 	&connwinit
137 };
138 
139 /*
140  * For each invocation of connopen(), create a new pipe. One end of the pipe
141  * is sent to the process on the other end of this STREAM. The vnode for
142  * the other end is returned to the open() system call as the vnode for
143  * the opened object.
144  *
145  * On the first invocation of connopen(), a flag is set and the routine
146  * returns 0, since the first open corresponds to the pushing of the module.
147  */
148 /*ARGSUSED*/
149 int
150 connopen(queue_t *rqp, dev_t *devp, int flag, int sflag, cred_t *crp)
151 {
152 	int error = 0;
153 	vnode_t *streamvp;
154 	fifonode_t *streamfnp;
155 
156 	if ((streamvp = strq2vp(rqp)) == NULL) {
157 		return (EINVAL);
158 	}
159 
160 	/*
161 	 * CONNLD is only allowed to be pushed onto a "pipe" that has both
162 	 * of its ends open.
163 	 */
164 	if (streamvp->v_type != VFIFO) {
165 		error = EINVAL;
166 		goto out;
167 	}
168 
169 	streamfnp = VTOF(streamvp);
170 
171 	if (!(streamfnp->fn_flag & ISPIPE) ||
172 	    streamfnp->fn_dest->fn_open == 0) {
173 		error = EPIPE;
174 		goto out;
175 	}
176 
177 	/*
178 	 * If this is the first time CONNLD was opened while on this stream,
179 	 * it is being pushed. Therefore, set a flag and return 0.
180 	 */
181 	if (rqp->q_ptr == 0) {
182 		if (streamfnp->fn_flag & FIFOCONNLD) {
183 			error = ENXIO;
184 			goto out;
185 		}
186 		rqp->q_ptr = (caddr_t)1;
187 		streamfnp->fn_flag |= FIFOCONNLD;
188 		qprocson(rqp);
189 	}
190 out:
191 	VN_RELE(streamvp);
192 	return (error);
193 }
194 
195 /*ARGSUSED*/
196 int
197 connclose(queue_t *q, int cflag, cred_t *crp)
198 {
199 	vnode_t *streamvp;
200 	fifonode_t *streamfnp;
201 
202 	qprocsoff(q);
203 	streamvp = strq2vp(q);
204 
205 	ASSERT(streamvp != NULL);
206 	ASSERT(streamvp->v_type == VFIFO);
207 
208 	streamfnp = VTOF(streamvp);
209 	streamfnp->fn_flag &= ~FIFOCONNLD;
210 	VN_RELE(streamvp);
211 	return (0);
212 }
213 
214 /*
215  * Use same put procedure for write and read queues.
216  */
217 int
218 connput(queue_t *q, mblk_t *bp)
219 {
220 	putnext(q, bp);
221 	return (0);
222 }
223