Annotation of XNU/bsd/netccitt/llc_input.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* 
        !            23:  * Copyright (C) Dirk Husemann, Computer Science Department IV, 
        !            24:  *              University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992
        !            25:  * Copyright (c) 1992, 1993
        !            26:  *     The Regents of the University of California.  All rights reserved.
        !            27:  * 
        !            28:  * This code is derived from software contributed to Berkeley by
        !            29:  * Dirk Husemann and the Computer Science Department (IV) of
        !            30:  * the University of Erlangen-Nuremberg, Germany.
        !            31:  *
        !            32:  * Redistribution and use in source and binary forms, with or without
        !            33:  * modification, are permitted provided that the following conditions
        !            34:  * are met:
        !            35:  * 1. Redistributions of source code must retain the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer.
        !            37:  * 2. Redistributions in binary form must reproduce the above copyright
        !            38:  *    notice, this list of conditions and the following disclaimer in the
        !            39:  *    documentation and/or other materials provided with the distribution.
        !            40:  * 3. All advertising materials mentioning features or use of this software
        !            41:  *    must display the following acknowledgement:
        !            42:  *     This product includes software developed by the University of
        !            43:  *     California, Berkeley and its contributors.
        !            44:  * 4. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)llc_input.c 8.1 (Berkeley) 6/10/93
        !            61:  */
        !            62: 
        !            63: #include <sys/param.h>
        !            64: #include <sys/systm.h>
        !            65: #include <sys/mbuf.h>
        !            66: #include <sys/domain.h>
        !            67: #include <sys/socket.h>
        !            68: #include <sys/protosw.h>
        !            69: #include <sys/errno.h>
        !            70: #include <sys/time.h>
        !            71: #include <sys/kernel.h>
        !            72: 
        !            73: #include <net/if.h>
        !            74: #include <net/if_dl.h>
        !            75: #include <net/if_llc.h>
        !            76: #include <net/route.h>
        !            77: 
        !            78: #include <netccitt/dll.h>
        !            79: #include <netccitt/llc_var.h>
        !            80: 
        !            81: /*
        !            82:  * This module implements LLC as specified by ISO 8802-2.
        !            83:  */
        !            84: 
        !            85: 
        !            86: /*
        !            87:  * llcintr() handles all LLC frames (except ISO CLNS ones for the time being)
        !            88:  *           and tries to pass them on to the appropriate network layer entity.
        !            89:  */
        !            90: void
        !            91: llcintr()
        !            92: {
        !            93:        register struct mbuf *m;
        !            94:        register int i;
        !            95:        register int frame_kind;
        !            96:        register u_char cmdrsp;
        !            97:        struct llc_linkcb *linkp;
        !            98:        struct rtentry *sirt;
        !            99:        struct npaidbentry *sapinfo;
        !           100:        struct sdl_hdr *sdlhdr;
        !           101:        struct llc *frame;
        !           102:        char *c;
        !           103:        long expected_len;
        !           104: 
        !           105:        struct ifnet   *ifp;
        !           106:        struct rtentry *llrt;
        !           107:        struct rtentry *nlrt;
        !           108: 
        !           109:        for (;;) {
        !           110:                i = splimp();
        !           111:                IF_DEQUEUE(&llcintrq, m);
        !           112:                splx(i);
        !           113:                if (m == 0)
        !           114:                        break;
        !           115: #if            DIAGNOSTIC
        !           116:                if ((m->m_flags & M_PKTHDR) == 0)
        !           117:                        panic("llcintr no HDR");
        !           118: #endif
        !           119:                /*
        !           120:                 * Get ifp this packet was received on
        !           121:                 */
        !           122:                ifp = m->m_pkthdr.rcvif;
        !           123: 
        !           124:                sdlhdr = mtod(m, struct sdl_hdr *);
        !           125: 
        !           126:                /*
        !           127:                 * [Copied from net/ip_input.c]
        !           128:                 *
        !           129:                 * Check that the amount of data in the buffers is
        !           130:                 * at least as much as the LLC header tells us.
        !           131:                 * Trim mbufs if longer than expected.
        !           132:                 * Drop packets if shorter than we think they are.
        !           133:                 *
        !           134:                 * Layout of mbuf chain at this point:
        !           135:                 *
        !           136:                 *  +-------------------------------+----+      -\
        !           137:                  *  |  sockaddr_dl src - sdlhdr_src | 20 |       \
        !           138:                  *  +-------------------------------+----+        |
        !           139:                 *  |  sockaddr_dl dst - sdlhdr_dst | 20 |          > sizeof(struct sdl_hdr) == 44
        !           140:                 *  +-------------------------------+----+         |
        !           141:                  *  |  LLC frame len - sdlhdr_len   | 04 |       /
        !           142:                 *  +-------------------------------+----+      -/
        !           143:                 * /
        !           144:                 * | m_next
        !           145:                 * \
        !           146:                  *  +----------------------------+----+         -\
        !           147:                  *  |  llc DSAP                 | 01 |    \
        !           148:                 *  +----------------------------+----+     |
        !           149:                  *  |  llc SSAP                 | 01 |     |
        !           150:                 *  +----------------------------+----+      > sdlhdr_len
        !           151:                  *  |  llc control              | 01 |     |
        !           152:                 *  +----------------------------+----+     |
        !           153:                 *  |  ...                       |    |    /
        !           154:                 *                                       -/
        !           155:                 *
        !           156:                 * Thus the we expect to have exactly 
        !           157:                 * (sdlhdr->sdlhdr_len+sizeof(struct sdl_hdr)) in the mbuf chain
        !           158:                 */
        !           159:                expected_len = sdlhdr->sdlhdr_len + sizeof(struct sdl_hdr);
        !           160: 
        !           161:                if (m->m_pkthdr.len < expected_len) {
        !           162:                        m_freem(m);
        !           163:                        continue;
        !           164:                }
        !           165:                if (m->m_pkthdr.len > expected_len) {
        !           166:                        if (m->m_len == m->m_pkthdr.len) {
        !           167:                                m->m_len = expected_len;
        !           168:                                m->m_pkthdr.len = expected_len;
        !           169:                        } else
        !           170:                                m_adj(m, expected_len - m->m_pkthdr.len);
        !           171:                }
        !           172: 
        !           173:                /*
        !           174:                 * Get llc header
        !           175:                 */
        !           176:                if (m->m_len > sizeof(struct sdl_hdr))
        !           177:                        frame = mtod((struct mbuf *)((struct sdl_hdr*)(m+1)),
        !           178:                                     struct llc *);
        !           179:                else frame = mtod(m->m_next, struct llc *);
        !           180:                if (frame == (struct llc *) NULL)
        !           181:                        panic("llcintr no llc header");
        !           182: 
        !           183:                /*
        !           184:                 * Now check for bogus I/S frame, i.e. those with a control
        !           185:                 * field telling us they're an I/S frame yet their length
        !           186:                 * is less than the established I/S frame length (DSAP + SSAP +
        !           187:                 * control + N(R)&P/F = 4) --- we drop those suckers
        !           188:                 */
        !           189:                if (((frame->llc_control & 0x03) != 0x03) 
        !           190:                    && ((expected_len - sizeof(struct sdl_hdr)) < LLC_ISFRAMELEN)) {
        !           191:                        m_freem(m);
        !           192:                        printf("llc: hurz error\n");
        !           193:                        continue;
        !           194:                }
        !           195: 
        !           196:                /*
        !           197:                 * Get link control block for the addressed link connection.
        !           198:                 * If there is none we take care of it later on.
        !           199:                 */
        !           200:                cmdrsp = (frame->llc_ssap & 0x01);
        !           201:                frame->llc_ssap &= ~0x01;
        !           202:                if (llrt = rtalloc1((struct sockaddr *)&sdlhdr->sdlhdr_src, 0))
        !           203:                        llrt->rt_refcnt--;
        !           204: #ifdef notyet
        !           205:                else llrt = npaidb_enter(&sdlhdr->sdlhdr_src, 0, 0, 0);
        !           206: #endif /* notyet */
        !           207:                else {
        !           208:                        /* 
        !           209:                         * We cannot do anything currently here as we
        !           210:                         * don't `know' this link --- drop it 
        !           211:                         */
        !           212:                        m_freem(m);
        !           213:                        continue;
        !           214:                }
        !           215:                linkp = ((struct npaidbentry *)(llrt->rt_llinfo))->np_link;
        !           216:                nlrt = ((struct npaidbentry *)(llrt->rt_llinfo))->np_rt;
        !           217: 
        !           218:                /*
        !           219:                 * If the link is not existing right now, we can try and look up
        !           220:                 * the SAP info block.
        !           221:                 */
        !           222:                if ((linkp == 0) && frame->llc_ssap) 
        !           223:                        sapinfo = llc_getsapinfo(frame->llc_dsap, ifp);
        !           224: 
        !           225:                /*
        !           226:                 * Handle XID and TEST frames
        !           227:                 * XID:         if DLSAP == 0, return   type-of-services
        !           228:                 *                                      window-0
        !           229:                 *                                      DLSAP-0
        !           230:                 *                                      format-identifier-?
        !           231:                 *              if DLSAP != 0, locate sapcb and return
        !           232:                 *                                      type-of-services
        !           233:                 *                                      SAP-window
        !           234:                 *                                      format-identifier-?
        !           235:                 * TEST:        swap (snpah_dst, snpah_src) and return frame
        !           236:                 *
        !           237:                 * Also toggle the CMD/RESP bit
        !           238:                 *
        !           239:                 * Is this behaviour correct? Check ISO 8802-2 (90)!
        !           240:                 */
        !           241:                frame_kind = llc_decode(frame, (struct llc_linkcb *)0);
        !           242:                switch(frame_kind) {
        !           243:                case LLCFT_XID:
        !           244:                        if (linkp || sapinfo) {
        !           245:                                if (linkp)
        !           246:                                        frame->llc_window = linkp->llcl_window;
        !           247:                                else frame->llc_window = sapinfo->si_window;
        !           248:                                frame->llc_fid = 9;                     /* XXX */
        !           249:                                frame->llc_class = sapinfo->si_class;
        !           250:                                frame->llc_ssap = frame->llc_dsap;
        !           251:                        } else {
        !           252:                                frame->llc_window = 0;
        !           253:                                frame->llc_fid = 9;
        !           254:                                frame->llc_class = 1;
        !           255:                                frame->llc_dsap = frame->llc_ssap = 0;
        !           256:                        }
        !           257: 
        !           258:                        /* fall thru to */
        !           259:                case LLCFT_TEST:
        !           260:                        sdl_swapaddr(&(mtod(m, struct sdl_hdr *)->sdlhdr_dst),
        !           261:                                     &(mtod(m, struct sdl_hdr *)->sdlhdr_src));
        !           262: 
        !           263:                        /* Now set the CMD/RESP bit */
        !           264:                        frame->llc_ssap |= (cmdrsp == 0x0 ? 0x1 : 0x0);
        !           265: 
        !           266:                        /* Ship it out again */
        !           267:                        (*ifp->if_output)(ifp, m,
        !           268:                                          (struct sockaddr *) &(mtod(m, struct sdl_hdr *)->sdlhdr_dst),
        !           269:                                          (struct rtentry *) 0);
        !           270:                        continue;
        !           271:                }
        !           272: 
        !           273:                /*
        !           274:                 * Create link control block in case it is not existing
        !           275:                 */
        !           276:                if (linkp == 0 && sapinfo) {
        !           277:                        if ((linkp = llc_newlink(&sdlhdr->sdlhdr_src, ifp, nlrt,
        !           278:                                                     (nlrt == 0) ? 0 : nlrt->rt_llinfo,
        !           279:                                                     llrt)) == 0) {
        !           280:                                printf("llcintr: couldn't create new link\n");
        !           281:                                m_freem(m);
        !           282:                                continue;
        !           283:                        }
        !           284:                        ((struct npaidbentry *)llrt->rt_llinfo)->np_link = linkp;
        !           285:                } else if (linkp == 0) {
        !           286:                        /* The link is not known to us, drop the frame and continue */
        !           287:                        m_freem(m);
        !           288:                        continue;
        !           289:                }
        !           290: 
        !           291:                /*
        !           292:                 * Drop SNPA header and get rid of empty mbuf at the
        !           293:                 * front of the mbuf chain (I don't like 'em)
        !           294:                 */
        !           295:                m_adj(m, sizeof(struct sdl_hdr));
        !           296:                /* 
        !           297:                 * LLC_UFRAMELEN is sufficient, m_pullup() will pull up
        !           298:                 * the min(m->m_len, maxprotohdr_len [=40]) thus doing
        !           299:                 * the trick ...
        !           300:                 */
        !           301:                if ((m = m_pullup(m, LLC_UFRAMELEN)))
        !           302:                        /*
        !           303:                         * Pass it on thru the elements of procedure
        !           304:                         */
        !           305:                        llc_input(linkp, m, cmdrsp);
        !           306:        }
        !           307:        return;
        !           308: }
        !           309: 
        !           310: /*
        !           311:  * llc_input() --- We deal with the various incoming frames here.
        !           312:  *                 Basically we (indirectly) call the appropriate
        !           313:  *                 state handler function that's pointed to by
        !           314:  *                 llcl_statehandler.
        !           315:  * 
        !           316:  *                 The statehandler returns an action code ---
        !           317:  *                 further actions like 
        !           318:  *                         o notify network layer
        !           319:  *                         o block further sending
        !           320:  *                         o deblock link
        !           321:  *                         o ...
        !           322:  *                 are then enacted accordingly.
        !           323:  */
        !           324: llc_input(struct llc_linkcb *linkp, struct mbuf *m, u_char cmdrsp)
        !           325: {
        !           326:        int frame_kind;
        !           327:        int pollfinal;
        !           328:        int action = 0;
        !           329:        struct llc *frame;
        !           330:        struct ifnet *ifp = linkp->llcl_if;
        !           331: 
        !           332:        if ((frame = mtod(m, struct llc *)) == (struct llc *) 0) {
        !           333:                m_freem(m);
        !           334:                return 0;
        !           335:        }
        !           336:        pollfinal = ((frame->llc_control & 0x03) == 0x03) ? 
        !           337:                LLCGBITS(frame->llc_control, u_pf) :
        !           338:                        LLCGBITS(frame->llc_control_ext, s_pf);
        !           339: 
        !           340:        /*
        !           341:         * first decode the frame
        !           342:         */
        !           343:        frame_kind = llc_decode(frame, linkp);
        !           344: 
        !           345:        switch (action = llc_statehandler(linkp, frame, frame_kind, cmdrsp, 
        !           346:                                          pollfinal)) {
        !           347:        case LLC_DATA_INDICATION:
        !           348:                m_adj(m, LLC_ISFRAMELEN);
        !           349:                if (m = m_pullup(m, NLHDRSIZEGUESS)) {
        !           350:                        m->m_pkthdr.rcvif = (struct ifnet *)linkp->llcl_nlnext;
        !           351:                        (*linkp->llcl_sapinfo->si_input)(m);
        !           352:                }
        !           353:                break;
        !           354:        }
        !           355: 
        !           356:        /* release mbuf if not an info frame */
        !           357:        if (action != LLC_DATA_INDICATION && m)
        !           358:                m_freem(m);
        !           359: 
        !           360:        /* try to get frames out ... */
        !           361:        llc_start(linkp);
        !           362: 
        !           363:        return 0;
        !           364: }
        !           365: 
        !           366: /*
        !           367:  * This routine is called by configuration setup. It sets up a station control
        !           368:  * block and notifies all registered upper level protocols.
        !           369:  */
        !           370: caddr_t
        !           371: llc_ctlinput(int prc, struct sockaddr *addr, caddr_t info)
        !           372: {
        !           373:        struct ifnet *ifp;
        !           374:        struct ifaddr *ifa;
        !           375:        struct dll_ctlinfo *ctlinfo = (struct dll_ctlinfo *)info;
        !           376:        u_char sap;
        !           377:        struct dllconfig *config;
        !           378:        caddr_t pcb;
        !           379:        struct rtentry *nlrt;
        !           380:        struct rtentry *llrt;
        !           381:        struct llc_linkcb *linkp;
        !           382:        register int i;
        !           383: 
        !           384:        /* info must point to something valid at all times */
        !           385:        if (info == 0)
        !           386:                return 0;
        !           387: 
        !           388:        if (prc == PRC_IFUP || prc == PRC_IFDOWN) {
        !           389:                /* we use either this set ... */
        !           390:                ifa = ifa_ifwithaddr(addr);
        !           391:                ifp = ifa ? ifa->ifa_ifp : 0;
        !           392:                if (ifp == 0)
        !           393:                        return 0;
        !           394: 
        !           395:                sap = ctlinfo->dlcti_lsap;
        !           396:                config = ctlinfo->dlcti_cfg;
        !           397:                pcb = (caddr_t) 0;
        !           398:                nlrt = (struct rtentry *) 0;
        !           399:        } else {
        !           400:                /* or this one */
        !           401:                sap = 0; 
        !           402:                config = (struct dllconfig *) 0;
        !           403:                pcb = ctlinfo->dlcti_pcb;
        !           404:                nlrt = ctlinfo->dlcti_rt;
        !           405: 
        !           406:                if ((llrt = rtalloc1(nlrt->rt_gateway, 0)))
        !           407:                        llrt->rt_refcnt--;
        !           408:                else return 0;
        !           409: 
        !           410:                linkp = ((struct npaidbentry *)llrt->rt_llinfo)->np_link;
        !           411:        }
        !           412:        
        !           413:        switch (prc) {
        !           414:        case PRC_IFUP:
        !           415:                (void) llc_setsapinfo(ifp, addr->sa_family, sap, config);
        !           416:                return 0;
        !           417: 
        !           418:        case PRC_IFDOWN: {
        !           419:                register struct llc_linkcb *linkp;
        !           420:                register struct llc_linkcb *nlinkp;
        !           421:                register int i;
        !           422: 
        !           423:                /*
        !           424:                 * All links are accessible over the doubly linked list llccb_q
        !           425:                 */
        !           426:                if (!LQEMPTY) {
        !           427:                        /*
        !           428:                         * A for-loop is not that great an idea as the linkp
        !           429:                         * will get deleted by llc_timer()
        !           430:                         */
        !           431:                        linkp = LQFIRST;
        !           432:                        while (LQVALID(linkp)) {
        !           433:                                nlinkp = LQNEXT(linkp);
        !           434:                                if (linkp->llcl_if = ifp) {
        !           435:                                        i = splimp();
        !           436:                                        (void)llc_statehandler(linkp, (struct llc *)0,
        !           437:                                                               NL_DISCONNECT_REQUEST,
        !           438:                                                               0, 1);
        !           439:                                        splx(i);
        !           440:                                }
        !           441:                                linkp = nlinkp;
        !           442:                        }
        !           443:                }
        !           444:        }
        !           445:        
        !           446:        case PRC_CONNECT_REQUEST: 
        !           447:                if (linkp == 0) {
        !           448:                        if ((linkp = llc_newlink((struct sockaddr_dl *) nlrt->rt_gateway, 
        !           449:                                                 nlrt->rt_ifp, nlrt, 
        !           450:                                                 pcb, llrt)) == 0)
        !           451:                                return (0);
        !           452:                        ((struct npaidbentry *)llrt->rt_llinfo)->np_link = linkp;
        !           453:                        i = splimp();
        !           454:                        (void)llc_statehandler(linkp, (struct llc *) 0,
        !           455:                                                NL_CONNECT_REQUEST, 0, 1);
        !           456:                        splx(i);
        !           457:                }
        !           458:                return ((caddr_t)linkp);
        !           459:        
        !           460:        case PRC_DISCONNECT_REQUEST:
        !           461:                if (linkp == 0) 
        !           462:                        panic("no link control block!");
        !           463: 
        !           464:                i = splimp();
        !           465:                (void)llc_statehandler(linkp, (struct llc *) 0,
        !           466:                                       NL_DISCONNECT_REQUEST, 0, 1);
        !           467:                splx(i);
        !           468: 
        !           469:                /*
        !           470:                 * The actual removal of the link control block is done by the
        !           471:                 * cleaning neutrum (i.e. llc_timer()).
        !           472:                 */
        !           473:                break;
        !           474:        
        !           475:        case PRC_RESET_REQUEST:
        !           476:                if (linkp == 0) 
        !           477:                        panic("no link control block!");
        !           478: 
        !           479:                i = splimp();
        !           480:                (void)llc_statehandler(linkp, (struct llc *) 0,
        !           481:                                       NL_RESET_REQUEST, 0, 1);
        !           482:                splx(i);
        !           483: 
        !           484:                break;
        !           485: 
        !           486:        }
        !           487:        
        !           488:        return 0;
        !           489: }

unix.superglobalmegacorp.com

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