Annotation of kernel/bsd/netiso/esis.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*-
        !            26:  * Copyright (c) 1991, 1993
        !            27:  *     The Regents of the University of California.  All rights reserved.
        !            28:  *
        !            29:  * Redistribution and use in source and binary forms, with or without
        !            30:  * modification, are permitted provided that the following conditions
        !            31:  * are met:
        !            32:  * 1. Redistributions of source code must retain the above copyright
        !            33:  *    notice, this list of conditions and the following disclaimer.
        !            34:  * 2. Redistributions in binary form must reproduce the above copyright
        !            35:  *    notice, this list of conditions and the following disclaimer in the
        !            36:  *    documentation and/or other materials provided with the distribution.
        !            37:  * 3. All advertising materials mentioning features or use of this software
        !            38:  *    must display the following acknowledgement:
        !            39:  *     This product includes software developed by the University of
        !            40:  *     California, Berkeley and its contributors.
        !            41:  * 4. Neither the name of the University nor the names of its contributors
        !            42:  *    may be used to endorse or promote products derived from this software
        !            43:  *    without specific prior written permission.
        !            44:  *
        !            45:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            46:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            47:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            48:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            49:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            50:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            51:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            52:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            53:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            54:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            55:  * SUCH DAMAGE.
        !            56:  *
        !            57:  *     @(#)esis.c      8.1 (Berkeley) 6/10/93
        !            58:  */
        !            59: 
        !            60: /***********************************************************
        !            61:                Copyright IBM Corporation 1987
        !            62: 
        !            63:                       All Rights Reserved
        !            64: 
        !            65: Permission to use, copy, modify, and distribute this software and its 
        !            66: documentation for any purpose and without fee is hereby granted, 
        !            67: provided that the above copyright notice appear in all copies and that
        !            68: both that copyright notice and this permission notice appear in 
        !            69: supporting documentation, and that the name of IBM not be
        !            70: used in advertising or publicity pertaining to distribution of the
        !            71: software without specific, written prior permission.  
        !            72: 
        !            73: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            74: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            75: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            76: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            77: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            78: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            79: SOFTWARE.
        !            80: 
        !            81: ******************************************************************/
        !            82: 
        !            83: /*
        !            84:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
        !            85:  */
        !            86: 
        !            87: #if ISO
        !            88: 
        !            89: #include <sys/param.h>
        !            90: #include <sys/systm.h>
        !            91: #include <sys/mbuf.h>
        !            92: #include <sys/domain.h>
        !            93: #include <sys/protosw.h>
        !            94: #include <sys/socket.h>
        !            95: #include <sys/socketvar.h>
        !            96: #include <sys/errno.h>
        !            97: #include <sys/kernel.h>
        !            98: 
        !            99: #include <net/if.h>
        !           100: #include <net/if_dl.h>
        !           101: #include <net/route.h>
        !           102: #include <net/raw_cb.h>
        !           103: 
        !           104: #include <netiso/iso.h>
        !           105: #include <netiso/iso_pcb.h>
        !           106: #include <netiso/iso_var.h>
        !           107: #include <netiso/iso_snpac.h>
        !           108: #include <netiso/clnl.h>
        !           109: #include <netiso/clnp.h>
        !           110: #include <netiso/clnp_stat.h>
        !           111: #include <netiso/esis.h>
        !           112: #include <netiso/argo_debug.h>
        !           113: 
        !           114: /*
        !           115:  *     Global variables to esis implementation
        !           116:  *
        !           117:  *     esis_holding_time - the holding time (sec) parameter for outgoing pdus
        !           118:  *     esis_config_time  - the frequency (sec) that hellos are generated
        !           119:  *     esis_esconfig_time - suggested es configuration time placed in the
        !           120:  *                                             ish.
        !           121:  *
        !           122:  */
        !           123: struct rawcb   esis_pcb;
        !           124: void                           esis_config(), snpac_age();
        !           125: int                            esis_sendspace = 2048;
        !           126: int                            esis_recvspace = 2048;
        !           127: short                  esis_holding_time = ESIS_HT;
        !           128: short                  esis_config_time = ESIS_CONFIG;
        !           129: short                  esis_esconfig_time = ESIS_CONFIG;
        !           130: extern int             iso_systype;
        !           131: struct sockaddr_dl     esis_dl = { sizeof(esis_dl), AF_LINK };
        !           132: extern char            all_es_snpa[], all_is_snpa[];
        !           133: 
        !           134: #define EXTEND_PACKET(m, mhdr, cp)\
        !           135:        if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\
        !           136:                esis_stat.es_nomem++;\
        !           137:                m_freem(mhdr);\
        !           138:                return;\
        !           139:        } else {\
        !           140:                (m) = (m)->m_next;\
        !           141:                (cp) = mtod((m), caddr_t);\
        !           142:        }
        !           143: /*
        !           144:  * FUNCTION:           esis_init
        !           145:  *
        !           146:  * PURPOSE:                    Initialize the kernel portion of esis protocol
        !           147:  *
        !           148:  * RETURNS:                    nothing
        !           149:  *
        !           150:  * SIDE EFFECTS:       
        !           151:  *
        !           152:  * NOTES:                      
        !           153:  */
        !           154: esis_init()
        !           155: {
        !           156:        extern struct clnl_protosw clnl_protox[256];
        !           157:        int     esis_input(), isis_input();
        !           158: #ifdef ISO_X25ESIS
        !           159:        int     x25esis_input();
        !           160: #endif /* ISO_X25ESIS */
        !           161: 
        !           162:        esis_pcb.rcb_next = esis_pcb.rcb_prev = &esis_pcb;
        !           163:        llinfo_llc.lc_next = llinfo_llc.lc_prev = &llinfo_llc;
        !           164: 
        !           165:        timeout(snpac_age, (caddr_t)0, hz);
        !           166:        timeout(esis_config, (caddr_t)0, hz);
        !           167: 
        !           168:        clnl_protox[ISO9542_ESIS].clnl_input = esis_input;
        !           169:        clnl_protox[ISO10589_ISIS].clnl_input = isis_input;
        !           170: #ifdef ISO_X25ESIS
        !           171:        clnl_protox[ISO9542X25_ESIS].clnl_input = x25esis_input;
        !           172: #endif /* ISO_X25ESIS */
        !           173: }
        !           174: 
        !           175: /*
        !           176:  * FUNCTION:           esis_usrreq
        !           177:  *
        !           178:  * PURPOSE:                    Handle user level esis requests
        !           179:  *
        !           180:  * RETURNS:                    0 or appropriate errno
        !           181:  *
        !           182:  * SIDE EFFECTS:       
        !           183:  *
        !           184:  */
        !           185: /*ARGSUSED*/
        !           186: esis_usrreq(so, req, m, nam, control)
        !           187: struct socket  *so;            /* socket: used only to get to this code */
        !           188: int                            req;            /* request */
        !           189: struct mbuf            *m;                     /* data for request */
        !           190: struct mbuf            *nam;           /* optional name */
        !           191: struct mbuf            *control;       /* optional control */
        !           192: {
        !           193:        struct rawcb *rp = sotorawcb(so);
        !           194:        int error = 0;
        !           195: 
        !           196:        if ((so->so_state & SS_PRIV) == 0) {
        !           197:                error = EACCES;
        !           198:                goto release;
        !           199:        }
        !           200:        if (rp == NULL && req != PRU_ATTACH) {
        !           201:                error = EINVAL;
        !           202:                goto release;
        !           203:        }
        !           204: 
        !           205:        switch (req) {
        !           206:        case PRU_ATTACH:
        !           207:                if (rp != NULL) {
        !           208:                        error = EINVAL;
        !           209:                        break;
        !           210:                }
        !           211:                MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
        !           212:                if (so->so_pcb = (caddr_t)rp) {
        !           213:                        bzero(so->so_pcb, sizeof(*rp));
        !           214:                        insque(rp, &esis_pcb);
        !           215:                        rp->rcb_socket = so;
        !           216:                        error = soreserve(so, esis_sendspace, esis_recvspace);
        !           217:                } else
        !           218:                        error = ENOBUFS;
        !           219:                break;
        !           220: 
        !           221:        case PRU_SEND:
        !           222:                if (nam == NULL) {
        !           223:                        error = EINVAL;
        !           224:                        break;
        !           225:                }
        !           226:                /* error checking here */
        !           227:                error = isis_output(mtod(nam,struct sockaddr_dl *), m);
        !           228:                m = NULL;
        !           229:                break;
        !           230: 
        !           231:        case PRU_DETACH:
        !           232:                raw_detach(rp);
        !           233:                break;
        !           234: 
        !           235:        case PRU_SHUTDOWN:
        !           236:                socantsendmore(so);
        !           237:                break;
        !           238: 
        !           239:        case PRU_ABORT:
        !           240:                soisdisconnected(so);
        !           241:                raw_detach(rp);
        !           242:                break;
        !           243: 
        !           244:        case PRU_SENSE:
        !           245:                return (0);
        !           246: 
        !           247:        default:
        !           248:                return (EOPNOTSUPP);
        !           249:        }
        !           250: release:
        !           251:        if (m != NULL)
        !           252:                m_freem(m);
        !           253: 
        !           254:        return (error);
        !           255: }
        !           256: 
        !           257: /*
        !           258:  * FUNCTION:           esis_input
        !           259:  *
        !           260:  * PURPOSE:                    Process an incoming esis packet
        !           261:  *
        !           262:  * RETURNS:                    nothing
        !           263:  *
        !           264:  * SIDE EFFECTS:       
        !           265:  *
        !           266:  * NOTES:                      
        !           267:  */
        !           268: esis_input(m0, shp)
        !           269: struct mbuf            *m0;            /* ptr to first mbuf of pkt */
        !           270: struct snpa_hdr        *shp;   /* subnetwork header */
        !           271: {
        !           272:        register struct esis_fixed      *pdu = mtod(m0, struct esis_fixed *);
        !           273:        register int type;
        !           274: 
        !           275:        /*
        !           276:         *      check checksum if necessary
        !           277:         */
        !           278:        if (ESIS_CKSUM_REQUIRED(pdu) && iso_check_csum(m0, (int)pdu->esis_hdr_len)) {
        !           279:                esis_stat.es_badcsum++;
        !           280:                goto bad;
        !           281:        }
        !           282: 
        !           283:        /* check version */
        !           284:        if (pdu->esis_vers != ESIS_VERSION) {
        !           285:                esis_stat.es_badvers++;
        !           286:                goto bad;
        !           287:        }
        !           288:        type = pdu->esis_type & 0x1f;
        !           289:        switch (type) {
        !           290:                case ESIS_ESH:
        !           291:                        esis_eshinput(m0, shp);
        !           292:                        break;
        !           293: 
        !           294:                case ESIS_ISH:
        !           295:                        esis_ishinput(m0, shp);
        !           296:                        break;
        !           297: 
        !           298:                case ESIS_RD:
        !           299:                        esis_rdinput(m0, shp);
        !           300:                        break;
        !           301: 
        !           302:                default:
        !           303:                        esis_stat.es_badtype++;
        !           304:        }
        !           305: 
        !           306: bad:
        !           307:        if (esis_pcb.rcb_next != &esis_pcb)
        !           308:                isis_input(m0, shp);
        !           309:        else
        !           310:                m_freem(m0);
        !           311: }
        !           312: 
        !           313: /*
        !           314:  * FUNCTION:           esis_rdoutput
        !           315:  *
        !           316:  * PURPOSE:                    Transmit a redirect pdu
        !           317:  *
        !           318:  * RETURNS:                    nothing
        !           319:  *
        !           320:  * SIDE EFFECTS:       
        !           321:  *
        !           322:  * NOTES:                      Assumes there is enough space for fixed part of header,
        !           323:  *                                     DA, BSNPA and NET in first mbuf.
        !           324:  */
        !           325: esis_rdoutput(inbound_shp, inbound_m, inbound_oidx, rd_dstnsap, rt)
        !           326: struct snpa_hdr                *inbound_shp;   /* snpa hdr from incoming packet */
        !           327: struct mbuf                    *inbound_m;             /* incoming pkt itself */
        !           328: struct clnp_optidx     *inbound_oidx;  /* clnp options assoc with incoming pkt */
        !           329: struct iso_addr                *rd_dstnsap;    /* ultimate destination of pkt */
        !           330: struct rtentry         *rt;                    /* snpa cache info regarding next hop of
        !           331:                                                                                pkt */
        !           332: {
        !           333:        struct mbuf                     *m, *m0;
        !           334:        caddr_t                         cp;
        !           335:        struct esis_fixed       *pdu;
        !           336:        int                                     len, total_len = 0;
        !           337:        struct sockaddr_iso     siso;
        !           338:        struct ifnet            *ifp = inbound_shp->snh_ifp;
        !           339:        struct sockaddr_dl *sdl;
        !           340:        struct iso_addr *rd_gwnsap;
        !           341: 
        !           342:        if (rt->rt_flags & RTF_GATEWAY) {
        !           343:                rd_gwnsap = &((struct sockaddr_iso *)rt->rt_gateway)->siso_addr;
        !           344:                rt = rtalloc1(rt->rt_gateway, 0);
        !           345:        } else
        !           346:                rd_gwnsap = &((struct sockaddr_iso *)rt_key(rt))->siso_addr;
        !           347:        if (rt == 0 || (sdl = (struct sockaddr_dl *)rt->rt_gateway) == 0 ||
        !           348:                sdl->sdl_family != AF_LINK) {
        !           349:                /* maybe we should have a function that you
        !           350:                   could put in the iso_ifaddr structure
        !           351:                   which could translate iso_addrs into snpa's
        !           352:                   where there is a known mapping for that address type */
        !           353:                esis_stat.es_badtype++;
        !           354:                return;
        !           355:        }
        !           356:        esis_stat.es_rdsent++;
        !           357:        IFDEBUG(D_ESISOUTPUT)
        !           358:                printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n",
        !           359:                        ifp, ifp->if_name, ifp->if_unit, esis_holding_time, inbound_m,
        !           360:                        inbound_oidx);
        !           361:                printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap));
        !           362:                printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap));
        !           363:        ENDDEBUG
        !           364: 
        !           365:        if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) {
        !           366:                esis_stat.es_nomem++;
        !           367:                return;
        !           368:        }
        !           369:        bzero(mtod(m, caddr_t), MHLEN);
        !           370: 
        !           371:        pdu = mtod(m, struct esis_fixed *);
        !           372:        cp = (caddr_t)(pdu + 1); /*pointer arith.; 1st byte after header */
        !           373:        len = sizeof(struct esis_fixed);
        !           374: 
        !           375:        /*
        !           376:         *      Build fixed part of header
        !           377:         */
        !           378:        pdu->esis_proto_id = ISO9542_ESIS;
        !           379:        pdu->esis_vers = ESIS_VERSION;
        !           380:        pdu->esis_type = ESIS_RD;
        !           381:        HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, esis_holding_time);
        !           382: 
        !           383:        /* Insert destination address */
        !           384:        (void) esis_insert_addr(&cp, &len, rd_dstnsap, m, 0);
        !           385: 
        !           386:        /* Insert the snpa of better next hop */
        !           387:        *cp++ = sdl->sdl_alen;
        !           388:        bcopy(LLADDR(sdl), cp, sdl->sdl_alen);
        !           389:        cp += sdl->sdl_alen;
        !           390:        len += (sdl->sdl_alen + 1);
        !           391: 
        !           392:        /* 
        !           393:         *      If the next hop is not the destination, then it ought to be
        !           394:         *      an IS and it should be inserted next. Else, set the
        !           395:         *      NETL to 0
        !           396:         */
        !           397:        /* PHASE2 use mask from ifp of outgoing interface */
        !           398:        if (!iso_addrmatch1(rd_dstnsap, rd_gwnsap)) {
        !           399:                /* this should not happen: 
        !           400:                if ((nhop_sc->sc_flags & SNPA_IS) == 0) {
        !           401:                        printf("esis_rdoutput: next hop is not dst and not an IS\n");
        !           402:                        m_freem(m0);
        !           403:                        return;
        !           404:                } */
        !           405:                (void) esis_insert_addr(&cp, &len, rd_gwnsap, m, 0);
        !           406:        } else {
        !           407:                *cp++ = 0;      /* NETL */
        !           408:                len++;
        !           409:        }
        !           410:        m->m_len = len;
        !           411: 
        !           412:        /*
        !           413:         *      PHASE2
        !           414:         *      If redirect is to an IS, add an address mask. The mask to be
        !           415:         *      used should be the mask present in the routing entry used to
        !           416:         *      forward the original data packet.
        !           417:         */
        !           418:        
        !           419:        /*
        !           420:         *      Copy Qos, priority, or security options present in original npdu
        !           421:         */
        !           422:        if (inbound_oidx) {
        !           423:                /* THIS CODE IS CURRENTLY (mostly) UNTESTED */
        !           424:                int optlen = 0;
        !           425:                if (inbound_oidx->cni_qos_formatp)
        !           426:                        optlen += (inbound_oidx->cni_qos_len + 2);
        !           427:                if (inbound_oidx->cni_priorp)   /* priority option is 1 byte long */
        !           428:                        optlen += 3;
        !           429:                if (inbound_oidx->cni_securep)
        !           430:                        optlen += (inbound_oidx->cni_secure_len + 2);
        !           431:                if (M_TRAILINGSPACE(m) < optlen) {
        !           432:                        EXTEND_PACKET(m, m0, cp);
        !           433:                        m->m_len = 0;
        !           434:                        /* assumes MLEN > optlen */
        !           435:                }
        !           436:                /* assume MLEN-len > optlen */
        !           437:                /* 
        !           438:                 *      When copying options, copy from ptr - 2 in order to grab
        !           439:                 *      the option code and length
        !           440:                 */
        !           441:                if (inbound_oidx->cni_qos_formatp) {
        !           442:                        bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_qos_formatp - 2,
        !           443:                                cp, (unsigned)(inbound_oidx->cni_qos_len + 2));
        !           444:                        cp += inbound_oidx->cni_qos_len + 2;
        !           445:                }
        !           446:                if (inbound_oidx->cni_priorp) {
        !           447:                        bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_priorp - 2,
        !           448:                                        cp, 3);
        !           449:                        cp += 3;
        !           450:                }
        !           451:                if (inbound_oidx->cni_securep) {
        !           452:                        bcopy(mtod(inbound_m, caddr_t) + inbound_oidx->cni_securep - 2, cp, 
        !           453:                                (unsigned)(inbound_oidx->cni_secure_len + 2));
        !           454:                        cp += inbound_oidx->cni_secure_len + 2;
        !           455:                }
        !           456:                m->m_len += optlen;
        !           457:                len += optlen;
        !           458:        }
        !           459: 
        !           460:        pdu->esis_hdr_len = m0->m_pkthdr.len = len;
        !           461:        iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len);
        !           462: 
        !           463:        bzero((caddr_t)&siso, sizeof(siso));
        !           464:        siso.siso_family = AF_ISO;
        !           465:        siso.siso_data[0] = AFI_SNA;
        !           466:        siso.siso_nlen = 6 + 1; /* should be taken from snpa_hdr */
        !           467:                                                                                /* +1 is for AFI */
        !           468:        bcopy(inbound_shp->snh_shost, siso.siso_data + 1, 6);
        !           469:        (ifp->if_output)(ifp, m0, (struct sockaddr *)&siso, 0);
        !           470: }
        !           471: 
        !           472: /*
        !           473:  * FUNCTION:           esis_insert_addr
        !           474:  *
        !           475:  * PURPOSE:                    Insert an iso_addr into a buffer
        !           476:  *
        !           477:  * RETURNS:                    true if buffer was big enough, else false
        !           478:  *
        !           479:  * SIDE EFFECTS:       Increment buf & len according to size of iso_addr
        !           480:  *
        !           481:  * NOTES:                      Plus 1 here is for length byte
        !           482:  */
        !           483: esis_insert_addr(buf, len, isoa, m, nsellen)
        !           484: register caddr_t                       *buf;           /* ptr to buffer to put address into */
        !           485: int                                                    *len;           /* ptr to length of buffer so far */
        !           486: register struct iso_addr       *isoa;          /* ptr to address */
        !           487: register struct mbuf           *m;                     /* determine if there remains space */
        !           488: int                                                    nsellen;
        !           489: {
        !           490:        register int newlen, result = 0;
        !           491: 
        !           492:        isoa->isoa_len -= nsellen;
        !           493:        newlen = isoa->isoa_len + 1;
        !           494:        if (newlen <=  M_TRAILINGSPACE(m)) {
        !           495:                bcopy((caddr_t)isoa, *buf, newlen);
        !           496:                *len += newlen;
        !           497:                *buf += newlen;
        !           498:                m->m_len += newlen;
        !           499:                result = 1;
        !           500:        }
        !           501:        isoa->isoa_len += nsellen;
        !           502:        return (result);
        !           503: }
        !           504: 
        !           505: #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \
        !           506:            if (b > buflim) {esis_stat.es_toosmall++; goto bad;}}
        !           507: #define ESIS_NEXT_OPTION(b)    { b += (2 + b[1]); \
        !           508:            if (b > buflim) {esis_stat.es_toosmall++; goto bad;}}
        !           509: int ESHonly = 0;
        !           510: /*
        !           511:  
        !           512: /*
        !           513:  * FUNCTION:           esis_eshinput
        !           514:  *
        !           515:  * PURPOSE:                    Process an incoming ESH pdu
        !           516:  *
        !           517:  * RETURNS:                    nothing
        !           518:  *
        !           519:  * SIDE EFFECTS:       
        !           520:  *
        !           521:  * NOTES:                      
        !           522:  */
        !           523: esis_eshinput(m, shp)
        !           524: struct mbuf            *m;     /* esh pdu */
        !           525: struct snpa_hdr        *shp;   /* subnetwork header */
        !           526: {
        !           527:        struct  esis_fixed      *pdu = mtod(m, struct esis_fixed *);
        !           528:        u_short                         ht;             /* holding time */
        !           529:        struct  iso_addr        *nsap;
        !           530:        int                                     naddr;
        !           531:        u_char                          *buf = (u_char *)(pdu + 1);
        !           532:        u_char                          *buflim = pdu->esis_hdr_len + (u_char *)pdu;
        !           533:        int                                     new_entry = 0;
        !           534: 
        !           535:        esis_stat.es_eshrcvd++;
        !           536: 
        !           537:        CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);
        !           538: 
        !           539:        naddr = *buf++;
        !           540:        if (buf >= buflim)
        !           541:                goto bad;
        !           542:        if (naddr == 1) {
        !           543:                ESIS_EXTRACT_ADDR(nsap, buf);
        !           544:                new_entry = snpac_add(shp->snh_ifp,
        !           545:                                                                 nsap, shp->snh_shost, SNPA_ES, ht, 0);
        !           546:        } else {
        !           547:                int nsellength = 0, nlen = 0;
        !           548:                {
        !           549:                /* See if we want to compress out multiple nsaps differing
        !           550:                   only by nsel */
        !           551:                        register struct ifaddr *ifa = shp->snh_ifp->if_addrlist;
        !           552:                        for (; ifa; ifa = ifa->ifa_next)
        !           553:                                if (ifa->ifa_addr->sa_family == AF_ISO) {
        !           554:                                        nsellength = ((struct iso_ifaddr *)ifa)->ia_addr.siso_tlen;
        !           555:                                        break;
        !           556:                        }
        !           557:                }
        !           558:                IFDEBUG(D_ESISINPUT)
        !           559:                        printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n",
        !           560:                                        ht, naddr, nsellength);
        !           561:                ENDDEBUG
        !           562:                while (naddr-- > 0) {
        !           563:                        struct iso_addr *nsap2; u_char *buf2;
        !           564:                        ESIS_EXTRACT_ADDR(nsap, buf);
        !           565:                        /* see if there is at least one more nsap in ESH differing
        !           566:                           only by nsel */
        !           567:                        if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) {
        !           568:                                ESIS_EXTRACT_ADDR(nsap2, buf2);
        !           569:                                IFDEBUG(D_ESISINPUT)
        !           570:                                        printf("esis_eshinput: comparing %s ", 
        !           571:                                                clnp_iso_addrp(nsap));
        !           572:                                        printf("and %s\n", clnp_iso_addrp(nsap2));
        !           573:                                ENDDEBUG
        !           574:                                if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr,
        !           575:                                                 nsap->isoa_len - nsellength) == 0) {
        !           576:                                        nlen = nsellength;
        !           577:                                        break;
        !           578:                                }
        !           579:                        }
        !           580:                        new_entry |= snpac_add(shp->snh_ifp,
        !           581:                                                                        nsap, shp->snh_shost, SNPA_ES, ht, nlen);
        !           582:                        nlen = 0;
        !           583:                }
        !           584:        }
        !           585:        IFDEBUG(D_ESISINPUT)
        !           586:                printf("esis_eshinput: nsap %s is %s\n", 
        !           587:                        clnp_iso_addrp(nsap), new_entry ? "new" : "old");
        !           588:        ENDDEBUG
        !           589:        if (new_entry && (iso_systype & SNPA_IS))
        !           590:                esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time,
        !           591:                                                shp->snh_shost, 6, (struct iso_addr *)0);
        !           592: bad:
        !           593:        return;
        !           594: }
        !           595: 
        !           596: /*
        !           597:  * FUNCTION:           esis_ishinput
        !           598:  *
        !           599:  * PURPOSE:                    process an incoming ISH pdu
        !           600:  *
        !           601:  * RETURNS:                    
        !           602:  *
        !           603:  * SIDE EFFECTS:       
        !           604:  *
        !           605:  * NOTES:                      
        !           606:  */
        !           607: esis_ishinput(m, shp)
        !           608: struct mbuf            *m;     /* esh pdu */
        !           609: struct snpa_hdr        *shp;   /* subnetwork header */
        !           610: {
        !           611:        struct esis_fixed       *pdu = mtod(m, struct esis_fixed *);
        !           612:        u_short                         ht, newct;                      /* holding time */
        !           613:        struct iso_addr         *nsap;                          /* Network Entity Title */
        !           614:        register u_char         *buf = (u_char *) (pdu + 1);
        !           615:        register u_char         *buflim = pdu->esis_hdr_len + (u_char *)pdu;
        !           616:        int                                     new_entry;
        !           617: 
        !           618:        esis_stat.es_ishrcvd++;
        !           619:        CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);
        !           620: 
        !           621:        IFDEBUG(D_ESISINPUT)
        !           622:                printf("esis_ishinput: ish: ht %d\n", ht);
        !           623:        ENDDEBUG
        !           624:        if (ESHonly)
        !           625:                goto bad;
        !           626: 
        !           627:        ESIS_EXTRACT_ADDR(nsap, buf);
        !           628: 
        !           629:        while (buf < buflim) {
        !           630:                switch (*buf) {
        !           631:                case ESISOVAL_ESCT:
        !           632:                        if (iso_systype & SNPA_IS)
        !           633:                                break;
        !           634:                        if (buf[1] != 2)
        !           635:                                goto bad;
        !           636:                        CTOH(buf[2], buf[3], newct);
        !           637:                        if (esis_config_time != newct) {
        !           638:                                untimeout(esis_config,0);
        !           639:                                esis_config_time = newct;
        !           640:                                esis_config();
        !           641:                        }
        !           642:                        break;
        !           643:                
        !           644:                default:
        !           645:                        printf("Unknown ISH option: %x\n", *buf);
        !           646:                }
        !           647:                ESIS_NEXT_OPTION(buf);
        !           648:        }
        !           649:        new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0);
        !           650:        IFDEBUG(D_ESISINPUT)
        !           651:                printf("esis_ishinput: nsap %s is %s\n", 
        !           652:                        clnp_iso_addrp(nsap), new_entry ? "new" : "old");
        !           653:        ENDDEBUG
        !           654: 
        !           655:        if (new_entry)
        !           656:                esis_shoutput(shp->snh_ifp, 
        !           657:                        iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH,
        !           658:                        esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0);
        !           659: bad:
        !           660:        return;
        !           661: }
        !           662: 
        !           663: /*
        !           664:  * FUNCTION:           esis_rdinput
        !           665:  *
        !           666:  * PURPOSE:                    Process an incoming RD pdu
        !           667:  *
        !           668:  * RETURNS:                    
        !           669:  *
        !           670:  * SIDE EFFECTS:       
        !           671:  *
        !           672:  * NOTES:                      
        !           673:  */
        !           674: esis_rdinput(m0, shp)
        !           675: struct mbuf            *m0;    /* esh pdu */
        !           676: struct snpa_hdr        *shp;   /* subnetwork header */
        !           677: {
        !           678:        struct esis_fixed       *pdu = mtod(m0, struct esis_fixed *);
        !           679:        u_short                         ht;             /* holding time */
        !           680:        struct iso_addr         *da, *net = 0, *netmask = 0, *snpamask = 0;
        !           681:        register struct iso_addr *bsnpa;
        !           682:        register u_char         *buf = (u_char *)(pdu + 1);
        !           683:        register u_char         *buflim = pdu->esis_hdr_len + (u_char *)pdu;
        !           684: 
        !           685:        esis_stat.es_rdrcvd++;
        !           686: 
        !           687:        /* intermediate systems ignore redirects */
        !           688:        if (iso_systype & SNPA_IS)
        !           689:                return;
        !           690:        if (ESHonly)
        !           691:                return;
        !           692: 
        !           693:        CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);
        !           694:        if (buf >= buflim)
        !           695:                return;
        !           696: 
        !           697:        /* Extract DA */
        !           698:        ESIS_EXTRACT_ADDR(da, buf);
        !           699: 
        !           700:        /* Extract better snpa */
        !           701:        ESIS_EXTRACT_ADDR(bsnpa, buf);
        !           702: 
        !           703:        /* Extract NET if present */
        !           704:        if (buf < buflim) {
        !           705:                if (*buf == 0)
        !           706:                        buf++; /* no NET present, skip NETL anyway */
        !           707:                else
        !           708:                        ESIS_EXTRACT_ADDR(net, buf);
        !           709:        }
        !           710: 
        !           711:        /* process options */
        !           712:        while (buf < buflim) {
        !           713:                switch (*buf) {
        !           714:                case ESISOVAL_SNPAMASK:
        !           715:                        if (snpamask) /* duplicate */
        !           716:                                return;
        !           717:                        snpamask = (struct iso_addr *)(buf + 1);
        !           718:                        break;
        !           719: 
        !           720:                case ESISOVAL_NETMASK:
        !           721:                        if (netmask) /* duplicate */
        !           722:                                return;
        !           723:                        netmask = (struct iso_addr *)(buf + 1);
        !           724:                        break;
        !           725: 
        !           726:                default:
        !           727:                        printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]);
        !           728:                }
        !           729:                ESIS_NEXT_OPTION(buf);
        !           730:        }
        !           731: 
        !           732:        IFDEBUG(D_ESISINPUT)
        !           733:                printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da));
        !           734:                if (net)
        !           735:                        printf("\t: net %s\n", clnp_iso_addrp(net));
        !           736:        ENDDEBUG
        !           737:        /*
        !           738:         *      If netl is zero, then redirect is to an ES. We need to add an entry
        !           739:         *      to the snpa cache for (destination, better snpa).
        !           740:         *      If netl is not zero, then the redirect is to an IS. In this
        !           741:         *      case, add an snpa cache entry for (net, better snpa).
        !           742:         *
        !           743:         *      If the redirect is to an IS, add a route entry towards that
        !           744:         *      IS.
        !           745:         */
        !           746:        if (net == 0 || net->isoa_len == 0 || snpamask) {
        !           747:                /* redirect to an ES */
        !           748:                snpac_add(shp->snh_ifp, da,
        !           749:                                bsnpa->isoa_genaddr, SNPA_ES, ht, 0);
        !           750:        } else {
        !           751:                snpac_add(shp->snh_ifp, net,
        !           752:                                bsnpa->isoa_genaddr, SNPA_IS, ht, 0);
        !           753:                snpac_addrt(shp->snh_ifp, da, net, netmask);
        !           754:        }
        !           755: bad: ;    /* Needed by ESIS_NEXT_OPTION */
        !           756: }
        !           757: 
        !           758: /*
        !           759:  * FUNCTION:           esis_config
        !           760:  *
        !           761:  * PURPOSE:                    Report configuration
        !           762:  *
        !           763:  * RETURNS:                    
        !           764:  *
        !           765:  * SIDE EFFECTS:       
        !           766:  *
        !           767:  * NOTES:                      Called every esis_config_time seconds
        !           768:  */
        !           769: void
        !           770: esis_config()
        !           771: {
        !           772:        register struct ifnet   *ifp;
        !           773: 
        !           774:        timeout(esis_config, (caddr_t)0, hz * esis_config_time);
        !           775: 
        !           776:        /* 
        !           777:         *      Report configuration for each interface that 
        !           778:         *      - is UP
        !           779:         *      - has BROADCAST capability
        !           780:         *      - has an ISO address
        !           781:         */
        !           782:        /* Todo: a better way would be to construct the esh or ish
        !           783:         * once and copy it out for all devices, possibly calling
        !           784:         * a method in the iso_ifaddr structure to encapsulate and
        !           785:         * transmit it.  This could work to advantage for non-broadcast media
        !           786:         */
        !           787:        
        !           788:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           789:                if ((ifp->if_flags & IFF_UP) &&
        !           790:                    (ifp->if_flags & IFF_BROADCAST)) {
        !           791:                        /* search for an ISO address family */
        !           792:                        struct ifaddr   *ia;
        !           793: 
        !           794:                        for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) {
        !           795:                                if (ia->ifa_addr->sa_family == AF_ISO) {
        !           796:                                        esis_shoutput(ifp, 
        !           797:                                                iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH,
        !           798:                                                esis_holding_time,
        !           799:                                                (caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 
        !           800:                                                all_es_snpa), 6, (struct iso_addr *)0);
        !           801:                                        break;
        !           802:                                }
        !           803:                        }
        !           804:                }
        !           805:        }
        !           806: }
        !           807: 
        !           808: /*
        !           809:  * FUNCTION:           esis_shoutput
        !           810:  *
        !           811:  * PURPOSE:                    Transmit an esh or ish pdu
        !           812:  *
        !           813:  * RETURNS:                    nothing
        !           814:  *
        !           815:  * SIDE EFFECTS:       
        !           816:  *
        !           817:  * NOTES:                      
        !           818:  */
        !           819: esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa)
        !           820: struct ifnet   *ifp;
        !           821: int                            type;
        !           822: short                  ht;
        !           823: caddr_t                sn_addr;
        !           824: int                            sn_len;
        !           825: struct iso_addr *isoa;
        !           826: {
        !           827:        struct mbuf                     *m, *m0;
        !           828:        caddr_t                         cp, naddrp;
        !           829:        int                                     naddr = 0;
        !           830:        struct esis_fixed       *pdu;
        !           831:        struct iso_ifaddr       *ia;
        !           832:        int                                     len;
        !           833:        struct sockaddr_iso     siso;
        !           834: 
        !           835:        if (type == ESIS_ESH)
        !           836:                esis_stat.es_eshsent++;
        !           837:        else if (type == ESIS_ISH) 
        !           838:                esis_stat.es_ishsent++;
        !           839:        else {
        !           840:                printf("esis_shoutput: bad pdu type\n");
        !           841:                return;
        !           842:        }
        !           843: 
        !           844:        IFDEBUG(D_ESISOUTPUT)
        !           845:                int     i;
        !           846:                printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ",
        !           847:                        ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish",
        !           848:                        ht, sn_len);
        !           849:                for (i=0; i<sn_len; i++)
        !           850:                        printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' ');
        !           851:                printf("\n");
        !           852:        ENDDEBUG
        !           853: 
        !           854:        if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) {
        !           855:                esis_stat.es_nomem++;
        !           856:                return;
        !           857:        }
        !           858:        bzero(mtod(m, caddr_t), MHLEN);
        !           859: 
        !           860:        pdu = mtod(m, struct esis_fixed *);
        !           861:        naddrp = cp = (caddr_t)(pdu + 1);
        !           862:        len = sizeof(struct esis_fixed);
        !           863: 
        !           864:        /*
        !           865:         *      Build fixed part of header
        !           866:         */
        !           867:        pdu->esis_proto_id = ISO9542_ESIS;
        !           868:        pdu->esis_vers = ESIS_VERSION;
        !           869:        pdu->esis_type = type;
        !           870:        HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);
        !           871: 
        !           872:        if (type == ESIS_ESH) {
        !           873:                cp++;
        !           874:                len++;
        !           875:        }
        !           876: 
        !           877:        m->m_len = len;
        !           878:        if (isoa) {
        !           879:                /*
        !           880:                 * Here we are responding to a clnp packet sent to an NSAP
        !           881:                 * that is ours which was sent to the MAC addr all_es's.
        !           882:                 * It is possible that we did not specifically advertise this
        !           883:                 * NSAP, even though it is ours, so we will respond
        !           884:                 * directly to the sender that we are here.  If we do have
        !           885:                 * multiple NSEL's we'll tack them on so he can compress them out.
        !           886:                 */
        !           887:                (void) esis_insert_addr(&cp, &len, isoa, m, 0);
        !           888:                naddr = 1;
        !           889:        }
        !           890:        for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
        !           891:                int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 
        !           892:                int n = ia->ia_addr.siso_nlen;
        !           893:                register struct iso_ifaddr *ia2;
        !           894: 
        !           895:                if (type == ESIS_ISH && naddr > 0)
        !           896:                        break;
        !           897:                for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next)
        !           898:                        if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0)
        !           899:                                        break;
        !           900:                if (ia2 != ia)
        !           901:                        continue;       /* Means we have previously copied this nsap */
        !           902:                if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) {
        !           903:                        isoa = 0;
        !           904:                        continue;       /* Ditto */
        !           905:                }
        !           906:                IFDEBUG(D_ESISOUTPUT)
        !           907:                        printf("esis_shoutput: adding NSAP %s\n", 
        !           908:                                clnp_iso_addrp(&ia->ia_addr.siso_addr));
        !           909:                ENDDEBUG
        !           910:                if (!esis_insert_addr(&cp, &len,
        !           911:                                                          &ia->ia_addr.siso_addr, m, nsellen)) {
        !           912:                        EXTEND_PACKET(m, m0, cp);
        !           913:                        (void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m,
        !           914:                                                                        nsellen);
        !           915:                }
        !           916:                naddr++;
        !           917:        }
        !           918: 
        !           919:        if (type == ESIS_ESH)
        !           920:                *naddrp = naddr;
        !           921:        else {
        !           922:                /* add suggested es config timer option to ISH */
        !           923:                if (M_TRAILINGSPACE(m) < 4) {
        !           924:                        printf("esis_shoutput: extending packet\n");
        !           925:                        EXTEND_PACKET(m, m0, cp);
        !           926:                }
        !           927:                *cp++ = ESISOVAL_ESCT;
        !           928:                *cp++ = 2;
        !           929:                HTOC(*cp, *(cp+1), esis_esconfig_time);
        !           930:                len += 4;
        !           931:                m->m_len += 4;
        !           932:                IFDEBUG(D_ESISOUTPUT)
        !           933:                        printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n",
        !           934:                        m0, m, m->m_data, m->m_len, cp);
        !           935:                ENDDEBUG
        !           936:        }
        !           937: 
        !           938:        m0->m_pkthdr.len = len;
        !           939:        pdu->esis_hdr_len = len;
        !           940:        iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len);
        !           941: 
        !           942:        bzero((caddr_t)&siso, sizeof(siso));
        !           943:        siso.siso_family = AF_ISO;
        !           944:        siso.siso_data[0] = AFI_SNA;
        !           945:        siso.siso_nlen = sn_len + 1;
        !           946:        bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len);
        !           947:        (ifp->if_output)(ifp, m0, (struct sockaddr *)&siso, 0);
        !           948: }
        !           949: 
        !           950: /*
        !           951:  * FUNCTION:           isis_input
        !           952:  *
        !           953:  * PURPOSE:                    Process an incoming isis packet
        !           954:  *
        !           955:  * RETURNS:                    nothing
        !           956:  *
        !           957:  * SIDE EFFECTS:       
        !           958:  *
        !           959:  * NOTES:                      
        !           960:  */
        !           961: isis_input(m0, shp)
        !           962: struct mbuf            *m0;            /* ptr to first mbuf of pkt */
        !           963: struct snpa_hdr        *shp;   /* subnetwork header */
        !           964: {
        !           965:        register int type;
        !           966:        register struct rawcb *rp, *first_rp = 0;
        !           967:        struct ifnet *ifp = shp->snh_ifp;
        !           968:        char workbuf[16];
        !           969:        struct mbuf *mm;
        !           970: 
        !           971:        IFDEBUG(D_ISISINPUT)
        !           972:                int i;
        !           973: 
        !           974:                printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 
        !           975:                        ifp->if_name, ifp->if_unit);
        !           976:                for (i=0; i<6; i++)
        !           977:                        printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' ');
        !           978:                printf(" to:");
        !           979:                for (i=0; i<6; i++)
        !           980:                        printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' ');
        !           981:                printf("\n");
        !           982:        ENDDEBUG
        !           983:        esis_dl.sdl_alen = ifp->if_addrlen;
        !           984:        esis_dl.sdl_index = ifp->if_index;
        !           985:        bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen);
        !           986:        for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) {
        !           987:                if (first_rp == 0) {
        !           988:                        first_rp = rp;
        !           989:                        continue;
        !           990:                }
        !           991:                if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */
        !           992:                        if (sbappendaddr(&rp->rcb_socket->so_rcv,
        !           993:                                                          &esis_dl, mm, (struct mbuf *)0) != 0) {
        !           994:                                sorwakeup(rp->rcb_socket);
        !           995:                         } else {
        !           996:                                IFDEBUG(D_ISISINPUT)
        !           997:                                        printf("Error in sbappenaddr, mm = 0x%x\n", mm);
        !           998:                                ENDDEBUG
        !           999:                                m_freem(mm);
        !          1000:                        }
        !          1001:                }
        !          1002:        }
        !          1003:        if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv,
        !          1004:                                                          &esis_dl, m0, (struct mbuf *)0) != 0) {
        !          1005:                sorwakeup(first_rp->rcb_socket);
        !          1006:                return;
        !          1007:        }
        !          1008:        m_freem(m0);
        !          1009: }
        !          1010: 
        !          1011: isis_output(sdl, m)
        !          1012: register struct sockaddr_dl    *sdl;
        !          1013: struct mbuf *m;
        !          1014: {
        !          1015:        register struct ifnet *ifp;
        !          1016:        struct ifaddr *ifa, *ifa_ifwithnet();
        !          1017:        struct sockaddr_iso siso;
        !          1018:        int error = 0;
        !          1019:        unsigned sn_len;
        !          1020: 
        !          1021:        ifa = ifa_ifwithnet((struct sockaddr *)sdl);    /* get ifp from sdl */
        !          1022:        if (ifa == 0) {
        !          1023:                IFDEBUG(D_ISISOUTPUT)
        !          1024:                        printf("isis_output: interface not found\n");
        !          1025:                ENDDEBUG
        !          1026:                error = EINVAL;
        !          1027:                goto release;
        !          1028:        }
        !          1029:        ifp = ifa->ifa_ifp;
        !          1030:        sn_len = sdl->sdl_alen;
        !          1031:        IFDEBUG(D_ISISOUTPUT)
        !          1032:                u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len;
        !          1033:                printf("isis_output: ifp 0x%x (%s%d), to: ",
        !          1034:                        ifp, ifp->if_name, ifp->if_unit);
        !          1035:                while (cp < cplim) {
        !          1036:                        printf("%x", *cp++);
        !          1037:                        printf("%c", (cp < cplim) ? ':' : ' ');
        !          1038:                }
        !          1039:                printf("\n");
        !          1040:        ENDDEBUG
        !          1041:        bzero((caddr_t)&siso, sizeof(siso));
        !          1042:        siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */
        !          1043:        siso.siso_data[0] = AFI_SNA;
        !          1044:        siso.siso_nlen = sn_len + 1;
        !          1045:        bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len);
        !          1046:        error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0);
        !          1047:        if (error) {
        !          1048:                IFDEBUG(D_ISISOUTPUT)
        !          1049:                        printf("isis_output: error from ether_output is %d\n", error);
        !          1050:                ENDDEBUG
        !          1051:        }
        !          1052:        return (error);
        !          1053: 
        !          1054: release:
        !          1055:        if (m != NULL)
        !          1056:                m_freem(m);
        !          1057:        return(error);
        !          1058: }
        !          1059: 
        !          1060: 
        !          1061: /*
        !          1062:  * FUNCTION:           esis_ctlinput
        !          1063:  *
        !          1064:  * PURPOSE:                    Handle the PRC_IFDOWN transition
        !          1065:  *
        !          1066:  * RETURNS:                    nothing
        !          1067:  *
        !          1068:  * SIDE EFFECTS:       
        !          1069:  *
        !          1070:  * NOTES:                      Calls snpac_flush for interface specified.
        !          1071:  *                                     The loop through iso_ifaddr is stupid because
        !          1072:  *                                     back in if_down, we knew the ifp...
        !          1073:  */
        !          1074: esis_ctlinput(req, siso)
        !          1075: int                                            req;            /* request: we handle only PRC_IFDOWN */
        !          1076: struct sockaddr_iso            *siso;          /* address of ifp */
        !          1077: {
        !          1078:        register struct iso_ifaddr *ia; /* scan through interface addresses */
        !          1079: 
        !          1080:        if (req == PRC_IFDOWN)
        !          1081:                for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
        !          1082:                        if (iso_addrmatch(IA_SIS(ia), siso))
        !          1083:                                snpac_flushifp(ia->ia_ifp);
        !          1084:                }
        !          1085: }
        !          1086: 
        !          1087: #endif /* ISO */

unix.superglobalmegacorp.com

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