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