xref: /illumos-gate/usr/src/uts/common/io/ppp/sppptun/sppptun_mod.c (revision 96d9f183facd90dbbc2268c9a51689be0b6a0b46)
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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * sppptun_mod.c - modload support for PPP multiplexing tunnel driver.
29  */
30 
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/stat.h>
34 #include <sys/systm.h>
35 #include <sys/socket.h>
36 #include <sys/stream.h>
37 #include <sys/stropts.h>
38 #include <sys/time.h>
39 #include <sys/conf.h>
40 #include <sys/kstat.h>
41 #include <sys/sunddi.h>
42 #include <net/sppptun.h>
43 #include <netinet/in.h>
44 
45 #include "sppptun_mod.h"
46 
47 /*
48  * Descriptions for flags values in cb_flags field:
49  *
50  * D_MTQPAIR:
51  *    An inner perimeter that spans the queue pair.
52  * D_MTOUTPERIM:
53  *    An outer perimeter that spans over all queues in the module.
54  * D_MTOCEXCL:
55  *    Open & close procedures are entered exclusively at outer perimeter.
56  * D_MTPUTSHARED:
57  *    Entry to put procedures are done with SHARED (reader) acess
58  *    and not EXCLUSIVE (writer) access.
59  *
60  * Therefore:
61  *
62  * 1. Open and close procedures are entered with EXCLUSIVE (writer)
63  *    access at the inner perimeter, and with EXCLUSIVE (writer) access at
64  *    the outer perimeter.
65  *
66  * 2. Put procedures are entered with SHARED (reader) access at the inner
67  *    perimeter, and with SHARED (reader) access at the outer perimeter.
68  *
69  * 3. Service procedures are entered with EXCLUSIVE (writer) access at
70  *    the inner perimeter, and with SHARED (reader) access at the
71  *    outer perimeter.
72  *
73  * Do not attempt to modify these flags unless the entire corresponding
74  * driver code is changed to accomodate the newly represented MT-STREAMS
75  * flags. Doing so without making proper modifications to the driver code
76  * will severely impact the intended driver behavior, and thus may affect
77  * the system's stability and performance.
78  */
79 
80 static int	tun_attach(dev_info_t *, ddi_attach_cmd_t);
81 static int	tun_detach(dev_info_t *, ddi_detach_cmd_t);
82 static int	tun_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
83 
84 static dev_info_t *tun_dev_info;
85 
86 DDI_DEFINE_STREAM_OPS(sppptun_ops,			\
87 	nulldev, nulldev,				\
88 	tun_attach, tun_detach, nodev, tun_info,	\
89 	D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED, \
90 	&sppptun_tab, ddi_quiesce_not_supported);
91 
92 /*
93  * This is the loadable module wrapper.
94  */
95 #include <sys/modctl.h>
96 
97 /*
98  * Module linkage information for the kernel.
99  */
100 static struct fmodsw sppptun_fmodsw = {
101 	PPP_TUN_NAME,
102 	&sppptun_tab,
103 	D_NEW | D_MP | D_MTQPAIR | D_MTOUTPERIM | D_MTOCEXCL | D_MTPUTSHARED
104 };
105 
106 static struct modldrv modldrv = {
107 	&mod_driverops,
108 	(char *)sppptun_driver_description,
109 	&sppptun_ops
110 };
111 
112 static struct modlstrmod modlstrmod = {
113 	&mod_strmodops,
114 	(char *)sppptun_module_description,
115 	&sppptun_fmodsw
116 };
117 
118 static struct modlinkage modlinkage = {
119 	MODREV_1,
120 	(void *)&modlstrmod,
121 	(void *)&modldrv,
122 	NULL
123 };
124 
125 int
126 _init(void)
127 {
128 	int retv;
129 
130 	sppptun_init();
131 	if ((retv = mod_install(&modlinkage)) == 0)
132 		sppptun_tcl_init();
133 	return (retv);
134 }
135 
136 int
137 _fini(void)
138 {
139 	int retv;
140 
141 	if ((retv = sppptun_tcl_fintest()) != 0)
142 		return (retv);
143 	retv = mod_remove(&modlinkage);
144 	if (retv != 0)
145 		return (retv);
146 	sppptun_tcl_fini();
147 	return (0);
148 }
149 
150 int
151 _info(struct modinfo *modinfop)
152 {
153 	return (mod_info(&modlinkage, modinfop));
154 }
155 
156 /*
157  * tun_attach()
158  *
159  * Description:
160  *    Attach a PPP tunnel driver to the system.
161  */
162 static int
163 tun_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
164 {
165 	if (cmd != DDI_ATTACH)
166 		return (DDI_FAILURE);
167 	if (ddi_create_minor_node(dip, PPP_TUN_NAME, S_IFCHR, 0, DDI_PSEUDO,
168 	    CLONE_DEV) == DDI_FAILURE) {
169 		ddi_remove_minor_node(dip, NULL);
170 		return (DDI_FAILURE);
171 	}
172 	tun_dev_info = dip;
173 	return (DDI_SUCCESS);
174 }
175 
176 /*
177  * tun_detach()
178  *
179  * Description:
180  *    Detach an interface to the system.
181  */
182 static int
183 tun_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
184 {
185 	if (cmd != DDI_DETACH)
186 		return (DDI_FAILURE);
187 	tun_dev_info = NULL;
188 	ddi_remove_minor_node(dip, NULL);
189 	return (DDI_SUCCESS);
190 }
191 
192 /*
193  * tun_info()
194  *
195  * Description:
196  *    Translate "dev_t" to a pointer to the associated "dev_info_t".
197  */
198 /* ARGSUSED */
199 static int
200 tun_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
201 	void **result)
202 {
203 	int	rc;
204 
205 	switch (infocmd) {
206 	case DDI_INFO_DEVT2DEVINFO:
207 		if (tun_dev_info == NULL) {
208 			rc = DDI_FAILURE;
209 		} else {
210 			*result = (void *)tun_dev_info;
211 			rc = DDI_SUCCESS;
212 		}
213 		break;
214 	case DDI_INFO_DEVT2INSTANCE:
215 		*result = NULL;
216 		rc = DDI_SUCCESS;
217 		break;
218 	default:
219 		rc = DDI_FAILURE;
220 		break;
221 	}
222 	return (rc);
223 }
224