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