Home | History | Annotate | Download | only in io
      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