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