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