inetddi.c revision 7656:2621e50fdf4a
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
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/stream.h>
30#include <sys/ddi.h>
31#include <sys/sunddi.h>
32#include <sys/priv_names.h>
33
34/*
35 * This file contains generic goo needed to hook the STREAMS modules and
36 * drivers that live under uts/common/inet into the DDI.  In order to use it,
37 * each module/driver should #define the symbols below (as appropriate) and
38 * then #include this source file; see the other uts/common/inet/<star>ddi.c
39 * files for examples of this in action.
40 *
41 * The symbols that all modules and drivers must define are:
42 *
43 *	INET_NAME	 The name of the module/driver.
44 *
45 * The symbols that all modules must define are:
46 *
47 *	INET_MODSTRTAB	 The name of the `streamtab' structure for this module.
48 *	INET_MODDESC	 The one-line description for this module.
49 *	INET_MODMTFLAGS  The mt-streams(9F) flags for the module.
50 *
51 * The symbols that all drivers must define are:
52 *
53 *	INET_DEVSTRTAB	 The name of the `streamtab' structure for this driver.
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 set INET_DEVSTRTAB to ipinfo.
60 */
61
62#if	!defined(INET_NAME)
63#error inetddi.c: INET_NAME is not defined!
64#elif	!defined(INET_DEVDESC) && !defined(INET_MODDESC)
65#error inetddi.c: at least one of INET_DEVDESC or INET_MODDESC must be defined!
66#elif	defined(INET_DEVDESC) && !defined(INET_DEVSTRTAB)
67#error inetddi.c: INET_DEVDESC is defined but INET_DEVSTRTAB is not!
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_MODSTRTAB)
73#error inetddi.c: INET_MODDESC is defined but INET_MODSTRTAB is not!
74#elif	defined(INET_MODDESC) && !defined(INET_MODMTFLAGS)
75#error inetddi.c: INET_MODDESC is defined but INET_MODMTFLAGS is not!
76#endif
77
78#ifdef	INET_DEVDESC
79
80extern struct streamtab INET_DEVSTRTAB;
81
82/*
83 * Drivers that actually want to be IP would set INET_DEVSTRTAB to ipinfo.
84 */
85
86static dev_info_t *inet_dev_info;
87
88#define	INET_DEFAULT_PRIV_MODE	0666
89
90static 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
107static int
108inet_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
130static int
131inet_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 */
144static int
145inet_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
169DDI_DEFINE_STREAM_OPS(inet_devops, nulldev, nulldev, inet_attach, inet_detach,
170    nulldev, inet_info, INET_DEVMTFLAGS, &INET_DEVSTRTAB,
171    ddi_quiesce_not_supported);
172
173static struct modldrv modldrv = {
174	&mod_driverops,
175	INET_DEVDESC,
176	&inet_devops
177};
178
179#endif /* INET_DEVDESC */
180
181#ifdef	INET_MODDESC
182extern struct streamtab INET_MODSTRTAB;
183
184static struct fmodsw fsw = {
185	INET_NAME,
186	&INET_MODSTRTAB,
187	INET_MODMTFLAGS
188};
189
190static struct modlstrmod modlstrmod = {
191	&mod_strmodops,
192	INET_MODDESC,
193	&fsw
194};
195#endif /* INET_MODDESC */
196
197static struct modlinkage modlinkage = {
198	MODREV_1,
199#ifdef	INET_DEVDESC
200	&modldrv,
201#endif
202#ifdef	INET_MODDESC
203	&modlstrmod,
204#endif
205	NULL
206};
207