Annotation of XNU/bsd/netiso/iso_snpac.c, revision 1.1.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.