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