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.12 (Berkeley) 04/26/91 */ 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 "systm.h" 40 #include "user.h" 41 #include "mbuf.h" 42 #include "domain.h" 43 #include "protosw.h" 44 #include "socket.h" 45 #include "socketvar.h" 46 #include "errno.h" 47 #include "ioctl.h" 48 #include "kernel.h" 49 #include "syslog.h" 50 51 #include "../net/if.h" 52 #include "../net/if_dl.h" 53 #include "../net/route.h" 54 55 #include "iso.h" 56 #include "iso_var.h" 57 #include "iso_snpac.h" 58 #include "clnp.h" 59 #include "clnp_stat.h" 60 #include "esis.h" 61 #include "argo_debug.h" 62 63 int iso_systype = SNPA_ES; /* default to be an ES */ 64 extern short esis_holding_time, esis_config_time, esis_esconfig_time; 65 extern int esis_config(); 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 static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 82 static struct sockaddr_dl gte_dl; 83 #define zap_linkaddr(a, b, c, i) \ 84 (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 85 86 /* 87 * We only keep track of a single IS at a time. 88 */ 89 struct rtentry *known_is; 90 91 /* 92 * Addresses taken from NBS agreements, December 1987. 93 * 94 * These addresses assume on-the-wire transmission of least significant 95 * bit first. This is the method used by 802.3. When these 96 * addresses are passed to the token ring driver, (802.5), they 97 * must be bit-swaped because 802.5 transmission order is MSb first. 98 * 99 * Furthermore, according to IBM Austin, these addresses are not 100 * true token ring multicast addresses. More work is necessary 101 * to get multicast to work right on token ring. 102 * 103 * Currently, the token ring driver does not handle multicast, so 104 * these addresses are converted into the broadcast address in 105 * lan_output() That means that if these multicast addresses change 106 * the token ring driver must be altered. 107 */ 108 char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; 109 char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; 110 char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14}; 111 char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15}; 112 113 union sockunion { 114 struct sockaddr_iso siso; 115 struct sockaddr_dl sdl; 116 struct sockaddr sa; 117 }; 118 119 /* 120 * FUNCTION: llc_rtrequest 121 * 122 * PURPOSE: Manage routing table entries specific to LLC for ISO. 123 * 124 * NOTES: This does a lot of obscure magic; 125 */ 126 llc_rtrequest(req, rt, sa) 127 int req; 128 register struct rtentry *rt; 129 struct sockaddr *sa; 130 { 131 register union sockunion *gate = (union sockunion *)rt->rt_gateway; 132 register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 133 struct rtentry *rt2; 134 struct ifnet *ifp = rt->rt_ifp; 135 int addrlen = ifp->if_addrlen; 136 static struct rtentry *recursing = 0; 137 #define LLC_SIZE 3 /* XXXXXX do this right later */ 138 139 IFDEBUG (D_SNPA) 140 printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 141 ENDDEBUG 142 if (rt->rt_flags & RTF_GATEWAY) { 143 if (recursing) { 144 log(LOG_DEBUG, "llc_rtrequest: gateway route points to same type %x %x\n", 145 recursing, rt); 146 } else switch (req) { 147 case RTM_RESOLVE: 148 case RTM_ADD: 149 recursing = rt; 150 rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 151 recursing = 0; 152 if (rt->rt_rmx.rmx_mtu == 0) { 153 rt->rt_rmx.rmx_mtu = 154 ((rt2 = (struct rtentry *)rt->rt_llinfo) && 155 (rt2->rt_rmx.rmx_mtu)) ? 156 rt2->rt_rmx.rmx_mtu : 157 rt->rt_ifp->if_mtu - LLC_SIZE; 158 } 159 return; 160 161 case RTM_DELETE: 162 if (lc) 163 RTFREE((struct rtentry *)lc); 164 rt->rt_llinfo = 0; 165 } 166 } else switch (req) { 167 case RTM_ADD: 168 /* 169 * Case 1: This route may come from a route to iface with mask 170 * or from a default route. 171 */ 172 if (rt->rt_flags & RTF_CLONING) { 173 register struct ifaddr *ifa; 174 register struct sockaddr *sa; 175 for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 176 if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 177 if (sa->sa_len > gate->sa.sa_len) 178 log(LOG_DEBUG, "llc_rtrequest: cloning address too small\n"); 179 else { 180 Bcopy(sa, gate, gate->sa.sa_len); 181 gate->sdl.sdl_alen = 0; 182 } 183 break; 184 } 185 if (ifa == 0) 186 log(LOG_DEBUG, "llc_rtrequest: can't find LL ifaddr for iface\n"); 187 break; 188 } 189 /* FALLTHROUGH */ 190 case RTM_RESOLVE: 191 /* 192 * Case 2: This route may come from cloning, or a manual route 193 * add with a LL address. 194 */ 195 if (gate->sdl.sdl_family != AF_LINK) { 196 log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n"); 197 break; 198 } 199 if (lc != 0) 200 log(LOG_DEBUG, "llc_rtrequest: losing old rt_llinfo\n"); 201 R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 202 rt->rt_llinfo = (caddr_t)lc; 203 if (lc == 0) { 204 log(LOG_DEBUG, "llc_rtrequest: malloc failed\n"); 205 break; 206 } 207 Bzero(lc, sizeof(*lc)); 208 lc->lc_rt = rt; 209 rt->rt_flags |= RTF_LLINFO; 210 insque(lc, &llinfo_llc); 211 if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 212 gate->sdl.sdl_alen -= sizeof(struct esis_req); 213 bcopy(addrlen + LLADDR(&gate->sdl), 214 (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 215 } else if (gate->sdl.sdl_alen == addrlen) 216 lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 217 break; 218 case RTM_DELETE: 219 if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 220 return; 221 remque(lc); 222 Free(lc); 223 rt->rt_llinfo = 0; 224 rt->rt_flags &= ~RTF_LLINFO; 225 break; 226 } 227 if (rt->rt_rmx.rmx_mtu == 0) { 228 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE; 229 } 230 } 231 /* 232 * FUNCTION: iso_snparesolve 233 * 234 * PURPOSE: Resolve an iso address into snpa address 235 * 236 * RETURNS: 0 if addr is resolved 237 * errno if addr is unknown 238 * 239 * SIDE EFFECTS: 240 * 241 * NOTES: Now that we have folded the snpa cache into the routing 242 * table, we know there is no snpa address known for this 243 * destination. If we know of a default IS, then the address 244 * of the IS is returned. If no IS is known, then return the 245 * multi-cast address for "all ES" for this interface. 246 * 247 * NB: the last case described above constitutes the 248 * query configuration function 9542, sec 6.5 249 * A mechanism is needed to prevent this function from 250 * being invoked if the system is an IS. 251 */ 252 iso_snparesolve(ifp, dest, snpa, snpa_len) 253 struct ifnet *ifp; /* outgoing interface */ 254 struct sockaddr_iso *dest; /* destination */ 255 caddr_t snpa; /* RESULT: snpa to be used */ 256 int *snpa_len; /* RESULT: length of snpa */ 257 { 258 struct llinfo_llc *sc; /* ptr to snpa table entry */ 259 caddr_t found_snpa; 260 int addrlen; 261 262 /* 263 * This hack allows us to send esis packets that have the destination snpa 264 * addresss embedded in the destination nsap address 265 */ 266 if (dest->siso_data[0] == AFI_SNA) { 267 /* 268 * This is a subnetwork address. Return it immediately 269 */ 270 IFDEBUG(D_SNPA) 271 printf("iso_snparesolve: return SN address\n"); 272 ENDDEBUG 273 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 274 found_snpa = (caddr_t) dest->siso_data + 1; 275 /* 276 * If we are an IS, we can't do much with the packet; 277 * Check if we know about an IS. 278 */ 279 } else if (iso_systype != SNPA_IS && known_is != 0 && 280 (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 281 (sc->lc_flags & SNPA_VALID)) { 282 register struct sockaddr_dl *sdl = 283 (struct sockaddr_dl *)(known_is->rt_gateway); 284 found_snpa = LLADDR(sdl); 285 addrlen = sdl->sdl_alen; 286 } else if (ifp->if_flags & IFF_BROADCAST) { 287 /* 288 * no IS, no match. Return "all es" multicast address for this 289 * interface, as per Query Configuration Function (9542 sec 6.5) 290 * 291 * Note: there is a potential problem here. If the destination 292 * is on the subnet and it does not respond with a ESH, but 293 * does send back a TP CC, a connection could be established 294 * where we always transmit the CLNP packet to "all es" 295 */ 296 addrlen = ifp->if_addrlen; 297 found_snpa = (caddr_t)all_es_snpa; 298 } else 299 return (ENETUNREACH); 300 bcopy(found_snpa, snpa, *snpa_len = addrlen); 301 return (0); 302 } 303 304 305 /* 306 * FUNCTION: snpac_free 307 * 308 * PURPOSE: free an entry in the iso address map table 309 * 310 * RETURNS: nothing 311 * 312 * SIDE EFFECTS: 313 * 314 * NOTES: If there is a route entry associated with cache 315 * entry, then delete that as well 316 */ 317 snpac_free(lc) 318 register struct llinfo_llc *lc; /* entry to free */ 319 { 320 register struct rtentry *rt = lc->lc_rt; 321 register struct iso_addr *r; 322 323 if (known_is == rt) 324 known_is = 0; 325 if (rt && (rt->rt_flags & RTF_UP) && 326 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 327 RTFREE(rt); 328 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 329 rt->rt_flags, (struct rtentry **)0); 330 RTFREE(rt); 331 } 332 } 333 334 /* 335 * FUNCTION: snpac_add 336 * 337 * PURPOSE: Add an entry to the snpa cache 338 * 339 * RETURNS: 340 * 341 * SIDE EFFECTS: 342 * 343 * NOTES: If entry already exists, then update holding time. 344 */ 345 snpac_add(ifp, nsap, snpa, type, ht, nsellength) 346 struct ifnet *ifp; /* interface info is related to */ 347 struct iso_addr *nsap; /* nsap to add */ 348 caddr_t snpa; /* translation */ 349 char type; /* SNPA_IS or SNPA_ES */ 350 u_short ht; /* holding time (in seconds) */ 351 int nsellength; /* nsaps may differ only in trailing bytes */ 352 { 353 register struct llinfo_llc *lc; 354 register struct rtentry *rt; 355 struct rtentry *mrt = 0; 356 register struct iso_addr *r; /* for zap_isoaddr macro */ 357 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 358 int new_entry = 0, index = ifp->if_index; 359 360 IFDEBUG(D_SNPA) 361 printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 362 ifp, nsap, snpa, type, ht, nsellength); 363 ENDDEBUG 364 zap_isoaddr(dst, nsap); 365 rt = rtalloc1(S(dst), 0); 366 IFDEBUG(D_SNPA) 367 printf("snpac_add: rtalloc1 returns %x\n", rt); 368 ENDDEBUG 369 if (rt == 0) { 370 struct sockaddr *netmask; 371 int flags; 372 add: 373 if (nsellength) { 374 netmask = S(msk); flags = RTF_UP; 375 snpac_fixdstandmask(nsellength); 376 } else { 377 netmask = 0; flags = RTF_UP | RTF_HOST; 378 } 379 new_entry = 1; 380 zap_linkaddr((>e_dl), snpa, snpalen, index); 381 if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 382 mrt == 0) 383 return (0); 384 rt = mrt; 385 rt->rt_refcnt--; 386 } else { 387 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 388 rt->rt_refcnt--; 389 if ((rt->rt_flags & RTF_LLINFO) == 0) 390 goto add; 391 if (nsellength && (rt->rt_flags & RTF_HOST)) { 392 if (rt->rt_refcnt == 0) { 393 rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 394 (struct sockaddr *)0, 0, (struct rtentry *)0); 395 rt = 0; 396 goto add; 397 } else { 398 static struct iso_addr nsap2; register char *cp; 399 nsap2 = *nsap; 400 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 401 while (cp < (char *)(1 + &nsap2)) 402 *cp++ = 0; 403 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 404 } 405 } 406 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 407 int old_sdl_len = sdl->sdl_len; 408 if (old_sdl_len < sizeof(*sdl)) { 409 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 410 return (0); 411 } 412 zap_linkaddr(sdl, snpa, snpalen, index); 413 sdl->sdl_len = old_sdl_len; 414 new_entry = 1; 415 } 416 } 417 if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 418 panic("snpac_rtrequest"); 419 rt->rt_idle = ht; 420 lc->lc_flags = SNPA_VALID | type; 421 if (type & SNPA_IS) 422 snpac_logdefis(rt); 423 return (new_entry); 424 } 425 426 static snpac_fixdstandmask(nsellength) 427 { 428 register char *cp = msk.siso_data, *cplim; 429 430 cplim = cp + (dst.siso_nlen -= nsellength); 431 msk.siso_len = cplim - (char *)&msk; 432 msk.siso_nlen = 0; 433 while (cp < cplim) 434 *cp++ = -1; 435 while (cp < (char *)msk.siso_pad) 436 *cp++ = 0; 437 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 438 *cp++ = 0; 439 } 440 441 /* 442 * FUNCTION: snpac_ioctl 443 * 444 * PURPOSE: Set/Get the system type and esis parameters 445 * 446 * RETURNS: 0 on success, or unix error code 447 * 448 * SIDE EFFECTS: 449 * 450 * NOTES: 451 */ 452 snpac_ioctl (cmd, data) 453 int cmd; /* ioctl to process */ 454 caddr_t data; /* data for the cmd */ 455 { 456 register struct systype_req *rq = (struct systype_req *)data; 457 458 IFDEBUG(D_IOCTL) 459 if (cmd == SIOCSSTYPE) 460 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 461 rq->sr_type, rq->sr_holdt, rq->sr_configt); 462 else 463 printf("snpac_ioctl: cmd get\n"); 464 ENDDEBUG 465 466 if (cmd == SIOCSSTYPE) { 467 if (suser(u.u_cred, &u.u_acflag)) 468 return(EACCES); 469 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 470 return(EINVAL); 471 if (rq->sr_type & SNPA_ES) { 472 iso_systype = SNPA_ES; 473 } else if (rq->sr_type & SNPA_IS) { 474 iso_systype = SNPA_IS; 475 } else { 476 return(EINVAL); 477 } 478 esis_holding_time = rq->sr_holdt; 479 esis_config_time = rq->sr_configt; 480 if (esis_esconfig_time != rq->sr_esconfigt) { 481 untimeout(esis_config, (caddr_t)0); 482 esis_esconfig_time = rq->sr_esconfigt; 483 esis_config(); 484 } 485 } else if (cmd == SIOCGSTYPE) { 486 rq->sr_type = iso_systype; 487 rq->sr_holdt = esis_holding_time; 488 rq->sr_configt = esis_config_time; 489 rq->sr_esconfigt = esis_esconfig_time; 490 } else { 491 return (EINVAL); 492 } 493 return (0); 494 } 495 496 /* 497 * FUNCTION: snpac_logdefis 498 * 499 * PURPOSE: Mark the IS passed as the default IS 500 * 501 * RETURNS: nothing 502 * 503 * SIDE EFFECTS: 504 * 505 * NOTES: 506 */ 507 snpac_logdefis(sc) 508 register struct rtentry *sc; 509 { 510 register struct iso_addr *r; 511 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 512 register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 513 514 zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 515 if (known_is == 0) 516 known_is = sc; 517 if (known_is != sc) { 518 rtfree(known_is); 519 known_is = sc; 520 } 521 if (rt == 0) { 522 rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 523 RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 524 return; 525 } 526 rt->rt_refcnt--; 527 if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 528 *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 529 } 530 } 531 532 /* 533 * FUNCTION: snpac_age 534 * 535 * PURPOSE: Time out snpac entries 536 * 537 * RETURNS: 538 * 539 * SIDE EFFECTS: 540 * 541 * NOTES: When encountering an entry for the first time, snpac_age 542 * may delete up to SNPAC_AGE too many seconds. Ie. 543 * if the entry is added a moment before snpac_age is 544 * called, the entry will immediately have SNPAC_AGE 545 * seconds taken off the holding time, even though 546 * it has only been held a brief moment. 547 * 548 * The proper way to do this is set an expiry timeval 549 * equal to current time + holding time. Then snpac_age 550 * would time out entries where expiry date is older 551 * than the current time. 552 */ 553 snpac_age() 554 { 555 register struct llinfo_llc *lc; 556 557 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 558 559 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 560 if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 561 lc->lc_rt->rt_idle -= SNPAC_AGE; 562 if (lc->lc_rt->rt_idle > 0) 563 continue; 564 else 565 snpac_free(lc); 566 } 567 } 568 } 569 570 /* 571 * FUNCTION: snpac_ownmulti 572 * 573 * PURPOSE: Determine if the snpa address is a multicast address 574 * of the same type as the system. 575 * 576 * RETURNS: true or false 577 * 578 * SIDE EFFECTS: 579 * 580 * NOTES: Used by interface drivers when not in eavesdrop mode 581 * as interm kludge until 582 * real multicast addresses can be configured 583 */ 584 snpac_ownmulti(snpa, len) 585 caddr_t snpa; 586 u_int len; 587 { 588 return (((iso_systype & SNPA_ES) && 589 (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 590 ((iso_systype & SNPA_IS) && 591 (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 592 } 593 594 /* 595 * FUNCTION: snpac_flushifp 596 * 597 * PURPOSE: Flush entries associated with specific ifp 598 * 599 * RETURNS: nothing 600 * 601 * SIDE EFFECTS: 602 * 603 * NOTES: 604 */ 605 snpac_flushifp(ifp) 606 struct ifnet *ifp; 607 { 608 register struct llinfo_llc *lc; 609 610 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 611 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 612 snpac_free(lc); 613 } 614 } 615 616 /* 617 * FUNCTION: snpac_rtrequest 618 * 619 * PURPOSE: Make a routing request 620 * 621 * RETURNS: nothing 622 * 623 * SIDE EFFECTS: 624 * 625 * NOTES: In the future, this should make a request of a user 626 * level routing daemon. 627 */ 628 snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 629 int req; 630 struct iso_addr *host; 631 struct iso_addr *gateway; 632 struct iso_addr *netmask; 633 short flags; 634 struct rtentry **ret_nrt; 635 { 636 register struct iso_addr *r; 637 638 IFDEBUG(D_SNPA) 639 printf("snpac_rtrequest: "); 640 if (req == RTM_ADD) 641 printf("add"); 642 else if (req == RTM_DELETE) 643 printf("delete"); 644 else 645 printf("unknown command"); 646 printf(" dst: %s\n", clnp_iso_addrp(host)); 647 printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 648 ENDDEBUG 649 650 651 zap_isoaddr(dst, host); 652 zap_isoaddr(gte, gateway); 653 if (netmask) { 654 zap_isoaddr(msk, netmask); 655 msk.siso_nlen = 0; 656 msk.siso_len = msk.siso_pad - (u_char *)&msk; 657 } 658 659 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 660 flags, ret_nrt); 661 } 662 663 /* 664 * FUNCTION: snpac_addrt 665 * 666 * PURPOSE: Associate a routing entry with an snpac entry 667 * 668 * RETURNS: nothing 669 * 670 * SIDE EFFECTS: 671 * 672 * NOTES: If a cache entry exists for gateway, then 673 * make a routing entry (host, gateway) and associate 674 * with gateway. 675 * 676 * If a route already exists and is different, first delete 677 * it. 678 * 679 * This could be made more efficient by checking 680 * the existing route before adding a new one. 681 */ 682 snpac_addrt(ifp, host, gateway, netmask) 683 struct ifnet *ifp; 684 struct iso_addr *host, *gateway, *netmask; 685 { 686 register struct iso_addr *r; 687 688 zap_isoaddr(dst, host); 689 zap_isoaddr(gte, gateway); 690 if (netmask) { 691 zap_isoaddr(msk, netmask); 692 msk.siso_nlen = 0; 693 msk.siso_len = msk.siso_pad - (u_char *)&msk; 694 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 695 } else 696 rtredirect(S(dst), S(gte), (struct sockaddr *)0, 697 RTF_DONE | RTF_HOST, S(gte), 0); 698 } 699 #endif ISO 700