17513SDarren.Reed@Sun.COM /* 27513SDarren.Reed@Sun.COM * CDDL HEADER START 37513SDarren.Reed@Sun.COM * 47513SDarren.Reed@Sun.COM * The contents of this file are subject to the terms of the 57513SDarren.Reed@Sun.COM * Common Development and Distribution License (the "License"). 67513SDarren.Reed@Sun.COM * You may not use this file except in compliance with the License. 77513SDarren.Reed@Sun.COM * 87513SDarren.Reed@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97513SDarren.Reed@Sun.COM * or http://www.opensolaris.org/os/licensing. 107513SDarren.Reed@Sun.COM * See the License for the specific language governing permissions 117513SDarren.Reed@Sun.COM * and limitations under the License. 127513SDarren.Reed@Sun.COM * 137513SDarren.Reed@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 147513SDarren.Reed@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157513SDarren.Reed@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 167513SDarren.Reed@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 177513SDarren.Reed@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 187513SDarren.Reed@Sun.COM * 197513SDarren.Reed@Sun.COM * CDDL HEADER END 207513SDarren.Reed@Sun.COM */ 217513SDarren.Reed@Sun.COM /* 227513SDarren.Reed@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237513SDarren.Reed@Sun.COM * Use is subject to license terms. 247513SDarren.Reed@Sun.COM */ 257513SDarren.Reed@Sun.COM 267513SDarren.Reed@Sun.COM #include <sys/param.h> 277513SDarren.Reed@Sun.COM #include <sys/atomic.h> 287513SDarren.Reed@Sun.COM #include <sys/kmem.h> 297513SDarren.Reed@Sun.COM #include <sys/rwlock.h> 307513SDarren.Reed@Sun.COM #include <sys/errno.h> 317513SDarren.Reed@Sun.COM #include <sys/queue.h> 327513SDarren.Reed@Sun.COM #include <inet/common.h> 337513SDarren.Reed@Sun.COM #include <inet/led.h> 347513SDarren.Reed@Sun.COM #include <inet/ip.h> 357513SDarren.Reed@Sun.COM #include <sys/neti.h> 367513SDarren.Reed@Sun.COM #include <sys/zone.h> 377513SDarren.Reed@Sun.COM 387513SDarren.Reed@Sun.COM static net_handle_t net_find(const char *protocol, neti_stack_t *ns); 397513SDarren.Reed@Sun.COM 407513SDarren.Reed@Sun.COM static net_handle_t 417513SDarren.Reed@Sun.COM net_find(const char *protocol, neti_stack_t *nts) 427513SDarren.Reed@Sun.COM { 437513SDarren.Reed@Sun.COM struct net_data *n; 447513SDarren.Reed@Sun.COM 457513SDarren.Reed@Sun.COM ASSERT(protocol != NULL); 467513SDarren.Reed@Sun.COM ASSERT(nts != NULL); 477513SDarren.Reed@Sun.COM 487513SDarren.Reed@Sun.COM LIST_FOREACH(n, &nts->nts_netd_head, netd_list) { 497513SDarren.Reed@Sun.COM ASSERT(n->netd_info.netp_name != NULL); 507513SDarren.Reed@Sun.COM /* 517513SDarren.Reed@Sun.COM * If they're trying to find a protocol that is being 527513SDarren.Reed@Sun.COM * shutdown, just ignore it.. 537513SDarren.Reed@Sun.COM */ 547513SDarren.Reed@Sun.COM if (n->netd_condemned != 0) 557513SDarren.Reed@Sun.COM continue; 567513SDarren.Reed@Sun.COM if (strcmp(n->netd_info.netp_name, protocol) == 0) { 577513SDarren.Reed@Sun.COM break; 587513SDarren.Reed@Sun.COM } 597513SDarren.Reed@Sun.COM } 607513SDarren.Reed@Sun.COM 617513SDarren.Reed@Sun.COM return (n); 627513SDarren.Reed@Sun.COM } 637513SDarren.Reed@Sun.COM 647513SDarren.Reed@Sun.COM net_handle_t 657513SDarren.Reed@Sun.COM net_protocol_register(netid_t id, const net_protocol_t *info) 667513SDarren.Reed@Sun.COM { 677513SDarren.Reed@Sun.COM struct net_data *n, *new; 687513SDarren.Reed@Sun.COM neti_stack_t *nts; 697513SDarren.Reed@Sun.COM 707513SDarren.Reed@Sun.COM ASSERT(info != NULL); 717513SDarren.Reed@Sun.COM 727513SDarren.Reed@Sun.COM nts = net_getnetistackbyid(id); 737513SDarren.Reed@Sun.COM if (nts == NULL) 747513SDarren.Reed@Sun.COM return (NULL); 757513SDarren.Reed@Sun.COM 767513SDarren.Reed@Sun.COM new = kmem_alloc(sizeof (*new), KM_SLEEP); 777513SDarren.Reed@Sun.COM new->netd_refcnt = 1; 787513SDarren.Reed@Sun.COM new->netd_hooks = NULL; 797513SDarren.Reed@Sun.COM new->netd_info = *info; 807513SDarren.Reed@Sun.COM new->netd_stack = nts; 817513SDarren.Reed@Sun.COM new->netd_condemned = 0; 827513SDarren.Reed@Sun.COM 837513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 847513SDarren.Reed@Sun.COM n = net_find(info->netp_name, nts); 857513SDarren.Reed@Sun.COM if (n != NULL) { 867513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 877513SDarren.Reed@Sun.COM kmem_free(new, sizeof (*new)); 887513SDarren.Reed@Sun.COM return (NULL); 897513SDarren.Reed@Sun.COM } 907513SDarren.Reed@Sun.COM 917513SDarren.Reed@Sun.COM if (LIST_EMPTY(&nts->nts_netd_head)) { 927513SDarren.Reed@Sun.COM LIST_INSERT_HEAD(&nts->nts_netd_head, new, netd_list); 937513SDarren.Reed@Sun.COM } else { 947513SDarren.Reed@Sun.COM LIST_INSERT_AFTER(LIST_FIRST(&nts->nts_netd_head), 957513SDarren.Reed@Sun.COM new, netd_list); 967513SDarren.Reed@Sun.COM } 977513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 987513SDarren.Reed@Sun.COM 997513SDarren.Reed@Sun.COM return (new); 1007513SDarren.Reed@Sun.COM } 1017513SDarren.Reed@Sun.COM 1027513SDarren.Reed@Sun.COM int 1037513SDarren.Reed@Sun.COM net_protocol_unregister(net_handle_t info) 1047513SDarren.Reed@Sun.COM { 1057513SDarren.Reed@Sun.COM neti_stack_t *nts; 1067513SDarren.Reed@Sun.COM 1077513SDarren.Reed@Sun.COM ASSERT(info != NULL); 1087513SDarren.Reed@Sun.COM 1097513SDarren.Reed@Sun.COM nts = info->netd_stack; 1107513SDarren.Reed@Sun.COM ASSERT(nts != NULL); 1117513SDarren.Reed@Sun.COM 1127513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 1137513SDarren.Reed@Sun.COM LIST_REMOVE(info, netd_list); 1147513SDarren.Reed@Sun.COM info->netd_stack = NULL; 1157513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 1167513SDarren.Reed@Sun.COM 1177513SDarren.Reed@Sun.COM (void) net_protocol_release(info); 1187513SDarren.Reed@Sun.COM 1197513SDarren.Reed@Sun.COM return (0); 1207513SDarren.Reed@Sun.COM } 1217513SDarren.Reed@Sun.COM 1227513SDarren.Reed@Sun.COM net_handle_t 1237513SDarren.Reed@Sun.COM net_protocol_lookup(netid_t netid, const char *protocol) 1247513SDarren.Reed@Sun.COM { 1257513SDarren.Reed@Sun.COM neti_stack_t *nts; 1267513SDarren.Reed@Sun.COM net_handle_t nd; 1277513SDarren.Reed@Sun.COM 1287513SDarren.Reed@Sun.COM ASSERT(protocol != NULL); 1297513SDarren.Reed@Sun.COM 1307513SDarren.Reed@Sun.COM nts = net_getnetistackbyid(netid); 1317513SDarren.Reed@Sun.COM if (nts == NULL) 1327513SDarren.Reed@Sun.COM return (NULL); 1337513SDarren.Reed@Sun.COM 1347513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 1357513SDarren.Reed@Sun.COM nd = net_find(protocol, nts); 1367513SDarren.Reed@Sun.COM if (nd != NULL) 1377513SDarren.Reed@Sun.COM atomic_add_32((uint_t *)&nd->netd_refcnt, 1); 1387513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 1397513SDarren.Reed@Sun.COM return (nd); 1407513SDarren.Reed@Sun.COM } 1417513SDarren.Reed@Sun.COM 1427513SDarren.Reed@Sun.COM /* 1437513SDarren.Reed@Sun.COM * Note: the man page specifies "returns -1 if the value passed in is unknown 1447513SDarren.Reed@Sun.COM * to this framework". We are not doing a lookup in this function, just a 1457513SDarren.Reed@Sun.COM * simply add to the netd_refcnt of the net_handle_t passed in, so -1 is never a 1467513SDarren.Reed@Sun.COM * return value. 1477513SDarren.Reed@Sun.COM */ 1487513SDarren.Reed@Sun.COM int 1497513SDarren.Reed@Sun.COM net_protocol_release(net_handle_t info) 1507513SDarren.Reed@Sun.COM { 1517513SDarren.Reed@Sun.COM 1527513SDarren.Reed@Sun.COM ASSERT(info->netd_refcnt > 0); 1537513SDarren.Reed@Sun.COM /* 1547513SDarren.Reed@Sun.COM * Is this safe? No hold on nts_lock? Consider that if the caller 1557513SDarren.Reed@Sun.COM * of net_protocol_release() is going to free this structure then 1567513SDarren.Reed@Sun.COM * it is now the only owner (refcnt==1) and it will have been 1577513SDarren.Reed@Sun.COM * removed from the nts_netd_head list on the neti_stack_t from a 1587513SDarren.Reed@Sun.COM * call to net_protocol_unregister already, so it is thus an orphan. 1597513SDarren.Reed@Sun.COM */ 1607513SDarren.Reed@Sun.COM if (atomic_add_32_nv((uint_t *)&info->netd_refcnt, -1) == 0) { 1617513SDarren.Reed@Sun.COM ASSERT(info->netd_hooks == NULL); 1627513SDarren.Reed@Sun.COM ASSERT(info->netd_stack == NULL); 1637513SDarren.Reed@Sun.COM kmem_free(info, sizeof (struct net_data)); 1647513SDarren.Reed@Sun.COM } 1657513SDarren.Reed@Sun.COM 1667513SDarren.Reed@Sun.COM return (0); 1677513SDarren.Reed@Sun.COM } 1687513SDarren.Reed@Sun.COM 1697513SDarren.Reed@Sun.COM net_handle_t 1707513SDarren.Reed@Sun.COM net_protocol_walk(netid_t netid, net_handle_t info) 1717513SDarren.Reed@Sun.COM { 1727513SDarren.Reed@Sun.COM struct net_data *n = NULL; 1737513SDarren.Reed@Sun.COM boolean_t found = B_FALSE; 1747513SDarren.Reed@Sun.COM neti_stack_t *nts; 1757513SDarren.Reed@Sun.COM 1767513SDarren.Reed@Sun.COM nts = net_getnetistackbyid(netid); 1777513SDarren.Reed@Sun.COM ASSERT(nts != NULL); 1787513SDarren.Reed@Sun.COM 1797513SDarren.Reed@Sun.COM if (info == NULL) 1807513SDarren.Reed@Sun.COM found = B_TRUE; 1817513SDarren.Reed@Sun.COM 1827513SDarren.Reed@Sun.COM mutex_enter(&nts->nts_lock); 1837513SDarren.Reed@Sun.COM LIST_FOREACH(n, &nts->nts_netd_head, netd_list) { 1847513SDarren.Reed@Sun.COM if (found) { 1857513SDarren.Reed@Sun.COM /* 1867513SDarren.Reed@Sun.COM * We are only interested in finding protocols that 1877513SDarren.Reed@Sun.COM * are not in some sort of shutdown state. There is 1887513SDarren.Reed@Sun.COM * no need to check for netd_stack==NULL because 1897513SDarren.Reed@Sun.COM * that implies it is no longer on this list. 1907513SDarren.Reed@Sun.COM */ 1917513SDarren.Reed@Sun.COM if (n->netd_condemned == 0) 1927513SDarren.Reed@Sun.COM continue; 1937513SDarren.Reed@Sun.COM break; 1947513SDarren.Reed@Sun.COM } 1957513SDarren.Reed@Sun.COM 1967513SDarren.Reed@Sun.COM if (n == info) 1977513SDarren.Reed@Sun.COM found = B_TRUE; 1987513SDarren.Reed@Sun.COM } 1997513SDarren.Reed@Sun.COM 2007513SDarren.Reed@Sun.COM if (info != NULL) 2017513SDarren.Reed@Sun.COM (void) net_protocol_release(info); 2027513SDarren.Reed@Sun.COM 2037513SDarren.Reed@Sun.COM if (n != NULL) 2047513SDarren.Reed@Sun.COM atomic_add_32((uint_t *)&n->netd_refcnt, 1); 2057513SDarren.Reed@Sun.COM 2067513SDarren.Reed@Sun.COM mutex_exit(&nts->nts_lock); 2077513SDarren.Reed@Sun.COM 2087513SDarren.Reed@Sun.COM return (n); 2097513SDarren.Reed@Sun.COM } 2107513SDarren.Reed@Sun.COM 2117513SDarren.Reed@Sun.COM /* 2127513SDarren.Reed@Sun.COM * Public accessor functions 2137513SDarren.Reed@Sun.COM */ 2147513SDarren.Reed@Sun.COM int 2157513SDarren.Reed@Sun.COM net_getifname(net_handle_t info, phy_if_t nic, char *buffer, 2167513SDarren.Reed@Sun.COM const size_t buflen) 2177513SDarren.Reed@Sun.COM { 2187513SDarren.Reed@Sun.COM 2197513SDarren.Reed@Sun.COM ASSERT(info != NULL); 2207513SDarren.Reed@Sun.COM 2217513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2227513SDarren.Reed@Sun.COM return (-1); 2237513SDarren.Reed@Sun.COM 2247513SDarren.Reed@Sun.COM return (info->netd_info.netp_getifname(info, nic, buffer, buflen)); 2257513SDarren.Reed@Sun.COM } 2267513SDarren.Reed@Sun.COM 2277513SDarren.Reed@Sun.COM int 2287513SDarren.Reed@Sun.COM net_getmtu(net_handle_t info, phy_if_t nic, lif_if_t ifdata) 2297513SDarren.Reed@Sun.COM { 2307513SDarren.Reed@Sun.COM 2317513SDarren.Reed@Sun.COM ASSERT(info != NULL); 2327513SDarren.Reed@Sun.COM 2337513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2347513SDarren.Reed@Sun.COM return (-1); 2357513SDarren.Reed@Sun.COM 2367513SDarren.Reed@Sun.COM return (info->netd_info.netp_getmtu(info, nic, ifdata)); 2377513SDarren.Reed@Sun.COM } 2387513SDarren.Reed@Sun.COM 2397513SDarren.Reed@Sun.COM int 2407513SDarren.Reed@Sun.COM net_getpmtuenabled(net_handle_t info) 2417513SDarren.Reed@Sun.COM { 2427513SDarren.Reed@Sun.COM 2437513SDarren.Reed@Sun.COM ASSERT(info != NULL); 2447513SDarren.Reed@Sun.COM 2457513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2467513SDarren.Reed@Sun.COM return (-1); 2477513SDarren.Reed@Sun.COM 2487513SDarren.Reed@Sun.COM return (info->netd_info.netp_getpmtuenabled(info)); 2497513SDarren.Reed@Sun.COM } 2507513SDarren.Reed@Sun.COM 2517513SDarren.Reed@Sun.COM int 2527513SDarren.Reed@Sun.COM net_getlifaddr(net_handle_t info, phy_if_t nic, lif_if_t ifdata, 2537513SDarren.Reed@Sun.COM int nelem, net_ifaddr_t type[], void *storage) 2547513SDarren.Reed@Sun.COM { 2557513SDarren.Reed@Sun.COM 2567513SDarren.Reed@Sun.COM ASSERT(info != NULL); 2577513SDarren.Reed@Sun.COM 2587513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2597513SDarren.Reed@Sun.COM return (-1); 2607513SDarren.Reed@Sun.COM 2617513SDarren.Reed@Sun.COM return (info->netd_info.netp_getlifaddr(info, nic, ifdata, 2627513SDarren.Reed@Sun.COM nelem, type, storage)); 2637513SDarren.Reed@Sun.COM } 2647513SDarren.Reed@Sun.COM 2658023SPhil.Kirk@Sun.COM int 2668023SPhil.Kirk@Sun.COM net_getlifzone(net_handle_t info, phy_if_t phy_ifdata, lif_if_t ifdata, 2678023SPhil.Kirk@Sun.COM zoneid_t *zoneid) 2688023SPhil.Kirk@Sun.COM { 2698023SPhil.Kirk@Sun.COM ASSERT(info != NULL); 2708023SPhil.Kirk@Sun.COM 2718023SPhil.Kirk@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2728023SPhil.Kirk@Sun.COM return (-1); 2738023SPhil.Kirk@Sun.COM 2748023SPhil.Kirk@Sun.COM return (info->netd_info.neti_getlifzone(info, phy_ifdata, ifdata, 2758023SPhil.Kirk@Sun.COM zoneid)); 2768023SPhil.Kirk@Sun.COM } 2778023SPhil.Kirk@Sun.COM 2788023SPhil.Kirk@Sun.COM int 2798023SPhil.Kirk@Sun.COM net_getlifflags(net_handle_t info, phy_if_t phy_ifdata, lif_if_t ifdata, 2808023SPhil.Kirk@Sun.COM uint64_t *flags) 2818023SPhil.Kirk@Sun.COM { 2828023SPhil.Kirk@Sun.COM ASSERT(info != NULL); 2838023SPhil.Kirk@Sun.COM 2848023SPhil.Kirk@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2858023SPhil.Kirk@Sun.COM return (-1); 2868023SPhil.Kirk@Sun.COM 2878023SPhil.Kirk@Sun.COM return (info->netd_info.neti_getlifflags(info, phy_ifdata, ifdata, 2888023SPhil.Kirk@Sun.COM flags)); 2898023SPhil.Kirk@Sun.COM } 2908023SPhil.Kirk@Sun.COM 2917513SDarren.Reed@Sun.COM phy_if_t 2927513SDarren.Reed@Sun.COM net_phygetnext(net_handle_t info, phy_if_t nic) 2937513SDarren.Reed@Sun.COM { 2947513SDarren.Reed@Sun.COM 2957513SDarren.Reed@Sun.COM ASSERT(info != NULL); 2967513SDarren.Reed@Sun.COM 2977513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 2987513SDarren.Reed@Sun.COM return ((phy_if_t)-1); 2997513SDarren.Reed@Sun.COM 3007513SDarren.Reed@Sun.COM return (info->netd_info.netp_phygetnext(info, nic)); 3017513SDarren.Reed@Sun.COM } 3027513SDarren.Reed@Sun.COM 3037513SDarren.Reed@Sun.COM phy_if_t 3047513SDarren.Reed@Sun.COM net_phylookup(net_handle_t info, const char *name) 3057513SDarren.Reed@Sun.COM { 3067513SDarren.Reed@Sun.COM 3077513SDarren.Reed@Sun.COM ASSERT(info != NULL); 3087513SDarren.Reed@Sun.COM 3097513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 3107513SDarren.Reed@Sun.COM return ((phy_if_t)-1); 3117513SDarren.Reed@Sun.COM 3127513SDarren.Reed@Sun.COM return (info->netd_info.netp_phylookup(info, name)); 3137513SDarren.Reed@Sun.COM } 3147513SDarren.Reed@Sun.COM 3157513SDarren.Reed@Sun.COM lif_if_t 3167513SDarren.Reed@Sun.COM net_lifgetnext(net_handle_t info, phy_if_t ifidx, lif_if_t ifdata) 3177513SDarren.Reed@Sun.COM { 3187513SDarren.Reed@Sun.COM 3197513SDarren.Reed@Sun.COM ASSERT(info != NULL); 3207513SDarren.Reed@Sun.COM 3217513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 3227513SDarren.Reed@Sun.COM return ((lif_if_t)-1); 3237513SDarren.Reed@Sun.COM 3247513SDarren.Reed@Sun.COM return (info->netd_info.netp_lifgetnext(info, ifidx, ifdata)); 3257513SDarren.Reed@Sun.COM } 3267513SDarren.Reed@Sun.COM 3277513SDarren.Reed@Sun.COM int 3287513SDarren.Reed@Sun.COM net_inject(net_handle_t info, inject_t style, net_inject_t *packet) 3297513SDarren.Reed@Sun.COM { 3307513SDarren.Reed@Sun.COM 3317513SDarren.Reed@Sun.COM ASSERT(info != NULL); 3327513SDarren.Reed@Sun.COM 3337513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 3347513SDarren.Reed@Sun.COM return (-1); 3357513SDarren.Reed@Sun.COM 3367513SDarren.Reed@Sun.COM return (info->netd_info.netp_inject(info, style, packet)); 3377513SDarren.Reed@Sun.COM } 3387513SDarren.Reed@Sun.COM 3397513SDarren.Reed@Sun.COM phy_if_t 3407513SDarren.Reed@Sun.COM net_routeto(net_handle_t info, struct sockaddr *address, struct sockaddr *next) 3417513SDarren.Reed@Sun.COM { 3427513SDarren.Reed@Sun.COM 3437513SDarren.Reed@Sun.COM ASSERT(info != NULL); 3447513SDarren.Reed@Sun.COM 3457513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 3467513SDarren.Reed@Sun.COM return ((phy_if_t)-1); 3477513SDarren.Reed@Sun.COM 3487513SDarren.Reed@Sun.COM return (info->netd_info.netp_routeto(info, address, next)); 3497513SDarren.Reed@Sun.COM } 3507513SDarren.Reed@Sun.COM 3517513SDarren.Reed@Sun.COM int 3527513SDarren.Reed@Sun.COM net_ispartialchecksum(net_handle_t info, mblk_t *mp) 3537513SDarren.Reed@Sun.COM { 3547513SDarren.Reed@Sun.COM 3557513SDarren.Reed@Sun.COM ASSERT(info != NULL); 3567513SDarren.Reed@Sun.COM ASSERT(mp != NULL); 3577513SDarren.Reed@Sun.COM 3587513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 3597513SDarren.Reed@Sun.COM return (-1); 3607513SDarren.Reed@Sun.COM 3617513SDarren.Reed@Sun.COM return (info->netd_info.netp_ispartialchecksum(info, mp)); 3627513SDarren.Reed@Sun.COM } 3637513SDarren.Reed@Sun.COM 3647513SDarren.Reed@Sun.COM int 3657513SDarren.Reed@Sun.COM net_isvalidchecksum(net_handle_t info, mblk_t *mp) 3667513SDarren.Reed@Sun.COM { 3677513SDarren.Reed@Sun.COM 3687513SDarren.Reed@Sun.COM ASSERT(info != NULL); 3697513SDarren.Reed@Sun.COM ASSERT(mp != NULL); 3707513SDarren.Reed@Sun.COM 3717513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 3727513SDarren.Reed@Sun.COM return (-1); 3737513SDarren.Reed@Sun.COM 3747513SDarren.Reed@Sun.COM return (info->netd_info.netp_isvalidchecksum(info, mp)); 3757513SDarren.Reed@Sun.COM } 3767513SDarren.Reed@Sun.COM 3777513SDarren.Reed@Sun.COM /* 3787513SDarren.Reed@Sun.COM * Hooks related functions 3797513SDarren.Reed@Sun.COM */ 3807513SDarren.Reed@Sun.COM 3817513SDarren.Reed@Sun.COM /* 3827513SDarren.Reed@Sun.COM * Function: net_family_register 3837513SDarren.Reed@Sun.COM * Returns: int - 0 = Succ, Else = Fail 3847513SDarren.Reed@Sun.COM * Parameters: info(I) - protocol 3857513SDarren.Reed@Sun.COM * hf(I) - family pointer 3867513SDarren.Reed@Sun.COM * 3877513SDarren.Reed@Sun.COM * Call hook_family_add to register family 3887513SDarren.Reed@Sun.COM * 3897513SDarren.Reed@Sun.COM * There is no need to bump netd_refcnt in the two functions 3907513SDarren.Reed@Sun.COM * net_family_register and net_family_unregister because the caller of these 3917513SDarren.Reed@Sun.COM * two functions is assumed to "own" a reference on 'info' via an earlier 3927513SDarren.Reed@Sun.COM * call to net_protocol_register(). Thus the owner is expected to do a 3937513SDarren.Reed@Sun.COM * call to net_protocol_unregister() after having done a 3947513SDarren.Reed@Sun.COM * net_family_unregister() to make sure things are properly cleaned up. 395*12263SDarren.Reed@Sun.COM * Passing a pointer to info->netd_hooks into hook_family_add is required 396*12263SDarren.Reed@Sun.COM * so that this can be set before the notify functions are called. If this 397*12263SDarren.Reed@Sun.COM * does not happen, the notify function may do something that seems fine, 398*12263SDarren.Reed@Sun.COM * like add a notify function to the family but cause a panic because 399*12263SDarren.Reed@Sun.COM * netd_hooks is NULL when we get to hook_family_notify_register. 4007513SDarren.Reed@Sun.COM */ 4017513SDarren.Reed@Sun.COM int 4027513SDarren.Reed@Sun.COM net_family_register(net_handle_t info, hook_family_t *hf) 4037513SDarren.Reed@Sun.COM { 4047513SDarren.Reed@Sun.COM hook_family_int_t *hfi; 4057513SDarren.Reed@Sun.COM netstack_t *ns; 4067513SDarren.Reed@Sun.COM 4077513SDarren.Reed@Sun.COM ASSERT(info != NULL); 4087513SDarren.Reed@Sun.COM ASSERT(hf != NULL); 4097513SDarren.Reed@Sun.COM 4107513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 4117513SDarren.Reed@Sun.COM return (ESHUTDOWN); 4127513SDarren.Reed@Sun.COM 4137513SDarren.Reed@Sun.COM if (info->netd_hooks != NULL) 4147513SDarren.Reed@Sun.COM return (EEXIST); 4157513SDarren.Reed@Sun.COM 4167513SDarren.Reed@Sun.COM ns = info->netd_stack->nts_netstack; 4177513SDarren.Reed@Sun.COM ASSERT(ns != NULL); 418*12263SDarren.Reed@Sun.COM if (hook_family_add(hf, ns->netstack_hook, 419*12263SDarren.Reed@Sun.COM (void **)&info->netd_hooks) == NULL) 4207513SDarren.Reed@Sun.COM return (EEXIST); 4217513SDarren.Reed@Sun.COM 4227513SDarren.Reed@Sun.COM return (0); 4237513SDarren.Reed@Sun.COM } 4247513SDarren.Reed@Sun.COM 4257513SDarren.Reed@Sun.COM /* 4267513SDarren.Reed@Sun.COM * Function: net_family_unregister 4277513SDarren.Reed@Sun.COM * Returns: int - transparent value, explained by caller 4287513SDarren.Reed@Sun.COM * Parameters: info(I) - protocol 4297513SDarren.Reed@Sun.COM * hf(I) - family pointer 4307513SDarren.Reed@Sun.COM * 4317513SDarren.Reed@Sun.COM * Call hook_family_remove to unregister family 4327513SDarren.Reed@Sun.COM */ 4337513SDarren.Reed@Sun.COM int 4347513SDarren.Reed@Sun.COM net_family_unregister(net_handle_t info, hook_family_t *hf) 4357513SDarren.Reed@Sun.COM { 4367513SDarren.Reed@Sun.COM int ret; 4377513SDarren.Reed@Sun.COM 4387513SDarren.Reed@Sun.COM ASSERT(info != NULL); 4397513SDarren.Reed@Sun.COM ASSERT(hf != NULL); 4407513SDarren.Reed@Sun.COM 4417513SDarren.Reed@Sun.COM if (info->netd_hooks == NULL) 4427513SDarren.Reed@Sun.COM return (ENXIO); 4437513SDarren.Reed@Sun.COM 4447513SDarren.Reed@Sun.COM if (strcmp(info->netd_hooks->hfi_family.hf_name, 4457513SDarren.Reed@Sun.COM hf->hf_name) != 0) 4467513SDarren.Reed@Sun.COM return (EINVAL); 4477513SDarren.Reed@Sun.COM 4487513SDarren.Reed@Sun.COM ret = hook_family_remove(info->netd_hooks); 4497513SDarren.Reed@Sun.COM if (ret == 0) 4507513SDarren.Reed@Sun.COM info->netd_hooks = NULL; 4517513SDarren.Reed@Sun.COM 4527513SDarren.Reed@Sun.COM return (ret); 4537513SDarren.Reed@Sun.COM } 4547513SDarren.Reed@Sun.COM 4557915SDarren.Reed@Sun.COM int 4567915SDarren.Reed@Sun.COM net_family_shutdown(net_handle_t info, hook_family_t *hf) 4577915SDarren.Reed@Sun.COM { 4587915SDarren.Reed@Sun.COM 4597915SDarren.Reed@Sun.COM ASSERT(info != NULL); 4607915SDarren.Reed@Sun.COM ASSERT(hf != NULL); 4617915SDarren.Reed@Sun.COM 4627915SDarren.Reed@Sun.COM if (info->netd_hooks == NULL) 4637915SDarren.Reed@Sun.COM return (ENXIO); 4647915SDarren.Reed@Sun.COM 4657915SDarren.Reed@Sun.COM if (strcmp(info->netd_hooks->hfi_family.hf_name, 4667915SDarren.Reed@Sun.COM hf->hf_name) != 0) 4677915SDarren.Reed@Sun.COM return (EINVAL); 4687915SDarren.Reed@Sun.COM 4697915SDarren.Reed@Sun.COM return (hook_family_shutdown(info->netd_hooks)); 4707915SDarren.Reed@Sun.COM } 4717915SDarren.Reed@Sun.COM 4727513SDarren.Reed@Sun.COM /* 4737513SDarren.Reed@Sun.COM * Function: net_event_register 4747513SDarren.Reed@Sun.COM * Returns: internal event pointer - NULL = Fail 4757513SDarren.Reed@Sun.COM * Parameters: info(I) - protocol 4767513SDarren.Reed@Sun.COM * he(I) - event pointer 4777513SDarren.Reed@Sun.COM * 4787513SDarren.Reed@Sun.COM * Call hook_event_add to register event on specific family 4797513SDarren.Reed@Sun.COM * Internal event pointer is returned so caller can get 4807513SDarren.Reed@Sun.COM * handle to run hooks 4817513SDarren.Reed@Sun.COM */ 4827513SDarren.Reed@Sun.COM hook_event_token_t 4837513SDarren.Reed@Sun.COM net_event_register(net_handle_t info, hook_event_t *he) 4847513SDarren.Reed@Sun.COM { 4857513SDarren.Reed@Sun.COM hook_event_int_t *hei; 4867513SDarren.Reed@Sun.COM 4877513SDarren.Reed@Sun.COM ASSERT(info != NULL); 4887513SDarren.Reed@Sun.COM ASSERT(he != NULL); 4897513SDarren.Reed@Sun.COM 4907513SDarren.Reed@Sun.COM if (info->netd_hooks == NULL || info->netd_condemned != 0 || 4917513SDarren.Reed@Sun.COM info->netd_stack == NULL) 4927513SDarren.Reed@Sun.COM return (NULL); 4937513SDarren.Reed@Sun.COM 4947513SDarren.Reed@Sun.COM hei = hook_event_add(info->netd_hooks, he); 4957513SDarren.Reed@Sun.COM return ((hook_event_token_t)hei); 4967513SDarren.Reed@Sun.COM } 4977513SDarren.Reed@Sun.COM 4987513SDarren.Reed@Sun.COM /* 4997513SDarren.Reed@Sun.COM * Function: net_event_unregister 5007513SDarren.Reed@Sun.COM * Returns: int - transparent value, explained by caller 5017513SDarren.Reed@Sun.COM * Parameters: info(I) - protocol 5027513SDarren.Reed@Sun.COM * he(I) - event pointer 5037513SDarren.Reed@Sun.COM * 5047513SDarren.Reed@Sun.COM * Call hook_event_remove to unregister event on specific family 5057513SDarren.Reed@Sun.COM */ 5067513SDarren.Reed@Sun.COM int 5077513SDarren.Reed@Sun.COM net_event_unregister(net_handle_t info, hook_event_t *he) 5087513SDarren.Reed@Sun.COM { 5097513SDarren.Reed@Sun.COM 5107513SDarren.Reed@Sun.COM ASSERT(info != NULL); 5117513SDarren.Reed@Sun.COM ASSERT(he != NULL); 5127513SDarren.Reed@Sun.COM 5137513SDarren.Reed@Sun.COM if (info->netd_hooks == NULL) 5147513SDarren.Reed@Sun.COM return (ENXIO); 5157513SDarren.Reed@Sun.COM 5167513SDarren.Reed@Sun.COM return (hook_event_remove(info->netd_hooks, he)); 5177513SDarren.Reed@Sun.COM } 5187513SDarren.Reed@Sun.COM 5197915SDarren.Reed@Sun.COM int 5207915SDarren.Reed@Sun.COM net_event_shutdown(net_handle_t info, hook_event_t *he) 5217915SDarren.Reed@Sun.COM { 5227915SDarren.Reed@Sun.COM 5237915SDarren.Reed@Sun.COM ASSERT(info != NULL); 5247915SDarren.Reed@Sun.COM ASSERT(he != NULL); 5257915SDarren.Reed@Sun.COM 5267915SDarren.Reed@Sun.COM if (info->netd_hooks == NULL) 5277915SDarren.Reed@Sun.COM return (ENXIO); 5287915SDarren.Reed@Sun.COM 5297915SDarren.Reed@Sun.COM return (hook_event_shutdown(info->netd_hooks, he)); 5307915SDarren.Reed@Sun.COM } 5317915SDarren.Reed@Sun.COM 5327513SDarren.Reed@Sun.COM /* 5337513SDarren.Reed@Sun.COM * Function: net_hook_register 5347513SDarren.Reed@Sun.COM * Returns: int - transparent value, explained by caller 5357513SDarren.Reed@Sun.COM * Parameters: info(I) - protocol 5367513SDarren.Reed@Sun.COM * event(I) - event name 5377513SDarren.Reed@Sun.COM * h(I) - hook pointer 5387513SDarren.Reed@Sun.COM * 5397513SDarren.Reed@Sun.COM * Call hook_register to add hook on specific family/event 5407513SDarren.Reed@Sun.COM */ 5417513SDarren.Reed@Sun.COM int 5427513SDarren.Reed@Sun.COM net_hook_register(net_handle_t info, char *event, hook_t *h) 5437513SDarren.Reed@Sun.COM { 5447513SDarren.Reed@Sun.COM 5457513SDarren.Reed@Sun.COM ASSERT(info != NULL); 5467513SDarren.Reed@Sun.COM ASSERT(event != NULL); 5477513SDarren.Reed@Sun.COM ASSERT(h != NULL); 5487513SDarren.Reed@Sun.COM 5497513SDarren.Reed@Sun.COM if (info->netd_condemned != 0 || info->netd_stack == NULL) 5507513SDarren.Reed@Sun.COM return (ESHUTDOWN); 5517513SDarren.Reed@Sun.COM 5527513SDarren.Reed@Sun.COM if (info->netd_hooks == NULL) 5537513SDarren.Reed@Sun.COM return (ENXIO); 5547513SDarren.Reed@Sun.COM 5557513SDarren.Reed@Sun.COM return (hook_register(info->netd_hooks, event, h)); 5567513SDarren.Reed@Sun.COM } 5577513SDarren.Reed@Sun.COM 5587513SDarren.Reed@Sun.COM /* 5597513SDarren.Reed@Sun.COM * Function: net_hook_unregister 5607513SDarren.Reed@Sun.COM * Returns: int - transparent value, explained by caller 5617513SDarren.Reed@Sun.COM * Parameters: info(I) - protocol 5627513SDarren.Reed@Sun.COM * event(I) - event name 5637513SDarren.Reed@Sun.COM * h(I) - hook pointer 5647513SDarren.Reed@Sun.COM * 5657513SDarren.Reed@Sun.COM * Call hook_unregister to remove hook on specific family/event 5667513SDarren.Reed@Sun.COM */ 5677513SDarren.Reed@Sun.COM int 5687513SDarren.Reed@Sun.COM net_hook_unregister(net_handle_t info, char *event, hook_t *h) 5697513SDarren.Reed@Sun.COM { 5707513SDarren.Reed@Sun.COM 5717513SDarren.Reed@Sun.COM ASSERT(info != NULL); 5727513SDarren.Reed@Sun.COM ASSERT(event != NULL); 5737513SDarren.Reed@Sun.COM ASSERT(h != NULL); 5747513SDarren.Reed@Sun.COM 5757513SDarren.Reed@Sun.COM if (info->netd_hooks == NULL) 5767513SDarren.Reed@Sun.COM return (ENXIO); 5777513SDarren.Reed@Sun.COM 5787513SDarren.Reed@Sun.COM return (hook_unregister(info->netd_hooks, event, h)); 5797513SDarren.Reed@Sun.COM } 5807513SDarren.Reed@Sun.COM 5817513SDarren.Reed@Sun.COM netid_t 5827513SDarren.Reed@Sun.COM net_getnetid(net_handle_t netd) 5837513SDarren.Reed@Sun.COM { 5847513SDarren.Reed@Sun.COM 5857513SDarren.Reed@Sun.COM if (netd->netd_stack == NULL) 5867513SDarren.Reed@Sun.COM return (-1); 5877513SDarren.Reed@Sun.COM return (netd->netd_stack->nts_id); 5887513SDarren.Reed@Sun.COM } 5897513SDarren.Reed@Sun.COM 5907513SDarren.Reed@Sun.COM net_inject_t * 5917513SDarren.Reed@Sun.COM net_inject_alloc(const int version) 5927513SDarren.Reed@Sun.COM { 5937513SDarren.Reed@Sun.COM net_inject_t *ni; 5947513SDarren.Reed@Sun.COM 5957513SDarren.Reed@Sun.COM ni = kmem_zalloc(sizeof (*ni), KM_NOSLEEP); 5967513SDarren.Reed@Sun.COM if (ni == NULL) 5977513SDarren.Reed@Sun.COM return (NULL); 5987513SDarren.Reed@Sun.COM 5997513SDarren.Reed@Sun.COM ni->ni_version = version; 6007513SDarren.Reed@Sun.COM return (ni); 6017513SDarren.Reed@Sun.COM } 6027513SDarren.Reed@Sun.COM 6037513SDarren.Reed@Sun.COM void 6047513SDarren.Reed@Sun.COM net_inject_free(net_inject_t *ni) 6057513SDarren.Reed@Sun.COM { 6067513SDarren.Reed@Sun.COM kmem_free(ni, sizeof (*ni)); 6077513SDarren.Reed@Sun.COM } 6087513SDarren.Reed@Sun.COM 6097513SDarren.Reed@Sun.COM kstat_t * 6107513SDarren.Reed@Sun.COM net_kstat_create(netid_t netid, char *module, int instance, char *name, 6117513SDarren.Reed@Sun.COM char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag) 6127513SDarren.Reed@Sun.COM { 6137513SDarren.Reed@Sun.COM netstackid_t stackid = net_getnetstackidbynetid(netid); 6147513SDarren.Reed@Sun.COM 6157513SDarren.Reed@Sun.COM if (stackid == -1) 6167513SDarren.Reed@Sun.COM return (NULL); 6177513SDarren.Reed@Sun.COM 6187513SDarren.Reed@Sun.COM return (kstat_create_netstack(module, instance, name, class, type, 6197513SDarren.Reed@Sun.COM ndata, ks_flag, stackid)); 6207513SDarren.Reed@Sun.COM } 6217513SDarren.Reed@Sun.COM 6227513SDarren.Reed@Sun.COM void 6237513SDarren.Reed@Sun.COM net_kstat_delete(netid_t netid, kstat_t *ks) 6247513SDarren.Reed@Sun.COM { 6257513SDarren.Reed@Sun.COM netstackid_t stackid = net_getnetstackidbynetid(netid); 6267513SDarren.Reed@Sun.COM 6277513SDarren.Reed@Sun.COM if (stackid != -1) 6287513SDarren.Reed@Sun.COM kstat_delete_netstack(ks, stackid); 6297513SDarren.Reed@Sun.COM } 6307513SDarren.Reed@Sun.COM 6317513SDarren.Reed@Sun.COM int 6327513SDarren.Reed@Sun.COM net_event_notify_register(net_handle_t family, char *event, 6337513SDarren.Reed@Sun.COM hook_notify_fn_t callback, void *arg) 6347513SDarren.Reed@Sun.COM { 6357513SDarren.Reed@Sun.COM int error; 6367513SDarren.Reed@Sun.COM 6377513SDarren.Reed@Sun.COM if (family->netd_condemned != 0 || family->netd_stack == NULL) 6387513SDarren.Reed@Sun.COM return (ESHUTDOWN); 6397513SDarren.Reed@Sun.COM 6407513SDarren.Reed@Sun.COM error = hook_event_notify_register(family->netd_hooks, event, 6417513SDarren.Reed@Sun.COM callback, arg); 6427513SDarren.Reed@Sun.COM 6437513SDarren.Reed@Sun.COM return (error); 6447513SDarren.Reed@Sun.COM } 6457513SDarren.Reed@Sun.COM 6467513SDarren.Reed@Sun.COM int 6477513SDarren.Reed@Sun.COM net_event_notify_unregister(net_handle_t family, char *event, 6487513SDarren.Reed@Sun.COM hook_notify_fn_t callback) 6497513SDarren.Reed@Sun.COM { 6507513SDarren.Reed@Sun.COM int error; 6517513SDarren.Reed@Sun.COM 6527513SDarren.Reed@Sun.COM error = hook_event_notify_unregister(family->netd_hooks, event, 6537513SDarren.Reed@Sun.COM callback); 6547513SDarren.Reed@Sun.COM 6557513SDarren.Reed@Sun.COM return (error); 6567513SDarren.Reed@Sun.COM } 6577513SDarren.Reed@Sun.COM 6587513SDarren.Reed@Sun.COM int 6597513SDarren.Reed@Sun.COM net_protocol_notify_register(net_handle_t family, hook_notify_fn_t callback, 6607513SDarren.Reed@Sun.COM void *arg) 6617513SDarren.Reed@Sun.COM { 6627513SDarren.Reed@Sun.COM int error; 6637513SDarren.Reed@Sun.COM 6647513SDarren.Reed@Sun.COM if (family->netd_condemned != 0 || family->netd_stack == NULL) 6657513SDarren.Reed@Sun.COM return (ESHUTDOWN); 6667513SDarren.Reed@Sun.COM 6677513SDarren.Reed@Sun.COM error = hook_family_notify_register(family->netd_hooks, callback, 6687513SDarren.Reed@Sun.COM arg); 6697513SDarren.Reed@Sun.COM 6707513SDarren.Reed@Sun.COM return (error); 6717513SDarren.Reed@Sun.COM } 6727513SDarren.Reed@Sun.COM 6737513SDarren.Reed@Sun.COM int 6747513SDarren.Reed@Sun.COM net_protocol_notify_unregister(net_handle_t family, hook_notify_fn_t callback) 6757513SDarren.Reed@Sun.COM { 6767513SDarren.Reed@Sun.COM int error; 6777513SDarren.Reed@Sun.COM 6787513SDarren.Reed@Sun.COM error = hook_family_notify_unregister(family->netd_hooks, callback); 6797513SDarren.Reed@Sun.COM 6807513SDarren.Reed@Sun.COM return (error); 6817513SDarren.Reed@Sun.COM } 682