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