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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <sys/stream.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/priv_names.h> 34 35 /* 36 * This file contains generic goo needed to hook the STREAMS modules and 37 * drivers that live under uts/common/inet into the DDI. In order to use it, 38 * each module/driver should #define the symbols below (as appropriate) and 39 * then #include this source file; see the other uts/common/inet/<star>ddi.c 40 * files for examples of this in action. 41 * 42 * The symbols that all modules and drivers must define are: 43 * 44 * INET_NAME The name of the module/driver. 45 * INET_STRTAB The name of the `streamtab' structure. 46 * 47 * The symbols that all modules must define are: 48 * 49 * INET_MODDESC The one-line description for this module. 50 * INET_MODMTFLAGS The mt-streams(9F) flags for the module. 51 * 52 * The symbols that all drivers must define are: 53 * 54 * INET_DEVDESC The one-line description for this driver. 55 * INET_DEVMTFLAGS The mt-streams(9F) flags for the driver. 56 * INET_DEVMINOR The minor number of the driver (usually 0). 57 * 58 * Drivers that need to masquerade as IP should set INET_DEVMTFLAGS to 59 * IP_DEVMTFLAGS and then call INET_BECOME_IP() in their _init(9E) routine. 60 */ 61 62 #if !defined(INET_STRTAB) 63 #error inetddi.c: INET_STRTAB is not defined! 64 #elif !defined(INET_NAME) 65 #error inetddi.c: INET_NAME is not defined! 66 #elif !defined(INET_DEVDESC) && !defined(INET_MODDESC) 67 #error inetddi.c: at least one of INET_DEVDESC or INET_MODDESC must be defined! 68 #elif defined(INET_DEVDESC) && !defined(INET_DEVMTFLAGS) 69 #error inetddi.c: INET_DEVDESC is defined but INET_DEVMTFLAGS is not! 70 #elif defined(INET_DEVDESC) && !defined(INET_DEVMINOR) 71 #error inetddi.c: INET_DEVDESC is defined but INET_DEVMINOR is not! 72 #elif defined(INET_MODDESC) && !defined(INET_MODMTFLAGS) 73 #error inetddi.c: INET_MODDESC is defined but INET_MODMTFLAGS is not! 74 #endif 75 76 extern struct streamtab INET_STRTAB, ipinfo; 77 78 #ifdef INET_DEVDESC 79 80 /* 81 * This macro is intended to be called from the _init() routine of drivers 82 * that actually want to be IP. Yes, this is a disgusting, vile hack. 83 */ 84 #define INET_BECOME_IP() (cb_inet_devops.cb_str = &ipinfo) 85 86 static dev_info_t *inet_dev_info; 87 88 #define INET_DEFAULT_PRIV_MODE 0666 89 90 static struct dev_priv { 91 char *driver; 92 int privonly; 93 const char *read_priv; 94 const char *write_priv; 95 } netdev_privs[] = { 96 {"icmp", PRIVONLY_DEV, PRIV_NET_ICMPACCESS, PRIV_NET_ICMPACCESS}, 97 {"icmp6", PRIVONLY_DEV, PRIV_NET_ICMPACCESS, PRIV_NET_ICMPACCESS}, 98 {"ip", PRIVONLY_DEV, PRIV_NET_RAWACCESS, PRIV_NET_RAWACCESS}, 99 {"ip6", PRIVONLY_DEV, PRIV_NET_RAWACCESS, PRIV_NET_RAWACCESS}, 100 {"keysock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 101 {"ipsecah", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 102 {"ipsecesp", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 103 {"spdsock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG, PRIV_SYS_IP_CONFIG}, 104 {NULL, 0, NULL, NULL} 105 }; 106 107 static int 108 inet_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 109 { 110 int i, ndevs; 111 112 if (cmd != DDI_ATTACH) 113 return (DDI_FAILURE); 114 115 inet_dev_info = devi; 116 117 ndevs = sizeof (netdev_privs) / sizeof (struct dev_priv); 118 for (i = 0; i < ndevs; i++) { 119 char *drv = netdev_privs[i].driver; 120 if (drv == NULL || strcmp(drv, ddi_driver_name(devi)) == 0) 121 break; 122 } 123 124 return (ddi_create_priv_minor_node(devi, INET_NAME, S_IFCHR, 125 INET_DEVMINOR, DDI_PSEUDO, netdev_privs[i].privonly, 126 netdev_privs[i].read_priv, netdev_privs[i].write_priv, 127 INET_DEFAULT_PRIV_MODE)); 128 } 129 130 static int 131 inet_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 132 { 133 if (cmd != DDI_DETACH) 134 return (DDI_FAILURE); 135 136 ASSERT(devi == inet_dev_info); 137 138 ddi_remove_minor_node(devi, NULL); 139 return (DDI_SUCCESS); 140 } 141 142 143 /* ARGSUSED */ 144 static int 145 inet_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 146 { 147 int error = DDI_FAILURE; 148 149 switch (cmd) { 150 case DDI_INFO_DEVT2DEVINFO: 151 if (inet_dev_info != NULL) { 152 *result = (void *)inet_dev_info; 153 error = DDI_SUCCESS; 154 } 155 break; 156 157 case DDI_INFO_DEVT2INSTANCE: 158 *result = NULL; 159 error = DDI_SUCCESS; 160 break; 161 162 default: 163 break; 164 } 165 166 return (error); 167 } 168 169 DDI_DEFINE_STREAM_OPS(inet_devops, nulldev, nulldev, inet_attach, inet_detach, 170 nulldev, inet_info, INET_DEVMTFLAGS, &INET_STRTAB); 171 172 static struct modldrv modldrv = { 173 &mod_driverops, 174 INET_DEVDESC, 175 &inet_devops 176 }; 177 178 #endif /* INET_DEVDESC */ 179 180 #ifdef INET_MODDESC 181 static struct fmodsw fsw = { 182 INET_NAME, 183 &INET_STRTAB, 184 INET_MODMTFLAGS 185 }; 186 187 static struct modlstrmod modlstrmod = { 188 &mod_strmodops, 189 INET_MODDESC, 190 &fsw 191 }; 192 #endif /* INET_MODDESC */ 193 194 static struct modlinkage modlinkage = { 195 MODREV_1, 196 #ifdef INET_DEVDESC 197 &modldrv, 198 #endif 199 #ifdef INET_MODDESC 200 &modlstrmod, 201 #endif 202 NULL 203 }; 204