|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1988, 1989, 1997, 1998 Apple Computer, Inc. ! 24: * ! 25: * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. ! 26: */ ! 27: ! 28: #include <string.h> ! 29: ! 30: #include <sys/errno.h> ! 31: #include <sys/types.h> ! 32: #include <sys/param.h> ! 33: #include <machine/spl.h> ! 34: #include <sys/systm.h> ! 35: #include <sys/kernel.h> ! 36: #include <sys/proc.h> ! 37: #include <sys/filedesc.h> ! 38: #include <sys/fcntl.h> ! 39: #include <sys/mbuf.h> ! 40: #include <sys/ioctl.h> ! 41: #include <sys/malloc.h> ! 42: #include <sys/socket.h> ! 43: #include <sys/socketvar.h> ! 44: ! 45: #include <net/if.h> ! 46: #include <net/if_types.h> ! 47: ! 48: #include <netat/sysglue.h> ! 49: #include <netat/appletalk.h> ! 50: #include <netat/at_var.h> ! 51: #include <netat/ddp.h> ! 52: #include <netat/nbp.h> ! 53: #include <netat/zip.h> ! 54: #include <netat/rtmp.h> ! 55: #include <netat/lap.h> ! 56: #include <netat/routing_tables.h> /* router */ ! 57: #include <netat/at_snmp.h> ! 58: #include <netat/at_pcb.h> ! 59: #include <netat/debug.h> ! 60: #include <netat/at_config.h> ! 61: ! 62: /* reaching for DDP and NBP headers in the datagram */ ! 63: #define DATA_DDP(mp) ((at_ddp_t *)(gbuf_rptr(mp))) ! 64: #define DATA_NBP(mp) ((at_nbp_t *)((DATA_DDP(mp))->data)) ! 65: ! 66: /* Get to the nve_entry_t part ofthe buffer */ ! 67: #define NVE_ENTRY(mp) (nve_entry_t *)(gbuf_rptr(mp)) ! 68: ! 69: #ifndef MIN ! 70: #define MIN(a,b) ((a)>(b)?(b):(a)) ! 71: #endif ! 72: ! 73: #define errno nbperrno ! 74: #define NBP_DEBUG 0 ! 75: ! 76: /* externs */ ! 77: extern at_ifaddr_t *ifID_table[]; ! 78: extern at_ifaddr_t *ifID_home; ! 79: ! 80: TAILQ_HEAD(name_registry, _nve_) name_registry; ! 81: ! 82: atlock_t nve_lock; ! 83: ! 84: /* statics */ ! 85: static int errno; ! 86: static gbuf_t *lzones=0; /* head of local zones list */ ! 87: static int lzonecnt=0; /* # zones stored in lzones */ ! 88: static u_int hzonehash=0; /* hash val of home zone */ ! 89: static int nve_lock_pri; ! 90: ! 91: static int nbp_lkup_reply(nbp_req_t *, nve_entry_t *); ! 92: static int nbp_strcmp(at_nvestr_t *, at_nvestr_t *, u_char); ! 93: static int nbp_setup_resp(nbp_req_t *, int); ! 94: static int nbp_send_resp(nbp_req_t *); ! 95: static int nbp_validate_n_hash(nbp_req_t *, int, int); ! 96: static nve_entry_t *nbp_search_nve(); ! 97: static int isZoneLocal(at_nvestr_t *); ! 98: ! 99: /* macros */ ! 100: #define NVE_LOCK nve_lock ! 101: ! 102: /* prototypes */ ! 103: void nbp_delete_entry(); ! 104: extern int at_reg_mcast(); ! 105: extern at_nvestr_t *getRTRLocalZone(if_zone_t *); ! 106: extern void nbp_add_multicast( at_nvestr_t *, at_ifaddr_t *); ! 107: ! 108: static long nbp_id_count = 0; ! 109: ! 110: void sethzonehash(elapp) ! 111: at_ifaddr_t *elapp; ! 112: { ! 113: if (elapp->startup_zone.len) { ! 114: hzonehash = nbp_strhash(&elapp->startup_zone); ! 115: } ! 116: } ! 117: ! 118: void nbp_shutdown() ! 119: { ! 120: /* delete all NVE's and release buffers */ ! 121: register nve_entry_t *nve_entry, *next_nve; ! 122: ! 123: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 124: TAILQ_FOREACH(nve_entry, &name_registry, nve_link) { ! 125: nbp_delete_entry(nve_entry); ! 126: } ! 127: ATENABLE(nve_lock_pri,NVE_LOCK); ! 128: ! 129: if (lzones) { ! 130: gbuf_freem(lzones); ! 131: lzonecnt = 0; ! 132: lzones = NULL; ! 133: } ! 134: } /* nbp_shutdown */ ! 135: ! 136: static ! 137: u_char *nbp2zone(nbp, maxp) ! 138: at_nbp_t *nbp; ! 139: u_char *maxp; ! 140: { ! 141: ! 142: u_char *p; ! 143: ! 144: p = (u_char*)&nbp->tuple[0].enu_entity; /* p -> object */ ! 145: if (p >= maxp) return NULL; ! 146: p += (*p +1); /* p -> type */ ! 147: if (p >= maxp) return NULL; ! 148: p += (*p +1); /* p -> zone */ ! 149: if (p >= maxp) return NULL; ! 150: if ((p + *p) >= maxp) return NULL; ! 151: return(p); ! 152: } ! 153: ! 154: void nbp_input(m, ifID) ! 155: register gbuf_t *m; ! 156: register at_ifaddr_t *ifID; ! 157: ! 158: { ! 159: register at_ddp_t *ddp = DATA_DDP(m); ! 160: register at_nbp_t *nbp = DATA_NBP(m); ! 161: register nve_entry_t *nve_entry, *next_nve; ! 162: register RT_entry *rt; ! 163: register int ddpSent = FALSE; /* true if we re-sent this pkt (don't free) */ ! 164: struct etalk_addr mcastAddr; ! 165: nbp_req_t nbp_req; ! 166: u_char *p; ! 167: ! 168: /* from original nbp_input() when this function was nbp_handler() */ ! 169: if ((gbuf_type(m) != MT_DATA && gbuf_type(m) != MSG_DATA) || ! 170: ddp->type != DDP_NBP) { ! 171: gbuf_freem(m); ! 172: return; ! 173: } ! 174: ! 175: /* Some initializations */ ! 176: nbp_req.response = NULL; ! 177: nbp_req.request = m; ! 178: nbp_req.space_unused = nbp_req.flags = 0; ! 179: ! 180: dPrintf(D_M_NBP_LOW, D_L_USR1, ! 181: ("nbp_input control:%d tuplecount:%d id:%d\n", ! 182: nbp->control, nbp->tuple_count, nbp->at_nbp_id)); ! 183: switch (nbp->control) { ! 184: case NBP_LKUP : ! 185: { ! 186: at_net_al dst_net; ! 187: ! 188: dst_net = NET_VALUE(ddp->dst_net); ! 189: dPrintf(D_M_NBP_LOW, D_L_USR2, (" LKUP %s\n", ! 190: ifID != ifID_home ? "non-home" : "home")); ! 191: if ( ROUTING_MODE && (NET_VALUE(ddp->dst_net) != 0) ! 192: && ((dst_net < ifID->ifThisCableStart) ! 193: || (dst_net > ifID->ifThisCableEnd)) ) { ! 194: routing_needed(m, ifID, TRUE); ! 195: ddpSent = TRUE; ! 196: break; ! 197: } ! 198: } ! 199: ! 200: if (nbp_validate_n_hash (&nbp_req, TRUE, FALSE) == 0) { ! 201: nbp_req.func = nbp_lkup_reply; ! 202: (void) nbp_search_nve(&nbp_req, ifID); ! 203: if (nbp_req.response) { ! 204: nbp_send_resp(&nbp_req); ! 205: } ! 206: } ! 207: #ifdef NBP_DEBUG ! 208: { ! 209: char zone[35],object[35],type[35]; ! 210: strncpy(zone,nbp_req.nve.zone.str, nbp_req.nve.zone.len); ! 211: strncpy(object,nbp_req.nve.object.str, nbp_req.nve.object.len); ! 212: strncpy(type,nbp_req.nve.type.str, nbp_req.nve.type.len); ! 213: object[nbp_req.nve.object.len] = '\0'; ! 214: zone[nbp_req.nve.zone.len] = '\0'; ! 215: type[nbp_req.nve.type.len] = '\0'; ! 216: if (ifID != ifID_home) ! 217: dPrintf(D_M_NBP_LOW,D_L_USR2, ! 218: ("nbp_LKUP for:%s:%s@%s", object, type, zone)); ! 219: } ! 220: #endif /* NBP_DEBUG */ ! 221: ! 222: break; ! 223: case NBP_FWDRQ: ! 224: { ! 225: register int zhome=0; ! 226: /* true if home zone == destination zone */ ! 227: register int zno, i; ! 228: register gbuf_t *m2; ! 229: register error_found =0; ! 230: register at_ifaddr_t *ifIDorig; ! 231: ! 232: if (!ROUTING_MODE) /* for routers only! */ ! 233: break; ! 234: ! 235: ifIDorig = ifID; ! 236: ifID= NULL; ! 237: for (i = 0 ; i < RT_maxentry; i++) { ! 238: rt = &RT_table[i]; ! 239: if ((rt->EntryState & RTE_STATE_PERMANENT) && ! 240: NET_VALUE(ddp->dst_net) >= rt->NetStart && ! 241: NET_VALUE(ddp->dst_net) <= rt->NetStop ! 242: ) { ! 243: /* sanity check */ ! 244: if (rt->NetPort >= IF_TOTAL_MAX) { ! 245: dPrintf(D_M_NBP,D_L_ERROR, ! 246: ("nbp_input:FWDREQ: bad port# from RT_table\n")); ! 247: error_found = TRUE; ! 248: break; ! 249: } ! 250: ifID = ifID_table[rt->NetPort]; ! 251: if (!ifID) { ! 252: dPrintf(D_M_NBP,D_L_ERROR, ! 253: ("nbp_input:FWDREQ: ifID %s\n", ! 254: !ifID ? "not found" : "invalid")); ! 255: error_found = TRUE; ! 256: break; ! 257: } ! 258: if (ifID->ifState == LAP_OFFLINE) { ! 259: dPrintf(D_M_NBP,D_L_ERROR, ! 260: ("nbp_input:FWDREQ: ifID offline (port %d)\n", ! 261: rt->NetPort)); ! 262: error_found = TRUE; ! 263: break; ! 264: } ! 265: break; ! 266: } ! 267: } ! 268: if (error_found) /* the port is not correct */ ! 269: break; ! 270: ! 271: if (!ifID) { /* this packet is not for us, let the routing engine handle it */ ! 272: routing_needed(m, ifIDorig, TRUE); ! 273: ddpSent= TRUE; ! 274: break; ! 275: } ! 276: ! 277: /* ! 278: * At this point, we have a valid Forward request for one of our ! 279: * directly connected port. Convert it to a NBP Lookup ! 280: */ ! 281: ! 282: nbp->control = NBP_LKUP; ! 283: NET_ASSIGN(ddp->dst_net, 0); ! 284: ddp->dst_node = 255; ! 285: ! 286: ! 287: /*### LD 01/18/94 Check if the dest is also the home zone. */ ! 288: ! 289: p = nbp2zone(nbp, gbuf_wptr(m)); ! 290: if ((p == NULL) || !(zno = zt_find_zname(p))) { ! 291: dPrintf(D_M_NBP,D_L_WARNING, ! 292: ("nbp_input: FWDRQ:zone not found\n")); ! 293: break; ! 294: } ! 295: if (isZoneLocal((at_nvestr_t*)p)) ! 296: zhome = TRUE; /* one of our ports is in destination zone */ ! 297: if (!zt_get_zmcast(ifID, p, &mcastAddr)) { ! 298: dPrintf(D_M_NBP,D_L_ERROR, ! 299: ("nbp_input: FDWREQ:zt_get_zmcast error\n")); ! 300: break; ! 301: } ! 302: ! 303: ! 304: if (zhome) { /*### LD 01/18/95 In case our home is here, call back nbp */ ! 305: ! 306: if (!(m2 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) { ! 307: dPrintf(D_M_NBP,D_L_ERROR, ! 308: ("nbp_input: FWDRQ:gbuf_copym failed\n")); ! 309: break; ! 310: } ! 311: ! 312: ddp = DATA_DDP(m2); ! 313: nbp = DATA_NBP(m2); ! 314: nbp->control = NBP_LKUP; ! 315: NET_ASSIGN(ddp->dst_net, 0); ! 316: ddp->dst_node = 255; ! 317: dPrintf(D_M_NBP,D_L_INFO, ! 318: ("nbp_input: FWDRQ:loop back for us\n")); ! 319: nbp_input(m2, ifID_home); ! 320: } ! 321: ! 322: if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type)) ! 323: ddp_bit_reverse(&mcastAddr); ! 324: ddp_router_output(m, ifID, ET_ADDR,NULL,NULL, &mcastAddr); ! 325: ddpSent = TRUE; ! 326: } ! 327: break; ! 328: ! 329: case NBP_BRRQ: ! 330: { ! 331: register int zno; /* zone table entry numb */ ! 332: register int ztind; /* zone bitmap index into RT_entry */ ! 333: register int ztbit; /* zone bit to check within above index */ ! 334: register int zhome=0; /* true if home zone == destination zone */ ! 335: register int i; ! 336: register gbuf_t *m2, *m3; ! 337: register int fromUs = FALSE; ! 338: register at_socket ourSkt; /* originating skt */ ! 339: ! 340: /* for router & MH local only */ ! 341: if ((!(MULTIHOME_MODE && FROM_US(ddp))) && !ROUTING_MODE) { ! 342: dPrintf(D_M_NBP,D_L_USR2, ! 343: ("nbp_input: BRREQ:non router or MH local\n")); ! 344: ! 345: break; ! 346: } ! 347: p = nbp2zone(nbp, gbuf_wptr(m)); ! 348: if ((p == NULL) || !(zno = zt_find_zname(p))) { ! 349: break; ! 350: } ! 351: if (MULTIHOME_MODE && ifID->ifRouterState == NO_ROUTER) { ! 352: ((at_nvestr_t*)p)->len = 1; ! 353: ((at_nvestr_t*)p)->str[0] = '*'; ! 354: } ! 355: if (isZoneLocal((at_nvestr_t*)p)) { ! 356: zhome = TRUE; /* one of our ports is in destination zone */ ! 357: } ! 358: if (FROM_US(ddp)){ /* save, before we munge it */ ! 359: fromUs = TRUE; ! 360: ourSkt = ddp->src_socket; ! 361: dPrintf(D_M_NBP,D_L_USR2, ! 362: ("nbp_input:BRRQ from us net:%d\n", ! 363: (int)NET_VALUE(ddp->src_net))); ! 364: } ! 365: /* from ZT_CLR_ZMAP */ ! 366: i = zno - 1; ! 367: ztind = i >> 3; ! 368: ztbit = 0x80 >> (i % 8); ! 369: for (i=0,rt=RT_table; i<RT_maxentry; i++,rt++) { ! 370: if (!(rt->ZoneBitMap[ztind] & ztbit)) /* if zone not in route, skip*/ ! 371: continue; ! 372: /* dPrintf(D_M_NBP, D_L_USR3, ! 373: ("nbp_input: BRREQ: port:%d, entry %d\n", ! 374: rt->NetPort, i)); ! 375: */ ! 376: ! 377: ifID = ifID_table[rt->NetPort]; ! 378: if (!ifID) { ! 379: dPrintf(D_M_NBP, D_L_ERROR, ! 380: ("nbp_input:BRRQ: ifID %s\n", ! 381: !ifID ? "not found" : "invalid")); ! 382: break; ! 383: } ! 384: ! 385: ddp = DATA_DDP(m); ! 386: ddp->src_node = ifID->ifThisNode.s_node; ! 387: NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); ! 388: ddp->src_socket = NBP_SOCKET; ! 389: if (!(m2 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) { ! 390: dPrintf(D_M_NBP,D_L_ERROR, ! 391: ("nbp_input: BRREQ:gbuf_copym failed\n")); ! 392: break; ! 393: } ! 394: ! 395: ddp = DATA_DDP(m2); ! 396: nbp = DATA_NBP(m2); ! 397: /* nbp->tuple[0].enu_addr.socket = NBP_SOCKET; */ ! 398: if (MULTIHOME_MODE && fromUs ) { ! 399: /* set the return address of the lookup to that of the ! 400: interface it's going out on so that replies come back ! 401: on that net */ ! 402: dPrintf(D_M_NBP,D_L_USR3, ! 403: ("nbp_input: BRREQ: src changed to %d.%d.%d\n", ! 404: ifID->ifThisNode.s_net, ! 405: ifID->ifThisNode.s_node, ourSkt)); ! 406: nbp->tuple[0].enu_addr.net = ifID->ifThisNode.s_net; ! 407: nbp->tuple[0].enu_addr.node = ifID->ifThisNode.s_node; ! 408: nbp->tuple[0].enu_addr.socket = ourSkt; ! 409: ddp->src_socket = NBP_SOCKET; ! 410: } ! 411: else ! 412: dPrintf(D_M_NBP, D_L_USR3, ! 413: ("nbp_input: BRREQ: not from us\n")); ! 414: ! 415: dPrintf(D_M_NBP, D_L_USR3, ! 416: ("nbp_input dist:%d\n", rt->NetDist)); ! 417: if (rt->NetDist == 0) { /* if direct connect, *we* do the LKUP */ ! 418: nbp->control = NBP_LKUP; ! 419: NET_ASSIGN(ddp->dst_net, 0); ! 420: ddp->dst_node = 255; ! 421: if (!zt_get_zmcast(ifID, p, &mcastAddr)) { ! 422: dPrintf(D_M_NBP,D_L_ERROR, ! 423: ("nbp_input: BRRQ:zt_get_zmcast error\n")); ! 424: break; ! 425: } ! 426: if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type)) ! 427: ddp_bit_reverse(&mcastAddr); ! 428: ddp_router_output(m2, ifID, ET_ADDR, NULL, NULL, &mcastAddr); ! 429: } ! 430: else { /* else fwd to router */ ! 431: ddp->dst_node = 0; ! 432: if (rt->NetStart == 0) /* if Ltalk */ ! 433: NET_ASSIGN(ddp->dst_net, rt->NetStop); ! 434: else ! 435: NET_ASSIGN(ddp->dst_net, rt->NetStart); ! 436: nbp->control = NBP_FWDRQ; ! 437: ddp_router_output(m2, ifID, AT_ADDR, ! 438: rt->NextIRNet, rt->NextIRNode, ! 439: NULL); ! 440: } ! 441: } ! 442: if (!zhome) ! 443: break; ! 444: ! 445: if (!(m3 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) { ! 446: dPrintf(D_M_NBP,D_L_ERROR, ! 447: ("nbp_input: BRREQ:gbuf_copym failed\n")); ! 448: break; ! 449: } ! 450: ! 451: ddp = DATA_DDP(m3); ! 452: nbp = DATA_NBP(m3); ! 453: ! 454: nbp->control = NBP_LKUP; ! 455: NET_ASSIGN(ddp->dst_net, 0); ! 456: ddp->dst_node = 255; ! 457: dPrintf(D_M_NBP,D_L_INFO, ("nbp_input: BRRQ:loop back for us\n")); ! 458: nbp_input(m3, ifID_home); ! 459: break; ! 460: } ! 461: ! 462: case NBP_LKUP_REPLY: ! 463: ! 464: if (!ROUTING_MODE) /* for routers only! */ ! 465: break; ! 466: ! 467: dPrintf(D_M_NBP,D_L_WARNING, ! 468: ("nbp_input: routing needed for LKUP_REPLY: from %d.%d\n", ! 469: NET_VALUE(ddp->src_net), ddp->src_node)); ! 470: routing_needed(m, ifID, TRUE); ! 471: ddpSent = TRUE; ! 472: break; ! 473: ! 474: default : ! 475: dPrintf(D_M_NBP,D_L_ERROR, ! 476: ("nbp_input: unhandled pkt: type:%d\n", nbp->control)); ! 477: ! 478: routing_needed(m, ifID, TRUE); ! 479: ddpSent = TRUE; ! 480: break; ! 481: } /* switch control */ ! 482: ! 483: if (!ddpSent) ! 484: gbuf_freem(m); ! 485: return; ! 486: } /* nbp_input */ ! 487: ! 488: static int nbp_validate_n_hash (nbp_req, wild_ok, checkLocal) ! 489: register nbp_req_t *nbp_req; ! 490: register int wild_ok; ! 491: register int checkLocal; /* if true check if local zone */ ! 492: { ! 493: register at_nvestr_t *object, *type, *zone; ! 494: at_nbptuple_t *tuple; ! 495: register int i, part_wild; ! 496: ! 497: tuple = DATA_NBP(nbp_req->request)->tuple; ! 498: nbp_req->flags = 0; ! 499: #ifdef COMMENTED_OUT ! 500: { ! 501: int net,node,skt; ! 502: net = tuple->enu_addr.net; ! 503: node = tuple->enu_addr.node; ! 504: skt = tuple->enu_addr.socket; ! 505: dPrintf(D_M_NBP_LOW,D_L_USR4, ! 506: ("nbp_validate: tuple addr:%d:%d:%d\n",net,node,skt)); ! 507: } ! 508: #endif /* COMMENTED_OUT */ ! 509: ! 510: /* tuple is in the compressed (no "filler") format */ ! 511: object = (at_nvestr_t *)&tuple->enu_entity; ! 512: type = (at_nvestr_t *)(&object->str[object->len]); ! 513: zone = (at_nvestr_t *)(&type->str[type->len]); ! 514: ! 515: if (object->len > NBP_NVE_STR_SIZE || type->len > NBP_NVE_STR_SIZE || ! 516: zone->len > NBP_NVE_STR_SIZE) { ! 517: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 518: ("nbp_val_n_hash: bad str len\n")); ! 519: errno = EINVAL; ! 520: return (-1); ! 521: } ! 522: ! 523: #ifdef NBP_DEBUG ! 524: { ! 525: char xzone[35],xobject[35],xtype[35]; ! 526: strncpy(xzone,zone->str, zone->len); ! 527: strncpy(xobject,object->str, object->len); ! 528: strncpy(xtype,type->str, type->len); ! 529: xobject[object->len] = '\0'; ! 530: xzone[zone->len] = '\0'; ! 531: xtype[type->len] = '\0'; ! 532: dPrintf(D_M_NBP_LOW, D_L_USR4, ! 533: ("nbp_validate: looking for %s:%s@%s\n", ! 534: xobject, xtype, xzone)); ! 535: } ! 536: #endif /* NBP_DEBUG */ ! 537: /* Is this request for our zone ?? */ ! 538: nbp_req->nve.zone.len = zone->len; ! 539: nbp_req->nve.zone_hash = 0; ! 540: bcopy(zone->str,nbp_req->nve.zone.str, zone->len); ! 541: ! 542: if (checkLocal && !isZoneLocal(zone)) { ! 543: char str[35]; ! 544: strncpy(str,zone->str,zone->len); ! 545: str[zone->len] = '\0'; ! 546: dPrintf(D_M_NBP_LOW,D_L_WARNING, ! 547: ("nbp_val_n_hash bad zone: %s\n", str)); ! 548: errno = EINVAL; ! 549: return(-1); ! 550: } ! 551: ! 552: if (!DEFAULT_ZONE(zone)) { ! 553: nbp_req->nve.zone_hash = nbp_strhash(& nbp_req->nve.zone); ! 554: } ! 555: ! 556: nbp_req->nve.address = tuple->enu_addr; ! 557: nbp_req->nve.object.len = object->len; ! 558: nbp_req->nve.object_hash = 0; ! 559: if (object->len == 1 && (object->str[0] == NBP_ORD_WILDCARD || ! 560: object->str[0] == NBP_SPL_WILDCARD)) { ! 561: if (wild_ok) ! 562: nbp_req->flags |= NBP_WILD_OBJECT; ! 563: else { ! 564: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 565: ("nbp_val_n_hash: wild not okay\n")); ! 566: errno = EINVAL; ! 567: return (-1); ! 568: } ! 569: } else{ ! 570: for (i = part_wild = 0; (unsigned) i<object->len; i++) { ! 571: if (object->str[i] == NBP_SPL_WILDCARD) ! 572: if (wild_ok) ! 573: if (part_wild) { ! 574: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 575: ("nbp_val_n_hash: too many parts wild\n")); ! 576: errno = EINVAL; ! 577: return (-1); ! 578: } else ! 579: part_wild++; ! 580: else { ! 581: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 582: ("nbp_val_n_hash: wild not okay2\n")); ! 583: errno = EINVAL; ! 584: return (-1); ! 585: } ! 586: nbp_req->nve.object.str[i] = object->str[i]; ! 587: } ! 588: if (!part_wild) ! 589: nbp_req->nve.object_hash = ! 590: nbp_strhash(&nbp_req->nve.object); ! 591: } ! 592: ! 593: nbp_req->nve.type.len = type->len; ! 594: nbp_req->nve.type_hash = 0; ! 595: if (type->len == 1 && (type->str[0] == NBP_ORD_WILDCARD || ! 596: type->str[0] == NBP_SPL_WILDCARD)) { ! 597: if (wild_ok) ! 598: nbp_req->flags |= NBP_WILD_TYPE; ! 599: else { ! 600: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 601: ("nbp_val_n_hash: wild not okay3\n")); ! 602: errno = EINVAL; ! 603: return (-1); ! 604: } ! 605: } else { ! 606: for (i = part_wild = 0; (unsigned) i<type->len; i++) { ! 607: if (type->str[i] == NBP_SPL_WILDCARD) ! 608: if (wild_ok) ! 609: if (part_wild) { ! 610: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 611: ("nbp_val_n_hash: too many parts wild2\n")); ! 612: errno = EINVAL; ! 613: return (-1); ! 614: } else ! 615: part_wild++; ! 616: else { ! 617: errno = EINVAL; ! 618: return (-1); ! 619: } ! 620: nbp_req->nve.type.str[i] = type->str[i]; ! 621: } ! 622: if (!part_wild) ! 623: nbp_req->nve.type_hash = ! 624: nbp_strhash(&nbp_req->nve.type); ! 625: } ! 626: #ifdef NBP_DEBUG ! 627: { ! 628: char zone[35],object[35],type[35]; ! 629: strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len); ! 630: strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len); ! 631: strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len); ! 632: object[nbp_req->nve.object.len] = '\0'; ! 633: zone[nbp_req->nve.zone.len] = '\0'; ! 634: type[nbp_req->nve.type.len] = '\0'; ! 635: dPrintf(D_M_NBP_LOW,D_L_USR4, ! 636: ("nbp_validate: after hash: %s:%s@%s\n", ! 637: object, type, zone)); ! 638: } ! 639: #endif /* NBP_DEBUG */ ! 640: return(0); ! 641: } /* nbp_validate_n_hash */ ! 642: ! 643: ! 644: /* Upshifts in place */ ! 645: static void nbp_upshift (str, count) ! 646: register u_char *str; ! 647: register int count; ! 648: { ! 649: register int i, j; ! 650: register u_char ch; ! 651: static unsigned char lower_case[] = ! 652: {0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0xbe, ! 653: 0xbf, 0xcf, 0x9b, 0x8b, 0x88, 0}; ! 654: static unsigned char upper_case[] = ! 655: {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xae, ! 656: 0xaf, 0xce, 0xcd, 0xcc, 0xcb, 0}; ! 657: ! 658: for (j=0 ; j<count ; j++) { ! 659: ch = str[j]; ! 660: if (ch >= 'a' && ch <= 'z') ! 661: str[j] = ch + 'A' - 'a'; ! 662: else if (ch & 0x80) ! 663: for (i=0; lower_case[i]; i++) ! 664: if (ch == lower_case[i]) ! 665: str[j] = upper_case[i]; ! 666: } ! 667: } ! 668: ! 669: ! 670: u_int nbp_strhash (nvestr) ! 671: register at_nvestr_t *nvestr; ! 672: { ! 673: /* upshift while hashing */ ! 674: register u_int hash = 0; ! 675: register int i, len; ! 676: union { ! 677: u_char h_4char[4]; ! 678: int h_int; ! 679: } un; ! 680: ! 681: for (i=0; (unsigned) i < nvestr->len; i+=sizeof(int)) { ! 682: len = MIN((nvestr->len-i), sizeof(int)); ! 683: if (len == sizeof(int)) ! 684: bcopy(&(nvestr->str[i]), &un, sizeof(un)); ! 685: else { ! 686: un.h_int = -1; ! 687: for ( ; (unsigned) i<nvestr->len; i++) ! 688: un.h_4char[i % sizeof(int)] = nvestr->str[i]; ! 689: } ! 690: nbp_upshift (un.h_4char, len); ! 691: hash ^= un.h_int; ! 692: } ! 693: ! 694: return (hash); ! 695: } /* nbp_strhash */ ! 696: ! 697: static nve_entry_t *nbp_search_nve (nbp_req, ifID) ! 698: register nbp_req_t *nbp_req; ! 699: register at_ifaddr_t *ifID; /* NULL ok */ ! 700: { ! 701: register nve_entry_t *nve_entry; ! 702: ! 703: #ifdef NBP_DEBUG ! 704: { ! 705: char zone[35],object[35],type[35]; ! 706: strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len); ! 707: strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len); ! 708: strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len); ! 709: object[nbp_req->nve.object.len] = '\0'; ! 710: zone[nbp_req->nve.zone.len] = '\0'; ! 711: type[nbp_req->nve.type.len] = '\0'; ! 712: dPrintf(D_M_NBP_LOW, D_L_USR4, ! 713: ("nbp_search: looking for %s:%s@%s resp:0x%x\n",object,type,zone, ! 714: (u_int) nbp_req->response)); ! 715: } ! 716: #endif /* NBP_DEBUG */ ! 717: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 718: TAILQ_FOREACH(nve_entry, &name_registry, nve_link) { ! 719: if ((nbp_req->nve.zone_hash) && ! 720: ((nbp_req->nve.zone_hash != ! 721: nve_entry->zone_hash) && ! 722: (nbp_req->nve.zone_hash != hzonehash) ! 723: ) ! 724: ) { ! 725: dPrintf(D_M_NBP_LOW,D_L_USR4, ! 726: ("nbp_search: no match for zone, req hash:%x\n", ! 727: nbp_req->nve.zone_hash)); ! 728: continue; ! 729: } ! 730: else { /* for this entry's zone OR no zone in request or entry */ ! 731: /* only in singleport mode (!MULTIPORT_MODE) with ! 732: empty PRAM can an entry have '*' for it's zone ! 733: */ ! 734: at_nvestr_t *ezone=&nve_entry->zone; ! 735: at_nvestr_t *rzone=&nbp_req->nve.zone; ! 736: if (!DEFAULT_ZONE(rzone) && !DEFAULT_ZONE(ezone)) { ! 737: if (nbp_strcmp (rzone, ezone, 0) != 0) ! 738: continue; ! 739: } ! 740: else { ! 741: if (MULTIHOME_MODE && ifID && ! 742: (nve_entry->address.net != ! 743: ifID->ifThisNode.s_net)) { ! 744: dPrintf(D_M_NBP, D_L_USR4, ! 745: ("nbp search ifID (%d) & req net (%d) not eq\n", ! 746: nve_entry->address.net, ! 747: ifID->ifThisNode.s_net)); ! 748: continue; ! 749: } ! 750: if (ifID) ! 751: dPrintf(D_M_NBP, D_L_USR4, ! 752: ("nbp search ifID (%d) & req net (%d) equal\n", ! 753: nve_entry->address.net, ! 754: ifID->ifThisNode.s_net)); ! 755: } ! 756: ! 757: } ! 758: if (!(nbp_req->flags & NBP_WILD_OBJECT)) { ! 759: if ((nbp_req->nve.object_hash) && ! 760: (nbp_req->nve.object_hash != ! 761: nve_entry->object_hash)) ! 762: continue; ! 763: else { ! 764: if (nbp_strcmp (&nbp_req->nve.object, ! 765: &nve_entry->object, ! 766: NBP_SPL_WILDCARD) != 0) ! 767: continue; ! 768: } ! 769: } ! 770: ! 771: ! 772: if (!(nbp_req->flags & NBP_WILD_TYPE)) { ! 773: if ((nbp_req->nve.type_hash) && ! 774: (nbp_req->nve.type_hash !=nve_entry->type_hash)) ! 775: continue; ! 776: else { ! 777: if (nbp_strcmp (&nbp_req->nve.type, ! 778: &nve_entry->type, ! 779: NBP_SPL_WILDCARD) != 0) ! 780: continue; ! 781: } ! 782: } ! 783: ! 784: /* Found a match! */ ! 785: #ifdef NBP_DEBUG ! 786: { ! 787: char zone[35],object[35],type[35]; ! 788: ! 789: strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len); ! 790: strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len); ! 791: strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len); ! 792: object[nbp_req->nve.object.len] = '\0'; ! 793: zone[nbp_req->nve.zone.len] = '\0'; ! 794: type[nbp_req->nve.type.len] = '\0'; ! 795: dPrintf(D_M_NBP_LOW, D_L_USR2, ! 796: ("nbp_search: found %s:%s@%s net:%d\n", ! 797: object, type, zone, (int)nve_entry->address.net)); ! 798: } ! 799: #endif /* NBP_DEBUG */ ! 800: if (nbp_req->func != NULL) { ! 801: if ((*(nbp_req->func))(nbp_req, nve_entry) != 0) { ! 802: /* errno expected to be set by func */ ! 803: ATENABLE(nve_lock_pri,NVE_LOCK); ! 804: return (NULL); ! 805: } ! 806: } else { ! 807: ATENABLE(nve_lock_pri,NVE_LOCK); ! 808: return (nve_entry); ! 809: } ! 810: } ! 811: ATENABLE(nve_lock_pri,NVE_LOCK); ! 812: ! 813: errno = 0; ! 814: return (NULL); ! 815: } /* nbp_search_nve */ ! 816: ! 817: static int nbp_lkup_reply (nbp_req, nve_entry) ! 818: register nbp_req_t *nbp_req; ! 819: register nve_entry_t *nve_entry; ! 820: { ! 821: register at_nbptuple_t *tuple; ! 822: register int tuple_size, buf_len; ! 823: register int obj_len, type_len; ! 824: u_char *p; ! 825: ! 826: /* size of the current tuple we want to write... */ ! 827: tuple_size = nve_entry->object.len + 1 + /* object */ ! 828: nve_entry->type.len + 1 + /* type */ ! 829: 2 + /* zone */ ! 830: sizeof (at_inet_t) + 1; /* addr + enum */ ! 831: ! 832: buf_len = ((nbp_req->flags & NBP_WILD_MASK) ? DDP_DATA_SIZE:tuple_size); ! 833: if (nbp_req->response == NULL) { ! 834: if (nbp_setup_resp (nbp_req, buf_len) != 0) ! 835: /* errno expected to be set by nbp_setup_resp() */ ! 836: return (-1); ! 837: } ! 838: ! 839: if ((nbp_req->space_unused < tuple_size) || ! 840: (DATA_NBP(nbp_req->response)->tuple_count == NBP_TUPLE_MAX)) { ! 841: if (nbp_send_resp (nbp_req) != 0) ! 842: return (-1); ! 843: if (nbp_setup_resp (nbp_req, buf_len) != 0) ! 844: return (-1); ! 845: } ! 846: ! 847: /* At this point, we have a response buffer that can accommodate the ! 848: * tuple we want to write. Write it! ! 849: */ ! 850: tuple = (at_nbptuple_t *)gbuf_wptr(nbp_req->response); ! 851: tuple->enu_addr = nve_entry->address; ! 852: tuple->enu_enum = nve_entry->enumerator; ! 853: ! 854: /* tuple is in the compressed (no "filler") format */ ! 855: p = (u_char *)&tuple->enu_entity.object; ! 856: obj_len = nve_entry->object.len + 1; ! 857: bcopy(&nve_entry->object, p, obj_len); ! 858: p += obj_len; ! 859: type_len = nve_entry->type.len + 1; ! 860: bcopy(&nve_entry->type, p, type_len); ! 861: p += type_len; ! 862: p[0] = (u_char)1; ! 863: p[1] = '*'; ! 864: ! 865: nbp_req->space_unused -= tuple_size; ! 866: gbuf_winc(nbp_req->response, tuple_size); ! 867: ! 868: /* increment the tuple count in header by 1 */ ! 869: DATA_NBP(nbp_req->response)->tuple_count++; ! 870: ! 871: return (0); ! 872: } ! 873: ! 874: ! 875: static int nbp_strcmp (str1, str2, embedded_wildcard) ! 876: register at_nvestr_t *str1, *str2; ! 877: register u_char embedded_wildcard; /* If str1 may contain a character ! 878: * that's to be treated as an ! 879: * embedded wildcard, this character ! 880: * is it. Making this special case ! 881: * since for zone names, squiggly ! 882: * equal is not to be treated as a ! 883: * wildcard. ! 884: */ ! 885: { ! 886: u_char ch1,ch2; ! 887: register int i1, i2; ! 888: register int reverse = 0; ! 889: register int left_index; ! 890: ! 891: /* Embedded wildcard, if any, could only be in the first string (str1). ! 892: * returns 0 if two strings are equal (modulo case), -1 otherwise ! 893: */ ! 894: ! 895: if (str1->len == 0 || str2->len == 0) { ! 896: return (-1); ! 897: } ! 898: ! 899: /* Wildcards are not allowed in str2. ! 900: * ! 901: * If str1 could potentially contain an embedded wildcard, since the ! 902: * embedded wildcard matches ZERO OR MORE characters, str1 can not be ! 903: * more than 1 character longer than str2. ! 904: * ! 905: * If str1 is not supposed to have embedded wildcards, the two strs ! 906: * must be of equal length. ! 907: */ ! 908: if ((embedded_wildcard && (str2->len < (unsigned) (str1->len-1))) || ! 909: (!embedded_wildcard && (str2->len != str1->len))) { ! 910: return (-1); ! 911: } ! 912: ! 913: for (i1 = i2 = left_index = 0; (unsigned) i1 < str1->len ;) { ! 914: ch1 = str1->str[i1]; ! 915: ch2 = str2->str[i2]; ! 916: ! 917: if (embedded_wildcard && (ch1==embedded_wildcard)) { ! 918: /* hit the embedded wild card... start comparing from ! 919: * the other end of the string. ! 920: */ ! 921: reverse++; ! 922: /* But, if embedded wildcard was the last character of ! 923: * the string, the two strings match, so return okay. ! 924: */ ! 925: if (i1 == str1->len-1) { ! 926: return (0); ! 927: } ! 928: ! 929: i1 = str1->len - 1; ! 930: i2 = str2->len - 1; ! 931: ! 932: continue; ! 933: } ! 934: ! 935: nbp_upshift(&ch1, 1); ! 936: nbp_upshift(&ch2, 1); ! 937: ! 938: if (ch1 != ch2) { ! 939: return (-1); ! 940: } ! 941: ! 942: if (reverse) { ! 943: i1--; i2--; ! 944: if (i1 == left_index) { ! 945: return (0); ! 946: } ! 947: } else { ! 948: i1++; i2++; left_index++; ! 949: } ! 950: } ! 951: return (0); ! 952: } ! 953: ! 954: ! 955: static void nbp_setup_hdr (nbp_req) ! 956: register nbp_req_t *nbp_req; ! 957: { ! 958: register at_ddp_t *ddp; ! 959: register at_nbp_t *nbp; ! 960: ! 961: ddp = DATA_DDP(nbp_req->response); ! 962: nbp = DATA_NBP(nbp_req->response); ! 963: ! 964: ddp->type = DDP_NBP; ! 965: UAS_ASSIGN(ddp->checksum, 0); ! 966: ddp->unused = ddp->hopcount = 0; ! 967: ! 968: switch(DATA_NBP(nbp_req->request)->control) { ! 969: case NBP_LKUP : ! 970: ddp->dst_socket = nbp_req->nve.address.socket; ! 971: ddp->dst_node = nbp_req->nve.address.node; ! 972: NET_ASSIGN(ddp->dst_net, nbp_req->nve.address.net); ! 973: nbp->control = NBP_LKUP_REPLY; ! 974: break; ! 975: } ! 976: nbp->at_nbp_id = DATA_NBP(nbp_req->request)->at_nbp_id; ! 977: return; ! 978: } ! 979: ! 980: ! 981: static int nbp_setup_resp (nbp_req, tuples_size) ! 982: register nbp_req_t *nbp_req; ! 983: register int tuples_size; ! 984: { ! 985: int buf_size = tuples_size + DDP_X_HDR_SIZE + NBP_HDR_SIZE; ! 986: nbp_req->response = gbuf_alloc(AT_WR_OFFSET+buf_size, PRI_MED); ! 987: if (nbp_req->response == NULL) { ! 988: errno = ENOBUFS; ! 989: return(-1); ! 990: } ! 991: gbuf_rinc(nbp_req->response, AT_WR_OFFSET); ! 992: gbuf_wset(nbp_req->response, DDP_X_HDR_SIZE + NBP_HDR_SIZE); ! 993: nbp_setup_hdr(nbp_req); ! 994: ! 995: DATA_NBP(nbp_req->response)->tuple_count = 0; ! 996: nbp_req->space_unused = tuples_size; ! 997: ! 998: return (0); ! 999: } /* nbp_setup_resp */ ! 1000: ! 1001: ! 1002: static int nbp_send_resp (nbp_req) ! 1003: register nbp_req_t *nbp_req; ! 1004: { ! 1005: int status; ! 1006: ! 1007: status = ddp_output(&nbp_req->response, (at_socket)NBP_SOCKET, FALSE); ! 1008: nbp_req->response = NULL; ! 1009: errno = status; ! 1010: return(errno?-1:0); ! 1011: } ! 1012: ! 1013: void nbp_add_multicast(zone, ifID) ! 1014: at_nvestr_t *zone; ! 1015: at_ifaddr_t *ifID; ! 1016: { ! 1017: char data[ETHERNET_ADDR_LEN]; ! 1018: int i; ! 1019: ! 1020: if (zone->str[0] == '*') ! 1021: return; ! 1022: ! 1023: { ! 1024: char str[35]; ! 1025: strncpy(str,zone->str,zone->len); ! 1026: str[zone->len] = '\0'; ! 1027: dPrintf(D_M_NBP_LOW, D_L_USR3, ! 1028: ("nbp_add_multi getting mc for %s\n", str)); ! 1029: } ! 1030: zt_get_zmcast(ifID, zone, data); ! 1031: if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type)) ! 1032: ddp_bit_reverse(data); ! 1033: dPrintf(D_M_NBP_LOW,D_L_USR3, ! 1034: ("nbp_add_multi adding 0x%x%x port:%d ifID:0x%x if:%s\n", ! 1035: *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, ! 1036: i, (u_int) ifID, ifID->ifName)); ! 1037: ! 1038: bcopy((caddr_t)data, (caddr_t)&ifID->ZoneMcastAddr, ETHERNET_ADDR_LEN); ! 1039: (void)at_reg_mcast(ifID, (caddr_t)&ifID->ZoneMcastAddr); ! 1040: } ! 1041: ! 1042: ! 1043: getNbpTableSize() ! 1044: ! 1045: /* for SNMP, returns size in # of entries */ ! 1046: { ! 1047: register nve_entry_t *nve; ! 1048: register int i=0; ! 1049: ! 1050: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 1051: for (nve = TAILQ_FIRST(&name_registry); nve; nve = TAILQ_NEXT(nve, nve_link), i++) ! 1052: i++; ! 1053: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1054: return(i); ! 1055: } ! 1056: ! 1057: getNbpTable(p, s, c) ! 1058: snmpNbpEntry_t *p; ! 1059: int s; /* starting entry */ ! 1060: int c; /* # entries to copy */ ! 1061: ! 1062: /* for SNMP, returns section of nbp table */ ! 1063: { ! 1064: register nve_entry_t *nve; ! 1065: register int i=0; ! 1066: static int nextNo=0; /* entry that *next points to */ ! 1067: static nve_entry_t *next = (nve_entry_t*)NULL; ! 1068: ! 1069: if (s && next && nextNo == s) { ! 1070: nve = next; ! 1071: i = nextNo; ! 1072: } ! 1073: else ! 1074: nve = TAILQ_FIRST(&name_registry); ! 1075: ! 1076: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 1077: for ( ; nve && c ; nve = TAILQ_NEXT(nve, nve_link), p++,i++) { ! 1078: if (i>= s) { ! 1079: p->nbpe_object = nve->object; ! 1080: p->nbpe_type = nve->type; ! 1081: c--; ! 1082: } ! 1083: } ! 1084: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1085: if (nve) { ! 1086: next = nve; ! 1087: nextNo = i; ! 1088: } else { ! 1089: next = (nve_entry_t*)NULL; ! 1090: nextNo = 0; ! 1091: } ! 1092: } ! 1093: ! 1094: ! 1095: #define ZONES_PER_BLK 31 /* 31 fits within a 1k blk) */ ! 1096: #define ZONE_BLK_SIZE ZONES_PER_BLK * sizeof(at_nvestr_t) ! 1097: ! 1098: int setLocalZones(newzones, size) ! 1099: at_nvestr_t *newzones; ! 1100: int size; ! 1101: /* updates list of zones which are local to all active ports ! 1102: missing zones are not deleted, only missing zones are added. ! 1103: */ ! 1104: { ! 1105: int bytesread=0; /* #bytes read from tuple */ ! 1106: int i=0, dupe; ! 1107: gbuf_t *m; ! 1108: at_nvestr_t *pnve, *pnew = newzones; ! 1109: ! 1110: if (!lzones) { ! 1111: if(!(lzones = gbuf_alloc(ZONE_BLK_SIZE, PRI_MED))) ! 1112: return(ENOBUFS); ! 1113: gbuf_wset(lzones,0); ! 1114: } ! 1115: while (bytesread < size) { /* for each new zone */ ! 1116: { ! 1117: char str[35]; ! 1118: strncpy(str,pnew->str,pnew->len); ! 1119: str[pnew->len] = '\0'; ! 1120: } ! 1121: m = lzones; ! 1122: pnve = (at_nvestr_t*)gbuf_rptr(m); ! 1123: dupe = 0; ! 1124: for (i=0; i<lzonecnt && !dupe; i++,pnve++) { ! 1125: if (i && !(i%ZONES_PER_BLK)) ! 1126: if (gbuf_cont(m)) { ! 1127: m = gbuf_cont(m); ! 1128: pnve = (at_nvestr_t*)gbuf_rptr(m); ! 1129: } ! 1130: else ! 1131: break; ! 1132: if (pnew->len != pnve->len) ! 1133: continue; ! 1134: if (pnew->len > 33) { ! 1135: return(0); ! 1136: } ! 1137: if (!strncmp(pnew->str, pnve->str, pnew->len)) { ! 1138: dupe=1; ! 1139: continue; ! 1140: } ! 1141: } ! 1142: if (!dupe) { ! 1143: /* add new zone */ ! 1144: if (lzonecnt && !(lzonecnt%ZONES_PER_BLK)) { ! 1145: if(!(gbuf_cont(m) = gbuf_alloc(ZONE_BLK_SIZE, PRI_MED))) ! 1146: return(ENOBUFS); ! 1147: gbuf_wset(gbuf_cont(m),0); ! 1148: pnve = (at_nvestr_t*)gbuf_rptr(gbuf_cont(m)); ! 1149: } ! 1150: strncpy(pnve->str,pnew->str,pnew->len); ! 1151: pnve->len = pnew->len; ! 1152: lzonecnt++; ! 1153: } ! 1154: bytesread += (pnew->len+1); ! 1155: pnew = (at_nvestr_t*) (((char *)pnew) + pnew->len + 1); ! 1156: } ! 1157: /* showLocalZones1(); */ ! 1158: return(0); ! 1159: } ! 1160: ! 1161: /********** ! 1162: showLocalZones1() ! 1163: { ! 1164: int i; ! 1165: at_nvestr_t *pnve; ! 1166: gbuf_t *m; ! 1167: char str[35]; ! 1168: ! 1169: for (i=0; ; i++) { ! 1170: if (!(pnve = getLocalZone(i))) { ! 1171: break; ! 1172: } ! 1173: strncpy(str,pnve->str,pnve->len); ! 1174: str[pnve->len] = '\0'; ! 1175: } ! 1176: } ! 1177: ! 1178: *********/ ! 1179: ! 1180: isZoneLocal(zone) ! 1181: at_nvestr_t *zone; ! 1182: { ! 1183: at_nvestr_t *pnve; ! 1184: int i; ! 1185: if (DEFAULT_ZONE(zone)) ! 1186: return(1); ! 1187: for (i=0; ; i++) { ! 1188: if (!(pnve = getLocalZone(i))) ! 1189: break; ! 1190: if (!nbp_strcmp(pnve,zone,0)) ! 1191: return(1); ! 1192: } ! 1193: return(0); ! 1194: } ! 1195: ! 1196: ! 1197: #define NULL_PNVESTR (at_nvestr_t *) 0 ! 1198: ! 1199: at_nvestr_t *getLocalZone(zno) ! 1200: int zno; /* zone number in virtual list to ! 1201: return, 0 for first zone */ ! 1202: /* returns pointer to a new local zone number zno, ! 1203: returns null when no zones left. ! 1204: */ ! 1205: { ! 1206: if_zone_t ifz; ! 1207: ifz.ifzn.zone = zno; ! 1208: if (MULTIPORT_MODE) ! 1209: return(getRTRLocalZone(&ifz)); ! 1210: else ! 1211: return(getSPLocalZone(zno)); ! 1212: } ! 1213: ! 1214: ! 1215: at_nvestr_t *getSPLocalZone(zno) ! 1216: int zno; /* zone number in virtual list to ! 1217: return, 0 for first zone */ ! 1218: /* single port mode version */ ! 1219: { ! 1220: int curz=0; /* current zone */ ! 1221: gbuf_t *m; ! 1222: at_nvestr_t *pnve; ! 1223: ! 1224: if (lzones) { ! 1225: m = lzones; ! 1226: pnve = (at_nvestr_t*)gbuf_rptr(m); ! 1227: } ! 1228: else ! 1229: return(NULL_PNVESTR); ! 1230: if ( zno>=lzonecnt ) ! 1231: return(NULL_PNVESTR); ! 1232: for (curz=0; curz<zno; curz++,pnve++ ) { ! 1233: if ( curz<lzonecnt ) { ! 1234: if (curz && !(curz%ZONES_PER_BLK) ) { ! 1235: if (gbuf_cont(m)) { ! 1236: m = gbuf_cont(m); ! 1237: pnve = (at_nvestr_t*)gbuf_rptr(m); ! 1238: } ! 1239: else { ! 1240: return(NULL_PNVESTR); ! 1241: } ! 1242: } ! 1243: if (pnve->len > NBP_NVE_STR_SIZE) { ! 1244: return(NULL_PNVESTR); ! 1245: } ! 1246: } ! 1247: else ! 1248: return(NULL_PNVESTR); ! 1249: } ! 1250: return(pnve); ! 1251: } ! 1252: ! 1253: /* The following functions are used in name registration and removal */ ! 1254: ! 1255: int nbp_fillin_nve(entity, nve) ! 1256: at_entity_t *entity; ! 1257: nve_entry_t *nve; ! 1258: { ! 1259: register int i; ! 1260: ! 1261: if (entity->object.len > NBP_NVE_STR_SIZE || ! 1262: entity->type.len > NBP_NVE_STR_SIZE || ! 1263: entity->zone.len > NBP_NVE_STR_SIZE) { ! 1264: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1265: ("nbp_fillin_nve: bad str len\n")); ! 1266: errno = EINVAL; ! 1267: return (-1); ! 1268: } ! 1269: ! 1270: nve->zone = entity->zone; ! 1271: nve->zone_hash = 0; ! 1272: if (!isZoneLocal(&entity->zone)) { ! 1273: errno = EINVAL; ! 1274: return(-1); ! 1275: } ! 1276: /* if there's no zone, '*' gets filled in when entry is created */ ! 1277: if (!DEFAULT_ZONE(&entity->zone)) ! 1278: nve->zone_hash = nbp_strhash(&nve->zone); ! 1279: ! 1280: nve->object = entity->object; ! 1281: nve->object_hash = 0; ! 1282: if (entity->object.len == 1 && ! 1283: (entity->object.str[0] == NBP_ORD_WILDCARD || ! 1284: entity->object.str[0] == NBP_SPL_WILDCARD)) { ! 1285: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1286: ("nbp_fillin_nve: wildcard\n")); ! 1287: errno = EINVAL; ! 1288: return (-1); ! 1289: } ! 1290: for (i = 0; i < entity->object.len; i++) { ! 1291: if (entity->object.str[i] == NBP_SPL_WILDCARD) { ! 1292: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1293: ("nbp_fillin_nve: wildcard2\n")); ! 1294: errno = EINVAL; ! 1295: return (-1); ! 1296: } ! 1297: } ! 1298: nve->object_hash = nbp_strhash(&nve->object); ! 1299: ! 1300: nve->type = entity->type; ! 1301: nve->type_hash = 0; ! 1302: if (entity->type.len == 1 && ! 1303: (entity->type.str[0] == NBP_ORD_WILDCARD || ! 1304: entity->type.str[0] == NBP_SPL_WILDCARD)) { ! 1305: errno = EINVAL; ! 1306: return (-1); ! 1307: } ! 1308: for (i = 0; i < entity->type.len; i++) { ! 1309: if (entity->type.str[i] == NBP_SPL_WILDCARD) { ! 1310: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1311: ("nbp_fillin_nve: wildcard3\n")); ! 1312: errno = EINVAL; ! 1313: return (-1); ! 1314: } ! 1315: } ! 1316: nve->type_hash = nbp_strhash(&nve->type); ! 1317: ! 1318: return(0); ! 1319: } /* nbp_fillin_nve */ ! 1320: ! 1321: nve_entry_t *nbp_find_nve(nve) ! 1322: nve_entry_t *nve; ! 1323: { ! 1324: register nve_entry_t *nve_entry; ! 1325: ! 1326: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 1327: TAILQ_FOREACH(nve_entry, &name_registry, nve_link) { ! 1328: if (nve->zone_hash && ! 1329: ((nve->zone_hash != nve_entry->zone_hash) && ! 1330: (nve->zone_hash != hzonehash))) { ! 1331: dPrintf(D_M_NBP_LOW,D_L_USR4, ! 1332: ("nbp_find_nve: no match for zone, req hash:%x\n", ! 1333: nve->zone_hash)); ! 1334: continue; ! 1335: } ! 1336: ! 1337: if ((nve->object_hash) && ! 1338: (nve->object_hash != nve_entry->object_hash)) ! 1339: continue; ! 1340: ! 1341: if ((nve->type_hash) && ! 1342: (nve->type_hash != nve_entry->type_hash)) ! 1343: continue; ! 1344: ! 1345: /* Found a match! */ ! 1346: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1347: return (nve_entry); ! 1348: } ! 1349: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1350: ! 1351: return (NULL); ! 1352: } /* nbp_find_nve */ ! 1353: ! 1354: static int nbp_enum_gen (nve_entry) ! 1355: register nve_entry_t *nve_entry; ! 1356: { ! 1357: register int new_enum = 0; ! 1358: register nve_entry_t *ne; ! 1359: ! 1360: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 1361: re_do: ! 1362: TAILQ_FOREACH(ne, &name_registry, nve_link) { ! 1363: if ((*(int *)&ne->address == *(int *)&nve_entry->address) && ! 1364: (ne->enumerator == new_enum)) { ! 1365: if (new_enum == 255) { ! 1366: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1367: return(EADDRNOTAVAIL); ! 1368: } else { ! 1369: new_enum++; ! 1370: goto re_do; ! 1371: } ! 1372: } ! 1373: } ! 1374: ! 1375: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1376: nve_entry->enumerator = new_enum; ! 1377: return (0); ! 1378: } ! 1379: ! 1380: int nbp_new_nve_entry(nve_entry, ifID) ! 1381: nve_entry_t *nve_entry; ! 1382: at_ifaddr_t *ifID; ! 1383: { ! 1384: gbuf_t *tag; ! 1385: nve_entry_t *new_entry; ! 1386: at_nvestr_t *zone; ! 1387: int error; ! 1388: ! 1389: if (!(valid_at_addr((at_inet_t *)&nve_entry->address))) { ! 1390: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1391: ("nbp_new_nve_entry: valid_at_addr\n")); ! 1392: return(EINVAL); ! 1393: } ! 1394: if ((error = nbp_enum_gen(nve_entry))) ! 1395: return(error); ! 1396: ! 1397: nve_entry->unique_nbp_id = ++nbp_id_count; ! 1398: ! 1399: /* Got an nve entry on hand.... allocate a buffer, copy the entry ! 1400: * on to it and stick it in the registry. ! 1401: */ ! 1402: if ((tag = gbuf_alloc(sizeof(nve_entry_t), PRI_HI)) == NULL){ ! 1403: return(ENOBUFS); ! 1404: } ! 1405: gbuf_wset(tag, sizeof(nve_entry_t)); ! 1406: new_entry = (nve_entry_t *)gbuf_rptr(tag); ! 1407: bcopy(nve_entry, new_entry, sizeof(nve_entry_t)); ! 1408: ! 1409: if (DEFAULT_ZONE(&nve_entry->zone)) { ! 1410: /* put actual zone name in entry instead of "*" */ ! 1411: /* if single port mode and no zone name, then a router ! 1412: is down, so use pram zone name hint from elap cfg */ ! 1413: if (!MULTIPORT_MODE && ifID_home->ifZoneName.str[0] == '*') { ! 1414: zone = &ifID_home->startup_zone; ! 1415: } else { ! 1416: zone = &ifID_home->ifZoneName; ! 1417: } ! 1418: new_entry->zone = *zone; ! 1419: if ( new_entry->zone.len == 0 ) { ! 1420: new_entry->zone.str[0] = '*'; ! 1421: new_entry->zone.len = 1; ! 1422: } ! 1423: new_entry->zone_hash = nbp_strhash(&new_entry->zone); ! 1424: } ! 1425: new_entry->tag = tag; ! 1426: new_entry->pid = current_proc()->p_pid; ! 1427: ! 1428: ATDISABLE(nve_lock_pri,NVE_LOCK); ! 1429: TAILQ_INSERT_TAIL(&name_registry, new_entry, nve_link); ! 1430: ATENABLE(nve_lock_pri,NVE_LOCK); ! 1431: at_state.flags |= AT_ST_NBP_CHANGED; ! 1432: ! 1433: #ifdef NBP_DEBUG ! 1434: { ! 1435: char zone[35],object[35],type[35]; ! 1436: strncpy(zone,new_entry->zone.str, new_entry->zone.len); ! 1437: strncpy(object,new_entry->object.str, new_entry->object.len); ! 1438: strncpy(type,new_entry->type.str, new_entry->type.len); ! 1439: object[new_entry->object.len] = '\0'; ! 1440: zone[new_entry->zone.len] = '\0'; ! 1441: type[new_entry->type.len] = '\0'; ! 1442: dPrintf(D_M_NBP_LOW, D_L_USR4, ! 1443: ("nbp_insert: adding %s:%s@%s addr:%d.%d ", ! 1444: object, type, zone, ! 1445: new_entry->address.net, new_entry->address.node)); ! 1446: } ! 1447: #endif /* NBP_DEBUG */ ! 1448: ! 1449: nbp_add_multicast(&new_entry->zone, ifID); ! 1450: return (0); ! 1451: } /* nbp_new_nve_entry */ ! 1452: ! 1453: void nbp_delete_entry (nve_entry) ! 1454: nve_entry_t *nve_entry; ! 1455: { ! 1456: TAILQ_REMOVE(&name_registry, nve_entry, nve_link); ! 1457: gbuf_freem(nve_entry->tag); ! 1458: at_state.flags |= AT_ST_NBP_CHANGED; ! 1459: } ! 1460: ! 1461: /* Registration of an NBP entity in multihoming mode, from AIOCNBPREG ! 1462: in at.c */ ! 1463: int nbp_mh_reg(nbpP) ! 1464: at_nbp_reg_t *nbpP; ! 1465: { ! 1466: nve_entry_t nve; ! 1467: at_ifaddr_t *ifID = 0; ! 1468: int registered = 0; ! 1469: int finished = FALSE; ! 1470: ! 1471: if (nbp_fillin_nve(&nbpP->name, &nve) != 0) { ! 1472: /* bad tuple... */ ! 1473: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1474: ("nbp_mh_reg: bad tuple\n")); ! 1475: return(EINVAL); ! 1476: } ! 1477: nve.address = nbpP->addr; ! 1478: nve.ddptype = nbpP->ddptype; ! 1479: ! 1480: if (DEFAULT_ZONE(&nbpP->name.zone)) { ! 1481: /* multihoming mode with the default zone specified */ ! 1482: ! 1483: /* now find the matching interfaces */ ! 1484: TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { ! 1485: if (nbpP->addr.net || nbpP->addr.node) { ! 1486: /* if address is specified */ ! 1487: if ((nbpP->addr.net != ifID->ifThisNode.s_net || ! 1488: nbpP->addr.node != ifID->ifThisNode.s_node)) ! 1489: continue; ! 1490: else ! 1491: /* the address was specified, and ! 1492: we found the matching interface */ ! 1493: finished = TRUE; ! 1494: } else { ! 1495: /* address is not specified, so fill in ! 1496: the address for the interface */ ! 1497: nve.address.net = ifID->ifThisNode.s_net; ! 1498: nve.address.node = ifID->ifThisNode.s_node; ! 1499: } ! 1500: nve.zone = ifID->ifZoneName; ! 1501: nve.zone_hash = nbp_strhash(&nve.zone); ! 1502: if (nbp_find_nve(&nve)) ! 1503: continue; ! 1504: if (nbp_new_nve_entry(&nve, ifID) == 0) ! 1505: registered++; ! 1506: } ! 1507: if (registered && !nbpP->addr.net && !nbpP->addr.node) { ! 1508: nbpP->addr.net = ifID_home->ifThisNode.s_net; ! 1509: nbpP->addr.node = ifID_home->ifThisNode.s_node; ! 1510: } ! 1511: } else { ! 1512: /* multihoming mode with a specific zone specified */ ! 1513: /* see which segments (interfaces) are seeded for this zone */ ! 1514: int zno; ! 1515: char ifs_in_zone[IF_TOTAL_MAX]; ! 1516: if (!(zno = zt_find_zname(&nve.zone))) { ! 1517: dPrintf(D_M_NBP_LOW, D_L_WARNING, ! 1518: ("nbp_mh_reg: didn't find zone name\n")); ! 1519: return(EINVAL); ! 1520: } ! 1521: getIfUsage(zno-1, ifs_in_zone); ! 1522: ! 1523: /* now find the first matching interface */ ! 1524: TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { ! 1525: if (!ifs_in_zone[ifID->ifPort]) ! 1526: /* zone doesn't match */ ! 1527: continue; ! 1528: else ! 1529: /* the zone matches, so unless the ! 1530: address is specified and doesn't ! 1531: match, we only need to do this once */ ! 1532: finished = TRUE; ! 1533: ! 1534: if (nbpP->addr.net || nbpP->addr.node) { ! 1535: /* address is specified */ ! 1536: finished = FALSE; ! 1537: if ((nbpP->addr.net != ifID->ifThisNode.s_net || ! 1538: nbpP->addr.node != ifID->ifThisNode.s_node)) ! 1539: continue; ! 1540: else ! 1541: /* the address was specified, and ! 1542: we found the matching interface */ ! 1543: finished = TRUE; ! 1544: } else { ! 1545: /* address is not specified, so fill in ! 1546: the address for the interface */ ! 1547: nve.address.net = ifID->ifThisNode.s_net; ! 1548: nve.address.node = ifID->ifThisNode.s_node; ! 1549: } ! 1550: if (nbp_find_nve(&nve)) ! 1551: continue; ! 1552: if (nbp_new_nve_entry(&nve, ifID) == 0) ! 1553: registered++; ! 1554: } ! 1555: if (registered && !nbpP->addr.net && !nbpP->addr.node) { ! 1556: nbpP->addr.net = ifID->ifThisNode.s_net; ! 1557: nbpP->addr.node = ifID->ifThisNode.s_node; ! 1558: } ! 1559: } ! 1560: nbpP->unique_nbp_id = (registered > 1)? 0: nve.unique_nbp_id; ! 1561: ! 1562: if (registered) ! 1563: return(0); ! 1564: else ! 1565: return(EADDRNOTAVAIL); ! 1566: ! 1567: } /* nbp_mh_reg */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.