Annotation of 43BSDReno/sys/netiso/esis.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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