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