1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)iso_snpac.c 8.1 (Berkeley) 06/10/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 void esis_config(); 68 extern int 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_delmulti(&ifr, (struct arpcom *)ifp) == ENETRESET) 227 doreset++; 228 } 229 if (doreset) { 230 if (ifp->if_reset) 231 (*ifp->if_reset)(ifp->if_unit); 232 else 233 printf("iso_setmcasts: %s%d needs reseting to receive iso mcasts\n", 234 ifp->if_name, ifp->if_unit); 235 } 236 } 237 /* 238 * FUNCTION: iso_snparesolve 239 * 240 * PURPOSE: Resolve an iso address into snpa address 241 * 242 * RETURNS: 0 if addr is resolved 243 * errno if addr is unknown 244 * 245 * SIDE EFFECTS: 246 * 247 * NOTES: Now that we have folded the snpa cache into the routing 248 * table, we know there is no snpa address known for this 249 * destination. If we know of a default IS, then the address 250 * of the IS is returned. If no IS is known, then return the 251 * multi-cast address for "all ES" for this interface. 252 * 253 * NB: the last case described above constitutes the 254 * query configuration function 9542, sec 6.5 255 * A mechanism is needed to prevent this function from 256 * being invoked if the system is an IS. 257 */ 258 iso_snparesolve(ifp, dest, snpa, snpa_len) 259 struct ifnet *ifp; /* outgoing interface */ 260 struct sockaddr_iso *dest; /* destination */ 261 caddr_t snpa; /* RESULT: snpa to be used */ 262 int *snpa_len; /* RESULT: length of snpa */ 263 { 264 struct llinfo_llc *sc; /* ptr to snpa table entry */ 265 caddr_t found_snpa; 266 int addrlen; 267 268 /* 269 * This hack allows us to send esis packets that have the destination snpa 270 * addresss embedded in the destination nsap address 271 */ 272 if (dest->siso_data[0] == AFI_SNA) { 273 /* 274 * This is a subnetwork address. Return it immediately 275 */ 276 IFDEBUG(D_SNPA) 277 printf("iso_snparesolve: return SN address\n"); 278 ENDDEBUG 279 addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 280 found_snpa = (caddr_t) dest->siso_data + 1; 281 /* 282 * If we are an IS, we can't do much with the packet; 283 * Check if we know about an IS. 284 */ 285 } else if (iso_systype != SNPA_IS && known_is != 0 && 286 (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 287 (sc->lc_flags & SNPA_VALID)) { 288 register struct sockaddr_dl *sdl = 289 (struct sockaddr_dl *)(known_is->rt_gateway); 290 found_snpa = LLADDR(sdl); 291 addrlen = sdl->sdl_alen; 292 } else if (ifp->if_flags & IFF_BROADCAST) { 293 /* 294 * no IS, no match. Return "all es" multicast address for this 295 * interface, as per Query Configuration Function (9542 sec 6.5) 296 * 297 * Note: there is a potential problem here. If the destination 298 * is on the subnet and it does not respond with a ESH, but 299 * does send back a TP CC, a connection could be established 300 * where we always transmit the CLNP packet to "all es" 301 */ 302 addrlen = ifp->if_addrlen; 303 found_snpa = (caddr_t)all_es_snpa; 304 } else 305 return (ENETUNREACH); 306 bcopy(found_snpa, snpa, *snpa_len = addrlen); 307 return (0); 308 } 309 310 311 /* 312 * FUNCTION: snpac_free 313 * 314 * PURPOSE: free an entry in the iso address map table 315 * 316 * RETURNS: nothing 317 * 318 * SIDE EFFECTS: 319 * 320 * NOTES: If there is a route entry associated with cache 321 * entry, then delete that as well 322 */ 323 snpac_free(lc) 324 register struct llinfo_llc *lc; /* entry to free */ 325 { 326 register struct rtentry *rt = lc->lc_rt; 327 register struct iso_addr *r; 328 329 if (known_is == rt) 330 known_is = 0; 331 if (rt && (rt->rt_flags & RTF_UP) && 332 (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 333 RTFREE(rt); 334 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 335 rt->rt_flags, (struct rtentry **)0); 336 RTFREE(rt); 337 } 338 } 339 340 /* 341 * FUNCTION: snpac_add 342 * 343 * PURPOSE: Add an entry to the snpa cache 344 * 345 * RETURNS: 346 * 347 * SIDE EFFECTS: 348 * 349 * NOTES: If entry already exists, then update holding time. 350 */ 351 snpac_add(ifp, nsap, snpa, type, ht, nsellength) 352 struct ifnet *ifp; /* interface info is related to */ 353 struct iso_addr *nsap; /* nsap to add */ 354 caddr_t snpa; /* translation */ 355 char type; /* SNPA_IS or SNPA_ES */ 356 u_short ht; /* holding time (in seconds) */ 357 int nsellength; /* nsaps may differ only in trailing bytes */ 358 { 359 register struct llinfo_llc *lc; 360 register struct rtentry *rt; 361 struct rtentry *mrt = 0; 362 register struct iso_addr *r; /* for zap_isoaddr macro */ 363 int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 364 int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type; 365 366 IFDEBUG(D_SNPA) 367 printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 368 ifp, nsap, snpa, type, ht, nsellength); 369 ENDDEBUG 370 zap_isoaddr(dst, nsap); 371 rt = rtalloc1(S(dst), 0); 372 IFDEBUG(D_SNPA) 373 printf("snpac_add: rtalloc1 returns %x\n", rt); 374 ENDDEBUG 375 if (rt == 0) { 376 struct sockaddr *netmask; 377 int flags; 378 add: 379 if (nsellength) { 380 netmask = S(msk); flags = RTF_UP; 381 snpac_fixdstandmask(nsellength); 382 } else { 383 netmask = 0; flags = RTF_UP | RTF_HOST; 384 } 385 new_entry = 1; 386 zap_linkaddr((>e_dl), snpa, snpalen, index); 387 gte_dl.sdl_type = iftype; 388 if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 389 mrt == 0) 390 return (0); 391 rt = mrt; 392 rt->rt_refcnt--; 393 } else { 394 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 395 rt->rt_refcnt--; 396 if ((rt->rt_flags & RTF_LLINFO) == 0) 397 goto add; 398 if (nsellength && (rt->rt_flags & RTF_HOST)) { 399 if (rt->rt_refcnt == 0) { 400 rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 401 (struct sockaddr *)0, 0, (struct rtentry *)0); 402 rt = 0; 403 goto add; 404 } else { 405 static struct iso_addr nsap2; register char *cp; 406 nsap2 = *nsap; 407 cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 408 while (cp < (char *)(1 + &nsap2)) 409 *cp++ = 0; 410 (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 411 } 412 } 413 if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 414 int old_sdl_len = sdl->sdl_len; 415 if (old_sdl_len < sizeof(*sdl)) { 416 log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 417 return (0); 418 } 419 zap_linkaddr(sdl, snpa, snpalen, index); 420 sdl->sdl_len = old_sdl_len; 421 sdl->sdl_type = iftype; 422 new_entry = 1; 423 } 424 } 425 if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 426 panic("snpac_rtrequest"); 427 rt->rt_rmx.rmx_expire = ht + time.tv_sec; 428 lc->lc_flags = SNPA_VALID | type; 429 if ((type & SNPA_IS) && !(iso_systype & SNPA_IS)) 430 snpac_logdefis(rt); 431 return (new_entry); 432 } 433 434 static void 435 snpac_fixdstandmask(nsellength) 436 { 437 register char *cp = msk.siso_data, *cplim; 438 439 cplim = cp + (dst.siso_nlen -= nsellength); 440 msk.siso_len = cplim - (char *)&msk; 441 msk.siso_nlen = 0; 442 while (cp < cplim) 443 *cp++ = -1; 444 while (cp < (char *)msk.siso_pad) 445 *cp++ = 0; 446 for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 447 *cp++ = 0; 448 } 449 450 /* 451 * FUNCTION: snpac_ioctl 452 * 453 * PURPOSE: Set/Get the system type and esis parameters 454 * 455 * RETURNS: 0 on success, or unix error code 456 * 457 * SIDE EFFECTS: 458 * 459 * NOTES: 460 */ 461 snpac_ioctl (so, cmd, data) 462 struct socket *so; 463 int cmd; /* ioctl to process */ 464 caddr_t data; /* data for the cmd */ 465 { 466 register struct systype_req *rq = (struct systype_req *)data; 467 468 IFDEBUG(D_IOCTL) 469 if (cmd == SIOCSSTYPE) 470 printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 471 rq->sr_type, rq->sr_holdt, rq->sr_configt); 472 else 473 printf("snpac_ioctl: cmd get\n"); 474 ENDDEBUG 475 476 if (cmd == SIOCSSTYPE) { 477 if ((so->so_state & SS_PRIV) == 0) 478 return (EPERM); 479 if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 480 return(EINVAL); 481 if (rq->sr_type & SNPA_ES) { 482 iso_systype = SNPA_ES; 483 } else if (rq->sr_type & SNPA_IS) { 484 iso_systype = SNPA_IS; 485 } else { 486 return(EINVAL); 487 } 488 esis_holding_time = rq->sr_holdt; 489 esis_config_time = rq->sr_configt; 490 if (esis_esconfig_time != rq->sr_esconfigt) { 491 untimeout(esis_config, (caddr_t)0); 492 esis_esconfig_time = rq->sr_esconfigt; 493 esis_config(); 494 } 495 } else if (cmd == SIOCGSTYPE) { 496 rq->sr_type = iso_systype; 497 rq->sr_holdt = esis_holding_time; 498 rq->sr_configt = esis_config_time; 499 rq->sr_esconfigt = esis_esconfig_time; 500 } else { 501 return (EINVAL); 502 } 503 return (0); 504 } 505 506 /* 507 * FUNCTION: snpac_logdefis 508 * 509 * PURPOSE: Mark the IS passed as the default IS 510 * 511 * RETURNS: nothing 512 * 513 * SIDE EFFECTS: 514 * 515 * NOTES: 516 */ 517 snpac_logdefis(sc) 518 register struct rtentry *sc; 519 { 520 register struct iso_addr *r; 521 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 522 register struct rtentry *rt; 523 524 if (known_is == sc || !(sc->rt_flags & RTF_HOST)) 525 return; 526 if (known_is) { 527 RTFREE(known_is); 528 } 529 known_is = sc; 530 sc->rt_refcnt++; 531 rt = rtalloc1((struct sockaddr *)&zsi, 0); 532 if (rt == 0) 533 rtrequest(RTM_ADD, S(zsi), rt_key(sc), S(zmk), 534 RTF_DYNAMIC|RTF_GATEWAY, 0); 535 else { 536 if ((rt->rt_flags & RTF_DYNAMIC) && 537 (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0) 538 rt_setgate(rt, rt_key(rt), rt_key(sc)); 539 } 540 } 541 542 /* 543 * FUNCTION: snpac_age 544 * 545 * PURPOSE: Time out snpac entries 546 * 547 * RETURNS: 548 * 549 * SIDE EFFECTS: 550 * 551 * NOTES: When encountering an entry for the first time, snpac_age 552 * may delete up to SNPAC_AGE too many seconds. Ie. 553 * if the entry is added a moment before snpac_age is 554 * called, the entry will immediately have SNPAC_AGE 555 * seconds taken off the holding time, even though 556 * it has only been held a brief moment. 557 * 558 * The proper way to do this is set an expiry timeval 559 * equal to current time + holding time. Then snpac_age 560 * would time out entries where expiry date is older 561 * than the current time. 562 */ 563 void 564 snpac_age() 565 { 566 register struct llinfo_llc *lc, *nlc; 567 register struct rtentry *rt; 568 569 timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 570 571 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) { 572 nlc = lc->lc_next; 573 if (lc->lc_flags & SNPA_VALID) { 574 rt = lc->lc_rt; 575 if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec) 576 snpac_free(lc); 577 } 578 } 579 } 580 581 /* 582 * FUNCTION: snpac_ownmulti 583 * 584 * PURPOSE: Determine if the snpa address is a multicast address 585 * of the same type as the system. 586 * 587 * RETURNS: true or false 588 * 589 * SIDE EFFECTS: 590 * 591 * NOTES: Used by interface drivers when not in eavesdrop mode 592 * as interm kludge until 593 * real multicast addresses can be configured 594 */ 595 snpac_ownmulti(snpa, len) 596 caddr_t snpa; 597 u_int len; 598 { 599 return (((iso_systype & SNPA_ES) && 600 (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 601 ((iso_systype & SNPA_IS) && 602 (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 603 } 604 605 /* 606 * FUNCTION: snpac_flushifp 607 * 608 * PURPOSE: Flush entries associated with specific ifp 609 * 610 * RETURNS: nothing 611 * 612 * SIDE EFFECTS: 613 * 614 * NOTES: 615 */ 616 snpac_flushifp(ifp) 617 struct ifnet *ifp; 618 { 619 register struct llinfo_llc *lc; 620 621 for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 622 if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 623 snpac_free(lc); 624 } 625 } 626 627 /* 628 * FUNCTION: snpac_rtrequest 629 * 630 * PURPOSE: Make a routing request 631 * 632 * RETURNS: nothing 633 * 634 * SIDE EFFECTS: 635 * 636 * NOTES: In the future, this should make a request of a user 637 * level routing daemon. 638 */ 639 snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 640 int req; 641 struct iso_addr *host; 642 struct iso_addr *gateway; 643 struct iso_addr *netmask; 644 short flags; 645 struct rtentry **ret_nrt; 646 { 647 register struct iso_addr *r; 648 649 IFDEBUG(D_SNPA) 650 printf("snpac_rtrequest: "); 651 if (req == RTM_ADD) 652 printf("add"); 653 else if (req == RTM_DELETE) 654 printf("delete"); 655 else 656 printf("unknown command"); 657 printf(" dst: %s\n", clnp_iso_addrp(host)); 658 printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 659 ENDDEBUG 660 661 662 zap_isoaddr(dst, host); 663 zap_isoaddr(gte, gateway); 664 if (netmask) { 665 zap_isoaddr(msk, netmask); 666 msk.siso_nlen = 0; 667 msk.siso_len = msk.siso_pad - (u_char *)&msk; 668 } 669 670 rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 671 flags, ret_nrt); 672 } 673 674 /* 675 * FUNCTION: snpac_addrt 676 * 677 * PURPOSE: Associate a routing entry with an snpac entry 678 * 679 * RETURNS: nothing 680 * 681 * SIDE EFFECTS: 682 * 683 * NOTES: If a cache entry exists for gateway, then 684 * make a routing entry (host, gateway) and associate 685 * with gateway. 686 * 687 * If a route already exists and is different, first delete 688 * it. 689 * 690 * This could be made more efficient by checking 691 * the existing route before adding a new one. 692 */ 693 snpac_addrt(ifp, host, gateway, netmask) 694 struct ifnet *ifp; 695 struct iso_addr *host, *gateway, *netmask; 696 { 697 register struct iso_addr *r; 698 699 zap_isoaddr(dst, host); 700 zap_isoaddr(gte, gateway); 701 if (netmask) { 702 zap_isoaddr(msk, netmask); 703 msk.siso_nlen = 0; 704 msk.siso_len = msk.siso_pad - (u_char *)&msk; 705 rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 706 } else 707 rtredirect(S(dst), S(gte), (struct sockaddr *)0, 708 RTF_DONE | RTF_HOST, S(gte), 0); 709 } 710 #endif /* ISO */ 711