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