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