xref: /titanic_50/usr/src/uts/common/inet/inetddi.c (revision 711890bc9379ceea66272dc8d4981812224ea86e)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/stream.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/priv_names.h>
34 
35 /*
36  * This file contains generic goo needed to hook the STREAMS modules and
37  * drivers that live under uts/common/inet into the DDI.  In order to use it,
38  * each module/driver should #define the symbols below (as appropriate) and
39  * then #include this source file; see the other uts/common/inet/<star>ddi.c
40  * files for examples of this in action.
41  *
42  * The symbols that all modules and drivers must define are:
43  *
44  *	INET_NAME	 The name of the module/driver.
45  *	INET_STRTAB	 The name of the `streamtab' structure.
46  *
47  * The symbols that all modules must define are:
48  *
49  *	INET_MODDESC	 The one-line description for this module.
50  *	INET_MODMTFLAGS  The mt-streams(9F) flags for the module.
51  *
52  * The symbols that all drivers must define are:
53  *
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 then call INET_BECOME_IP() in their _init(9E) routine.
60  */
61 
62 #if	!defined(INET_STRTAB)
63 #error inetddi.c: INET_STRTAB is not defined!
64 #elif	!defined(INET_NAME)
65 #error inetddi.c: INET_NAME is not defined!
66 #elif	!defined(INET_DEVDESC) && !defined(INET_MODDESC)
67 #error inetddi.c: at least one of INET_DEVDESC or INET_MODDESC must be defined!
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_MODMTFLAGS)
73 #error inetddi.c: INET_MODDESC is defined but INET_MODMTFLAGS is not!
74 #endif
75 
76 extern struct streamtab INET_STRTAB, ipinfo;
77 
78 #ifdef	INET_DEVDESC
79 
80 /*
81  * This macro is intended to be called from the _init() routine of drivers
82  * that actually want to be IP.  Yes, this is a disgusting, vile hack.
83  */
84 #define	INET_BECOME_IP()	(cb_inet_devops.cb_str = &ipinfo)
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_STRTAB);
171 
172 static struct modldrv modldrv = {
173 	&mod_driverops,
174 	INET_DEVDESC,
175 	&inet_devops
176 };
177 
178 #endif /* INET_DEVDESC */
179 
180 #ifdef	INET_MODDESC
181 static struct fmodsw fsw = {
182 	INET_NAME,
183 	&INET_STRTAB,
184 	INET_MODMTFLAGS
185 };
186 
187 static struct modlstrmod modlstrmod = {
188 	&mod_strmodops,
189 	INET_MODDESC,
190 	&fsw
191 };
192 #endif /* INET_MODDESC */
193 
194 static struct modlinkage modlinkage = {
195 	MODREV_1,
196 #ifdef	INET_DEVDESC
197 	&modldrv,
198 #endif
199 #ifdef	INET_MODDESC
200 	&modlstrmod,
201 #endif
202 	NULL
203 };
204