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