Annotation of XNU/bsd/netiso/iso_snpac.c, revision 1.1

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((&gte_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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.