xref: /illumos-gate/usr/src/uts/common/inet/inetddi.c (revision 628e3cbed6489fa1db545d8524a06cd6535af456)
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 
80 extern struct streamtab INET_DEVSTRTAB;
81 
82 /*
83  * Drivers that actually want to be IP would set INET_DEVSTRTAB to ipinfo.
84  */
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_DEVSTRTAB,
171     ddi_quiesce_not_supported);
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 extern struct streamtab INET_MODSTRTAB;
183 
184 static struct fmodsw fsw = {
185 	INET_NAME,
186 	&INET_MODSTRTAB,
187 	INET_MODMTFLAGS
188 };
189 
190 static struct modlstrmod modlstrmod = {
191 	&mod_strmodops,
192 	INET_MODDESC,
193 	&fsw
194 };
195 #endif /* INET_MODDESC */
196 
197 static 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