1 /*********************************************************** 2 Copyright IBM Corporation 1987 3 4 All Rights Reserved 5 6 Permission to use, copy, modify, and distribute this software and its 7 documentation for any purpose and without fee is hereby granted, 8 provided that the above copyright notice appear in all copies and that 9 both that copyright notice and this permission notice appear in 10 supporting documentation, and that the name of IBM not be 11 used in advertising or publicity pertaining to distribution of the 12 software without specific, written prior permission. 13 14 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20 SOFTWARE. 21 22 ******************************************************************/ 23 24 /* 25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26 */ 27 /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */ 28 /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */ 29 30 #ifndef lint 31 static char *rcsid = "$Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $"; 32 #endif lint 33 34 #ifdef ISO 35 36 #include "types.h" 37 #include "param.h" 38 #include "user.h" 39 #include "mbuf.h" 40 #include "domain.h" 41 #include "protosw.h" 42 #include "socket.h" 43 #include "socketvar.h" 44 #include "errno.h" 45 #include "ioctl.h" 46 #include "kernel.h" 47 48 #include "../net/if.h" 49 #include "../net/route.h" 50 51 #include "iso.h" 52 #include "iso_var.h" 53 #include "iso_snpac.h" 54 #include "clnp.h" 55 #include "clnp_stat.h" 56 #include "argo_debug.h" 57 #include "esis.h" 58 59 #define SNPAC_BSIZ 20 /* bucket size */ 60 #define SNPAC_NB 13 /* number of buckets */ 61 #define SNPAC_SIZE (SNPAC_BSIZ * SNPAC_NB) 62 struct snpa_cache iso_snpac[SNPAC_SIZE]; 63 u_int iso_snpac_size = SNPAC_SIZE;/* for iso_map command */ 64 int iso_systype = SNPA_ES; /* default to be an ES */ 65 66 struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 67 extern u_long iso_hashchar(); 68 static struct sockaddr_iso 69 dst = {sizeof(dst), AF_ISO}, 70 gte = {sizeof(dst), AF_ISO}, 71 src = {sizeof(dst), AF_ISO}, 72 msk = {sizeof(dst), AF_ISO}, 73 zmk = {1}; 74 #define zsi blank_siso 75 #define zero_isoa zsi.siso_addr 76 #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 77 ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 78 #define S(x) ((struct sockaddr *)&(x)) 79 80 #define SNPAC_HASH(addr) \ 81 (((u_long) iso_hashchar((caddr_t)addr, (int)addr->isoa_len)) % SNPAC_NB) 82 83 #define SNPAC_LOOK(sc,addr) { \ 84 register n; \ 85 sc = &iso_snpac[SNPAC_HASH(addr) * SNPAC_BSIZ]; \ 86 for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) \ 87 if ((sc->sc_flags & SNPA_VALID) && \ 88 (iso_addrmatch1(&sc->sc_nsap, addr))) \ 89 break; \ 90 if (n >= SNPAC_BSIZ) \ 91 sc = 0; \ 92 } 93 94 struct snpa_cache *snpac_new(); 95 96 /* 97 * We only keep track of a single IS at a time. 98 */ 99 struct snpa_cache *known_is; 100 101 /* 102 * Addresses taken from NBS agreements, December 1987. 103 * 104 * These addresses assume on-the-wire transmission of least significant 105 * bit first. This is the method used by 802.3. When these 106 * addresses are passed to the token ring driver, (802.5), they 107 * must be bit-swaped because 802.5 transmission order is MSb first. 108 * 109 * Furthermore, according to IBM Austin, these addresses are not 110 * true token ring multicast addresses. More work is necessary 111 * to get multicast to work right on token ring. 112 * 113 * Currently, the token ring driver does not handle multicast, so 114 * these addresses are converted into the broadcast address in 115 * lan_output() That means that if these multicast addresses change 116 * the token ring driver must be altered. 117 */ 118 struct snpa_cache all_es = { 119 { { 0x0 }, /* sc_nsap */ 120 6, /* sc_len */ 121 { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */ 122 SNPA_VALID, /* sc_flags */ 123 0 } /* sc_ht */ 124 }; 125 struct snpa_cache all_is = { 126 { { 0x0 }, /* sc_nsap */ 127 6, /* sc_len */ 128 { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */ 129 SNPA_VALID, /* sc_flags */ 130 0 } /* sc_ht */ 131 }; 132 133 134 /* 135 * FUNCTION: iso_snparesolve 136 * 137 * PURPOSE: Resolve an iso address into snpa address 138 * 139 * RETURNS: 0 if addr is resolved 140 * errno if addr is unknown 141 * 142 * SIDE EFFECTS: 143 * 144 * NOTES: If an entry is found that matches the address, that 145 * snpa is returned. If no entry is found, but an IS is 146 * known, then the address of the IS is returned. If 147 * neither an address is found that matches or an IS is 148 * known, then the multi-cast address for "all ES" for 149 * this interface is returned. 150 * 151 * NB: the last case described above constitutes the 152 * query configuration function 9542, sec 6.5 153 * A mechanism is needed to prevent this function from 154 * being invoked if the system is an IS. 155 */ 156 iso_snparesolve(ifp, dest, snpa, snpa_len) 157 struct ifnet *ifp; /* outgoing interface */ 158 struct sockaddr_iso *dest; /* destination */ 159 char *snpa; /* RESULT: snpa to be used */ 160 int *snpa_len; /* RESULT: length of snpa */ 161 { 162 extern struct ifnet loif; /* loopback interface */ 163 struct snpa_cache *sc; /* ptr to snpa table entry */ 164 struct iso_addr *destiso; /* destination iso addr */ 165 166 destiso = &dest->siso_addr; 167 168 /* 169 * This hack allows us to send esis packets that have the destination snpa 170 * addresss embedded in the destination nsap address 171 */ 172 if (destiso->isoa_genaddr[0] == AFI_SNA) { 173 /* 174 * This is a subnetwork address. Return it immediately 175 */ 176 IFDEBUG(D_SNPA) 177 printf("iso_snparesolve: return SN address\n"); 178 ENDDEBUG 179 180 *snpa_len = destiso->isoa_len - 1; /* subtract size of AFI */ 181 bcopy((caddr_t) destiso->isoa_genaddr + 1, (caddr_t)snpa, 182 (unsigned)*snpa_len); 183 return (0); 184 } 185 186 IFDEBUG(D_SNPA) 187 printf("iso_snparesolve: resolving %s\n", clnp_iso_addrp(destiso)); 188 ENDDEBUG 189 190 /* 191 * packet is not for us, check cache for an entry 192 */ 193 SNPAC_LOOK(sc, destiso); 194 if (sc == 0) { /* not found */ 195 /* If we are an IS, we can't do much with the packet */ 196 if (iso_systype == SNPA_IS) 197 goto bad; 198 199 /* 200 * Check if we know about an IS 201 */ 202 if ((known_is) && (known_is->sc_flags & SNPA_VALID)) { 203 sc = known_is; 204 } else if (ifp->if_flags & IFF_BROADCAST) { 205 /* 206 * no IS, no match. Return "all es" multicast address for this 207 * interface, as per Query Configuration Function (9542 sec 6.5) 208 * 209 * Note: there is a potential problem here. If the destination 210 * is on the subnet and it does not respond with a ESH, but 211 * does send back a TP CC, a connection could be established 212 * where we always transmit the CLNP packet to "all es" 213 */ 214 sc = &all_es; 215 } else { 216 goto bad; 217 } 218 } 219 220 bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 221 *snpa_len = sc->sc_len; 222 return (0); 223 224 bad: 225 return(ENETUNREACH); 226 } 227 228 229 /* 230 * FUNCTION: snpac_look 231 * 232 * PURPOSE: Look up an entry in the snpa cache 233 * 234 * RETURNS: Pointer to snpa_cache structure, or null 235 * 236 * SIDE EFFECTS: 237 * 238 * NOTES: This is simply SNPAC_LOOK as a procedure. 239 */ 240 struct snpa_cache * 241 snpac_look(isoa) 242 struct iso_addr *isoa; /* destination nsap */ 243 { 244 struct snpa_cache *sc; 245 int s = splimp(); 246 247 SNPAC_LOOK(sc, isoa); 248 249 splx(s); 250 return(sc); 251 } 252 253 /* 254 * FUNCTION: iso_8208snparesolve 255 * 256 * PURPOSE: Find the X.121 address that corresponds to an NSAP addr 257 * 258 * RETURNS: 0 or unix errno 259 * 260 * SIDE EFFECTS: 261 * 262 * NOTES: This ought to invoke the 8208 ES-IS function 263 */ 264 iso_8208snparesolve(dest, snpa, snpa_len) 265 struct sockaddr_iso *dest; /* destination */ 266 char *snpa; /* RESULT: snpa to be used */ 267 int *snpa_len; /* RESULT: length of snpa */ 268 { 269 struct snpa_cache *sc; /* ptr to snpa table entry */ 270 struct iso_addr *destiso; /* destination iso addr */ 271 int s; 272 int err = 0; 273 274 destiso = &dest->siso_addr; 275 276 s = splimp(); 277 SNPAC_LOOK(sc, destiso); 278 if (sc) { 279 bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 280 *snpa_len = sc->sc_len; 281 } else { 282 err = ENETUNREACH; 283 } 284 splx(s); 285 return (err); 286 } 287 288 /* 289 * FUNCTION: iso_8208snpaadd 290 * 291 * PURPOSE: Add an entry to the snpa cache 292 * 293 * RETURNS: 294 * 295 * SIDE EFFECTS: 296 * 297 * NOTES: used by cons 298 */ 299 iso_8208snpaadd(ifp, nsap, snpa, snpalen, ht) 300 struct ifnet *ifp; /* interface info is related to */ 301 struct iso_addr *nsap; /* nsap to add */ 302 caddr_t snpa; /* translation */ 303 int snpalen; /* length in bytes */ 304 short ht; /* holding time (in seconds) */ 305 { 306 snpac_add(ifp, nsap, snpa, snpalen, SNPA_ES, (u_short)ht); 307 } 308 309 /* 310 * FUNCTION: iso_8208snpadelete 311 * 312 * PURPOSE: Delete an entry from the snpa cache 313 * 314 * RETURNS: nothing 315 * 316 * SIDE EFFECTS: 317 * 318 * NOTES: used by CONS 319 */ 320 iso_8208snpadelete(nsap) 321 struct iso_addr *nsap; 322 { 323 struct snpa_cache *sc = snpac_look(nsap); 324 325 if (sc != NULL) 326 snpac_free(sc); 327 } 328 329 /* 330 * FUNCTION: snpac_new 331 * 332 * PURPOSE: create a new entry in the iso address to ethernet 333 * address table 334 * 335 * RETURNS: pointer to newest entry 336 * 337 * SIDE EFFECTS: times out old entries if no new entries are found 338 * 339 * NOTES: If the bucket is full, then timeout the oldest entry 340 * (ie. the one with the youngest holding time) 341 */ 342 struct snpa_cache * 343 snpac_new(isoa) 344 struct iso_addr *isoa; /* iso address to enter into table */ 345 { 346 register struct snpa_cache *sc; 347 register int n; 348 int smallest_ht = 1000000; 349 struct snpa_cache *maybe; 350 351 sc = &iso_snpac[SNPAC_HASH(isoa) * SNPAC_BSIZ]; 352 for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) { 353 354 IFDEBUG (D_IOCTL) 355 printf("snpac_new: sc x%x ", sc); 356 357 if (sc->sc_flags & SNPA_VALID) { 358 int i; 359 360 printf("(valid) %s ", clnp_iso_addrp(&sc->sc_nsap)); 361 for (i=0; i<sc->sc_len; i++) 362 printf("%x%c", sc->sc_snpa[i], i < (sc->sc_len-1) ? ':' 363 : '\n'); 364 } else { 365 printf("invalid\n"); 366 } 367 ENDDEBUG 368 369 if (sc->sc_flags & SNPA_VALID) { 370 if (sc->sc_ht < smallest_ht) { 371 smallest_ht = sc->sc_ht; 372 maybe = sc; 373 } 374 } else { 375 return sc; /* found unused slot */ 376 } 377 } 378 snpac_free(maybe); 379 return maybe; 380 } 381 /* 382 * FUNCTION: snpac_free 383 * 384 * PURPOSE: free an entry in the iso address map table 385 * 386 * RETURNS: nothing 387 * 388 * SIDE EFFECTS: 389 * 390 * NOTES: If there is a route entry associated with cache 391 * entry, then delete that as well 392 */ 393 snpac_free(sc) 394 register struct snpa_cache *sc; /* entry to free */ 395 { 396 register struct rtentry *rt; 397 register struct iso_addr *r; 398 399 if (known_is == sc) { 400 known_is = NULL; 401 } 402 if (sc->sc_rt) { 403 zap_isoaddr(dst, (&(sc->sc_da))); 404 rt = rtalloc1((struct sockaddr *)&dst, 0); 405 if ((sc->sc_rt == rt) && (rt->rt_flags & RTF_UP) 406 && (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 407 RTFREE(rt); 408 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 409 rt->rt_flags, (struct rtentry **)0); 410 } 411 RTFREE(rt); 412 } 413 bzero((caddr_t)sc, sizeof(struct snpa_cache)); 414 } 415 416 /* 417 * FUNCTION: snpac_add 418 * 419 * PURPOSE: Add an entry to the snpa cache 420 * 421 * RETURNS: 422 * 423 * SIDE EFFECTS: 424 * 425 * NOTES: If entry already exists, then update holding time. 426 */ 427 snpac_add(ifp, nsap, snpa, snpalen, type, ht) 428 struct ifnet *ifp; /* interface info is related to */ 429 struct iso_addr *nsap; /* nsap to add */ 430 caddr_t snpa; /* translation */ 431 int snpalen; /* translation length */ 432 char type; /* SNPA_IS or SNPA_ES */ 433 u_short ht; /* holding time (in seconds) */ 434 { 435 struct snpa_cache *sc; 436 437 SNPAC_LOOK(sc, nsap); 438 if (sc == NULL) { 439 sc = snpac_new(nsap); 440 sc->sc_nsap = *nsap; 441 } 442 443 sc->sc_ht = ht; 444 445 sc->sc_len = min(snpalen, MAX_SNPALEN); 446 bcopy(snpa, (caddr_t)sc->sc_snpa, sc->sc_len); 447 sc->sc_flags = SNPA_VALID | type; 448 sc->sc_ifp = ifp; 449 450 if (type & SNPA_IS) 451 snpac_logdefis(sc); 452 } 453 454 /* 455 * FUNCTION: snpac_ioctl 456 * 457 * PURPOSE: handle ioctls to change the iso address map 458 * 459 * RETURNS: unix error code 460 * 461 * SIDE EFFECTS: changes the snpa_cache table declared above. 462 * 463 * NOTES: 464 */ 465 snpac_ioctl(cmd, data) 466 int cmd; /* ioctl to process */ 467 caddr_t data; /* data for the cmd */ 468 { 469 register struct snpa_req *rq = (struct snpa_req *)data; 470 register struct snpa_cache *sc; 471 register struct iso_addr *isoa; 472 int s; 473 char *type; 474 475 switch(cmd) { 476 case SIOCSISOMAP: type = "set"; break; 477 case SIOCDISOMAP: type = "delete"; break; 478 case SIOCGISOMAP: type = "get"; break; 479 default: return(snpac_systype(cmd, data)); 480 } 481 482 /* sanity check */ 483 if (rq->sr_len > MAX_SNPALEN) 484 return(EINVAL); 485 486 IFDEBUG (D_IOCTL) 487 int i; 488 489 printf("snpac_ioctl: %s %s to ", type, clnp_iso_addrp(isoa)); 490 for (i=0; i<rq->sr_len; i++) 491 printf("%x%c", rq->sr_snpa[i], i < (rq->sr_len-1) ? ':' : '\n'); 492 ENDDEBUG 493 494 /* look up this address in table */ 495 isoa = &rq->sr_isoa; 496 497 SNPAC_LOOK(sc, isoa); 498 if (sc == NULL) { /* not found */ 499 if (cmd != SIOCSISOMAP) 500 return(ENXIO); 501 } 502 503 switch(cmd) { 504 case SIOCSISOMAP: /* set entry */ 505 snpac_add((struct ifnet *)NULL, isoa, (caddr_t)rq->sr_snpa, 506 (int)rq->sr_len, 507 (char)(rq->sr_flags & (SNPA_ES|SNPA_IS|SNPA_PERM)), 508 rq->sr_ht); 509 break; 510 511 case SIOCDISOMAP: /* delete entry */ 512 snpac_free(sc); 513 break; 514 515 case SIOCGISOMAP: /* get entry */ 516 bcopy((caddr_t)&sc->sc_sr, (caddr_t)rq, sizeof(struct snpa_req)); 517 break; 518 } 519 return(0); 520 } 521 522 /* 523 * FUNCTION: iso_tryloopback 524 * 525 * PURPOSE: Attempt to use the software loopback interface for pkt 526 * 527 * RETURNS: 0 if packet was sent successfully 528 * errno if there was a problem sending the packet 529 * Ie. the return value of looutput 530 * -1 if software loopback is not appropriate 531 * 532 * SIDE EFFECTS: 533 * 534 * NOTES: 535 */ 536 iso_tryloopback(m, dest) 537 struct mbuf *m; /* pkt */ 538 struct sockaddr_iso *dest; /* destination */ 539 { 540 struct iso_addr *destiso; /* destination iso addr */ 541 542 destiso = &dest->siso_addr; 543 544 if (clnp_ours(destiso)) { 545 IFDEBUG(D_SNPA) 546 printf("iso_tryloopback: local destination\n"); 547 ENDDEBUG 548 if (loif.if_flags & IFF_UP) { 549 IFDEBUG(D_SNPA) 550 printf("iso_tryloopback: calling looutput\n"); 551 ENDDEBUG 552 return (looutput(&loif, m, (struct sockaddr *)dest)); 553 } 554 } 555 return (-1); 556 } 557 558 /* 559 * FUNCTION: snpac_systype 560 * 561 * PURPOSE: Set/Get the system type and esis parameters 562 * 563 * RETURNS: 0 on success, or unix error code 564 * 565 * SIDE EFFECTS: 566 * 567 * NOTES: 568 */ 569 snpac_systype (cmd, data) 570 int cmd; /* ioctl to process */ 571 caddr_t data; /* data for the cmd */ 572 { 573 register struct systype_req *rq = (struct systype_req *)data; 574 extern short esis_holding_time, esis_config_time; 575 576 IFDEBUG (D_IOCTL) 577 if (cmd == SIOCSSTYPE) 578 printf("snpac_systype: cmd set, type x%x, ht %d, ct %d\n", 579 rq->sr_type, rq->sr_holdt, rq->sr_configt); 580 else 581 printf("snpac_systype: cmd get\n"); 582 ENDDEBUG 583 584 if (cmd == SIOCSSTYPE) { 585 if (suser(u.u_cred, &u.u_acflag)) 586 return(EACCES); 587 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 588 return(EINVAL); 589 if (rq->sr_type & SNPA_ES) { 590 iso_systype = SNPA_ES; 591 } else if (rq->sr_type & SNPA_IS) { 592 iso_systype = SNPA_IS; 593 } else { 594 return(EINVAL); 595 } 596 esis_holding_time = rq->sr_holdt; 597 esis_config_time = rq->sr_configt; 598 } else if (cmd == SIOCGSTYPE) { 599 rq->sr_type = iso_systype; 600 rq->sr_holdt = esis_holding_time; 601 rq->sr_configt = esis_config_time; 602 } else { 603 return(EINVAL); 604 } 605 return(0); 606 } 607 608 /* 609 * FUNCTION: snpac_logdefis 610 * 611 * PURPOSE: Mark the IS passed as the default IS 612 * 613 * RETURNS: nothing 614 * 615 * SIDE EFFECTS: 616 * 617 * NOTES: 618 */ 619 snpac_logdefis(sc) 620 register struct snpa_cache *sc; 621 { 622 register struct iso_addr *r; 623 register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 624 if (known_is == 0) 625 known_is = sc; 626 if (known_is != sc) { 627 if (known_is->sc_rt) { 628 rtfree(known_is->sc_rt); 629 known_is->sc_rt = 0; 630 } 631 known_is = sc; 632 } 633 if (rt == 0) { 634 zap_isoaddr(dst, &(sc->sc_nsap)); 635 rtrequest(RTM_ADD, S(zsi), S(dst), S(zmk), 636 RTF_DYNAMIC|RTF_GATEWAY, &sc->sc_rt); 637 return; 638 } 639 if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 640 ((struct sockaddr_iso *)rt->rt_gateway)->siso_addr = sc->sc_nsap; 641 known_is = sc; 642 sc->sc_rt = rt; 643 } 644 } 645 646 /* 647 * FUNCTION: snpac_age 648 * 649 * PURPOSE: Time out snpac entries 650 * 651 * RETURNS: 652 * 653 * SIDE EFFECTS: 654 * 655 * NOTES: When encountering an entry for the first time, snpac_age 656 * may delete up to SNPAC_AGE too many seconds. Ie. 657 * if the entry is added a moment before snpac_age is 658 * called, the entry will immediately have SNPAC_AGE 659 * seconds taken off the holding time, even though 660 * it has only been held a brief moment. 661 * 662 * The proper way to do this is set an expiry timeval 663 * equal to current time + holding time. Then snpac_age 664 * would time out entries where expiry date is older 665 * than the current time. 666 */ 667 snpac_age() 668 { 669 register struct snpa_cache *sc; 670 register int i; 671 672 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 673 674 sc = &iso_snpac[0]; 675 for (i=0; i<SNPAC_SIZE; i++, sc++) { 676 if (((sc->sc_flags & SNPA_PERM) == 0) && (sc->sc_flags & SNPA_VALID)) { 677 sc->sc_ht -= SNPAC_AGE; 678 if (sc->sc_ht > 0) 679 continue; 680 else 681 snpac_free(sc); 682 } 683 } 684 } 685 686 /* 687 * FUNCTION: snpac_ownmulti 688 * 689 * PURPOSE: Determine if the snpa address is a multicast address 690 * of the same type as the system. 691 * 692 * RETURNS: true or false 693 * 694 * SIDE EFFECTS: 695 * 696 * NOTES: Used by interface drivers when not in eavesdrop mode 697 * as interm kludge until 698 * real multicast addresses can be configured 699 */ 700 snpac_ownmulti(snpa, len) 701 char *snpa; 702 int len; 703 { 704 return (((iso_systype & SNPA_ES) && 705 (!bcmp((caddr_t)snpa, (caddr_t)all_es.sc_snpa, (unsigned)len))) || 706 ((iso_systype & SNPA_IS) && 707 (!bcmp((caddr_t)snpa, (caddr_t)all_is.sc_snpa, (unsigned)len)))); 708 } 709 710 /* 711 * FUNCTION: snpac_flushifp 712 * 713 * PURPOSE: Flush entries associated with specific ifp 714 * 715 * RETURNS: nothing 716 * 717 * SIDE EFFECTS: 718 * 719 * NOTES: 720 */ 721 snpac_flushifp(ifp) 722 struct ifnet *ifp; 723 { 724 register struct snpa_cache *sc; 725 register int i; 726 727 sc = &iso_snpac[0]; 728 for (i=0; i<SNPAC_SIZE; i++, sc++) { 729 if ((sc->sc_ifp == ifp) && (sc->sc_flags & SNPA_VALID)) { 730 snpac_free(sc); 731 } 732 } 733 } 734 735 /* 736 * FUNCTION: snpac_rtrequest 737 * 738 * PURPOSE: Make a routing request 739 * 740 * RETURNS: nothing 741 * 742 * SIDE EFFECTS: 743 * 744 * NOTES: In the future, this should make a request of a user 745 * level routing daemon. 746 */ 747 snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 748 int req; 749 struct iso_addr *host; 750 struct iso_addr *gateway; 751 struct iso_addr *netmask; 752 short flags; 753 struct rtentry **ret_nrt; 754 { 755 register struct iso_addr *r; 756 757 IFDEBUG(D_SNPA) 758 printf("snpac_rtrequest: "); 759 if (req == RTM_ADD) 760 printf("add"); 761 else if (req == RTM_DELETE) 762 printf("delete"); 763 else 764 printf("unknown command"); 765 printf(" dst: %s\n", clnp_iso_addrp(host)); 766 printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 767 ENDDEBUG 768 769 770 zap_isoaddr(dst, host); 771 zap_isoaddr(gte, gateway); 772 zap_isoaddr(msk, netmask); 773 774 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 775 flags, ret_nrt); 776 } 777 778 /* 779 * FUNCTION: snpac_addrt 780 * 781 * PURPOSE: Associate a routing entry with an snpac entry 782 * 783 * RETURNS: nothing 784 * 785 * SIDE EFFECTS: 786 * 787 * NOTES: If a cache entry exists for gateway, then 788 * make a routing entry (host, gateway) and associate 789 * with gateway. 790 * 791 * If a route already exists and is different, first delete 792 * it. 793 * 794 * This could be made more efficient by checking 795 * the existing route before adding a new one. 796 */ 797 snpac_addrt(host, gateway, source, netmask) 798 struct iso_addr *host, *gateway, *source, *netmask; 799 { 800 register struct snpa_cache *sc; 801 register struct iso_addr *r; 802 803 SNPAC_LOOK(sc, gateway); 804 if (sc != NULL) { 805 bcopy((caddr_t)host, (caddr_t)&sc->sc_da, sizeof(struct iso_addr)); 806 zap_isoaddr(dst, host); 807 zap_isoaddr(gte, gateway); 808 zap_isoaddr(src, source); 809 zap_isoaddr(msk, netmask); 810 if (netmask) { 811 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(src), &sc->sc_rt); 812 } else 813 rtredirect(S(dst), S(gte), (struct sockaddr *)0, 814 RTF_DONE | RTF_HOST, S(src), &sc->sc_rt); 815 } 816 } 817 #endif ISO 818