xref: /titanic_51/usr/src/uts/common/io/neti_impl.c (revision 1a5e258f5471356ca102c7176637cdce45bac147)
17ddc9b1aSDarren Reed /*
27ddc9b1aSDarren Reed  * CDDL HEADER START
37ddc9b1aSDarren Reed  *
47ddc9b1aSDarren Reed  * The contents of this file are subject to the terms of the
57ddc9b1aSDarren Reed  * Common Development and Distribution License (the "License").
67ddc9b1aSDarren Reed  * You may not use this file except in compliance with the License.
77ddc9b1aSDarren Reed  *
87ddc9b1aSDarren Reed  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97ddc9b1aSDarren Reed  * or http://www.opensolaris.org/os/licensing.
107ddc9b1aSDarren Reed  * See the License for the specific language governing permissions
117ddc9b1aSDarren Reed  * and limitations under the License.
127ddc9b1aSDarren Reed  *
137ddc9b1aSDarren Reed  * When distributing Covered Code, include this CDDL HEADER in each
147ddc9b1aSDarren Reed  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157ddc9b1aSDarren Reed  * If applicable, add the following below this CDDL HEADER, with the
167ddc9b1aSDarren Reed  * fields enclosed by brackets "[]" replaced with your own identifying
177ddc9b1aSDarren Reed  * information: Portions Copyright [yyyy] [name of copyright owner]
187ddc9b1aSDarren Reed  *
197ddc9b1aSDarren Reed  * CDDL HEADER END
207ddc9b1aSDarren Reed  */
217ddc9b1aSDarren Reed /*
227ddc9b1aSDarren Reed  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237ddc9b1aSDarren Reed  * Use is subject to license terms.
247ddc9b1aSDarren Reed  */
257ddc9b1aSDarren Reed 
267ddc9b1aSDarren Reed #include <sys/param.h>
277ddc9b1aSDarren Reed #include <sys/atomic.h>
287ddc9b1aSDarren Reed #include <sys/kmem.h>
297ddc9b1aSDarren Reed #include <sys/rwlock.h>
307ddc9b1aSDarren Reed #include <sys/errno.h>
317ddc9b1aSDarren Reed #include <sys/queue.h>
327ddc9b1aSDarren Reed #include <inet/common.h>
337ddc9b1aSDarren Reed #include <inet/led.h>
347ddc9b1aSDarren Reed #include <inet/ip.h>
357ddc9b1aSDarren Reed #include <sys/neti.h>
367ddc9b1aSDarren Reed #include <sys/zone.h>
377ddc9b1aSDarren Reed 
387ddc9b1aSDarren Reed static net_handle_t net_find(const char *protocol, neti_stack_t *ns);
397ddc9b1aSDarren Reed 
407ddc9b1aSDarren Reed static net_handle_t
417ddc9b1aSDarren Reed net_find(const char *protocol, neti_stack_t *nts)
427ddc9b1aSDarren Reed {
437ddc9b1aSDarren Reed 	struct net_data *n;
447ddc9b1aSDarren Reed 
457ddc9b1aSDarren Reed 	ASSERT(protocol != NULL);
467ddc9b1aSDarren Reed 	ASSERT(nts != NULL);
477ddc9b1aSDarren Reed 
487ddc9b1aSDarren Reed 	LIST_FOREACH(n, &nts->nts_netd_head, netd_list) {
497ddc9b1aSDarren Reed 		ASSERT(n->netd_info.netp_name != NULL);
507ddc9b1aSDarren Reed 		/*
517ddc9b1aSDarren Reed 		 * If they're trying to find a protocol that is being
527ddc9b1aSDarren Reed 		 * shutdown, just ignore it..
537ddc9b1aSDarren Reed 		 */
547ddc9b1aSDarren Reed 		if (n->netd_condemned != 0)
557ddc9b1aSDarren Reed 			continue;
567ddc9b1aSDarren Reed 		if (strcmp(n->netd_info.netp_name, protocol) == 0) {
577ddc9b1aSDarren Reed 			break;
587ddc9b1aSDarren Reed 		}
597ddc9b1aSDarren Reed 	}
607ddc9b1aSDarren Reed 
617ddc9b1aSDarren Reed 	return (n);
627ddc9b1aSDarren Reed }
637ddc9b1aSDarren Reed 
647ddc9b1aSDarren Reed net_handle_t
657ddc9b1aSDarren Reed net_protocol_register(netid_t id, const net_protocol_t *info)
667ddc9b1aSDarren Reed {
677ddc9b1aSDarren Reed 	struct net_data *n, *new;
687ddc9b1aSDarren Reed 	neti_stack_t *nts;
697ddc9b1aSDarren Reed 
707ddc9b1aSDarren Reed 	ASSERT(info != NULL);
717ddc9b1aSDarren Reed 
727ddc9b1aSDarren Reed 	nts = net_getnetistackbyid(id);
737ddc9b1aSDarren Reed 	if (nts == NULL)
747ddc9b1aSDarren Reed 		return (NULL);
757ddc9b1aSDarren Reed 
767ddc9b1aSDarren Reed 	new = kmem_alloc(sizeof (*new), KM_SLEEP);
777ddc9b1aSDarren Reed 	new->netd_refcnt = 1;
787ddc9b1aSDarren Reed 	new->netd_hooks = NULL;
797ddc9b1aSDarren Reed 	new->netd_info = *info;
807ddc9b1aSDarren Reed 	new->netd_stack = nts;
817ddc9b1aSDarren Reed 	new->netd_condemned = 0;
827ddc9b1aSDarren Reed 
837ddc9b1aSDarren Reed 	mutex_enter(&nts->nts_lock);
847ddc9b1aSDarren Reed 	n = net_find(info->netp_name, nts);
857ddc9b1aSDarren Reed 	if (n != NULL) {
867ddc9b1aSDarren Reed 		mutex_exit(&nts->nts_lock);
877ddc9b1aSDarren Reed 		kmem_free(new, sizeof (*new));
887ddc9b1aSDarren Reed 		return (NULL);
897ddc9b1aSDarren Reed 	}
907ddc9b1aSDarren Reed 
917ddc9b1aSDarren Reed 	if (LIST_EMPTY(&nts->nts_netd_head)) {
927ddc9b1aSDarren Reed 		LIST_INSERT_HEAD(&nts->nts_netd_head, new, netd_list);
937ddc9b1aSDarren Reed 	} else {
947ddc9b1aSDarren Reed 		LIST_INSERT_AFTER(LIST_FIRST(&nts->nts_netd_head),
957ddc9b1aSDarren Reed 		    new, netd_list);
967ddc9b1aSDarren Reed 	}
977ddc9b1aSDarren Reed 	mutex_exit(&nts->nts_lock);
987ddc9b1aSDarren Reed 
997ddc9b1aSDarren Reed 	return (new);
1007ddc9b1aSDarren Reed }
1017ddc9b1aSDarren Reed 
1027ddc9b1aSDarren Reed int
1037ddc9b1aSDarren Reed net_protocol_unregister(net_handle_t info)
1047ddc9b1aSDarren Reed {
1057ddc9b1aSDarren Reed 	neti_stack_t *nts;
1067ddc9b1aSDarren Reed 
1077ddc9b1aSDarren Reed 	ASSERT(info != NULL);
1087ddc9b1aSDarren Reed 
1097ddc9b1aSDarren Reed 	nts = info->netd_stack;
1107ddc9b1aSDarren Reed 	ASSERT(nts != NULL);
1117ddc9b1aSDarren Reed 
1127ddc9b1aSDarren Reed 	mutex_enter(&nts->nts_lock);
1137ddc9b1aSDarren Reed 	LIST_REMOVE(info, netd_list);
1147ddc9b1aSDarren Reed 	info->netd_stack = NULL;
1157ddc9b1aSDarren Reed 	mutex_exit(&nts->nts_lock);
1167ddc9b1aSDarren Reed 
1177ddc9b1aSDarren Reed 	(void) net_protocol_release(info);
1187ddc9b1aSDarren Reed 
1197ddc9b1aSDarren Reed 	return (0);
1207ddc9b1aSDarren Reed }
1217ddc9b1aSDarren Reed 
1227ddc9b1aSDarren Reed net_handle_t
1237ddc9b1aSDarren Reed net_protocol_lookup(netid_t netid, const char *protocol)
1247ddc9b1aSDarren Reed {
1257ddc9b1aSDarren Reed 	neti_stack_t *nts;
1267ddc9b1aSDarren Reed 	net_handle_t nd;
1277ddc9b1aSDarren Reed 
1287ddc9b1aSDarren Reed 	ASSERT(protocol != NULL);
1297ddc9b1aSDarren Reed 
1307ddc9b1aSDarren Reed 	nts = net_getnetistackbyid(netid);
1317ddc9b1aSDarren Reed 	if (nts == NULL)
1327ddc9b1aSDarren Reed 		return (NULL);
1337ddc9b1aSDarren Reed 
1347ddc9b1aSDarren Reed 	mutex_enter(&nts->nts_lock);
1357ddc9b1aSDarren Reed 	nd = net_find(protocol, nts);
1367ddc9b1aSDarren Reed 	if (nd != NULL)
137*1a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32((uint_t *)&nd->netd_refcnt);
1387ddc9b1aSDarren Reed 	mutex_exit(&nts->nts_lock);
1397ddc9b1aSDarren Reed 	return (nd);
1407ddc9b1aSDarren Reed }
1417ddc9b1aSDarren Reed 
1427ddc9b1aSDarren Reed /*
1437ddc9b1aSDarren Reed  * Note: the man page specifies "returns -1 if the value passed in is unknown
1447ddc9b1aSDarren Reed  * to this framework".  We are not doing a lookup in this function, just a
1457ddc9b1aSDarren Reed  * simply add to the netd_refcnt of the net_handle_t passed in, so -1 is never a
1467ddc9b1aSDarren Reed  * return value.
1477ddc9b1aSDarren Reed  */
1487ddc9b1aSDarren Reed int
1497ddc9b1aSDarren Reed net_protocol_release(net_handle_t info)
1507ddc9b1aSDarren Reed {
1517ddc9b1aSDarren Reed 
1527ddc9b1aSDarren Reed 	ASSERT(info->netd_refcnt > 0);
1537ddc9b1aSDarren Reed 	/*
1547ddc9b1aSDarren Reed 	 * Is this safe? No hold on nts_lock? Consider that if the caller
1557ddc9b1aSDarren Reed 	 * of net_protocol_release() is going to free this structure then
1567ddc9b1aSDarren Reed 	 * it is now the only owner (refcnt==1) and it will have been
1577ddc9b1aSDarren Reed 	 * removed from the nts_netd_head list on the neti_stack_t from a
1587ddc9b1aSDarren Reed 	 * call to net_protocol_unregister already, so it is thus an orphan.
1597ddc9b1aSDarren Reed 	 */
160*1a5e258fSJosef 'Jeff' Sipek 	if (atomic_dec_32_nv((uint_t *)&info->netd_refcnt) == 0) {
1617ddc9b1aSDarren Reed 		ASSERT(info->netd_hooks == NULL);
1627ddc9b1aSDarren Reed 		ASSERT(info->netd_stack == NULL);
1637ddc9b1aSDarren Reed 		kmem_free(info, sizeof (struct net_data));
1647ddc9b1aSDarren Reed 	}
1657ddc9b1aSDarren Reed 
1667ddc9b1aSDarren Reed 	return (0);
1677ddc9b1aSDarren Reed }
1687ddc9b1aSDarren Reed 
1697ddc9b1aSDarren Reed net_handle_t
1707ddc9b1aSDarren Reed net_protocol_walk(netid_t netid, net_handle_t info)
1717ddc9b1aSDarren Reed {
1727ddc9b1aSDarren Reed 	struct net_data *n = NULL;
1737ddc9b1aSDarren Reed 	boolean_t found = B_FALSE;
1747ddc9b1aSDarren Reed 	neti_stack_t *nts;
1757ddc9b1aSDarren Reed 
1767ddc9b1aSDarren Reed 	nts = net_getnetistackbyid(netid);
1777ddc9b1aSDarren Reed 	ASSERT(nts != NULL);
1787ddc9b1aSDarren Reed 
1797ddc9b1aSDarren Reed 	if (info == NULL)
1807ddc9b1aSDarren Reed 		found = B_TRUE;
1817ddc9b1aSDarren Reed 
1827ddc9b1aSDarren Reed 	mutex_enter(&nts->nts_lock);
1837ddc9b1aSDarren Reed 	LIST_FOREACH(n, &nts->nts_netd_head, netd_list) {
1847ddc9b1aSDarren Reed 		if (found) {
1857ddc9b1aSDarren Reed 			/*
1867ddc9b1aSDarren Reed 			 * We are only interested in finding protocols that
1877ddc9b1aSDarren Reed 			 * are not in some sort of shutdown state.  There is
1887ddc9b1aSDarren Reed 			 * no need to check for netd_stack==NULL because
1897ddc9b1aSDarren Reed 			 * that implies it is no longer on this list.
1907ddc9b1aSDarren Reed 			 */
1917ddc9b1aSDarren Reed 			if (n->netd_condemned == 0)
1927ddc9b1aSDarren Reed 				continue;
1937ddc9b1aSDarren Reed 			break;
1947ddc9b1aSDarren Reed 		}
1957ddc9b1aSDarren Reed 
1967ddc9b1aSDarren Reed 		if (n == info)
1977ddc9b1aSDarren Reed 			found = B_TRUE;
1987ddc9b1aSDarren Reed 	}
1997ddc9b1aSDarren Reed 
2007ddc9b1aSDarren Reed 	if (info != NULL)
2017ddc9b1aSDarren Reed 		(void) net_protocol_release(info);
2027ddc9b1aSDarren Reed 
2037ddc9b1aSDarren Reed 	if (n != NULL)
204*1a5e258fSJosef 'Jeff' Sipek 		atomic_inc_32((uint_t *)&n->netd_refcnt);
2057ddc9b1aSDarren Reed 
2067ddc9b1aSDarren Reed 	mutex_exit(&nts->nts_lock);
2077ddc9b1aSDarren Reed 
2087ddc9b1aSDarren Reed 	return (n);
2097ddc9b1aSDarren Reed }
2107ddc9b1aSDarren Reed 
2117ddc9b1aSDarren Reed /*
2127ddc9b1aSDarren Reed  * Public accessor functions
2137ddc9b1aSDarren Reed  */
2147ddc9b1aSDarren Reed int
2157ddc9b1aSDarren Reed net_getifname(net_handle_t info, phy_if_t nic, char *buffer,
2167ddc9b1aSDarren Reed     const size_t buflen)
2177ddc9b1aSDarren Reed {
2187ddc9b1aSDarren Reed 
2197ddc9b1aSDarren Reed 	ASSERT(info != NULL);
2207ddc9b1aSDarren Reed 
2217ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
2227ddc9b1aSDarren Reed 		return (-1);
2237ddc9b1aSDarren Reed 
2247ddc9b1aSDarren Reed 	return (info->netd_info.netp_getifname(info, nic, buffer, buflen));
2257ddc9b1aSDarren Reed }
2267ddc9b1aSDarren Reed 
2277ddc9b1aSDarren Reed int
2287ddc9b1aSDarren Reed net_getmtu(net_handle_t info, phy_if_t nic, lif_if_t ifdata)
2297ddc9b1aSDarren Reed {
2307ddc9b1aSDarren Reed 
2317ddc9b1aSDarren Reed 	ASSERT(info != NULL);
2327ddc9b1aSDarren Reed 
2337ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
2347ddc9b1aSDarren Reed 		return (-1);
2357ddc9b1aSDarren Reed 
2367ddc9b1aSDarren Reed 	return (info->netd_info.netp_getmtu(info, nic, ifdata));
2377ddc9b1aSDarren Reed }
2387ddc9b1aSDarren Reed 
2397ddc9b1aSDarren Reed int
2407ddc9b1aSDarren Reed net_getpmtuenabled(net_handle_t info)
2417ddc9b1aSDarren Reed {
2427ddc9b1aSDarren Reed 
2437ddc9b1aSDarren Reed 	ASSERT(info != NULL);
2447ddc9b1aSDarren Reed 
2457ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
2467ddc9b1aSDarren Reed 		return (-1);
2477ddc9b1aSDarren Reed 
2487ddc9b1aSDarren Reed 	return (info->netd_info.netp_getpmtuenabled(info));
2497ddc9b1aSDarren Reed }
2507ddc9b1aSDarren Reed 
2517ddc9b1aSDarren Reed int
2527ddc9b1aSDarren Reed net_getlifaddr(net_handle_t info, phy_if_t nic, lif_if_t ifdata,
2537ddc9b1aSDarren Reed     int nelem, net_ifaddr_t type[], void *storage)
2547ddc9b1aSDarren Reed {
2557ddc9b1aSDarren Reed 
2567ddc9b1aSDarren Reed 	ASSERT(info != NULL);
2577ddc9b1aSDarren Reed 
2587ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
2597ddc9b1aSDarren Reed 		return (-1);
2607ddc9b1aSDarren Reed 
2617ddc9b1aSDarren Reed 	return (info->netd_info.netp_getlifaddr(info, nic, ifdata,
2627ddc9b1aSDarren Reed 	    nelem, type, storage));
2637ddc9b1aSDarren Reed }
2647ddc9b1aSDarren Reed 
265b127ac41SPhilip Kirk int
266b127ac41SPhilip Kirk net_getlifzone(net_handle_t info, phy_if_t phy_ifdata, lif_if_t ifdata,
267b127ac41SPhilip Kirk     zoneid_t *zoneid)
268b127ac41SPhilip Kirk {
269b127ac41SPhilip Kirk 	ASSERT(info != NULL);
270b127ac41SPhilip Kirk 
271b127ac41SPhilip Kirk 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
272b127ac41SPhilip Kirk 		return (-1);
273b127ac41SPhilip Kirk 
274b127ac41SPhilip Kirk 	return (info->netd_info.neti_getlifzone(info, phy_ifdata, ifdata,
275b127ac41SPhilip Kirk 	    zoneid));
276b127ac41SPhilip Kirk }
277b127ac41SPhilip Kirk 
278b127ac41SPhilip Kirk int
279b127ac41SPhilip Kirk net_getlifflags(net_handle_t info, phy_if_t phy_ifdata, lif_if_t ifdata,
280b127ac41SPhilip Kirk     uint64_t *flags)
281b127ac41SPhilip Kirk {
282b127ac41SPhilip Kirk 	ASSERT(info != NULL);
283b127ac41SPhilip Kirk 
284b127ac41SPhilip Kirk 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
285b127ac41SPhilip Kirk 		return (-1);
286b127ac41SPhilip Kirk 
287b127ac41SPhilip Kirk 	return (info->netd_info.neti_getlifflags(info, phy_ifdata, ifdata,
288b127ac41SPhilip Kirk 	    flags));
289b127ac41SPhilip Kirk }
290b127ac41SPhilip Kirk 
2917ddc9b1aSDarren Reed phy_if_t
2927ddc9b1aSDarren Reed net_phygetnext(net_handle_t info, phy_if_t nic)
2937ddc9b1aSDarren Reed {
2947ddc9b1aSDarren Reed 
2957ddc9b1aSDarren Reed 	ASSERT(info != NULL);
2967ddc9b1aSDarren Reed 
2977ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
2987ddc9b1aSDarren Reed 		return ((phy_if_t)-1);
2997ddc9b1aSDarren Reed 
3007ddc9b1aSDarren Reed 	return (info->netd_info.netp_phygetnext(info, nic));
3017ddc9b1aSDarren Reed }
3027ddc9b1aSDarren Reed 
3037ddc9b1aSDarren Reed phy_if_t
3047ddc9b1aSDarren Reed net_phylookup(net_handle_t info, const char *name)
3057ddc9b1aSDarren Reed {
3067ddc9b1aSDarren Reed 
3077ddc9b1aSDarren Reed 	ASSERT(info != NULL);
3087ddc9b1aSDarren Reed 
3097ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
3107ddc9b1aSDarren Reed 		return ((phy_if_t)-1);
3117ddc9b1aSDarren Reed 
3127ddc9b1aSDarren Reed 	return (info->netd_info.netp_phylookup(info, name));
3137ddc9b1aSDarren Reed }
3147ddc9b1aSDarren Reed 
3157ddc9b1aSDarren Reed lif_if_t
3167ddc9b1aSDarren Reed net_lifgetnext(net_handle_t info, phy_if_t ifidx, lif_if_t ifdata)
3177ddc9b1aSDarren Reed {
3187ddc9b1aSDarren Reed 
3197ddc9b1aSDarren Reed 	ASSERT(info != NULL);
3207ddc9b1aSDarren Reed 
3217ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
3227ddc9b1aSDarren Reed 		return ((lif_if_t)-1);
3237ddc9b1aSDarren Reed 
3247ddc9b1aSDarren Reed 	return (info->netd_info.netp_lifgetnext(info, ifidx, ifdata));
3257ddc9b1aSDarren Reed }
3267ddc9b1aSDarren Reed 
3277ddc9b1aSDarren Reed int
3287ddc9b1aSDarren Reed net_inject(net_handle_t info, inject_t style, net_inject_t *packet)
3297ddc9b1aSDarren Reed {
3307ddc9b1aSDarren Reed 
3317ddc9b1aSDarren Reed 	ASSERT(info != NULL);
3327ddc9b1aSDarren Reed 
3337ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
3347ddc9b1aSDarren Reed 		return (-1);
3357ddc9b1aSDarren Reed 
3367ddc9b1aSDarren Reed 	return (info->netd_info.netp_inject(info, style, packet));
3377ddc9b1aSDarren Reed }
3387ddc9b1aSDarren Reed 
3397ddc9b1aSDarren Reed phy_if_t
3407ddc9b1aSDarren Reed net_routeto(net_handle_t info, struct sockaddr *address, struct sockaddr *next)
3417ddc9b1aSDarren Reed {
3427ddc9b1aSDarren Reed 
3437ddc9b1aSDarren Reed 	ASSERT(info != NULL);
3447ddc9b1aSDarren Reed 
3457ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
3467ddc9b1aSDarren Reed 		return ((phy_if_t)-1);
3477ddc9b1aSDarren Reed 
3487ddc9b1aSDarren Reed 	return (info->netd_info.netp_routeto(info, address, next));
3497ddc9b1aSDarren Reed }
3507ddc9b1aSDarren Reed 
3517ddc9b1aSDarren Reed int
3527ddc9b1aSDarren Reed net_ispartialchecksum(net_handle_t info, mblk_t *mp)
3537ddc9b1aSDarren Reed {
3547ddc9b1aSDarren Reed 
3557ddc9b1aSDarren Reed 	ASSERT(info != NULL);
3567ddc9b1aSDarren Reed 	ASSERT(mp != NULL);
3577ddc9b1aSDarren Reed 
3587ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
3597ddc9b1aSDarren Reed 		return (-1);
3607ddc9b1aSDarren Reed 
3617ddc9b1aSDarren Reed 	return (info->netd_info.netp_ispartialchecksum(info, mp));
3627ddc9b1aSDarren Reed }
3637ddc9b1aSDarren Reed 
3647ddc9b1aSDarren Reed int
3657ddc9b1aSDarren Reed net_isvalidchecksum(net_handle_t info, mblk_t *mp)
3667ddc9b1aSDarren Reed {
3677ddc9b1aSDarren Reed 
3687ddc9b1aSDarren Reed 	ASSERT(info != NULL);
3697ddc9b1aSDarren Reed 	ASSERT(mp != NULL);
3707ddc9b1aSDarren Reed 
3717ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
3727ddc9b1aSDarren Reed 		return (-1);
3737ddc9b1aSDarren Reed 
3747ddc9b1aSDarren Reed 	return (info->netd_info.netp_isvalidchecksum(info, mp));
3757ddc9b1aSDarren Reed }
3767ddc9b1aSDarren Reed 
3777ddc9b1aSDarren Reed /*
3787ddc9b1aSDarren Reed  * Hooks related functions
3797ddc9b1aSDarren Reed  */
3807ddc9b1aSDarren Reed 
3817ddc9b1aSDarren Reed /*
3827ddc9b1aSDarren Reed  * Function:	net_family_register
3837ddc9b1aSDarren Reed  * Returns:	int - 0 = Succ, Else = Fail
3847ddc9b1aSDarren Reed  * Parameters:	info(I) - protocol
3857ddc9b1aSDarren Reed  *		hf(I) - family pointer
3867ddc9b1aSDarren Reed  *
3877ddc9b1aSDarren Reed  * Call hook_family_add to register family
3887ddc9b1aSDarren Reed  *
3897ddc9b1aSDarren Reed  * There is no need to bump netd_refcnt in the two functions
3907ddc9b1aSDarren Reed  * net_family_register and net_family_unregister because the caller of these
3917ddc9b1aSDarren Reed  * two functions is assumed to "own" a reference on 'info' via an earlier
3927ddc9b1aSDarren Reed  * call to net_protocol_register().  Thus the owner is expected to do a
3937ddc9b1aSDarren Reed  * call to net_protocol_unregister() after having done a
3947ddc9b1aSDarren Reed  * net_family_unregister() to make sure things are properly cleaned up.
3954a9b8375SDarren Reed  * Passing a pointer to info->netd_hooks into hook_family_add is required
3964a9b8375SDarren Reed  * so that this can be set before the notify functions are called. If this
3974a9b8375SDarren Reed  * does not happen, the notify function may do something that seems fine,
3984a9b8375SDarren Reed  * like add a notify function to the family but cause a panic because
3994a9b8375SDarren Reed  * netd_hooks is NULL when we get to hook_family_notify_register.
4007ddc9b1aSDarren Reed  */
4017ddc9b1aSDarren Reed int
4027ddc9b1aSDarren Reed net_family_register(net_handle_t info, hook_family_t *hf)
4037ddc9b1aSDarren Reed {
4047ddc9b1aSDarren Reed 	netstack_t *ns;
4057ddc9b1aSDarren Reed 
4067ddc9b1aSDarren Reed 	ASSERT(info != NULL);
4077ddc9b1aSDarren Reed 	ASSERT(hf != NULL);
4087ddc9b1aSDarren Reed 
4097ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
4107ddc9b1aSDarren Reed 		return (ESHUTDOWN);
4117ddc9b1aSDarren Reed 
4127ddc9b1aSDarren Reed 	if (info->netd_hooks != NULL)
4137ddc9b1aSDarren Reed 		return (EEXIST);
4147ddc9b1aSDarren Reed 
4157ddc9b1aSDarren Reed 	ns = info->netd_stack->nts_netstack;
4167ddc9b1aSDarren Reed 	ASSERT(ns != NULL);
4174a9b8375SDarren Reed 	if (hook_family_add(hf, ns->netstack_hook,
4184a9b8375SDarren Reed 	    (void **)&info->netd_hooks) == NULL)
4197ddc9b1aSDarren Reed 		return (EEXIST);
4207ddc9b1aSDarren Reed 
4217ddc9b1aSDarren Reed 	return (0);
4227ddc9b1aSDarren Reed }
4237ddc9b1aSDarren Reed 
4247ddc9b1aSDarren Reed /*
4257ddc9b1aSDarren Reed  * Function:	net_family_unregister
4267ddc9b1aSDarren Reed  * Returns:	int - transparent value, explained by caller
4277ddc9b1aSDarren Reed  * Parameters:	info(I) - protocol
4287ddc9b1aSDarren Reed  *		hf(I) - family pointer
4297ddc9b1aSDarren Reed  *
4307ddc9b1aSDarren Reed  * Call hook_family_remove to unregister family
4317ddc9b1aSDarren Reed  */
4327ddc9b1aSDarren Reed int
4337ddc9b1aSDarren Reed net_family_unregister(net_handle_t info, hook_family_t *hf)
4347ddc9b1aSDarren Reed {
4357ddc9b1aSDarren Reed 	int ret;
4367ddc9b1aSDarren Reed 
4377ddc9b1aSDarren Reed 	ASSERT(info != NULL);
4387ddc9b1aSDarren Reed 	ASSERT(hf != NULL);
4397ddc9b1aSDarren Reed 
4407ddc9b1aSDarren Reed 	if (info->netd_hooks == NULL)
4417ddc9b1aSDarren Reed 		return (ENXIO);
4427ddc9b1aSDarren Reed 
4437ddc9b1aSDarren Reed 	if (strcmp(info->netd_hooks->hfi_family.hf_name,
4447ddc9b1aSDarren Reed 	    hf->hf_name) != 0)
4457ddc9b1aSDarren Reed 		return (EINVAL);
4467ddc9b1aSDarren Reed 
4477ddc9b1aSDarren Reed 	ret = hook_family_remove(info->netd_hooks);
4487ddc9b1aSDarren Reed 	if (ret == 0)
4497ddc9b1aSDarren Reed 		info->netd_hooks = NULL;
4507ddc9b1aSDarren Reed 
4517ddc9b1aSDarren Reed 	return (ret);
4527ddc9b1aSDarren Reed }
4537ddc9b1aSDarren Reed 
4548ad74188SDarren Reed int
4558ad74188SDarren Reed net_family_shutdown(net_handle_t info, hook_family_t *hf)
4568ad74188SDarren Reed {
4578ad74188SDarren Reed 
4588ad74188SDarren Reed 	ASSERT(info != NULL);
4598ad74188SDarren Reed 	ASSERT(hf != NULL);
4608ad74188SDarren Reed 
4618ad74188SDarren Reed 	if (info->netd_hooks == NULL)
4628ad74188SDarren Reed 		return (ENXIO);
4638ad74188SDarren Reed 
4648ad74188SDarren Reed 	if (strcmp(info->netd_hooks->hfi_family.hf_name,
4658ad74188SDarren Reed 	    hf->hf_name) != 0)
4668ad74188SDarren Reed 		return (EINVAL);
4678ad74188SDarren Reed 
4688ad74188SDarren Reed 	return (hook_family_shutdown(info->netd_hooks));
4698ad74188SDarren Reed }
4708ad74188SDarren Reed 
4717ddc9b1aSDarren Reed /*
4727ddc9b1aSDarren Reed  * Function:	net_event_register
4737ddc9b1aSDarren Reed  * Returns:	internal event pointer - NULL = Fail
4747ddc9b1aSDarren Reed  * Parameters:	info(I) - protocol
4757ddc9b1aSDarren Reed  *		he(I) - event pointer
4767ddc9b1aSDarren Reed  *
4777ddc9b1aSDarren Reed  * Call hook_event_add to register event on specific family
4787ddc9b1aSDarren Reed  * 	Internal event pointer is returned so caller can get
4797ddc9b1aSDarren Reed  * 	handle to run hooks
4807ddc9b1aSDarren Reed  */
4817ddc9b1aSDarren Reed hook_event_token_t
4827ddc9b1aSDarren Reed net_event_register(net_handle_t info, hook_event_t *he)
4837ddc9b1aSDarren Reed {
4847ddc9b1aSDarren Reed 	hook_event_int_t *hei;
4857ddc9b1aSDarren Reed 
4867ddc9b1aSDarren Reed 	ASSERT(info != NULL);
4877ddc9b1aSDarren Reed 	ASSERT(he != NULL);
4887ddc9b1aSDarren Reed 
4897ddc9b1aSDarren Reed 	if (info->netd_hooks == NULL || info->netd_condemned != 0 ||
4907ddc9b1aSDarren Reed 	    info->netd_stack == NULL)
4917ddc9b1aSDarren Reed 		return (NULL);
4927ddc9b1aSDarren Reed 
4937ddc9b1aSDarren Reed 	hei = hook_event_add(info->netd_hooks, he);
4947ddc9b1aSDarren Reed 	return ((hook_event_token_t)hei);
4957ddc9b1aSDarren Reed }
4967ddc9b1aSDarren Reed 
4977ddc9b1aSDarren Reed /*
4987ddc9b1aSDarren Reed  * Function:	net_event_unregister
4997ddc9b1aSDarren Reed  * Returns:	int - transparent value, explained by caller
5007ddc9b1aSDarren Reed  * Parameters:	info(I) - protocol
5017ddc9b1aSDarren Reed  *		he(I) - event pointer
5027ddc9b1aSDarren Reed  *
5037ddc9b1aSDarren Reed  * Call hook_event_remove to unregister event on specific family
5047ddc9b1aSDarren Reed  */
5057ddc9b1aSDarren Reed int
5067ddc9b1aSDarren Reed net_event_unregister(net_handle_t info, hook_event_t *he)
5077ddc9b1aSDarren Reed {
5087ddc9b1aSDarren Reed 
5097ddc9b1aSDarren Reed 	ASSERT(info != NULL);
5107ddc9b1aSDarren Reed 	ASSERT(he != NULL);
5117ddc9b1aSDarren Reed 
5127ddc9b1aSDarren Reed 	if (info->netd_hooks == NULL)
5137ddc9b1aSDarren Reed 		return (ENXIO);
5147ddc9b1aSDarren Reed 
5157ddc9b1aSDarren Reed 	return (hook_event_remove(info->netd_hooks, he));
5167ddc9b1aSDarren Reed }
5177ddc9b1aSDarren Reed 
5188ad74188SDarren Reed int
5198ad74188SDarren Reed net_event_shutdown(net_handle_t info, hook_event_t *he)
5208ad74188SDarren Reed {
5218ad74188SDarren Reed 
5228ad74188SDarren Reed 	ASSERT(info != NULL);
5238ad74188SDarren Reed 	ASSERT(he != NULL);
5248ad74188SDarren Reed 
5258ad74188SDarren Reed 	if (info->netd_hooks == NULL)
5268ad74188SDarren Reed 		return (ENXIO);
5278ad74188SDarren Reed 
5288ad74188SDarren Reed 	return (hook_event_shutdown(info->netd_hooks, he));
5298ad74188SDarren Reed }
5308ad74188SDarren Reed 
5317ddc9b1aSDarren Reed /*
5327ddc9b1aSDarren Reed  * Function:	net_hook_register
5337ddc9b1aSDarren Reed  * Returns:	int - transparent value, explained by caller
5347ddc9b1aSDarren Reed  * Parameters:	info(I) - protocol
5357ddc9b1aSDarren Reed  *		event(I) - event name
5367ddc9b1aSDarren Reed  *		h(I) - hook pointer
5377ddc9b1aSDarren Reed  *
5387ddc9b1aSDarren Reed  * Call hook_register to add hook on specific family/event
5397ddc9b1aSDarren Reed  */
5407ddc9b1aSDarren Reed int
5417ddc9b1aSDarren Reed net_hook_register(net_handle_t info, char *event, hook_t *h)
5427ddc9b1aSDarren Reed {
5437ddc9b1aSDarren Reed 
5447ddc9b1aSDarren Reed 	ASSERT(info != NULL);
5457ddc9b1aSDarren Reed 	ASSERT(event != NULL);
5467ddc9b1aSDarren Reed 	ASSERT(h != NULL);
5477ddc9b1aSDarren Reed 
5487ddc9b1aSDarren Reed 	if (info->netd_condemned != 0 || info->netd_stack == NULL)
5497ddc9b1aSDarren Reed 		return (ESHUTDOWN);
5507ddc9b1aSDarren Reed 
5517ddc9b1aSDarren Reed 	if (info->netd_hooks == NULL)
5527ddc9b1aSDarren Reed 		return (ENXIO);
5537ddc9b1aSDarren Reed 
5547ddc9b1aSDarren Reed 	return (hook_register(info->netd_hooks, event, h));
5557ddc9b1aSDarren Reed }
5567ddc9b1aSDarren Reed 
5577ddc9b1aSDarren Reed /*
5587ddc9b1aSDarren Reed  * Function:	net_hook_unregister
5597ddc9b1aSDarren Reed  * Returns:	int - transparent value, explained by caller
5607ddc9b1aSDarren Reed  * Parameters:	info(I) - protocol
5617ddc9b1aSDarren Reed  *		event(I) - event name
5627ddc9b1aSDarren Reed  *		h(I) - hook pointer
5637ddc9b1aSDarren Reed  *
5647ddc9b1aSDarren Reed  * Call hook_unregister to remove hook on specific family/event
5657ddc9b1aSDarren Reed  */
5667ddc9b1aSDarren Reed int
5677ddc9b1aSDarren Reed net_hook_unregister(net_handle_t info, char *event, hook_t *h)
5687ddc9b1aSDarren Reed {
5697ddc9b1aSDarren Reed 
5707ddc9b1aSDarren Reed 	ASSERT(info != NULL);
5717ddc9b1aSDarren Reed 	ASSERT(event != NULL);
5727ddc9b1aSDarren Reed 	ASSERT(h != NULL);
5737ddc9b1aSDarren Reed 
5747ddc9b1aSDarren Reed 	if (info->netd_hooks == NULL)
5757ddc9b1aSDarren Reed 		return (ENXIO);
5767ddc9b1aSDarren Reed 
5777ddc9b1aSDarren Reed 	return (hook_unregister(info->netd_hooks, event, h));
5787ddc9b1aSDarren Reed }
5797ddc9b1aSDarren Reed 
5807ddc9b1aSDarren Reed netid_t
5817ddc9b1aSDarren Reed net_getnetid(net_handle_t netd)
5827ddc9b1aSDarren Reed {
5837ddc9b1aSDarren Reed 
5847ddc9b1aSDarren Reed 	if (netd->netd_stack == NULL)
5857ddc9b1aSDarren Reed 		return (-1);
5867ddc9b1aSDarren Reed 	return (netd->netd_stack->nts_id);
5877ddc9b1aSDarren Reed }
5887ddc9b1aSDarren Reed 
5897ddc9b1aSDarren Reed net_inject_t *
5907ddc9b1aSDarren Reed net_inject_alloc(const int version)
5917ddc9b1aSDarren Reed {
5927ddc9b1aSDarren Reed 	net_inject_t *ni;
5937ddc9b1aSDarren Reed 
5947ddc9b1aSDarren Reed 	ni = kmem_zalloc(sizeof (*ni), KM_NOSLEEP);
5957ddc9b1aSDarren Reed 	if (ni == NULL)
5967ddc9b1aSDarren Reed 		return (NULL);
5977ddc9b1aSDarren Reed 
5987ddc9b1aSDarren Reed 	ni->ni_version = version;
5997ddc9b1aSDarren Reed 	return (ni);
6007ddc9b1aSDarren Reed }
6017ddc9b1aSDarren Reed 
6027ddc9b1aSDarren Reed void
6037ddc9b1aSDarren Reed net_inject_free(net_inject_t *ni)
6047ddc9b1aSDarren Reed {
6057ddc9b1aSDarren Reed 	kmem_free(ni, sizeof (*ni));
6067ddc9b1aSDarren Reed }
6077ddc9b1aSDarren Reed 
6087ddc9b1aSDarren Reed kstat_t *
6097ddc9b1aSDarren Reed net_kstat_create(netid_t netid, char *module, int instance, char *name,
6107ddc9b1aSDarren Reed     char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
6117ddc9b1aSDarren Reed {
6127ddc9b1aSDarren Reed 	netstackid_t stackid = net_getnetstackidbynetid(netid);
6137ddc9b1aSDarren Reed 
6147ddc9b1aSDarren Reed 	if (stackid == -1)
6157ddc9b1aSDarren Reed 		return (NULL);
6167ddc9b1aSDarren Reed 
6177ddc9b1aSDarren Reed 	return (kstat_create_netstack(module, instance, name, class, type,
6187ddc9b1aSDarren Reed 	    ndata, ks_flag, stackid));
6197ddc9b1aSDarren Reed }
6207ddc9b1aSDarren Reed 
6217ddc9b1aSDarren Reed void
6227ddc9b1aSDarren Reed net_kstat_delete(netid_t netid, kstat_t *ks)
6237ddc9b1aSDarren Reed {
6247ddc9b1aSDarren Reed 	netstackid_t stackid = net_getnetstackidbynetid(netid);
6257ddc9b1aSDarren Reed 
6267ddc9b1aSDarren Reed 	if (stackid != -1)
6277ddc9b1aSDarren Reed 		kstat_delete_netstack(ks, stackid);
6287ddc9b1aSDarren Reed }
6297ddc9b1aSDarren Reed 
6307ddc9b1aSDarren Reed int
6317ddc9b1aSDarren Reed net_event_notify_register(net_handle_t family, char *event,
6327ddc9b1aSDarren Reed     hook_notify_fn_t callback, void *arg)
6337ddc9b1aSDarren Reed {
6347ddc9b1aSDarren Reed 	int error;
6357ddc9b1aSDarren Reed 
6367ddc9b1aSDarren Reed 	if (family->netd_condemned != 0 || family->netd_stack == NULL)
6377ddc9b1aSDarren Reed 		return (ESHUTDOWN);
6387ddc9b1aSDarren Reed 
6397ddc9b1aSDarren Reed 	error = hook_event_notify_register(family->netd_hooks, event,
6407ddc9b1aSDarren Reed 	    callback, arg);
6417ddc9b1aSDarren Reed 
6427ddc9b1aSDarren Reed 	return (error);
6437ddc9b1aSDarren Reed }
6447ddc9b1aSDarren Reed 
6457ddc9b1aSDarren Reed int
6467ddc9b1aSDarren Reed net_event_notify_unregister(net_handle_t family, char *event,
6477ddc9b1aSDarren Reed     hook_notify_fn_t callback)
6487ddc9b1aSDarren Reed {
6497ddc9b1aSDarren Reed 	int error;
6507ddc9b1aSDarren Reed 
6517ddc9b1aSDarren Reed 	error = hook_event_notify_unregister(family->netd_hooks, event,
6527ddc9b1aSDarren Reed 	    callback);
6537ddc9b1aSDarren Reed 
6547ddc9b1aSDarren Reed 	return (error);
6557ddc9b1aSDarren Reed }
6567ddc9b1aSDarren Reed 
6577ddc9b1aSDarren Reed int
6587ddc9b1aSDarren Reed net_protocol_notify_register(net_handle_t family, hook_notify_fn_t callback,
6597ddc9b1aSDarren Reed     void *arg)
6607ddc9b1aSDarren Reed {
6617ddc9b1aSDarren Reed 	int error;
6627ddc9b1aSDarren Reed 
6637ddc9b1aSDarren Reed 	if (family->netd_condemned != 0 || family->netd_stack == NULL)
6647ddc9b1aSDarren Reed 		return (ESHUTDOWN);
6657ddc9b1aSDarren Reed 
6667ddc9b1aSDarren Reed 	error = hook_family_notify_register(family->netd_hooks, callback,
6677ddc9b1aSDarren Reed 	    arg);
6687ddc9b1aSDarren Reed 
6697ddc9b1aSDarren Reed 	return (error);
6707ddc9b1aSDarren Reed }
6717ddc9b1aSDarren Reed 
6727ddc9b1aSDarren Reed int
6737ddc9b1aSDarren Reed net_protocol_notify_unregister(net_handle_t family, hook_notify_fn_t callback)
6747ddc9b1aSDarren Reed {
6757ddc9b1aSDarren Reed 	int error;
6767ddc9b1aSDarren Reed 
6777ddc9b1aSDarren Reed 	error = hook_family_notify_unregister(family->netd_hooks, callback);
6787ddc9b1aSDarren Reed 
6797ddc9b1aSDarren Reed 	return (error);
6807ddc9b1aSDarren Reed }
681