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 }