xref: /illumos-gate/usr/src/uts/common/inet/inetddi.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
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 (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
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.
42  *
43  * The symbols that all modules must define are:
44  *
45  *	INET_MODSTRTAB	 The name of the `streamtab' structure for this module.
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  *
51  *	INET_DEVSTRTAB	 The name of the `streamtab' structure for this driver.
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
57  * IP_DEVMTFLAGS and set INET_DEVSTRTAB to ipinfo.
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
67  */
68 
69 #if	!defined(INET_NAME)
70 #error inetddi.c: INET_NAME is not defined!
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!
75 #elif	defined(INET_DEVDESC) && !defined(INET_DEVSTRTAB)
76 #error inetddi.c: INET_DEVDESC is defined but INET_DEVSTRTAB is not!
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!
81 #elif	defined(INET_MODDESC) && !defined(INET_MODSTRTAB)
82 #error inetddi.c: INET_MODDESC is defined but INET_MODSTRTAB is not!
83 #elif	defined(INET_MODDESC) && !defined(INET_MODMTFLAGS)
84 #error inetddi.c: INET_MODDESC is defined but INET_MODMTFLAGS is not!
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!
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!
96 #endif
97 
98 #ifdef	INET_DEVDESC
99 
100 extern struct streamtab INET_DEVSTRTAB;
101 
102 /*
103  * Drivers that actually want to be IP would set INET_DEVSTRTAB to ipinfo.
104  */
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},
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},
124 	{NULL,	0,		NULL,			NULL}
125 };
126 
127 static int
128 inet_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
129 {
130 	size_t i, ndevs;
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 
144 	/* smatch has no idea what VERIFY does. */
145 	if (i == ndevs) {
146 		VERIFY(i < ndevs);
147 		return (DDI_FAILURE);
148 	}
149 
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,
196     nulldev, inet_info, INET_DEVMTFLAGS, &INET_DEVSTRTAB,
197     ddi_quiesce_not_supported);
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
208 extern struct streamtab INET_MODSTRTAB;
209 
210 static struct fmodsw fsw = {
211 	INET_NAME,
212 	&INET_MODSTRTAB,
213 	INET_MODMTFLAGS
214 };
215 
216 static struct modlstrmod modlstrmod = {
217 	&mod_strmodops,
218 	INET_MODDESC,
219 	&fsw
220 };
221 
222 #endif /* INET_MODDESC */
223 
224 #ifdef  INET_SOCKDESC
225 
226 #ifdef	INET_SOCK_PROTO_FB_FUNC
227 static __smod_priv_t smodpriv = {
228 	NULL,
229 	NULL,
230 	INET_SOCK_PROTO_FB_FUNC,
231 	INET_SOCK_FALLBACK_DEV_V4,
232 	INET_SOCK_FALLBACK_DEV_V6
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 
256 static struct modlinkage modlinkage = {
257 	MODREV_1,
258 #ifdef	INET_DEVDESC
259 	&modldrv,
260 #endif
261 #ifdef	INET_MODDESC
262 	&modlstrmod,
263 #endif
264 #ifdef	INET_SOCKDESC
265 	&modlsockmod,
266 #endif
267 	NULL
268 };
269