Home | History | Annotate | Download | only in sppptun
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * sppptun_mod.c - modload support for PPP multiplexing tunnel driver.
     29  */
     30 
     31 #include <sys/types.h>
     32 #include <sys/param.h>
     33 #include <sys/stat.h>
     34 #include <sys/systm.h>
     35 #include <sys/socket.h>
     36 #include <sys/stream.h>
     37 #include <sys/stropts.h>
     38 #include <sys/time.h>
     39 #include <sys/conf.h>
     40 #include <sys/kstat.h>
     41 #include <sys/sunddi.h>
     42 #include <net/sppptun.h>
     43 #include <netinet/in.h>
     44 
     45 #include "sppptun_mod.h"
     46 
     47 /*
     48  * Descriptions for flags values in cb_flags field:
     49  *
     50  * D_MTQPAIR:
     51  *    An inner perimeter that spans the queue pair.
     52  * D_MTOUTPERIM:
     53  *    An outer perimeter that spans over all queues in the module.
     54  * D_MTOCEXCL:
     55  *    Open & close procedures are entered exclusively at outer perimeter.
     56  * D_MTPUTSHARED:
     57  *    Entry to put procedures are done with SHARED (reader) acess
     58  *    and not EXCLUSIVE (writer) access.
     59  *
     60  * Therefore:
     61  *
     62  * 1. Open and close procedures are entered with EXCLUSIVE (writer)
     63  *    access at the inner perimeter, and with EXCLUSIVE (writer) access at
     64  *    the outer perimeter.
     65  *
     66  * 2. Put procedures are entered with SHARED (reader) access at the inner
     67  *    perimeter, and with SHARED (reader) access at the outer perimeter.
     68  *
     69  * 3. Service procedures are entered with EXCLUSIVE (writer) access at
     70  *    the inner perimeter, and with SHARED (reader) access at the
     71  *    outer perimeter.
     72  *
     73  * Do not attempt to modify these flags unless the entire corresponding
     74  * driver code is changed to accomodate the newly represented MT-STREAMS
     75  * flags. Doing so without making proper modifications to the driver code
     76  * will severely impact the intended driver behavior, and thus may affect
     77  * the system's stability and performance.
     78  */
     79 
     80 static int	tun_attach(dev_info_t *, ddi_attach_cmd_t);
     81 static int	tun_detach(dev_info_t *, ddi_detach_cmd_t);
     82 static int	tun_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
     83 
     84 static dev_info_t *tun_dev_info;
     85 
     86 DDI_DEFINE_STREAM_OPS(sppptun_ops,			\
     87 	nulldev, nulldev,				\
     88 	tun_attach, tun_detach, nodev, tun_info,	\
     89 	D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED, \
     90 	&sppptun_tab, ddi_quiesce_not_supported);
     91 
     92 /*
     93  * This is the loadable module wrapper.
     94  */
     95 #include <sys/modctl.h>
     96 
     97 /*
     98  * Module linkage information for the kernel.
     99  */
    100 static struct fmodsw sppptun_fmodsw = {
    101 	PPP_TUN_NAME,
    102 	&sppptun_tab,
    103 	D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED
    104 };
    105 
    106 static struct modldrv modldrv = {
    107 	&mod_driverops,
    108 	(char *)sppptun_driver_description,
    109 	&sppptun_ops
    110 };
    111 
    112 static struct modlstrmod modlstrmod = {
    113 	&mod_strmodops,
    114 	(char *)sppptun_module_description,
    115 	&sppptun_fmodsw
    116 };
    117 
    118 static struct modlinkage modlinkage = {
    119 	MODREV_1,
    120 	(void *)&modlstrmod,
    121 	(void *)&modldrv,
    122 	NULL
    123 };
    124 
    125 int
    126 _init(void)
    127 {
    128 	int retv;
    129 
    130 	sppptun_init();
    131 	if ((retv = mod_install(&modlinkage)) == 0)
    132 		sppptun_tcl_init();
    133 	return (retv);
    134 }
    135 
    136 int
    137 _fini(void)
    138 {
    139 	int retv;
    140 
    141 	if ((retv = sppptun_tcl_fintest()) != 0)
    142 		return (retv);
    143 	retv = mod_remove(&modlinkage);
    144 	if (retv != 0)
    145 		return (retv);
    146 	sppptun_tcl_fini();
    147 	return (0);
    148 }
    149 
    150 int
    151 _info(struct modinfo *modinfop)
    152 {
    153 	return (mod_info(&modlinkage, modinfop));
    154 }
    155 
    156 /*
    157  * tun_attach()
    158  *
    159  * Description:
    160  *    Attach a PPP tunnel driver to the system.
    161  */
    162 static int
    163 tun_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
    164 {
    165 	if (cmd != DDI_ATTACH)
    166 		return (DDI_FAILURE);
    167 	if (ddi_create_minor_node(dip, PPP_TUN_NAME, S_IFCHR, 0, DDI_PSEUDO,
    168 	    CLONE_DEV) == DDI_FAILURE) {
    169 		ddi_remove_minor_node(dip, NULL);
    170 		return (DDI_FAILURE);
    171 	}
    172 	tun_dev_info = dip;
    173 	return (DDI_SUCCESS);
    174 }
    175 
    176 /*
    177  * tun_detach()
    178  *
    179  * Description:
    180  *    Detach an interface to the system.
    181  */
    182 static int
    183 tun_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    184 {
    185 	if (cmd != DDI_DETACH)
    186 		return (DDI_FAILURE);
    187 	tun_dev_info = NULL;
    188 	ddi_remove_minor_node(dip, NULL);
    189 	return (DDI_SUCCESS);
    190 }
    191 
    192 /*
    193  * tun_info()
    194  *
    195  * Description:
    196  *    Translate "dev_t" to a pointer to the associated "dev_info_t".
    197  */
    198 /* ARGSUSED */
    199 static int
    200 tun_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
    201 	void **result)
    202 {
    203 	int	rc;
    204 
    205 	switch (infocmd) {
    206 	case DDI_INFO_DEVT2DEVINFO:
    207 		if (tun_dev_info == NULL) {
    208 			rc = DDI_FAILURE;
    209 		} else {
    210 			*result = (void *)tun_dev_info;
    211 			rc = DDI_SUCCESS;
    212 		}
    213 		break;
    214 	case DDI_INFO_DEVT2INSTANCE:
    215 		*result = NULL;
    216 		rc = DDI_SUCCESS;
    217 		break;
    218 	default:
    219 		rc = DDI_FAILURE;
    220 		break;
    221 	}
    222 	return (rc);
    223 }
    224