blob: 5acc22879fa4a96a51c802c9d1d419a79b35a4fb [file] [log] [blame]
stevel@tonic-gate7c478bd2005-06-14 00:00:00 -07001/*
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
60extern struct streamtab conninfo;
61
62static struct fmodsw fsw = {
63 "connld",
64 &conninfo,
65 D_NEW | D_MP
66};
67
68/*
69 * Module linkage information for the kernel.
70 */
71
72static struct modlstrmod modlstrmod = {
73 &mod_strmodops, "Streams-based pipes", &fsw
74};
75
76static struct modlinkage modlinkage = {
77 MODREV_1, (void *)&modlstrmod, NULL
78};
79
80int
81_init()
82{
83 return (mod_install(&modlinkage));
84}
85
86int
87_fini()
88{
89 return (mod_remove(&modlinkage));
90}
91
92int
93_info(struct modinfo *modinfop)
94{
95 return (mod_info(&modlinkage, modinfop));
96}
97
98/*
99 * Define local and external routines.
100 */
101int connopen(queue_t *, dev_t *, int, int, cred_t *);
102int connclose(queue_t *, int, cred_t *);
103int connput(queue_t *, mblk_t *);
104
105/*
106 * Define STREAMS header information.
107 */
108static struct module_info conn_info = {
109 1003,
110 "connld",
111 0,
112 INFPSZ,
113 STRHIGH,
114 STRLOW
115};
116static struct qinit connrinit = {
117 connput,
118 NULL,
119 connopen,
120 connclose,
121 NULL,
122 &conn_info,
123 NULL
124};
125static struct qinit connwinit = {
126 connput,
127 NULL,
128 NULL,
129 NULL,
130 NULL,
131 &conn_info,
132 NULL
133};
134struct 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*/
149int
150connopen(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 }
190out:
191 VN_RELE(streamvp);
192 return (error);
193}
194
195/*ARGSUSED*/
196int
197connclose(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 */
217int
218connput(queue_t *q, mblk_t *bp)
219{
220 putnext(q, bp);
221 return (0);
222}