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