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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <sys/stream.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/priv_names.h> 32 33 /* 34 * This file contains generic goo needed to hook the STREAMS modules and 35 * drivers that live under uts/common/inet into the DDI. In order to use it, 36 * each module/driver should #define the symbols below (as appropriate) and 37 * then #include this source file; see the other uts/common/inet/<star>ddi.c 38 * files for examples of this in action. 39 * 40 * The symbols that all modules and drivers must define are: 41 * 42 * INET_NAME The name of the module/driver. 43 * 44 * The symbols that all modules must define are: 45 * 46 * INET_MODSTRTAB The name of the `streamtab' structure for this module. 47 * INET_MODDESC The one-line description for this module. 48 * INET_MODMTFLAGS The mt-streams(9F) flags for the module. 49 * 50 * The symbols that all drivers must define are: 51 * 52 * INET_DEVSTRTAB The name of the `streamtab' structure for this driver. 53 * INET_DEVDESC The one-line description for this driver. 54 * INET_DEVMTFLAGS The mt-streams(9F) flags for the driver. 55 * INET_DEVMINOR The minor number of the driver (usually 0). 56 * 57 * Drivers that need to masquerade as IP should set INET_DEVMTFLAGS to 58 * IP_DEVMTFLAGS and set INET_DEVSTRTAB to ipinfo. 59 * 60 * The symbols that all socket modules must define are: 61 * 62 * INET_SOCKDESC The one-line description for this socket module 63 * INET_SOCK_PROTO_CREATE_FUNC The function used to create PCBs 64 * 65 * In addition, socket modules that can be converted to TPI must define: 66 * 67 * INET_SOCK_PROTO_FB_FUNC The function used to fallback to TPI 68 */ 69 70 #if !defined(INET_NAME) 71 #error inetddi.c: INET_NAME is not defined! 72 #elif !defined(INET_DEVDESC) && !defined(INET_MODDESC) && \ 73 !defined(INET_SOCKDESC) 74 #error inetddi.c: at least one of INET_DEVDESC or INET_MODDESC or \ 75 INET_SOCKDESC must be defined! 76 #elif defined(INET_DEVDESC) && !defined(INET_DEVSTRTAB) 77 #error inetddi.c: INET_DEVDESC is defined but INET_DEVSTRTAB is not! 78 #elif defined(INET_DEVDESC) && !defined(INET_DEVMTFLAGS) 79 #error inetddi.c: INET_DEVDESC is defined but INET_DEVMTFLAGS is not! 80 #elif defined(INET_DEVDESC) && !defined(INET_DEVMINOR) 81 #error inetddi.c: INET_DEVDESC is defined but INET_DEVMINOR is not! 82 #elif defined(INET_MODDESC) && !defined(INET_MODSTRTAB) 83 #error inetddi.c: INET_MODDESC is defined but INET_MODSTRTAB is not! 84 #elif defined(INET_MODDESC) && !defined(INET_MODMTFLAGS) 85 #error inetddi.c: INET_MODDESC is defined but INET_MODMTFLAGS is not! 86 #elif defined(INET_SOCKDESC) && !defined(SOCKMOD_VERSION) 87 #error inetddi.c: INET_SOCKDESC is defined but SOCKMOD_VERSION is not! 88 #elif defined(INET_SOCKDESC) && !defined(INET_SOCK_PROTO_CREATE_FUNC) 89 #error inetddi.c: INET_SOCKDESC is defined but INET_SOCK_PROTO_CREATE_FUNC \ 90 is not! 91 #endif 92 93 #ifdef INET_DEVDESC 94 95 extern struct streamtab INET_DEVSTRTAB; 96 97 /* 98 * Drivers that actually want to be IP would set INET_DEVSTRTAB to ipinfo. 99 */ 100 101 static dev_info_t *inet_dev_info; 102 103 #define INET_DEFAULT_PRIV_MODE 0666 104 105 static struct dev_priv { 106 char *driver; 107 int privonly; 108 const char *read_priv; 109 const char *write_priv; 110 } netdev_privs[] = { 111 {"icmp", PRIVONLY_DEV, PRIV_NET_ICMPACCESS, PRIV_NET_ICMPACCESS}, 112 {"icmp6", PRIVONLY_DEV, PRIV_NET_ICMPACCESS, PRIV_NET_ICMPACCESS}, 113 {"ip", PRIVONLY_DEV, PRIV_NET_RAWACCESS, PRIV_NET_RAWACCESS}, 114 {"ip6", PRIVONLY_DEV, PRIV_NET_RAWACCESS, PRIV_NET_RAWACCESS}, 115 {"keysock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 116 {"ipsecah", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 117 {"ipsecesp", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 118 {"spdsock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 119 {NULL, 0, NULL, NULL} 120 }; 121 122 static int 123 inet_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 124 { 125 int i, ndevs; 126 127 if (cmd != DDI_ATTACH) 128 return (DDI_FAILURE); 129 130 inet_dev_info = devi; 131 132 ndevs = sizeof (netdev_privs) / sizeof (struct dev_priv); 133 for (i = 0; i < ndevs; i++) { 134 char *drv = netdev_privs[i].driver; 135 if (drv == NULL || strcmp(drv, ddi_driver_name(devi)) == 0) 136 break; 137 } 138 139 return (ddi_create_priv_minor_node(devi, INET_NAME, S_IFCHR, 140 INET_DEVMINOR, DDI_PSEUDO, netdev_privs[i].privonly, 141 netdev_privs[i].read_priv, netdev_privs[i].write_priv, 142 INET_DEFAULT_PRIV_MODE)); 143 } 144 145 static int 146 inet_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 147 { 148 if (cmd != DDI_DETACH) 149 return (DDI_FAILURE); 150 151 ASSERT(devi == inet_dev_info); 152 153 ddi_remove_minor_node(devi, NULL); 154 return (DDI_SUCCESS); 155 } 156 157 158 /* ARGSUSED */ 159 static int 160 inet_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 161 { 162 int error = DDI_FAILURE; 163 164 switch (cmd) { 165 case DDI_INFO_DEVT2DEVINFO: 166 if (inet_dev_info != NULL) { 167 *result = (void *)inet_dev_info; 168 error = DDI_SUCCESS; 169 } 170 break; 171 172 case DDI_INFO_DEVT2INSTANCE: 173 *result = NULL; 174 error = DDI_SUCCESS; 175 break; 176 177 default: 178 break; 179 } 180 181 return (error); 182 } 183 184 DDI_DEFINE_STREAM_OPS(inet_devops, nulldev, nulldev, inet_attach, inet_detach, 185 nulldev, inet_info, INET_DEVMTFLAGS, &INET_DEVSTRTAB, 186 ddi_quiesce_not_supported); 187 188 static struct modldrv modldrv = { 189 &mod_driverops, 190 INET_DEVDESC, 191 &inet_devops 192 }; 193 194 #endif /* INET_DEVDESC */ 195 196 #ifdef INET_MODDESC 197 extern struct streamtab INET_MODSTRTAB; 198 199 static struct fmodsw fsw = { 200 INET_NAME, 201 &INET_MODSTRTAB, 202 INET_MODMTFLAGS 203 }; 204 205 static struct modlstrmod modlstrmod = { 206 &mod_strmodops, 207 INET_MODDESC, 208 &fsw 209 }; 210 211 #endif /* INET_MODDESC */ 212 213 #ifdef INET_SOCKDESC 214 215 #ifdef INET_SOCK_PROTO_FB_FUNC 216 static __smod_priv_t smodpriv = { 217 NULL, 218 NULL, 219 INET_SOCK_PROTO_FB_FUNC 220 }; 221 #endif /* INET_SOCK_PROTO_FB_FUNC */ 222 223 static struct smod_reg_s smodreg = { 224 SOCKMOD_VERSION, 225 INET_NAME, 226 SOCK_UC_VERSION, 227 SOCK_DC_VERSION, 228 INET_SOCK_PROTO_CREATE_FUNC, 229 #ifdef INET_SOCK_PROTO_FB_FUNC 230 &smodpriv 231 #else 232 NULL 233 #endif /* INET_SOCK_PROTO_FB_FUNC */ 234 }; 235 236 static struct modlsockmod modlsockmod = { 237 &mod_sockmodops, 238 INET_SOCKDESC, 239 &smodreg 240 }; 241 #endif /* INET_SOCKDESC */ 242 243 static struct modlinkage modlinkage = { 244 MODREV_1, 245 #ifdef INET_DEVDESC 246 &modldrv, 247 #endif 248 #ifdef INET_MODDESC 249 &modlstrmod, 250 #endif 251 #ifdef INET_SOCKDESC 252 &modlsockmod, 253 #endif 254 NULL 255 }; 256