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