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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * Copyright (C) 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.