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