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