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