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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2006 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  * It passes all messages on unchanged, in both directions.
  37  */
  38 
  39 #include <sys/types.h>
  40 #include <sys/param.h>
  41 #include <sys/errno.h>
  42 #include <sys/stream.h>
  43 #include <sys/stropts.h>
  44 #include <sys/debug.h>
  45 #include <sys/strredir.h>
  46 #include <sys/strsubr.h>
  47 #include <sys/strsun.h>
  48 #include <sys/conf.h>
  49 #include <sys/ddi.h>
  50 #include <sys/sunddi.h>
  51 #include <sys/modctl.h>
  52 
  53 /*
  54  * Forward declarations for private routines.
  55  */
  56 static int      wcmopen(queue_t *, dev_t *, int, int, cred_t *);
  57 static int      wcmclose(queue_t *, int, cred_t *);
  58 static int      wcmrput(queue_t *, mblk_t *);
  59 
  60 static struct module_info       wcminfo = {
  61         STRREDIR_MODID,
  62         STRREDIR_MOD,
  63         0,
  64         INFPSZ,
  65         5120,
  66         1024
  67 };
  68 
  69 static struct qinit     wcmrinit = {
  70         wcmrput,                /* put */
  71         NULL,                   /* service */
  72         wcmopen,                /* open */
  73         wcmclose,               /* close */
  74         NULL,                   /* qadmin */
  75         &wcminfo,
  76         NULL                    /* mstat */
  77 };
  78 
  79 static struct qinit     wcmwinit = {
  80         (int (*)())putnext,     /* put */
  81         NULL,                   /* service */
  82         wcmopen,                /* open */
  83         wcmclose,               /* close */
  84         NULL,                   /* qadmin */
  85         &wcminfo,
  86         NULL                    /* mstat */
  87 };
  88 
  89 static struct streamtab redirminfo = {
  90         &wcmrinit,
  91         &wcmwinit,
  92         NULL,
  93         NULL
  94 };
  95 
  96 static struct fmodsw fsw = {
  97         "redirmod",
  98         &redirminfo,
  99         D_MP
 100 };
 101 
 102 static struct modlstrmod modlstrmod = {
 103         &mod_strmodops,
 104         "redirection module",
 105         &fsw
 106 };
 107 
 108 static struct modlinkage modlinkage = {
 109         MODREV_1, &modlstrmod, NULL
 110 };
 111 
 112 int
 113 _init()
 114 {
 115         return (mod_install(&modlinkage));
 116 }
 117 
 118 int
 119 _fini()
 120 {
 121         return (EBUSY);
 122 }
 123 
 124 int
 125 _info(struct modinfo *modinfop)
 126 {
 127         return (mod_info(&modlinkage, modinfop));
 128 }
 129 
 130 /* ARGSUSED */
 131 static int
 132 wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
 133 {
 134         if (sflag != MODOPEN)
 135                 return (EINVAL);
 136         qprocson(q);
 137         return (0);
 138 }
 139 
 140 /* ARGSUSED */
 141 static int
 142 wcmclose(queue_t *q, int flag, cred_t *cred)
 143 {
 144         qprocsoff(q);
 145         srpop(q->q_stream->sd_vnode, B_TRUE);
 146         return (0);
 147 }
 148 
 149 /*
 150  * Upstream messages are passed unchanged.
 151  * If a hangup occurs the target is no longer usable, so deprecate it.
 152  */
 153 static int
 154 wcmrput(queue_t *q, mblk_t *mp)
 155 {
 156         if (DB_TYPE(mp) == M_HANGUP)
 157                 /* Don't block waiting for outstanding operations to complete */
 158                 srpop(q->q_stream->sd_vnode, B_FALSE);
 159         putnext(q, mp);
 160         return (0);
 161 }