/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * Redirection STREAMS module. * * This module is intended for use in conjunction with instantiations of the * redirection driver. Its purpose in life is to detect when the stream that * it's pushed on is closed, thereupon calling back into the redirection * driver so that the driver can cancel redirection to the stream. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Forward declarations for private routines. */ static int wcmopen(queue_t *, dev_t *, int, int, cred_t *); static int wcmclose(queue_t *, int, cred_t *); static int wcmput(queue_t *, mblk_t *); static struct module_info wcminfo = { _STRREDIR_MODID, "redirmod", 0, INFPSZ, 5120, 1024 }; static struct qinit wcmrinit = { wcmput, /* put */ NULL, /* service */ wcmopen, /* open */ wcmclose, /* close */ NULL, /* qadmin */ &wcminfo, NULL /* mstat */ }; static struct qinit wcmwinit = { wcmput, /* put */ NULL, /* service */ wcmopen, /* open */ wcmclose, /* close */ NULL, /* qadmin */ &wcminfo, NULL /* mstat */ }; static struct streamtab redirminfo = { &wcmrinit, &wcmwinit, NULL, NULL }; static struct fmodsw fsw = { "redirmod", &redirminfo, D_NEW | D_MP }; static struct modlstrmod modlstrmod = { &mod_strmodops, "redirection module", &fsw }; static struct modlinkage modlinkage = { MODREV_1, &modlstrmod, NULL }; int _init() { return (mod_install(&modlinkage)); } int _fini() { return (EBUSY); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } /* ARGSUSED */ static int wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred) { extern kthread_t *iwscn_thread; extern wcm_data_t *iwscn_wcm_data; if (sflag != MODOPEN) return (EINVAL); /* * There's nothing to do if we're already open. */ if (q->q_ptr == NULL) { /* * Attach the per open instance state structure. * Its fields were * initialized elsewhere (from the * SRIOCSREDIR case of of the redirection driver's ioctl * routine). * To prevent other threads from getting this, check thread_id. */ if (curthread != iwscn_thread) return (EINVAL); q->q_ptr = WR(q)->q_ptr = iwscn_wcm_data; } qprocson(q); return (0); } /* ARGSUSED */ static int wcmclose(queue_t *q, int flag, cred_t *cred) { wcm_data_t *mdp = (wcm_data_t *)q->q_ptr; qprocsoff(q); srpop(mdp, flag, cred); WR(q)->q_ptr = q->q_ptr = NULL; kmem_free(mdp, sizeof (*mdp)); return (0); } /* * This module's only purpose in life is to intercept closes on the stream * it's pushed on. It passes all messages on unchanged, in both directions. */ static int wcmput(queue_t *q, mblk_t *mp) { putnext(q, mp); return (0); }