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