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

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

unix.superglobalmegacorp.com

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