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