Annotation of XNU/bsd/netccitt/llc_input.c, revision 1.1.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.