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