xref: /onnv-gate/usr/src/uts/common/io/neti_impl.c (revision 7513:18aa777d3f09)
1*7513SDarren.Reed@Sun.COM /*
2*7513SDarren.Reed@Sun.COM  * CDDL HEADER START
3*7513SDarren.Reed@Sun.COM  *
4*7513SDarren.Reed@Sun.COM  * The contents of this file are subject to the terms of the
5*7513SDarren.Reed@Sun.COM  * Common Development and Distribution License (the "License").
6*7513SDarren.Reed@Sun.COM  * You may not use this file except in compliance with the License.
7*7513SDarren.Reed@Sun.COM  *
8*7513SDarren.Reed@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7513SDarren.Reed@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*7513SDarren.Reed@Sun.COM  * See the License for the specific language governing permissions
11*7513SDarren.Reed@Sun.COM  * and limitations under the License.
12*7513SDarren.Reed@Sun.COM  *
13*7513SDarren.Reed@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*7513SDarren.Reed@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7513SDarren.Reed@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*7513SDarren.Reed@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*7513SDarren.Reed@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*7513SDarren.Reed@Sun.COM  *
19*7513SDarren.Reed@Sun.COM  * CDDL HEADER END
20*7513SDarren.Reed@Sun.COM  */
21*7513SDarren.Reed@Sun.COM /*
22*7513SDarren.Reed@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*7513SDarren.Reed@Sun.COM  * Use is subject to license terms.
24*7513SDarren.Reed@Sun.COM  */
25*7513SDarren.Reed@Sun.COM 
26*7513SDarren.Reed@Sun.COM #include <sys/param.h>
27*7513SDarren.Reed@Sun.COM #include <sys/atomic.h>
28*7513SDarren.Reed@Sun.COM #include <sys/kmem.h>
29*7513SDarren.Reed@Sun.COM #include <sys/rwlock.h>
30*7513SDarren.Reed@Sun.COM #include <sys/errno.h>
31*7513SDarren.Reed@Sun.COM #include <sys/queue.h>
32*7513SDarren.Reed@Sun.COM #include <inet/common.h>
33*7513SDarren.Reed@Sun.COM #include <inet/led.h>
34*7513SDarren.Reed@Sun.COM #include <inet/ip.h>
35*7513SDarren.Reed@Sun.COM #include <sys/neti.h>
36*7513SDarren.Reed@Sun.COM #include <sys/zone.h>
37*7513SDarren.Reed@Sun.COM 
38*7513SDarren.Reed@Sun.COM static net_handle_t net_find(const char *protocol, neti_stack_t *ns);
39*7513SDarren.Reed@Sun.COM 
40*7513SDarren.Reed@Sun.COM static net_handle_t
41*7513SDarren.Reed@Sun.COM net_find(const char *protocol, neti_stack_t *nts)
42*7513SDarren.Reed@Sun.COM {
43*7513SDarren.Reed@Sun.COM 	struct net_data *n;
44*7513SDarren.Reed@Sun.COM 
45*7513SDarren.Reed@Sun.COM 	ASSERT(protocol != NULL);
46*7513SDarren.Reed@Sun.COM 	ASSERT(nts != NULL);
47*7513SDarren.Reed@Sun.COM 
48*7513SDarren.Reed@Sun.COM 	LIST_FOREACH(n, &nts->nts_netd_head, netd_list) {
49*7513SDarren.Reed@Sun.COM 		ASSERT(n->netd_info.netp_name != NULL);
50*7513SDarren.Reed@Sun.COM 		/*
51*7513SDarren.Reed@Sun.COM 		 * If they're trying to find a protocol that is being
52*7513SDarren.Reed@Sun.COM 		 * shutdown, just ignore it..
53*7513SDarren.Reed@Sun.COM 		 */
54*7513SDarren.Reed@Sun.COM 		if (n->netd_condemned != 0)
55*7513SDarren.Reed@Sun.COM 			continue;
56*7513SDarren.Reed@Sun.COM 		if (strcmp(n->netd_info.netp_name, protocol) == 0) {
57*7513SDarren.Reed@Sun.COM 			break;
58*7513SDarren.Reed@Sun.COM 		}
59*7513SDarren.Reed@Sun.COM 	}
60*7513SDarren.Reed@Sun.COM 
61*7513SDarren.Reed@Sun.COM 	return (n);
62*7513SDarren.Reed@Sun.COM }
63*7513SDarren.Reed@Sun.COM 
64*7513SDarren.Reed@Sun.COM net_handle_t
65*7513SDarren.Reed@Sun.COM net_protocol_register(netid_t id, const net_protocol_t *info)
66*7513SDarren.Reed@Sun.COM {
67*7513SDarren.Reed@Sun.COM 	struct net_data *n, *new;
68*7513SDarren.Reed@Sun.COM 	neti_stack_t *nts;
69*7513SDarren.Reed@Sun.COM 
70*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
71*7513SDarren.Reed@Sun.COM 
72*7513SDarren.Reed@Sun.COM 	nts = net_getnetistackbyid(id);
73*7513SDarren.Reed@Sun.COM 	if (nts == NULL)
74*7513SDarren.Reed@Sun.COM 		return (NULL);
75*7513SDarren.Reed@Sun.COM 
76*7513SDarren.Reed@Sun.COM 	new = kmem_alloc(sizeof (*new), KM_SLEEP);
77*7513SDarren.Reed@Sun.COM 	new->netd_refcnt = 1;
78*7513SDarren.Reed@Sun.COM 	new->netd_hooks = NULL;
79*7513SDarren.Reed@Sun.COM 	new->netd_info = *info;
80*7513SDarren.Reed@Sun.COM 	new->netd_stack = nts;
81*7513SDarren.Reed@Sun.COM 	new->netd_condemned = 0;
82*7513SDarren.Reed@Sun.COM 
83*7513SDarren.Reed@Sun.COM 	mutex_enter(&nts->nts_lock);
84*7513SDarren.Reed@Sun.COM 	n = net_find(info->netp_name, nts);
85*7513SDarren.Reed@Sun.COM 	if (n != NULL) {
86*7513SDarren.Reed@Sun.COM 		mutex_exit(&nts->nts_lock);
87*7513SDarren.Reed@Sun.COM 		kmem_free(new, sizeof (*new));
88*7513SDarren.Reed@Sun.COM 		return (NULL);
89*7513SDarren.Reed@Sun.COM 	}
90*7513SDarren.Reed@Sun.COM 
91*7513SDarren.Reed@Sun.COM 	if (LIST_EMPTY(&nts->nts_netd_head)) {
92*7513SDarren.Reed@Sun.COM 		LIST_INSERT_HEAD(&nts->nts_netd_head, new, netd_list);
93*7513SDarren.Reed@Sun.COM 	} else {
94*7513SDarren.Reed@Sun.COM 		LIST_INSERT_AFTER(LIST_FIRST(&nts->nts_netd_head),
95*7513SDarren.Reed@Sun.COM 		    new, netd_list);
96*7513SDarren.Reed@Sun.COM 	}
97*7513SDarren.Reed@Sun.COM 	mutex_exit(&nts->nts_lock);
98*7513SDarren.Reed@Sun.COM 
99*7513SDarren.Reed@Sun.COM 	return (new);
100*7513SDarren.Reed@Sun.COM }
101*7513SDarren.Reed@Sun.COM 
102*7513SDarren.Reed@Sun.COM int
103*7513SDarren.Reed@Sun.COM net_protocol_unregister(net_handle_t info)
104*7513SDarren.Reed@Sun.COM {
105*7513SDarren.Reed@Sun.COM 	neti_stack_t *nts;
106*7513SDarren.Reed@Sun.COM 
107*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
108*7513SDarren.Reed@Sun.COM 
109*7513SDarren.Reed@Sun.COM 	nts = info->netd_stack;
110*7513SDarren.Reed@Sun.COM 	ASSERT(nts != NULL);
111*7513SDarren.Reed@Sun.COM 
112*7513SDarren.Reed@Sun.COM 	mutex_enter(&nts->nts_lock);
113*7513SDarren.Reed@Sun.COM 	LIST_REMOVE(info, netd_list);
114*7513SDarren.Reed@Sun.COM 	info->netd_stack = NULL;
115*7513SDarren.Reed@Sun.COM 	mutex_exit(&nts->nts_lock);
116*7513SDarren.Reed@Sun.COM 
117*7513SDarren.Reed@Sun.COM 	(void) net_protocol_release(info);
118*7513SDarren.Reed@Sun.COM 
119*7513SDarren.Reed@Sun.COM 	return (0);
120*7513SDarren.Reed@Sun.COM }
121*7513SDarren.Reed@Sun.COM 
122*7513SDarren.Reed@Sun.COM net_handle_t
123*7513SDarren.Reed@Sun.COM net_protocol_lookup(netid_t netid, const char *protocol)
124*7513SDarren.Reed@Sun.COM {
125*7513SDarren.Reed@Sun.COM 	neti_stack_t *nts;
126*7513SDarren.Reed@Sun.COM 	net_handle_t nd;
127*7513SDarren.Reed@Sun.COM 
128*7513SDarren.Reed@Sun.COM 	ASSERT(protocol != NULL);
129*7513SDarren.Reed@Sun.COM 
130*7513SDarren.Reed@Sun.COM 	nts = net_getnetistackbyid(netid);
131*7513SDarren.Reed@Sun.COM 	if (nts == NULL)
132*7513SDarren.Reed@Sun.COM 		return (NULL);
133*7513SDarren.Reed@Sun.COM 
134*7513SDarren.Reed@Sun.COM 	mutex_enter(&nts->nts_lock);
135*7513SDarren.Reed@Sun.COM 	nd = net_find(protocol, nts);
136*7513SDarren.Reed@Sun.COM 	if (nd != NULL)
137*7513SDarren.Reed@Sun.COM 		atomic_add_32((uint_t *)&nd->netd_refcnt, 1);
138*7513SDarren.Reed@Sun.COM 	mutex_exit(&nts->nts_lock);
139*7513SDarren.Reed@Sun.COM 	return (nd);
140*7513SDarren.Reed@Sun.COM }
141*7513SDarren.Reed@Sun.COM 
142*7513SDarren.Reed@Sun.COM /*
143*7513SDarren.Reed@Sun.COM  * Note: the man page specifies "returns -1 if the value passed in is unknown
144*7513SDarren.Reed@Sun.COM  * to this framework".  We are not doing a lookup in this function, just a
145*7513SDarren.Reed@Sun.COM  * simply add to the netd_refcnt of the net_handle_t passed in, so -1 is never a
146*7513SDarren.Reed@Sun.COM  * return value.
147*7513SDarren.Reed@Sun.COM  */
148*7513SDarren.Reed@Sun.COM int
149*7513SDarren.Reed@Sun.COM net_protocol_release(net_handle_t info)
150*7513SDarren.Reed@Sun.COM {
151*7513SDarren.Reed@Sun.COM 
152*7513SDarren.Reed@Sun.COM 	ASSERT(info->netd_refcnt > 0);
153*7513SDarren.Reed@Sun.COM 	/*
154*7513SDarren.Reed@Sun.COM 	 * Is this safe? No hold on nts_lock? Consider that if the caller
155*7513SDarren.Reed@Sun.COM 	 * of net_protocol_release() is going to free this structure then
156*7513SDarren.Reed@Sun.COM 	 * it is now the only owner (refcnt==1) and it will have been
157*7513SDarren.Reed@Sun.COM 	 * removed from the nts_netd_head list on the neti_stack_t from a
158*7513SDarren.Reed@Sun.COM 	 * call to net_protocol_unregister already, so it is thus an orphan.
159*7513SDarren.Reed@Sun.COM 	 */
160*7513SDarren.Reed@Sun.COM 	if (atomic_add_32_nv((uint_t *)&info->netd_refcnt, -1) == 0) {
161*7513SDarren.Reed@Sun.COM 		ASSERT(info->netd_hooks == NULL);
162*7513SDarren.Reed@Sun.COM 		ASSERT(info->netd_stack == NULL);
163*7513SDarren.Reed@Sun.COM 		kmem_free(info, sizeof (struct net_data));
164*7513SDarren.Reed@Sun.COM 	}
165*7513SDarren.Reed@Sun.COM 
166*7513SDarren.Reed@Sun.COM 	return (0);
167*7513SDarren.Reed@Sun.COM }
168*7513SDarren.Reed@Sun.COM 
169*7513SDarren.Reed@Sun.COM net_handle_t
170*7513SDarren.Reed@Sun.COM net_protocol_walk(netid_t netid, net_handle_t info)
171*7513SDarren.Reed@Sun.COM {
172*7513SDarren.Reed@Sun.COM 	struct net_data *n = NULL;
173*7513SDarren.Reed@Sun.COM 	boolean_t found = B_FALSE;
174*7513SDarren.Reed@Sun.COM 	neti_stack_t *nts;
175*7513SDarren.Reed@Sun.COM 
176*7513SDarren.Reed@Sun.COM 	nts = net_getnetistackbyid(netid);
177*7513SDarren.Reed@Sun.COM 	ASSERT(nts != NULL);
178*7513SDarren.Reed@Sun.COM 
179*7513SDarren.Reed@Sun.COM 	if (info == NULL)
180*7513SDarren.Reed@Sun.COM 		found = B_TRUE;
181*7513SDarren.Reed@Sun.COM 
182*7513SDarren.Reed@Sun.COM 	mutex_enter(&nts->nts_lock);
183*7513SDarren.Reed@Sun.COM 	LIST_FOREACH(n, &nts->nts_netd_head, netd_list) {
184*7513SDarren.Reed@Sun.COM 		if (found) {
185*7513SDarren.Reed@Sun.COM 			/*
186*7513SDarren.Reed@Sun.COM 			 * We are only interested in finding protocols that
187*7513SDarren.Reed@Sun.COM 			 * are not in some sort of shutdown state.  There is
188*7513SDarren.Reed@Sun.COM 			 * no need to check for netd_stack==NULL because
189*7513SDarren.Reed@Sun.COM 			 * that implies it is no longer on this list.
190*7513SDarren.Reed@Sun.COM 			 */
191*7513SDarren.Reed@Sun.COM 			if (n->netd_condemned == 0)
192*7513SDarren.Reed@Sun.COM 				continue;
193*7513SDarren.Reed@Sun.COM 			break;
194*7513SDarren.Reed@Sun.COM 		}
195*7513SDarren.Reed@Sun.COM 
196*7513SDarren.Reed@Sun.COM 		if (n == info)
197*7513SDarren.Reed@Sun.COM 			found = B_TRUE;
198*7513SDarren.Reed@Sun.COM 	}
199*7513SDarren.Reed@Sun.COM 
200*7513SDarren.Reed@Sun.COM 	if (info != NULL)
201*7513SDarren.Reed@Sun.COM 		(void) net_protocol_release(info);
202*7513SDarren.Reed@Sun.COM 
203*7513SDarren.Reed@Sun.COM 	if (n != NULL)
204*7513SDarren.Reed@Sun.COM 		atomic_add_32((uint_t *)&n->netd_refcnt, 1);
205*7513SDarren.Reed@Sun.COM 
206*7513SDarren.Reed@Sun.COM 	mutex_exit(&nts->nts_lock);
207*7513SDarren.Reed@Sun.COM 
208*7513SDarren.Reed@Sun.COM 	return (n);
209*7513SDarren.Reed@Sun.COM }
210*7513SDarren.Reed@Sun.COM 
211*7513SDarren.Reed@Sun.COM /*
212*7513SDarren.Reed@Sun.COM  * Public accessor functions
213*7513SDarren.Reed@Sun.COM  */
214*7513SDarren.Reed@Sun.COM int
215*7513SDarren.Reed@Sun.COM net_getifname(net_handle_t info, phy_if_t nic, char *buffer,
216*7513SDarren.Reed@Sun.COM     const size_t buflen)
217*7513SDarren.Reed@Sun.COM {
218*7513SDarren.Reed@Sun.COM 
219*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
220*7513SDarren.Reed@Sun.COM 
221*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
222*7513SDarren.Reed@Sun.COM 		return (-1);
223*7513SDarren.Reed@Sun.COM 
224*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_getifname(info, nic, buffer, buflen));
225*7513SDarren.Reed@Sun.COM }
226*7513SDarren.Reed@Sun.COM 
227*7513SDarren.Reed@Sun.COM int
228*7513SDarren.Reed@Sun.COM net_getmtu(net_handle_t info, phy_if_t nic, lif_if_t ifdata)
229*7513SDarren.Reed@Sun.COM {
230*7513SDarren.Reed@Sun.COM 
231*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
232*7513SDarren.Reed@Sun.COM 
233*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
234*7513SDarren.Reed@Sun.COM 		return (-1);
235*7513SDarren.Reed@Sun.COM 
236*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_getmtu(info, nic, ifdata));
237*7513SDarren.Reed@Sun.COM }
238*7513SDarren.Reed@Sun.COM 
239*7513SDarren.Reed@Sun.COM int
240*7513SDarren.Reed@Sun.COM net_getpmtuenabled(net_handle_t info)
241*7513SDarren.Reed@Sun.COM {
242*7513SDarren.Reed@Sun.COM 
243*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
244*7513SDarren.Reed@Sun.COM 
245*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
246*7513SDarren.Reed@Sun.COM 		return (-1);
247*7513SDarren.Reed@Sun.COM 
248*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_getpmtuenabled(info));
249*7513SDarren.Reed@Sun.COM }
250*7513SDarren.Reed@Sun.COM 
251*7513SDarren.Reed@Sun.COM int
252*7513SDarren.Reed@Sun.COM net_getlifaddr(net_handle_t info, phy_if_t nic, lif_if_t ifdata,
253*7513SDarren.Reed@Sun.COM     int nelem, net_ifaddr_t type[], void *storage)
254*7513SDarren.Reed@Sun.COM {
255*7513SDarren.Reed@Sun.COM 
256*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
257*7513SDarren.Reed@Sun.COM 
258*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
259*7513SDarren.Reed@Sun.COM 		return (-1);
260*7513SDarren.Reed@Sun.COM 
261*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_getlifaddr(info, nic, ifdata,
262*7513SDarren.Reed@Sun.COM 	    nelem, type, storage));
263*7513SDarren.Reed@Sun.COM }
264*7513SDarren.Reed@Sun.COM 
265*7513SDarren.Reed@Sun.COM phy_if_t
266*7513SDarren.Reed@Sun.COM net_phygetnext(net_handle_t info, phy_if_t nic)
267*7513SDarren.Reed@Sun.COM {
268*7513SDarren.Reed@Sun.COM 
269*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
270*7513SDarren.Reed@Sun.COM 
271*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
272*7513SDarren.Reed@Sun.COM 		return ((phy_if_t)-1);
273*7513SDarren.Reed@Sun.COM 
274*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_phygetnext(info, nic));
275*7513SDarren.Reed@Sun.COM }
276*7513SDarren.Reed@Sun.COM 
277*7513SDarren.Reed@Sun.COM phy_if_t
278*7513SDarren.Reed@Sun.COM net_phylookup(net_handle_t info, const char *name)
279*7513SDarren.Reed@Sun.COM {
280*7513SDarren.Reed@Sun.COM 
281*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
282*7513SDarren.Reed@Sun.COM 
283*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
284*7513SDarren.Reed@Sun.COM 		return ((phy_if_t)-1);
285*7513SDarren.Reed@Sun.COM 
286*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_phylookup(info, name));
287*7513SDarren.Reed@Sun.COM }
288*7513SDarren.Reed@Sun.COM 
289*7513SDarren.Reed@Sun.COM lif_if_t
290*7513SDarren.Reed@Sun.COM net_lifgetnext(net_handle_t info, phy_if_t ifidx, lif_if_t ifdata)
291*7513SDarren.Reed@Sun.COM {
292*7513SDarren.Reed@Sun.COM 
293*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
294*7513SDarren.Reed@Sun.COM 
295*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
296*7513SDarren.Reed@Sun.COM 		return ((lif_if_t)-1);
297*7513SDarren.Reed@Sun.COM 
298*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_lifgetnext(info, ifidx, ifdata));
299*7513SDarren.Reed@Sun.COM }
300*7513SDarren.Reed@Sun.COM 
301*7513SDarren.Reed@Sun.COM int
302*7513SDarren.Reed@Sun.COM net_inject(net_handle_t info, inject_t style, net_inject_t *packet)
303*7513SDarren.Reed@Sun.COM {
304*7513SDarren.Reed@Sun.COM 
305*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
306*7513SDarren.Reed@Sun.COM 
307*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
308*7513SDarren.Reed@Sun.COM 		return (-1);
309*7513SDarren.Reed@Sun.COM 
310*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_inject(info, style, packet));
311*7513SDarren.Reed@Sun.COM }
312*7513SDarren.Reed@Sun.COM 
313*7513SDarren.Reed@Sun.COM phy_if_t
314*7513SDarren.Reed@Sun.COM net_routeto(net_handle_t info, struct sockaddr *address, struct sockaddr *next)
315*7513SDarren.Reed@Sun.COM {
316*7513SDarren.Reed@Sun.COM 
317*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
318*7513SDarren.Reed@Sun.COM 
319*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
320*7513SDarren.Reed@Sun.COM 		return ((phy_if_t)-1);
321*7513SDarren.Reed@Sun.COM 
322*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_routeto(info, address, next));
323*7513SDarren.Reed@Sun.COM }
324*7513SDarren.Reed@Sun.COM 
325*7513SDarren.Reed@Sun.COM int
326*7513SDarren.Reed@Sun.COM net_ispartialchecksum(net_handle_t info, mblk_t *mp)
327*7513SDarren.Reed@Sun.COM {
328*7513SDarren.Reed@Sun.COM 
329*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
330*7513SDarren.Reed@Sun.COM 	ASSERT(mp != NULL);
331*7513SDarren.Reed@Sun.COM 
332*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
333*7513SDarren.Reed@Sun.COM 		return (-1);
334*7513SDarren.Reed@Sun.COM 
335*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_ispartialchecksum(info, mp));
336*7513SDarren.Reed@Sun.COM }
337*7513SDarren.Reed@Sun.COM 
338*7513SDarren.Reed@Sun.COM int
339*7513SDarren.Reed@Sun.COM net_isvalidchecksum(net_handle_t info, mblk_t *mp)
340*7513SDarren.Reed@Sun.COM {
341*7513SDarren.Reed@Sun.COM 
342*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
343*7513SDarren.Reed@Sun.COM 	ASSERT(mp != NULL);
344*7513SDarren.Reed@Sun.COM 
345*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
346*7513SDarren.Reed@Sun.COM 		return (-1);
347*7513SDarren.Reed@Sun.COM 
348*7513SDarren.Reed@Sun.COM 	return (info->netd_info.netp_isvalidchecksum(info, mp));
349*7513SDarren.Reed@Sun.COM }
350*7513SDarren.Reed@Sun.COM 
351*7513SDarren.Reed@Sun.COM /*
352*7513SDarren.Reed@Sun.COM  * Hooks related functions
353*7513SDarren.Reed@Sun.COM  */
354*7513SDarren.Reed@Sun.COM 
355*7513SDarren.Reed@Sun.COM /*
356*7513SDarren.Reed@Sun.COM  * Function:	net_family_register
357*7513SDarren.Reed@Sun.COM  * Returns:	int - 0 = Succ, Else = Fail
358*7513SDarren.Reed@Sun.COM  * Parameters:	info(I) - protocol
359*7513SDarren.Reed@Sun.COM  *		hf(I) - family pointer
360*7513SDarren.Reed@Sun.COM  *
361*7513SDarren.Reed@Sun.COM  * Call hook_family_add to register family
362*7513SDarren.Reed@Sun.COM  *
363*7513SDarren.Reed@Sun.COM  * There is no need to bump netd_refcnt in the two functions
364*7513SDarren.Reed@Sun.COM  * net_family_register and net_family_unregister because the caller of these
365*7513SDarren.Reed@Sun.COM  * two functions is assumed to "own" a reference on 'info' via an earlier
366*7513SDarren.Reed@Sun.COM  * call to net_protocol_register().  Thus the owner is expected to do a
367*7513SDarren.Reed@Sun.COM  * call to net_protocol_unregister() after having done a
368*7513SDarren.Reed@Sun.COM  * net_family_unregister() to make sure things are properly cleaned up.
369*7513SDarren.Reed@Sun.COM  */
370*7513SDarren.Reed@Sun.COM int
371*7513SDarren.Reed@Sun.COM net_family_register(net_handle_t info, hook_family_t *hf)
372*7513SDarren.Reed@Sun.COM {
373*7513SDarren.Reed@Sun.COM 	hook_family_int_t *hfi;
374*7513SDarren.Reed@Sun.COM 	netstack_t *ns;
375*7513SDarren.Reed@Sun.COM 
376*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
377*7513SDarren.Reed@Sun.COM 	ASSERT(hf != NULL);
378*7513SDarren.Reed@Sun.COM 
379*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
380*7513SDarren.Reed@Sun.COM 		return (ESHUTDOWN);
381*7513SDarren.Reed@Sun.COM 
382*7513SDarren.Reed@Sun.COM 	if (info->netd_hooks != NULL)
383*7513SDarren.Reed@Sun.COM 		return (EEXIST);
384*7513SDarren.Reed@Sun.COM 
385*7513SDarren.Reed@Sun.COM 	ns = info->netd_stack->nts_netstack;
386*7513SDarren.Reed@Sun.COM 	ASSERT(ns != NULL);
387*7513SDarren.Reed@Sun.COM 	hfi = hook_family_add(hf, ns->netstack_hook);
388*7513SDarren.Reed@Sun.COM 	if (hfi == NULL)
389*7513SDarren.Reed@Sun.COM 		return (EEXIST);
390*7513SDarren.Reed@Sun.COM 
391*7513SDarren.Reed@Sun.COM 	info->netd_hooks = hfi;
392*7513SDarren.Reed@Sun.COM 	return (0);
393*7513SDarren.Reed@Sun.COM }
394*7513SDarren.Reed@Sun.COM 
395*7513SDarren.Reed@Sun.COM /*
396*7513SDarren.Reed@Sun.COM  * Function:	net_family_unregister
397*7513SDarren.Reed@Sun.COM  * Returns:	int - transparent value, explained by caller
398*7513SDarren.Reed@Sun.COM  * Parameters:	info(I) - protocol
399*7513SDarren.Reed@Sun.COM  *		hf(I) - family pointer
400*7513SDarren.Reed@Sun.COM  *
401*7513SDarren.Reed@Sun.COM  * Call hook_family_remove to unregister family
402*7513SDarren.Reed@Sun.COM  */
403*7513SDarren.Reed@Sun.COM int
404*7513SDarren.Reed@Sun.COM net_family_unregister(net_handle_t info, hook_family_t *hf)
405*7513SDarren.Reed@Sun.COM {
406*7513SDarren.Reed@Sun.COM 	int ret;
407*7513SDarren.Reed@Sun.COM 
408*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
409*7513SDarren.Reed@Sun.COM 	ASSERT(hf != NULL);
410*7513SDarren.Reed@Sun.COM 
411*7513SDarren.Reed@Sun.COM 	if (info->netd_hooks == NULL)
412*7513SDarren.Reed@Sun.COM 		return (ENXIO);
413*7513SDarren.Reed@Sun.COM 
414*7513SDarren.Reed@Sun.COM 	if (strcmp(info->netd_hooks->hfi_family.hf_name,
415*7513SDarren.Reed@Sun.COM 	    hf->hf_name) != 0)
416*7513SDarren.Reed@Sun.COM 		return (EINVAL);
417*7513SDarren.Reed@Sun.COM 
418*7513SDarren.Reed@Sun.COM 	ret = hook_family_remove(info->netd_hooks);
419*7513SDarren.Reed@Sun.COM 	if (ret == 0)
420*7513SDarren.Reed@Sun.COM 		info->netd_hooks = NULL;
421*7513SDarren.Reed@Sun.COM 
422*7513SDarren.Reed@Sun.COM 	return (ret);
423*7513SDarren.Reed@Sun.COM }
424*7513SDarren.Reed@Sun.COM 
425*7513SDarren.Reed@Sun.COM /*
426*7513SDarren.Reed@Sun.COM  * Function:	net_event_register
427*7513SDarren.Reed@Sun.COM  * Returns:	internal event pointer - NULL = Fail
428*7513SDarren.Reed@Sun.COM  * Parameters:	info(I) - protocol
429*7513SDarren.Reed@Sun.COM  *		he(I) - event pointer
430*7513SDarren.Reed@Sun.COM  *
431*7513SDarren.Reed@Sun.COM  * Call hook_event_add to register event on specific family
432*7513SDarren.Reed@Sun.COM  * 	Internal event pointer is returned so caller can get
433*7513SDarren.Reed@Sun.COM  * 	handle to run hooks
434*7513SDarren.Reed@Sun.COM  */
435*7513SDarren.Reed@Sun.COM hook_event_token_t
436*7513SDarren.Reed@Sun.COM net_event_register(net_handle_t info, hook_event_t *he)
437*7513SDarren.Reed@Sun.COM {
438*7513SDarren.Reed@Sun.COM 	hook_event_int_t *hei;
439*7513SDarren.Reed@Sun.COM 
440*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
441*7513SDarren.Reed@Sun.COM 	ASSERT(he != NULL);
442*7513SDarren.Reed@Sun.COM 
443*7513SDarren.Reed@Sun.COM 	if (info->netd_hooks == NULL || info->netd_condemned != 0 ||
444*7513SDarren.Reed@Sun.COM 	    info->netd_stack == NULL)
445*7513SDarren.Reed@Sun.COM 		return (NULL);
446*7513SDarren.Reed@Sun.COM 
447*7513SDarren.Reed@Sun.COM 	hei = hook_event_add(info->netd_hooks, he);
448*7513SDarren.Reed@Sun.COM 	return ((hook_event_token_t)hei);
449*7513SDarren.Reed@Sun.COM }
450*7513SDarren.Reed@Sun.COM 
451*7513SDarren.Reed@Sun.COM /*
452*7513SDarren.Reed@Sun.COM  * Function:	net_event_unregister
453*7513SDarren.Reed@Sun.COM  * Returns:	int - transparent value, explained by caller
454*7513SDarren.Reed@Sun.COM  * Parameters:	info(I) - protocol
455*7513SDarren.Reed@Sun.COM  *		he(I) - event pointer
456*7513SDarren.Reed@Sun.COM  *
457*7513SDarren.Reed@Sun.COM  * Call hook_event_remove to unregister event on specific family
458*7513SDarren.Reed@Sun.COM  */
459*7513SDarren.Reed@Sun.COM int
460*7513SDarren.Reed@Sun.COM net_event_unregister(net_handle_t info, hook_event_t *he)
461*7513SDarren.Reed@Sun.COM {
462*7513SDarren.Reed@Sun.COM 
463*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
464*7513SDarren.Reed@Sun.COM 	ASSERT(he != NULL);
465*7513SDarren.Reed@Sun.COM 
466*7513SDarren.Reed@Sun.COM 	if (info->netd_hooks == NULL)
467*7513SDarren.Reed@Sun.COM 		return (ENXIO);
468*7513SDarren.Reed@Sun.COM 
469*7513SDarren.Reed@Sun.COM 	return (hook_event_remove(info->netd_hooks, he));
470*7513SDarren.Reed@Sun.COM }
471*7513SDarren.Reed@Sun.COM 
472*7513SDarren.Reed@Sun.COM /*
473*7513SDarren.Reed@Sun.COM  * Function:	net_hook_register
474*7513SDarren.Reed@Sun.COM  * Returns:	int - transparent value, explained by caller
475*7513SDarren.Reed@Sun.COM  * Parameters:	info(I) - protocol
476*7513SDarren.Reed@Sun.COM  *		event(I) - event name
477*7513SDarren.Reed@Sun.COM  *		h(I) - hook pointer
478*7513SDarren.Reed@Sun.COM  *
479*7513SDarren.Reed@Sun.COM  * Call hook_register to add hook on specific family/event
480*7513SDarren.Reed@Sun.COM  */
481*7513SDarren.Reed@Sun.COM int
482*7513SDarren.Reed@Sun.COM net_hook_register(net_handle_t info, char *event, hook_t *h)
483*7513SDarren.Reed@Sun.COM {
484*7513SDarren.Reed@Sun.COM 
485*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
486*7513SDarren.Reed@Sun.COM 	ASSERT(event != NULL);
487*7513SDarren.Reed@Sun.COM 	ASSERT(h != NULL);
488*7513SDarren.Reed@Sun.COM 
489*7513SDarren.Reed@Sun.COM 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
490*7513SDarren.Reed@Sun.COM 		return (ESHUTDOWN);
491*7513SDarren.Reed@Sun.COM 
492*7513SDarren.Reed@Sun.COM 	if (info->netd_hooks == NULL)
493*7513SDarren.Reed@Sun.COM 		return (ENXIO);
494*7513SDarren.Reed@Sun.COM 
495*7513SDarren.Reed@Sun.COM 	return (hook_register(info->netd_hooks, event, h));
496*7513SDarren.Reed@Sun.COM }
497*7513SDarren.Reed@Sun.COM 
498*7513SDarren.Reed@Sun.COM /*
499*7513SDarren.Reed@Sun.COM  * Function:	net_hook_unregister
500*7513SDarren.Reed@Sun.COM  * Returns:	int - transparent value, explained by caller
501*7513SDarren.Reed@Sun.COM  * Parameters:	info(I) - protocol
502*7513SDarren.Reed@Sun.COM  *		event(I) - event name
503*7513SDarren.Reed@Sun.COM  *		h(I) - hook pointer
504*7513SDarren.Reed@Sun.COM  *
505*7513SDarren.Reed@Sun.COM  * Call hook_unregister to remove hook on specific family/event
506*7513SDarren.Reed@Sun.COM  */
507*7513SDarren.Reed@Sun.COM int
508*7513SDarren.Reed@Sun.COM net_hook_unregister(net_handle_t info, char *event, hook_t *h)
509*7513SDarren.Reed@Sun.COM {
510*7513SDarren.Reed@Sun.COM 
511*7513SDarren.Reed@Sun.COM 	ASSERT(info != NULL);
512*7513SDarren.Reed@Sun.COM 	ASSERT(event != NULL);
513*7513SDarren.Reed@Sun.COM 	ASSERT(h != NULL);
514*7513SDarren.Reed@Sun.COM 
515*7513SDarren.Reed@Sun.COM 	if (info->netd_hooks == NULL)
516*7513SDarren.Reed@Sun.COM 		return (ENXIO);
517*7513SDarren.Reed@Sun.COM 
518*7513SDarren.Reed@Sun.COM 	return (hook_unregister(info->netd_hooks, event, h));
519*7513SDarren.Reed@Sun.COM }
520*7513SDarren.Reed@Sun.COM 
521*7513SDarren.Reed@Sun.COM netid_t
522*7513SDarren.Reed@Sun.COM net_getnetid(net_handle_t netd)
523*7513SDarren.Reed@Sun.COM {
524*7513SDarren.Reed@Sun.COM 
525*7513SDarren.Reed@Sun.COM 	if (netd->netd_stack == NULL)
526*7513SDarren.Reed@Sun.COM 		return (-1);
527*7513SDarren.Reed@Sun.COM 	return (netd->netd_stack->nts_id);
528*7513SDarren.Reed@Sun.COM }
529*7513SDarren.Reed@Sun.COM 
530*7513SDarren.Reed@Sun.COM net_inject_t *
531*7513SDarren.Reed@Sun.COM net_inject_alloc(const int version)
532*7513SDarren.Reed@Sun.COM {
533*7513SDarren.Reed@Sun.COM 	net_inject_t *ni;
534*7513SDarren.Reed@Sun.COM 
535*7513SDarren.Reed@Sun.COM 	ni = kmem_zalloc(sizeof (*ni), KM_NOSLEEP);
536*7513SDarren.Reed@Sun.COM 	if (ni == NULL)
537*7513SDarren.Reed@Sun.COM 		return (NULL);
538*7513SDarren.Reed@Sun.COM 
539*7513SDarren.Reed@Sun.COM 	ni->ni_version = version;
540*7513SDarren.Reed@Sun.COM 	return (ni);
541*7513SDarren.Reed@Sun.COM }
542*7513SDarren.Reed@Sun.COM 
543*7513SDarren.Reed@Sun.COM void
544*7513SDarren.Reed@Sun.COM net_inject_free(net_inject_t *ni)
545*7513SDarren.Reed@Sun.COM {
546*7513SDarren.Reed@Sun.COM 	kmem_free(ni, sizeof (*ni));
547*7513SDarren.Reed@Sun.COM }
548*7513SDarren.Reed@Sun.COM 
549*7513SDarren.Reed@Sun.COM kstat_t *
550*7513SDarren.Reed@Sun.COM net_kstat_create(netid_t netid, char *module, int instance, char *name,
551*7513SDarren.Reed@Sun.COM     char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
552*7513SDarren.Reed@Sun.COM {
553*7513SDarren.Reed@Sun.COM 	netstackid_t stackid = net_getnetstackidbynetid(netid);
554*7513SDarren.Reed@Sun.COM 
555*7513SDarren.Reed@Sun.COM 	if (stackid == -1)
556*7513SDarren.Reed@Sun.COM 		return (NULL);
557*7513SDarren.Reed@Sun.COM 
558*7513SDarren.Reed@Sun.COM 	return (kstat_create_netstack(module, instance, name, class, type,
559*7513SDarren.Reed@Sun.COM 	    ndata, ks_flag, stackid));
560*7513SDarren.Reed@Sun.COM }
561*7513SDarren.Reed@Sun.COM 
562*7513SDarren.Reed@Sun.COM void
563*7513SDarren.Reed@Sun.COM net_kstat_delete(netid_t netid, kstat_t *ks)
564*7513SDarren.Reed@Sun.COM {
565*7513SDarren.Reed@Sun.COM 	netstackid_t stackid = net_getnetstackidbynetid(netid);
566*7513SDarren.Reed@Sun.COM 
567*7513SDarren.Reed@Sun.COM 	if (stackid != -1)
568*7513SDarren.Reed@Sun.COM 		kstat_delete_netstack(ks, stackid);
569*7513SDarren.Reed@Sun.COM }
570*7513SDarren.Reed@Sun.COM 
571*7513SDarren.Reed@Sun.COM int
572*7513SDarren.Reed@Sun.COM net_event_notify_register(net_handle_t family, char *event,
573*7513SDarren.Reed@Sun.COM     hook_notify_fn_t callback, void *arg)
574*7513SDarren.Reed@Sun.COM {
575*7513SDarren.Reed@Sun.COM 	int error;
576*7513SDarren.Reed@Sun.COM 
577*7513SDarren.Reed@Sun.COM 	if (family->netd_condemned != 0 || family->netd_stack == NULL)
578*7513SDarren.Reed@Sun.COM 		return (ESHUTDOWN);
579*7513SDarren.Reed@Sun.COM 
580*7513SDarren.Reed@Sun.COM 	error = hook_event_notify_register(family->netd_hooks, event,
581*7513SDarren.Reed@Sun.COM 	    callback, arg);
582*7513SDarren.Reed@Sun.COM 
583*7513SDarren.Reed@Sun.COM 	return (error);
584*7513SDarren.Reed@Sun.COM }
585*7513SDarren.Reed@Sun.COM 
586*7513SDarren.Reed@Sun.COM int
587*7513SDarren.Reed@Sun.COM net_event_notify_unregister(net_handle_t family, char *event,
588*7513SDarren.Reed@Sun.COM     hook_notify_fn_t callback)
589*7513SDarren.Reed@Sun.COM {
590*7513SDarren.Reed@Sun.COM 	int error;
591*7513SDarren.Reed@Sun.COM 
592*7513SDarren.Reed@Sun.COM 	error = hook_event_notify_unregister(family->netd_hooks, event,
593*7513SDarren.Reed@Sun.COM 	    callback);
594*7513SDarren.Reed@Sun.COM 
595*7513SDarren.Reed@Sun.COM 	return (error);
596*7513SDarren.Reed@Sun.COM }
597*7513SDarren.Reed@Sun.COM 
598*7513SDarren.Reed@Sun.COM int
599*7513SDarren.Reed@Sun.COM net_protocol_notify_register(net_handle_t family, hook_notify_fn_t callback,
600*7513SDarren.Reed@Sun.COM     void *arg)
601*7513SDarren.Reed@Sun.COM {
602*7513SDarren.Reed@Sun.COM 	int error;
603*7513SDarren.Reed@Sun.COM 
604*7513SDarren.Reed@Sun.COM 	if (family->netd_condemned != 0 || family->netd_stack == NULL)
605*7513SDarren.Reed@Sun.COM 		return (ESHUTDOWN);
606*7513SDarren.Reed@Sun.COM 
607*7513SDarren.Reed@Sun.COM 	error = hook_family_notify_register(family->netd_hooks, callback,
608*7513SDarren.Reed@Sun.COM 	    arg);
609*7513SDarren.Reed@Sun.COM 
610*7513SDarren.Reed@Sun.COM 	return (error);
611*7513SDarren.Reed@Sun.COM }
612*7513SDarren.Reed@Sun.COM 
613*7513SDarren.Reed@Sun.COM int
614*7513SDarren.Reed@Sun.COM net_protocol_notify_unregister(net_handle_t family, hook_notify_fn_t callback)
615*7513SDarren.Reed@Sun.COM {
616*7513SDarren.Reed@Sun.COM 	int error;
617*7513SDarren.Reed@Sun.COM 
618*7513SDarren.Reed@Sun.COM 	error = hook_family_notify_unregister(family->netd_hooks, callback);
619*7513SDarren.Reed@Sun.COM 
620*7513SDarren.Reed@Sun.COM 	return (error);
621*7513SDarren.Reed@Sun.COM }
622