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