Annotation of XNU/bsd/netccitt/llc_subr.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_subr.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/socketvar.h>
                     70: #include <sys/errno.h>
                     71: #include <sys/time.h>
                     72: #include <sys/kernel.h>
                     73: #include <sys/malloc.h>
                     74: 
                     75: #include <net/if.h>
                     76: #include <net/if_dl.h>
                     77: #include <net/if_llc.h>
                     78: #include <net/route.h>
                     79: 
                     80: #include <netccitt/dll.h>
                     81: #include <netccitt/llc_var.h>
                     82: 
                     83: /*
                     84:  * Frame names for diagnostic messages
                     85:  */
                     86: char *frame_names[] = { "INFO", "RR", "RNR", "REJ", "DM", "SABME", "DISC",
                     87:        "UA", "FRMR", "UI", "XID", "TEST", "ILLEGAL", "TIMER", "N2xT1"};
                     88: 
                     89: 
                     90: /*
                     91:  * Trace level
                     92:  */
                     93: int llc_tracelevel = LLCTR_URGENT;
                     94: 
                     95: /*
                     96:  * Values for accessing various bitfields
                     97:  */
                     98: struct bitslice llc_bitslice[] = {
                     99: /*       mask, shift value */
                    100:        { 0x1,  0x0 },
                    101:        { 0xfe, 0x1 },
                    102:        { 0x3,  0x0 },
                    103:        { 0xc,  0x2 },
                    104:        { 0x10, 0x4 },
                    105:        { 0xe0, 0x5 },
                    106:        { 0x1f, 0x0 }
                    107: };
                    108: 
                    109: /*
                    110:  * We keep the link control blocks on a doubly linked list - 
                    111:  * primarily for checking in llc_time() 
                    112:  */
                    113: 
                    114: struct llccb_q llccb_q = { &llccb_q, &llccb_q };
                    115: 
                    116: /*
                    117:  * Flag for signalling wether route tree for AF_LINK has been
                    118:  * initialized yet.
                    119:  */
                    120: 
                    121: int af_link_rts_init_done = 0; 
                    122: 
                    123: 
                    124: /*
                    125:  * Functions dealing with struct sockaddr_dl */
                    126: 
                    127: /* Compare sdl_a w/ sdl_b */
                    128: 
                    129: sdl_cmp(struct sockaddr_dl *sdl_a, struct sockaddr_dl *sdl_b)
                    130: {
                    131:        if (LLADDRLEN(sdl_a) != LLADDRLEN(sdl_b))
                    132:                return(1);
                    133:        return(bcmp((caddr_t) sdl_a->sdl_data, (caddr_t) sdl_b->sdl_data,
                    134:                    LLADDRLEN(sdl_a)));
                    135: }
                    136: 
                    137: /* Copy sdl_f to sdl_t */
                    138: 
                    139: sdl_copy(struct sockaddr_dl *sdl_f, struct sockaddr_dl *sdl_t)
                    140: {
                    141:        bcopy((caddr_t) sdl_f, (caddr_t) sdl_t, sdl_f->sdl_len);
                    142: }
                    143: 
                    144: /* Swap sdl_a w/ sdl_b */
                    145: 
                    146: sdl_swapaddr(struct sockaddr_dl *sdl_a, struct sockaddr_dl *sdl_b)
                    147: {
                    148:        struct sockaddr_dl sdl_tmp;
                    149: 
                    150:        sdl_copy(sdl_a, &sdl_tmp); 
                    151:        sdl_copy(sdl_b, sdl_a); 
                    152:        sdl_copy(&sdl_tmp, sdl_b);
                    153: }
                    154: 
                    155: /* Fetch the sdl of the associated if */
                    156: 
                    157: struct sockaddr_dl * 
                    158: sdl_getaddrif(struct ifnet *ifp)
                    159: {
                    160:        register struct ifaddr *ifa;
                    161: 
                    162:        for(ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)   
                    163:                if (ifa->ifa_addr->sa_family == AF_LINK )               
                    164:                        return((struct sockaddr_dl *)(ifa->ifa_addr));
                    165: 
                    166:        return((struct sockaddr_dl *)0);
                    167: }
                    168: 
                    169: /* Check addr of interface with the one given */
                    170: 
                    171: sdl_checkaddrif(struct ifnet *ifp, struct sockaddr_dl *sdl_c)
                    172: {
                    173:        register struct ifaddr *ifa;
                    174: 
                    175:        for(ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)   
                    176:                if ((ifa->ifa_addr->sa_family == AF_LINK ) &&    
                    177:                    !sdl_cmp((struct sockaddr_dl *)(ifa->ifa_addr), sdl_c))
                    178:                        return(1);
                    179:        
                    180:        return(0);
                    181: }
                    182: 
                    183: /* Build an sdl from MAC addr, DLSAP addr, and interface */
                    184: 
                    185: sdl_setaddrif(struct ifnet *ifp, u_char *mac_addr, u_char dlsap_addr, 
                    186:              u_char mac_len, struct sockaddr_dl *sdl_to)
                    187: {
                    188:        register struct sockaddr_dl *sdl_tmp;
                    189: 
                    190:        if ((sdl_tmp = sdl_getaddrif(ifp)) ) {  
                    191:                sdl_copy(sdl_tmp, sdl_to);      
                    192:                bcopy((caddr_t) mac_addr, (caddr_t) LLADDR(sdl_to), mac_len);
                    193:                *(LLADDR(sdl_to)+mac_len) = dlsap_addr;
                    194:                sdl_to->sdl_alen = mac_len+1;   
                    195:                return(1); 
                    196:        } else return(0);
                    197: }
                    198: 
                    199: /* Fill out the sdl header aggregate */
                    200: 
                    201: sdl_sethdrif(struct ifnet *ifp, u_char *mac_src, u_char dlsap_src, u_char *mac_dst,
                    202:             u_char dlsap_dst, u_char mac_len, struct sdl_hdr *sdlhdr_to)
                    203: {
                    204:        if ( !sdl_setaddrif(ifp, mac_src, dlsap_src, mac_len,
                    205:                             &sdlhdr_to->sdlhdr_src) ||
                    206:             !sdl_setaddrif(ifp, mac_dst, dlsap_dst, mac_len,
                    207:                             &sdlhdr_to->sdlhdr_dst) )
                    208:                return(0);
                    209:        else return(1);
                    210: }
                    211: 
                    212: static struct sockaddr_dl sap_saddr; 
                    213: static struct sockaddr_dl sap_sgate = {
                    214:        sizeof(struct sockaddr_dl), /* _len */ 
                    215:        AF_LINK                     /* _af */
                    216: };
                    217: 
                    218: /*
                    219:  * Set sapinfo for SAP address, llcconfig, af, and interface
                    220:  */
                    221: struct npaidbentry *
                    222: llc_setsapinfo(struct ifnet *ifp, u_char af, u_char sap, struct dllconfig *llconf)
                    223: {
                    224:        struct protosw *pp; 
                    225:        struct sockaddr_dl *ifdl_addr; 
                    226:        struct rtentry *sirt = (struct rtentry *)0; 
                    227:        struct npaidbentry *sapinfo; 
                    228:        u_char saploc; 
                    229:        int size = sizeof(struct npaidbentry);
                    230: 
                    231:        USES_AF_LINK_RTS;
                    232: 
                    233:        /* 
                    234:         * We rely/assume that only STREAM protocols will make use of 
                    235:         * connection oriented LLC2. If this will one day not be the 
                    236:         * case this will obviously fail. 
                    237:         */ 
                    238:        pp = pffindtype (af, SOCK_STREAM); 
                    239:        if (pp == 0 || pp->pr_input == 0 || pp->pr_ctlinput == 0) {     
                    240:                printf("network level protosw error");  
                    241:                return 0; 
                    242:        }
                    243: 
                    244:        /*
                    245:         * We need a way to jot down the LLC2 configuration for
                    246:         * a certain LSAP address. To do this we enter 
                    247:         * a "route" for the SAP.
                    248:         */
                    249:        ifdl_addr = sdl_getaddrif(ifp);
                    250:        sdl_copy(ifdl_addr, &sap_saddr); 
                    251:        sdl_copy(ifdl_addr, &sap_sgate);
                    252:        saploc = LLSAPLOC(&sap_saddr, ifp); 
                    253:        sap_saddr.sdl_data[saploc] = sap;
                    254:        sap_saddr.sdl_alen++;
                    255: 
                    256:        /* now enter it */ 
                    257:        rtrequest(RTM_ADD, (struct sockaddr *)&sap_saddr,
                    258:                        (struct sockaddr *)&sap_sgate, 0, 0, &sirt); 
                    259:        if (sirt == 0)  
                    260:                return 0;
                    261: 
                    262:        /* Plug in config information in rt->rt_llinfo */
                    263: 
                    264: //     sirt->rt_llinfo = malloc(size , M_PCB, M_WAITOK); 
                    265:        MALLOC(sirt->rt_llinfo, caddr_t, size, M_PCB, M_WAITOK);
                    266:        sapinfo = (struct npaidbentry *) sirt->rt_llinfo; 
                    267:        if (sapinfo) {  
                    268:                bzero ((caddr_t)sapinfo, size);         
                    269:                /*       
                    270:                 * For the time being we support LLC CLASS II here       
                    271:                 * only          
                    272:                 */     
                    273:                sapinfo->si_class = LLC_CLASS_II;       
                    274:                sapinfo->si_window = llconf->dllcfg_window;
                    275:                sapinfo->si_trace = llconf->dllcfg_trace;       
                    276:                if (sapinfo->si_trace)
                    277:                        llc_tracelevel--;
                    278:                else llc_tracelevel++;
                    279:                sapinfo->si_input = pp->pr_input;       
                    280:                sapinfo->si_ctlinput = (caddr_t (*)())pp->pr_ctlinput;
                    281: 
                    282:                return (sapinfo);
                    283:        }
                    284: 
                    285:        return 0;
                    286: }
                    287: 
                    288: /*
                    289:  * Get sapinfo for SAP address and interface 
                    290:  */
                    291: struct npaidbentry *
                    292: llc_getsapinfo(u_char sap, struct ifnet *ifp)
                    293: {
                    294:        struct sockaddr_dl *ifdl_addr; 
                    295:        struct sockaddr_dl si_addr; 
                    296:        struct rtentry *sirt; 
                    297:        u_char saploc;
                    298: 
                    299:        USES_AF_LINK_RTS;
                    300: 
                    301:        ifdl_addr = sdl_getaddrif(ifp); 
                    302:        sdl_copy(ifdl_addr, &si_addr); 
                    303:        saploc = LLSAPLOC(&si_addr, ifp); 
                    304:        si_addr.sdl_data[saploc] = sap;
                    305:        si_addr.sdl_alen++;
                    306: 
                    307:        if ((sirt = rtalloc1((struct sockaddr *)&si_addr, 0)))  
                    308:                sirt->rt_refcnt--; 
                    309:        else return(0);
                    310: 
                    311:        return((struct npaidbentry *)sirt->rt_llinfo);
                    312: }
                    313: 
                    314: /*
                    315:  * llc_seq2slot() --- We only allocate enough memory to hold the window. This
                    316:  * introduces the necessity to keep track of two ``pointers''
                    317:  *
                    318:  *        o llcl_freeslot     the next free slot to be used
                    319:  *                            this one advances modulo llcl_window
                    320:  *        o llcl_projvs       the V(S) associated with the next frame
                    321:  *                            to be set via llcl_freeslot
                    322:  *                            this one advances modulo LLC_MAX_SEQUENCE
                    323:  *
                    324:  * A new frame is inserted at llcl_output_buffers[llcl_freeslot], after
                    325:  * which both llcl_freeslot and llcl_projvs are incremented.
                    326:  *
                    327:  * The slot sl(sn) for any given sequence number sn is given by
                    328:  *
                    329:  *        sl(sn) = (llcl_freeslot + llcl_window - 1 - (llcl_projvs +
                    330:  *                  LLC_MAX_SEQUENCE- sn) % LLC_MAX_SEQUENCE) % 
                    331:  *                  llcl_window 
                    332:  *
                    333:  * i.e. we first calculate the number of frames we need to ``go back''
                    334:  * from the current one (really the next one, but that doesn't matter as
                    335:  * llcl_projvs is likewise of by plus one) and subtract that from the
                    336:  * pointer to the most recently taken frame (llcl_freeslot - 1).
                    337:  */
                    338: 
                    339: short
                    340: llc_seq2slot(struct llc_linkcb *linkp, short seqn)
                    341: {
                    342:        register sn = 0;
                    343: 
                    344:        sn = (linkp->llcl_freeslot + linkp->llcl_window - 
                    345:              (linkp->llcl_projvs + LLC_MAX_SEQUENCE - seqn) % 
                    346:              LLC_MAX_SEQUENCE) % linkp->llcl_window;
                    347: 
                    348:        return sn;
                    349: }
                    350: 
                    351: /*
                    352:  * LLC2 link state handler
                    353:  *
                    354:  * There is in most cases one function per LLC2 state. The LLC2 standard
                    355:  * ISO 8802-2 allows in some cases for ambiguities, i.e. we have the choice
                    356:  * to do one thing or the other. Right now I have just chosen one but have also 
                    357:  * indicated the spot by "multiple possibilities". One could make the behavior 
                    358:  * in those cases configurable, allowing the superuser to enter a profile word
                    359:  * (32/64 bits, whatever is needed) that would suit her needs [I quite like 
                    360:  * that idea, perhaps I'll get around to it].
                    361:  *
                    362:  * [Preceeding each state handler function is the description as taken from
                    363:  * ISO 8802-2, section 7.9.2.1]
                    364:  */
                    365: 
                    366: /*
                    367:  * ADM --- The connection component is in the asynchronous disconnected mode.
                    368:  *         It can accept an SABME PDU from a remote LLC SSAP or, at the request
                    369:  *         of the service access point user, can initiate an SABME PDU
                    370:  *         transmission to a remote LLC DSAP, to establish a data link
                    371:  *         connection. It also responds to a DISC command PDU and to any
                    372:  *         command PDU with the P bit set to ``1''.
                    373:  */
                    374: int
                    375: llc_state_ADM(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    376:              int cmdrsp, int pollfinal)
                    377: {
                    378:        int action = 0;
                    379: 
                    380:        switch(frame_kind + cmdrsp) {
                    381:        case NL_CONNECT_REQUEST:
                    382:                llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
                    383:                LLC_SETFLAG(linkp, P, pollfinal);
                    384:                LLC_SETFLAG(linkp, S, 0);
                    385:                linkp->llcl_retry = 0;
                    386:                LLC_NEWSTATE(linkp, SETUP);
                    387:                break;
                    388:        case LLCFT_SABME + LLC_CMD:
                    389:                /* 
                    390:                 * ISO 8802-2, table 7-1, ADM state says to set
                    391:                 * the P flag, yet this will cause an SABME [P] to be
                    392:                 * answered with an UA only, not an UA [F], all
                    393:                 * other `disconnected' states set the F flag, so ...
                    394:                 */
                    395:                LLC_SETFLAG(linkp, F, pollfinal);
                    396:                LLC_NEWSTATE(linkp, CONN);
                    397:                action = LLC_CONNECT_INDICATION;
                    398:                break;
                    399:        case LLCFT_DISC + LLC_CMD:
                    400:                llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
                    401:                break;
                    402:        default:
                    403:                if (cmdrsp == LLC_CMD && pollfinal == 1) 
                    404:                        llc_send(linkp, LLCFT_DM, LLC_RSP, 1);
                    405:                /* remain in ADM state */
                    406:        }
                    407: 
                    408:        return action;
                    409: }
                    410: 
                    411: /*
                    412:  * CONN --- The local connection component has received an SABME PDU from a
                    413:  *          remote LLC SSAP, and it is waiting for the local user to accept or
                    414:  *          refuse the connection.
                    415:  */
                    416: int
                    417: llc_state_CONN(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    418:               int cmdrsp, int pollfinal)
                    419: {
                    420:        int action = 0;
                    421: 
                    422:        switch(frame_kind + cmdrsp) {
                    423:        case NL_CONNECT_RESPONSE:
                    424:                llc_send(linkp, LLCFT_UA, LLC_RSP, LLC_GETFLAG(linkp, F));
                    425:                LLC_RESETCOUNTER(linkp);
                    426:                LLC_SETFLAG(linkp, P, 0);
                    427:                LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
                    428:                LLC_NEWSTATE(linkp, NORMAL);
                    429:                break;
                    430:        case NL_DISCONNECT_REQUEST:
                    431:                llc_send(linkp, LLCFT_DM, LLC_RSP, LLC_GETFLAG(linkp, F));
                    432:                LLC_NEWSTATE(linkp, ADM);
                    433:                break;
                    434:        case LLCFT_SABME + LLC_CMD:
                    435:                LLC_SETFLAG(linkp, F, pollfinal);
                    436:                break;
                    437:        case LLCFT_DM + LLC_RSP:
                    438:                LLC_NEWSTATE(linkp, ADM);
                    439:                action = LLC_DISCONNECT_INDICATION;
                    440:                break;
                    441:        /* all other frames effect nothing here */
                    442:        }
                    443: 
                    444:        return action;
                    445: }
                    446: 
                    447: /*
                    448:  * RESET_WAIT --- The local connection component is waiting for the local user
                    449:  *                 to indicate a RESET_REQUEST or a DISCONNECT_REQUEST.  
                    450:  */
                    451: int
                    452: llc_state_RESET_WAIT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    453:                     int cmdrsp, int pollfinal)
                    454: {
                    455:        int action = 0;
                    456: 
                    457:        switch(frame_kind + cmdrsp) {
                    458:        case NL_RESET_REQUEST:
                    459:                if (LLC_GETFLAG(linkp, S) == 0) {
                    460:                        llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
                    461:                        LLC_SETFLAG(linkp, P, pollfinal);
                    462:                        LLC_START_ACK_TIMER(linkp);
                    463:                        linkp->llcl_retry = 0;
                    464:                        LLC_NEWSTATE(linkp, RESET);
                    465:                } else {
                    466:                        llc_send(linkp, LLCFT_UA, LLC_RSP, 
                    467:                                      LLC_GETFLAG(linkp, F));
                    468:                        LLC_RESETCOUNTER(linkp);
                    469:                        LLC_SETFLAG(linkp, P, 0);
                    470:                        LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
                    471:                        LLC_NEWSTATE(linkp, NORMAL);
                    472:                        action = LLC_RESET_CONFIRM;
                    473:                }
                    474:                break;
                    475:        case NL_DISCONNECT_REQUEST:
                    476:                if (LLC_GETFLAG(linkp, S) == 0) {
                    477:                        llc_send(linkp, LLCFT_DISC, LLC_CMD, pollfinal);
                    478:                        LLC_SETFLAG(linkp, P, pollfinal);
                    479:                        LLC_START_ACK_TIMER(linkp);
                    480:                        linkp->llcl_retry = 0;
                    481:                        LLC_NEWSTATE(linkp, D_CONN);
                    482:                } else {
                    483:                        llc_send(linkp, LLCFT_DM, LLC_RSP, 
                    484:                                      LLC_GETFLAG(linkp, F));
                    485:                        LLC_NEWSTATE(linkp, ADM);
                    486:                }
                    487:                break;
                    488:        case LLCFT_DM + LLC_RSP:
                    489:                LLC_NEWSTATE(linkp, ADM);
                    490:                action = LLC_DISCONNECT_INDICATION;
                    491:                break;
                    492:        case LLCFT_SABME + LLC_CMD:
                    493:                LLC_SETFLAG(linkp, S, 1);
                    494:                LLC_SETFLAG(linkp, F, pollfinal);
                    495:                break;
                    496:        case LLCFT_DISC + LLC_CMD:
                    497:                llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
                    498:                LLC_NEWSTATE(linkp, ADM);
                    499:                action = LLC_DISCONNECT_INDICATION;
                    500:                break;
                    501:        }
                    502: 
                    503:        return action;
                    504: }
                    505: 
                    506: /*
                    507:  * RESET_CHECK --- The local connection component is waiting for the local user
                    508:  *                 to accept or refuse a remote reset request.
                    509:  */
                    510: int
                    511: llc_state_RESET_CHECK(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    512:                      int cmdrsp, int pollfinal)
                    513: {
                    514:        int action = 0;
                    515: 
                    516:        switch(frame_kind + cmdrsp) {
                    517:        case NL_RESET_RESPONSE:
                    518:                llc_send(linkp, LLCFT_UA, LLC_RSP, LLC_GETFLAG(linkp, F));
                    519:                LLC_RESETCOUNTER(linkp);
                    520:                LLC_SETFLAG(linkp, P, 0);
                    521:                LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
                    522:                LLC_NEWSTATE(linkp, NORMAL);
                    523:                break;
                    524:        case NL_DISCONNECT_REQUEST:
                    525:                llc_send(linkp, LLCFT_DM, LLC_RSP, LLC_GETFLAG(linkp, F));
                    526:                LLC_NEWSTATE(linkp, ADM);
                    527:                break;
                    528:        case LLCFT_DM + LLC_RSP:
                    529:                action = LLC_DISCONNECT_INDICATION;
                    530:                break;
                    531:        case LLCFT_SABME + LLC_CMD:
                    532:                LLC_SETFLAG(linkp, F, pollfinal);
                    533:                break;
                    534:        case LLCFT_DISC + LLC_CMD:
                    535:                llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
                    536:                LLC_NEWSTATE(linkp, ADM);
                    537:                action = LLC_DISCONNECT_INDICATION;
                    538:                break;
                    539:        }
                    540: 
                    541:        return action;
                    542: }
                    543: 
                    544: /*
                    545:  * SETUP --- The connection component has transmitted an SABME command PDU to a
                    546:  *           remote LLC DSAP and is waiting for a reply.
                    547:  */
                    548: int
                    549: llc_state_SETUP(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    550:                int cmdrsp, int pollfinal)
                    551: {
                    552:        int action = 0;
                    553: 
                    554:        switch(frame_kind + cmdrsp) {
                    555:        case LLCFT_SABME + LLC_CMD:
                    556:                LLC_RESETCOUNTER(linkp);
                    557:                llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
                    558:                LLC_SETFLAG(linkp, S, 1);
                    559:                break;
                    560:        case LLCFT_UA + LLC_RSP:
                    561:                if (LLC_GETFLAG(linkp, P) == pollfinal) {
                    562:                        LLC_STOP_ACK_TIMER(linkp);
                    563:                        LLC_RESETCOUNTER(linkp);
                    564:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                    565:                        LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
                    566:                        LLC_NEWSTATE(linkp, NORMAL);
                    567:                        action = LLC_CONNECT_CONFIRM;
                    568:                }
                    569:                break;
                    570:        case LLC_ACK_TIMER_EXPIRED:
                    571:                if (LLC_GETFLAG(linkp, S) == 1) {
                    572:                        LLC_SETFLAG(linkp, P, 0);
                    573:                        LLC_SETFLAG(linkp, REMOTE_BUSY, 0),
                    574:                        LLC_NEWSTATE(linkp, NORMAL);
                    575:                        action = LLC_CONNECT_CONFIRM;
                    576:                } else if (linkp->llcl_retry < llc_n2) {
                    577:                        llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
                    578:                        LLC_SETFLAG(linkp, P, pollfinal);
                    579:                        LLC_START_ACK_TIMER(linkp);
                    580:                        linkp->llcl_retry++;
                    581:                } else {
                    582:                        LLC_NEWSTATE(linkp, ADM);
                    583:                        action = LLC_DISCONNECT_INDICATION;
                    584:                }
                    585:                break;
                    586:        case LLCFT_DISC + LLC_CMD:
                    587:                llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
                    588:                LLC_STOP_ACK_TIMER(linkp);
                    589:                LLC_NEWSTATE(linkp, ADM);
                    590:                action = LLC_DISCONNECT_INDICATION;
                    591:                break;
                    592:        case LLCFT_DM + LLC_RSP:
                    593:                LLC_STOP_ACK_TIMER(linkp);
                    594:                LLC_NEWSTATE(linkp, ADM);
                    595:                action = LLC_DISCONNECT_INDICATION;
                    596:                break;
                    597:        }
                    598: 
                    599:        return action;
                    600: }
                    601: 
                    602: /*
                    603:  * RESET --- As a result of a service access point user request or the receipt
                    604:  *           of a FRMR response PDU, the local connection component has sent an
                    605:  *           SABME command PDU to the remote LLC DSAP to reset the data link
                    606:  *           connection and is waiting for a reply.
                    607:  */
                    608: int
                    609: llc_state_RESET(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    610:                int cmdrsp, int pollfinal)
                    611: {
                    612:        int action = 0;
                    613: 
                    614:        switch(frame_kind + cmdrsp) {
                    615:        case LLCFT_SABME + LLC_CMD:
                    616:                LLC_RESETCOUNTER(linkp);
                    617:                LLC_SETFLAG(linkp, S, 1);
                    618:                llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
                    619:                break;
                    620:        case LLCFT_UA + LLC_RSP:
                    621:                if (LLC_GETFLAG(linkp, P) == pollfinal) {
                    622:                        LLC_STOP_ACK_TIMER(linkp);
                    623:                        LLC_RESETCOUNTER(linkp);
                    624:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                    625:                        LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
                    626:                        LLC_NEWSTATE(linkp, NORMAL);
                    627:                        action = LLC_RESET_CONFIRM;
                    628:                }
                    629:                break;
                    630:        case LLC_ACK_TIMER_EXPIRED:
                    631:                if (LLC_GETFLAG(linkp, S) == 1) {
                    632:                        LLC_SETFLAG(linkp, P, 0);
                    633:                        LLC_SETFLAG(linkp, REMOTE_BUSY, 0);
                    634:                        LLC_NEWSTATE(linkp, NORMAL);
                    635:                        action = LLC_RESET_CONFIRM;
                    636:                } else if (linkp->llcl_retry < llc_n2) {
                    637:                        llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
                    638:                        LLC_SETFLAG(linkp, P, pollfinal);
                    639:                        LLC_START_ACK_TIMER(linkp);
                    640:                        linkp->llcl_retry++;
                    641:                } else {
                    642:                        LLC_NEWSTATE(linkp, ADM);
                    643:                        action = LLC_DISCONNECT_INDICATION;
                    644:                }
                    645:                break;
                    646:        case LLCFT_DISC + LLC_CMD:
                    647:                llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
                    648:                LLC_STOP_ACK_TIMER(linkp);
                    649:                LLC_NEWSTATE(linkp, ADM);
                    650:                action = LLC_DISCONNECT_INDICATION;
                    651:                break;
                    652:        case LLCFT_DM + LLC_RSP:
                    653:                LLC_STOP_ACK_TIMER(linkp);
                    654:                LLC_NEWSTATE(linkp, ADM);
                    655:                action = LLC_DISCONNECT_INDICATION;
                    656:                break;
                    657:        }
                    658: 
                    659:        return action;
                    660: }
                    661: 
                    662: /*
                    663:  * D_CONN --- At the request of the service access point user, the local LLC
                    664:  *            has sent a DISC command PDU to the remote LLC DSAP and is waiting
                    665:  *            for a reply.
                    666:  */
                    667: int
                    668: llc_state_D_CONN(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    669:                 int cmdrsp, int pollfinal)
                    670: {
                    671:        int action = 0;
                    672: 
                    673:        switch(frame_kind + cmdrsp) {
                    674:        case LLCFT_SABME + LLC_CMD:
                    675:                llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);
                    676:                LLC_STOP_ACK_TIMER(linkp);
                    677:                LLC_NEWSTATE(linkp, ADM);
                    678:                break;
                    679:        case LLCFT_UA + LLC_RSP:
                    680:                if (LLC_GETFLAG(linkp, P) == pollfinal) {
                    681:                        LLC_STOP_ACK_TIMER(linkp);
                    682:                        LLC_NEWSTATE(linkp, ADM);
                    683:                }
                    684:                break;
                    685:        case LLCFT_DISC + LLC_CMD:
                    686:                llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
                    687:                break;
                    688:        case LLCFT_DM + LLC_RSP:
                    689:                LLC_STOP_ACK_TIMER(linkp);
                    690:                LLC_NEWSTATE(linkp, ADM);
                    691:                break;
                    692:        case LLC_ACK_TIMER_EXPIRED:
                    693:                if (linkp->llcl_retry < llc_n2) {
                    694:                        llc_send(linkp, LLCFT_DISC, LLC_CMD, pollfinal);
                    695:                        LLC_SETFLAG(linkp, P, pollfinal);
                    696:                        LLC_START_ACK_TIMER(linkp);
                    697:                        linkp->llcl_retry++;
                    698:                } else LLC_NEWSTATE(linkp, ADM);
                    699:                break;
                    700:        }
                    701: 
                    702:        return action;
                    703: }
                    704: 
                    705: /*
                    706:  * ERROR --- The local connection component has detected an error in a received
                    707:  *           PDU and has sent a FRMR response PDU. It is waiting for a reply from 
                    708:  *           the remote connection component.
                    709:  */
                    710: int
                    711: llc_state_ERROR(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    712:                int cmdrsp, int pollfinal)
                    713: {
                    714:        int action = 0;
                    715: 
                    716:        switch(frame_kind + cmdrsp) {
                    717:        case LLCFT_SABME + LLC_CMD:
                    718:                LLC_STOP_ACK_TIMER(linkp);
                    719:                LLC_NEWSTATE(linkp, RESET_CHECK);
                    720:                action = LLC_RESET_INDICATION_REMOTE;
                    721:                break;
                    722:        case LLCFT_DISC + LLC_CMD:
                    723:                llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
                    724:                LLC_STOP_ACK_TIMER(linkp);
                    725:                LLC_NEWSTATE(linkp, ADM);
                    726:                action = LLC_DISCONNECT_INDICATION;
                    727:                break;
                    728:        case LLCFT_DM + LLC_RSP:
                    729:                LLC_STOP_ACK_TIMER(linkp);
                    730:                LLC_NEWSTATE(linkp, ADM);
                    731:                action = LLC_DISCONNECT_INDICATION;
                    732:                break;
                    733:        case LLCFT_FRMR + LLC_RSP:
                    734:                LLC_STOP_ACK_TIMER(linkp);
                    735:                LLC_SETFLAG(linkp, S, 0);
                    736:                LLC_NEWSTATE(linkp, RESET_WAIT);
                    737:                action = LLC_FRMR_RECEIVED;
                    738:                break;
                    739:        case LLC_ACK_TIMER_EXPIRED:
                    740:                if (linkp->llcl_retry < llc_n2) {
                    741:                        llc_send(linkp, LLCFT_FRMR, LLC_RSP, 0);
                    742:                        LLC_START_ACK_TIMER(linkp);
                    743:                        linkp->llcl_retry++;
                    744:                } else {
                    745:                        LLC_SETFLAG(linkp, S, 0);
                    746:                        LLC_NEWSTATE(linkp, RESET_WAIT);
                    747:                        action = LLC_RESET_INDICATION_LOCAL;
                    748:                }
                    749:                break;
                    750:        default:
                    751:                if (cmdrsp == LLC_CMD){
                    752:                        llc_send(linkp, LLCFT_FRMR, LLC_RSP, pollfinal);
                    753:                        LLC_START_ACK_TIMER(linkp);
                    754:                }
                    755:                break;
                    756: 
                    757:        }
                    758: 
                    759:        return action;
                    760: }
                    761: 
                    762: /*
                    763:  * NORMAL, BUSY, REJECT, AWAIT, AWAIT_BUSY, and AWAIT_REJECT all share
                    764:  * a common core state handler.
                    765:  */
                    766: int
                    767: llc_state_NBRAcore(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    768:                   int cmdrsp, int pollfinal)
                    769: {
                    770:        int action = 0;
                    771: 
                    772:        switch(frame_kind + cmdrsp) {
                    773:        case NL_DISCONNECT_REQUEST:
                    774:                llc_send(linkp, LLCFT_DISC, LLC_CMD, pollfinal);
                    775:                LLC_SETFLAG(linkp, P, pollfinal);
                    776:                LLC_STOP_ALL_TIMERS(linkp);
                    777:                LLC_START_ACK_TIMER(linkp);
                    778:                linkp->llcl_retry = 0;
                    779:                LLC_NEWSTATE(linkp, D_CONN);
                    780:                break;
                    781:        case NL_RESET_REQUEST:
                    782:                llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);
                    783:                LLC_SETFLAG(linkp, P, pollfinal);
                    784:                LLC_STOP_ALL_TIMERS(linkp);
                    785:                LLC_START_ACK_TIMER(linkp);
                    786:                linkp->llcl_retry = 0;
                    787:                LLC_SETFLAG(linkp, S, 0);
                    788:                LLC_NEWSTATE(linkp, RESET);
                    789:                break;
                    790:        case LLCFT_SABME + LLC_CMD:
                    791:                LLC_SETFLAG(linkp, F, pollfinal);
                    792:                LLC_STOP_ALL_TIMERS(linkp);
                    793:                LLC_NEWSTATE(linkp, RESET_CHECK);
                    794:                action = LLC_RESET_INDICATION_REMOTE;
                    795:                break;
                    796:        case LLCFT_DISC + LLC_CMD:
                    797:                llc_send(linkp, LLCFT_UA, LLC_RSP, pollfinal);
                    798:                LLC_STOP_ALL_TIMERS(linkp);
                    799:                LLC_NEWSTATE(linkp, ADM);
                    800:                action = LLC_DISCONNECT_INDICATION;
                    801:                break;
                    802:        case LLCFT_FRMR + LLC_RSP:
                    803:                LLC_STOP_ALL_TIMERS(linkp);
                    804:                LLC_SETFLAG(linkp, S, 0);
                    805:                LLC_NEWSTATE(linkp, RESET_WAIT);
                    806:                action =  LLC_FRMR_RECEIVED;
                    807:                break;
                    808:        case LLCFT_DM + LLC_RSP:
                    809:                LLC_STOP_ALL_TIMERS(linkp);
                    810:                LLC_NEWSTATE(linkp, ADM);
                    811:                action = LLC_DISCONNECT_INDICATION;
                    812:                break;
                    813:        case LLC_INVALID_NR + LLC_CMD:
                    814:        case LLC_INVALID_NS + LLC_CMD:
                    815:                LLC_SETFRMR(linkp, frame, cmdrsp, 
                    816:                         (frame_kind == LLC_INVALID_NR ? LLC_FRMR_Z :
                    817:                          (LLC_FRMR_V | LLC_FRMR_W)));
                    818:                llc_send(linkp, LLCFT_FRMR, LLC_RSP, pollfinal);
                    819:                LLC_STOP_ALL_TIMERS(linkp);
                    820:                LLC_START_ACK_TIMER(linkp);
                    821:                linkp->llcl_retry = 0;
                    822:                LLC_NEWSTATE(linkp, ERROR);
                    823:                action = LLC_FRMR_SENT;
                    824:                break;
                    825:        case LLC_INVALID_NR + LLC_RSP:
                    826:        case LLC_INVALID_NS + LLC_RSP:
                    827:        case LLCFT_UA + LLC_RSP:
                    828:        case LLC_BAD_PDU: {
                    829:                char frmrcause = 0;
                    830: 
                    831:                switch (frame_kind) {
                    832:                case LLC_INVALID_NR: frmrcause = LLC_FRMR_Z; break;
                    833:                case LLC_INVALID_NS: frmrcause = LLC_FRMR_V | LLC_FRMR_W; break;
                    834:                default: frmrcause = LLC_FRMR_W;
                    835:                }
                    836:                LLC_SETFRMR(linkp, frame, cmdrsp, frmrcause);
                    837:                llc_send(linkp, LLCFT_FRMR, LLC_RSP, 0);
                    838:                LLC_STOP_ALL_TIMERS(linkp);
                    839:                LLC_START_ACK_TIMER(linkp);
                    840:                linkp->llcl_retry = 0;
                    841:                LLC_NEWSTATE(linkp, ERROR);
                    842:                action = LLC_FRMR_SENT;
                    843:                break;
                    844:        }
                    845:        default:
                    846:                if (cmdrsp == LLC_RSP && pollfinal == 1 && 
                    847:                    LLC_GETFLAG(linkp, P) == 0) {
                    848:                        LLC_SETFRMR(linkp, frame, cmdrsp, LLC_FRMR_W);
                    849:                        LLC_STOP_ALL_TIMERS(linkp);
                    850:                        LLC_START_ACK_TIMER(linkp);
                    851:                        linkp->llcl_retry = 0;
                    852:                        LLC_NEWSTATE(linkp, ERROR);
                    853:                        action = LLC_FRMR_SENT;
                    854:                }
                    855:                break;
                    856:        case LLC_P_TIMER_EXPIRED:
                    857:        case LLC_ACK_TIMER_EXPIRED:
                    858:        case LLC_REJ_TIMER_EXPIRED:
                    859:        case LLC_BUSY_TIMER_EXPIRED:
                    860:                if (linkp->llcl_retry >= llc_n2) {
                    861:                        LLC_STOP_ALL_TIMERS(linkp);
                    862:                        LLC_SETFLAG(linkp, S, 0);
                    863:                        LLC_NEWSTATE(linkp, RESET_WAIT);
                    864:                        action = LLC_RESET_INDICATION_LOCAL;
                    865:                }
                    866:                break;
                    867:        }
                    868: 
                    869:        return action;
                    870: }
                    871: 
                    872: /*
                    873:  * NORMAL --- A data link connection exists between the local LLC service access
                    874:  *            point and the remote LLC service access point. Sending and
                    875:  *            reception of information and supervisory PDUs can be performed.
                    876:  */
                    877: int
                    878: llc_state_NORMAL(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                    879:                 int cmdrsp, int pollfinal)
                    880: {
                    881:        int action = LLC_PASSITON;
                    882: 
                    883:        switch(frame_kind + cmdrsp) {
                    884:        case NL_DATA_REQUEST:
                    885:                if (LLC_GETFLAG(linkp, REMOTE_BUSY) == 0) {
                    886: #ifdef not_now
                    887:                        if (LLC_GETFLAG(linkp, P) == 0) {
                    888:                                /* multiple possibilities */
                    889:                                llc_send(linkp, LLCFT_INFO, LLC_CMD, 1);
                    890:                                LLC_START_P_TIMER(linkp);
                    891:                                if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
                    892:                                        LLC_START_ACK_TIMER(linkp);
                    893:                        } else {
                    894: #endif 
                    895:                                /* multiple possibilities */
                    896:                                llc_send(linkp, LLCFT_INFO, LLC_CMD, 0);
                    897:                                if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
                    898:                                        LLC_START_ACK_TIMER(linkp);
                    899: #ifdef not_now
                    900:                        }
                    901: #endif
                    902:                        action = 0;
                    903:                }
                    904:                break;
                    905:        case LLC_LOCAL_BUSY_DETECTED:
                    906:                if (LLC_GETFLAG(linkp, P) == 0) {
                    907:                        /* multiple possibilities --- action-wise */
                    908:                        /* multiple possibilities --- CMD/RSP-wise */
                    909:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                    910:                        LLC_START_P_TIMER(linkp);
                    911:                        LLC_SETFLAG(linkp, DATA, 0);
                    912:                        LLC_NEWSTATE(linkp, BUSY);
                    913:                        action = 0;
                    914:                } else { 
                    915:                        /* multiple possibilities --- CMD/RSP-wise */
                    916:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                    917:                        LLC_SETFLAG(linkp, DATA, 0);
                    918:                        LLC_NEWSTATE(linkp, BUSY);
                    919:                        action = 0;                     
                    920:                }
                    921:                break;
                    922:        case LLC_INVALID_NS + LLC_CMD:
                    923:        case LLC_INVALID_NS + LLC_RSP: {
                    924:                register int p = LLC_GETFLAG(linkp, P);
                    925:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                    926: 
                    927:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                    928:                        llc_send(linkp, LLCFT_REJ, LLC_RSP, 1);
                    929:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    930:                        LLC_START_REJ_TIMER(linkp);
                    931:                        LLC_NEWSTATE(linkp, REJECT);
                    932:                        action = 0;
                    933:                } else if (pollfinal == 0 && p == 1) {
                    934:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
                    935:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    936:                        LLC_START_REJ_TIMER(linkp);
                    937:                        LLC_NEWSTATE(linkp, REJECT);
                    938:                        action = 0;
                    939:                } else if ((pollfinal == 0 && p == 0) || 
                    940:                           (pollfinal == 1 && p == 1 && cmdrsp == LLC_RSP)) {
                    941:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
                    942:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    943:                        LLC_START_P_TIMER(linkp);
                    944:                        LLC_START_REJ_TIMER(linkp);
                    945:                        if (cmdrsp == LLC_RSP && pollfinal == 1) {
                    946:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                    947:                        } else action = 0;
                    948:                        LLC_NEWSTATE(linkp, REJECT);
                    949:                }
                    950:                break;
                    951:        } 
                    952:        case LLCFT_INFO + LLC_CMD:
                    953:        case LLCFT_INFO + LLC_RSP: {
                    954:                register int p = LLC_GETFLAG(linkp, P);
                    955:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                    956:                
                    957:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                    958:                        LLC_INC(linkp->llcl_vr);
                    959:                        LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
                    960:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    961:                        action = LLC_DATA_INDICATION;
                    962:                } else if (pollfinal == 0 && p == 1) {
                    963:                        LLC_INC(linkp->llcl_vr);
                    964:                        LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 0);
                    965:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    966:                        action = LLC_DATA_INDICATION;
                    967:                } else if ((pollfinal == 0 && p == 0 && cmdrsp == LLC_CMD) ||
                    968:                           (pollfinal == p && cmdrsp == LLC_RSP)) {
                    969:                        LLC_INC(linkp->llcl_vr);
                    970:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                    971:                        LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 0);
                    972:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    973:                        if (cmdrsp == LLC_RSP && pollfinal == 1) 
                    974:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                    975:                        action = LLC_DATA_INDICATION;
                    976:                }
                    977:                break;
                    978:        }
                    979:        case LLCFT_RR + LLC_CMD:
                    980:        case LLCFT_RR + LLC_RSP: {
                    981:                register int p = LLC_GETFLAG(linkp, P);
                    982:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                    983: 
                    984:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                    985:                        LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
                    986:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    987:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                    988:                } else if ((pollfinal == 0) || 
                    989:                           (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
                    990:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                    991:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                    992:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                    993:                } 
                    994:                break;
                    995:        }
                    996:        case LLCFT_RNR + LLC_CMD:
                    997:        case LLCFT_RNR + LLC_RSP: {
                    998:                register int p = LLC_GETFLAG(linkp, P);
                    999:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1000:                
                   1001:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1002:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1003:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1004:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1005:                } else if ((pollfinal == 0) || 
                   1006:                           (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
                   1007:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1008:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1009:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1010:                }
                   1011:                break;
                   1012:        }
                   1013:        case LLCFT_REJ + LLC_CMD:
                   1014:        case LLCFT_REJ + LLC_RSP: {
                   1015:                register int p = LLC_GETFLAG(linkp, P);
                   1016:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1017: 
                   1018:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1019:                        linkp->llcl_vs = nr;
                   1020:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1021:                        llc_resend(linkp, LLC_RSP, 1);
                   1022:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1023:                } else if (pollfinal == 0 && p == 1) {
                   1024:                        linkp->llcl_vs = nr;
                   1025:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1026:                        llc_resend(linkp, LLC_CMD, 0);
                   1027:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1028:                } else if ((pollfinal == 0 && p == 0 && cmdrsp == LLC_CMD) ||
                   1029:                           (pollfinal == p && cmdrsp == LLC_RSP)) {
                   1030:                        linkp->llcl_vs = nr;
                   1031:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1032:                        LLC_START_P_TIMER(linkp);
                   1033:                        llc_resend(linkp, LLC_CMD, 1);
                   1034:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1035:                }
                   1036:                break;
                   1037:        }
                   1038:        case NL_INITIATE_PF_CYCLE:
                   1039:                if (LLC_GETFLAG(linkp, P) == 0) {
                   1040:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1041:                        LLC_START_P_TIMER(linkp);
                   1042:                        action = 0;
                   1043:                }
                   1044:                break;
                   1045:        case LLC_P_TIMER_EXPIRED:
                   1046:                if (linkp->llcl_retry < llc_n2) {
                   1047:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1048:                        LLC_START_P_TIMER(linkp);
                   1049:                        linkp->llcl_retry++;
                   1050:                        LLC_NEWSTATE(linkp, AWAIT);
                   1051:                        action = 0;
                   1052:                }
                   1053:                break;
                   1054:        case LLC_ACK_TIMER_EXPIRED:
                   1055:        case LLC_BUSY_TIMER_EXPIRED:
                   1056:                if ((LLC_GETFLAG(linkp, P) == 0) 
                   1057:                    && (linkp->llcl_retry < llc_n2)) {
                   1058:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1059:                        LLC_START_P_TIMER(linkp);
                   1060:                        linkp->llcl_retry++;
                   1061:                        LLC_NEWSTATE(linkp, AWAIT);
                   1062:                        action = 0;
                   1063:                }
                   1064:                break;
                   1065:        }
                   1066:        if (action == LLC_PASSITON)
                   1067:                action = llc_state_NBRAcore(linkp, frame, frame_kind, 
                   1068:                                            cmdrsp, pollfinal);
                   1069: 
                   1070:        return action;
                   1071: }
                   1072: 
                   1073: /*
                   1074:  * BUSY --- A data link connection exists between the local LLC service access
                   1075:  *          point and the remote LLC service access point. I PDUs may be sent.
                   1076:  *          Local conditions make it likely that the information feld of
                   1077:  *          received I PDUs will be ignored. Supervisory PDUs may be both sent
                   1078:  *          and received.
                   1079:  */
                   1080: int
                   1081: llc_state_BUSY(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                   1082:               int cmdrsp, int pollfinal)
                   1083: {
                   1084:        int action = LLC_PASSITON;
                   1085: 
                   1086:        switch(frame_kind + cmdrsp) {
                   1087:        case NL_DATA_REQUEST:
                   1088:                if (LLC_GETFLAG(linkp, REMOTE_BUSY) == 0)
                   1089:                        if (LLC_GETFLAG(linkp, P) == 0) {
                   1090:                                llc_send(linkp, LLCFT_INFO, LLC_CMD, 1);
                   1091:                                LLC_START_P_TIMER(linkp);
                   1092:                                if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
                   1093:                                        LLC_START_ACK_TIMER(linkp);
                   1094:                                action = 0;
                   1095:                        } else {
                   1096:                                llc_send(linkp, LLCFT_INFO, LLC_CMD, 0);
                   1097:                                if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
                   1098:                                        LLC_START_ACK_TIMER(linkp);
                   1099:                                action = 0;
                   1100:                        }
                   1101:                break;
                   1102:        case LLC_LOCAL_BUSY_CLEARED: {
                   1103:                register int p = LLC_GETFLAG(linkp, P);
                   1104:                register int df = LLC_GETFLAG(linkp, DATA);
                   1105: 
                   1106:                switch (df) {
                   1107:                case 1: 
                   1108:                        if (p == 0) {
                   1109:                                /* multiple possibilities */
                   1110:                                llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
                   1111:                                LLC_START_REJ_TIMER(linkp);
                   1112:                                LLC_START_P_TIMER(linkp);
                   1113:                                LLC_NEWSTATE(linkp, REJECT);
                   1114:                                action = 0;
                   1115:                        } else {
                   1116:                                llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
                   1117:                                LLC_START_REJ_TIMER(linkp);
                   1118:                                LLC_NEWSTATE(linkp, REJECT);
                   1119:                                action = 0;
                   1120:                        }
                   1121:                        break;
                   1122:                case 0:
                   1123:                        if (p == 0) {
                   1124:                                /* multiple possibilities */
                   1125:                                llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1126:                                LLC_START_P_TIMER(linkp);
                   1127:                                LLC_NEWSTATE(linkp, NORMAL);
                   1128:                                action = 0;
                   1129:                        } else {
                   1130:                                llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
                   1131:                                LLC_NEWSTATE(linkp, NORMAL);
                   1132:                                action = 0;
                   1133:                        }
                   1134:                        break;
                   1135:                case 2:
                   1136:                        if (p == 0) {
                   1137:                                /* multiple possibilities */
                   1138:                                llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1139:                                LLC_START_P_TIMER(linkp);
                   1140:                                LLC_NEWSTATE(linkp, REJECT);
                   1141:                                action = 0;
                   1142:                        } else {
                   1143:                                llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
                   1144:                                LLC_NEWSTATE(linkp, REJECT);
                   1145:                                action =0;
                   1146:                        }
                   1147:                        break;
                   1148:                }
                   1149:                break;
                   1150:        }
                   1151:        case LLC_INVALID_NS + LLC_CMD:
                   1152:        case LLC_INVALID_NS + LLC_RSP: {
                   1153:                register int p = LLC_GETFLAG(linkp, P);
                   1154:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1155: 
                   1156:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1157:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1158:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1159:                        if (LLC_GETFLAG(linkp, DATA) == 0)
                   1160:                                LLC_SETFLAG(linkp, DATA, 1);
                   1161:                        action = 0;
                   1162:                } else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
                   1163:                           (cmdrsp == LLC_RSP && pollfinal == p)) {
                   1164:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1165:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1166:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1167:                        if (LLC_GETFLAG(linkp, DATA) == 0) 
                   1168:                                LLC_SETFLAG(linkp, DATA, 1);
                   1169:                        if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1170:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1171:                        } else action = 0;
                   1172:                } else if (pollfinal == 0 && p == 1) {
                   1173:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1174:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1175:                        if (LLC_GETFLAG(linkp, DATA) == 0)
                   1176:                                LLC_SETFLAG(linkp, DATA, 1);
                   1177:                        action = 0;
                   1178:                }
                   1179:                break;
                   1180:        }
                   1181:        case LLCFT_INFO + LLC_CMD:
                   1182:        case LLCFT_INFO + LLC_RSP: {
                   1183:                register int p = LLC_GETFLAG(linkp, P);
                   1184:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1185:                
                   1186:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1187:                        LLC_INC(linkp->llcl_vr);
                   1188:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1189:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1190:                        if (LLC_GETFLAG(linkp, DATA) == 2)
                   1191:                                LLC_STOP_REJ_TIMER(linkp);
                   1192:                        LLC_SETFLAG(linkp, DATA, 0);
                   1193:                        action = LLC_DATA_INDICATION;                   
                   1194:                } else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
                   1195:                           (cmdrsp == LLC_RSP && pollfinal == p)) {
                   1196:                        LLC_INC(linkp->llcl_vr);
                   1197:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1198:                        LLC_START_P_TIMER(linkp);
                   1199:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1200:                        if (LLC_GETFLAG(linkp, DATA) == 2)
                   1201:                                LLC_STOP_REJ_TIMER(linkp);
                   1202:                        if (cmdrsp == LLC_RSP && pollfinal == 1)
                   1203:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1204:                        action = LLC_DATA_INDICATION;
                   1205:                } else if (pollfinal == 0 && p == 1) {
                   1206:                        LLC_INC(linkp->llcl_vr);
                   1207:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1208:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1209:                        if (LLC_GETFLAG(linkp, DATA) == 2)
                   1210:                                LLC_STOP_REJ_TIMER(linkp);
                   1211:                        LLC_SETFLAG(linkp, DATA, 0);
                   1212:                        action = LLC_DATA_INDICATION;
                   1213:                }
                   1214:                break;
                   1215:        }
                   1216:        case LLCFT_RR + LLC_CMD:
                   1217:        case LLCFT_RR + LLC_RSP: 
                   1218:        case LLCFT_RNR + LLC_CMD:
                   1219:        case LLCFT_RNR + LLC_RSP: { 
                   1220:                register int p = LLC_GETFLAG(linkp, P);
                   1221:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1222:                
                   1223:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1224:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1225:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1226:                        if (frame_kind == LLCFT_RR) {
                   1227:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1228:                        } else {
                   1229:                                LLC_SET_REMOTE_BUSY(linkp, action);
                   1230:                        }
                   1231:                } else if (pollfinal = 0 || 
                   1232:                           (cmdrsp == LLC_RSP && pollfinal == 1)) {
                   1233:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1234:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1235:                        if (frame_kind == LLCFT_RR) {
                   1236:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1237:                        } else  {
                   1238:                                LLC_SET_REMOTE_BUSY(linkp, action);
                   1239:                        }
                   1240:                }
                   1241:                break;
                   1242:        }
                   1243:        case LLCFT_REJ + LLC_CMD:
                   1244:        case LLCFT_REJ + LLC_RSP: {
                   1245:                register int p = LLC_GETFLAG(linkp, P);
                   1246:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1247: 
                   1248:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1249:                        linkp->llcl_vs = nr;
                   1250:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1251:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1252:                        llc_resend(linkp, LLC_CMD, 0);
                   1253:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1254:                } else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
                   1255:                           (cmdrsp == LLC_RSP && pollfinal == p)) {
                   1256:                        linkp->llcl_vs = nr;
                   1257:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1258:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1259:                        llc_resend(linkp, LLC_CMD, 0);
                   1260:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1261:                } else if (pollfinal == 0 && p == 1) {
                   1262:                        linkp->llcl_vs = nr;
                   1263:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1264:                        llc_resend(linkp, LLC_CMD, 0);
                   1265:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1266:                }
                   1267:                break;
                   1268:        }
                   1269:        case NL_INITIATE_PF_CYCLE:
                   1270:                if (LLC_GETFLAG(linkp, P) == 0) {
                   1271:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1272:                        LLC_START_P_TIMER(linkp);
                   1273:                        action = 0;
                   1274:                }
                   1275:                break;
                   1276:        case LLC_P_TIMER_EXPIRED:
                   1277:                /* multiple possibilities */
                   1278:                if (linkp->llcl_retry < llc_n2) {
                   1279:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1280:                        LLC_START_P_TIMER(linkp);
                   1281:                        linkp->llcl_retry++;
                   1282:                        LLC_NEWSTATE(linkp, AWAIT_BUSY);
                   1283:                        action = 0;
                   1284:                }
                   1285:                break;
                   1286:        case LLC_ACK_TIMER_EXPIRED:
                   1287:        case LLC_BUSY_TIMER_EXPIRED:
                   1288:                if (LLC_GETFLAG(linkp, P) == 0 && linkp->llcl_retry < llc_n2) {
                   1289:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1290:                        LLC_START_P_TIMER(linkp);
                   1291:                        linkp->llcl_retry++;
                   1292:                        LLC_NEWSTATE(linkp, AWAIT_BUSY);
                   1293:                        action = 0;
                   1294:                }
                   1295:                break;
                   1296:        case LLC_REJ_TIMER_EXPIRED:
                   1297:                if (linkp->llcl_retry < llc_n2) 
                   1298:                        if (LLC_GETFLAG(linkp, P) == 0) {
                   1299:                                /* multiple possibilities */
                   1300:                                llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1301:                                LLC_START_P_TIMER(linkp);
                   1302:                                linkp->llcl_retry++;
                   1303:                                LLC_SETFLAG(linkp, DATA, 1);
                   1304:                                LLC_NEWSTATE(linkp, AWAIT_BUSY);
                   1305:                                action = 0;
                   1306:                        } else{
                   1307:                                LLC_SETFLAG(linkp, DATA, 1);
                   1308:                                LLC_NEWSTATE(linkp, BUSY);
                   1309:                                action = 0;
                   1310:                        }
                   1311:                
                   1312:                break;
                   1313:        }
                   1314:        if (action == LLC_PASSITON)
                   1315:                action = llc_state_NBRAcore(linkp, frame, frame_kind, 
                   1316:                                            cmdrsp, pollfinal);
                   1317: 
                   1318:        return action;
                   1319: }
                   1320: 
                   1321: /*
                   1322:  * REJECT --- A data link connection exists between the local LLC service
                   1323:  *            access point and the remote LLC service access point. The local
                   1324:  *            connection component has requested that the remote connection
                   1325:  *            component resend a specific I PDU that the local connection
                   1326:  *            componnent has detected as being out of sequence. Both I PDUs and
                   1327:  *            supervisory PDUs may be sent and received.
                   1328:  */ 
                   1329: int
                   1330: llc_state_REJECT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                   1331:                 int cmdrsp, int pollfinal)
                   1332: {
                   1333:        int action = LLC_PASSITON;
                   1334: 
                   1335:        switch(frame_kind + cmdrsp) {
                   1336:        case NL_DATA_REQUEST:
                   1337:                if (LLC_GETFLAG(linkp, P) == 0) {
                   1338:                        llc_send(linkp, LLCFT_INFO, LLC_CMD, 1);
                   1339:                        LLC_START_P_TIMER(linkp);
                   1340:                        if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
                   1341:                                LLC_START_ACK_TIMER(linkp);
                   1342:                        LLC_NEWSTATE(linkp, REJECT);
                   1343:                        action = 0;
                   1344:                } else { 
                   1345:                        llc_send(linkp, LLCFT_INFO, LLC_CMD, 0);
                   1346:                        if (LLC_TIMERXPIRED(linkp, ACK) != LLC_TIMER_RUNNING)
                   1347:                                LLC_START_ACK_TIMER(linkp);
                   1348:                        LLC_NEWSTATE(linkp, REJECT);
                   1349:                        action = 0;
                   1350:                }
                   1351:                break;
                   1352:        case NL_LOCAL_BUSY_DETECTED:
                   1353:                if (LLC_GETFLAG(linkp, P) == 0) {
                   1354:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1355:                        LLC_START_P_TIMER(linkp);
                   1356:                        LLC_SETFLAG(linkp, DATA, 2);
                   1357:                        LLC_NEWSTATE(linkp, BUSY);
                   1358:                        action = 0;
                   1359:                } else {
                   1360:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1361:                        LLC_SETFLAG(linkp, DATA, 2);
                   1362:                        LLC_NEWSTATE(linkp, BUSY);
                   1363:                        action = 0;
                   1364:                }
                   1365:                break;
                   1366:        case LLC_INVALID_NS + LLC_CMD:
                   1367:        case LLC_INVALID_NS + LLC_RSP: { 
                   1368:                register int p = LLC_GETFLAG(linkp, P);
                   1369:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1370: 
                   1371:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1372:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1373:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1374:                        action = 0;
                   1375:                } else if (pollfinal == 0 || 
                   1376:                           (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
                   1377:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1378:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1379:                        if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1380:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1381:                        } else action = 0;
                   1382:                }
                   1383:                break;
                   1384:        }
                   1385:        case LLCFT_INFO + LLC_CMD:
                   1386:        case LLCFT_INFO + LLC_RSP: {
                   1387:                register int p = LLC_GETFLAG(linkp, P);
                   1388:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1389:                
                   1390:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1391:                        LLC_INC(linkp->llcl_vr);
                   1392:                        LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
                   1393:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1394:                        LLC_STOP_REJ_TIMER(linkp);
                   1395:                        LLC_NEWSTATE(linkp, NORMAL);
                   1396:                        action = LLC_DATA_INDICATION;
                   1397:                } else if ((cmdrsp = LLC_RSP && pollfinal == p) ||
                   1398:                           (cmdrsp == LLC_CMD && pollfinal == 0 && p == 0)) {
                   1399:                        LLC_INC(linkp->llcl_vr);
                   1400:                        LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 1);
                   1401:                        LLC_START_P_TIMER(linkp);
                   1402:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1403:                        if (cmdrsp == LLC_RSP && pollfinal == 1)
                   1404:                                LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1405:                        LLC_STOP_REJ_TIMER(linkp);
                   1406:                        LLC_NEWSTATE(linkp, NORMAL);
                   1407:                        action = LLC_DATA_INDICATION;
                   1408:                } else if (pollfinal == 0 && p == 1) {
                   1409:                        LLC_INC(linkp->llcl_vr);
                   1410:                        LLC_SENDACKNOWLEDGE(linkp, LLC_CMD, 0);
                   1411:                        LLC_STOP_REJ_TIMER(linkp);
                   1412:                        LLC_NEWSTATE(linkp, NORMAL);
                   1413:                        action = LLC_DATA_INDICATION;
                   1414:                }
                   1415:                break;
                   1416:        }
                   1417:        case LLCFT_RR + LLC_CMD:
                   1418:        case LLCFT_RR + LLC_RSP: {
                   1419:                register int p = LLC_GETFLAG(linkp, P);
                   1420:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1421: 
                   1422:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1423:                        LLC_SENDACKNOWLEDGE(linkp, LLC_RSP, 1);
                   1424:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1425:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1426:                } else if (pollfinal == 0 || 
                   1427:                           (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
                   1428:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1429:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1430:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1431:                }
                   1432:                break;
                   1433:        }
                   1434:        case LLCFT_RNR + LLC_CMD:
                   1435:        case LLCFT_RNR + LLC_RSP: {
                   1436:                register int p = LLC_GETFLAG(linkp, P);
                   1437:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1438:                
                   1439:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1440:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1441:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1442:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1443:                } else if (pollfinal == 0 ||
                   1444:                           (cmdrsp == LLC_RSP && pollfinal == 1 && p == 1)) {
                   1445:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1446:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1447:                        action = 0;
                   1448:                }
                   1449:                break;
                   1450:        }
                   1451:        case LLCFT_REJ + LLC_CMD:
                   1452:        case LLCFT_REJ + LLC_RSP: {
                   1453:                register int p = LLC_GETFLAG(linkp, P);
                   1454:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1455: 
                   1456:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1457:                        linkp->llcl_vs = nr;
                   1458:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1459:                        llc_resend(linkp, LLC_RSP, 1);
                   1460:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1461:                } else if ((cmdrsp == LLC_CMD && pollfinal == 0 && p == 0) ||
                   1462:                           (cmdrsp == LLC_RSP && pollfinal == p)) {
                   1463:                        linkp->llcl_vs = nr;
                   1464:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1465:                        LLC_UPDATE_P_FLAG(linkp, cmdrsp, pollfinal);
                   1466:                        llc_resend(linkp, LLC_CMD, 0);
                   1467:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1468:                } else if (pollfinal == 0 && p == 1) {
                   1469:                        linkp->llcl_vs = nr;
                   1470:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1471:                        llc_resend(linkp, LLC_CMD, 0);
                   1472:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1473:                }
                   1474:                break;
                   1475:        }
                   1476:        case NL_INITIATE_PF_CYCLE:
                   1477:                if (LLC_GETFLAG(linkp, P) == 0) {
                   1478:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1479:                        LLC_START_P_TIMER(linkp);
                   1480:                        action = 0;
                   1481:                }
                   1482:                break;
                   1483:        case LLC_REJ_TIMER_EXPIRED:
                   1484:                if (LLC_GETFLAG(linkp, P) == 0 && linkp->llcl_retry < llc_n2) {
                   1485:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
                   1486:                        LLC_START_P_TIMER(linkp);
                   1487:                        LLC_START_REJ_TIMER(linkp);
                   1488:                        linkp->llcl_retry++;
                   1489:                        action = 0;
                   1490:                }
                   1491:        case LLC_P_TIMER_EXPIRED:
                   1492:                if (linkp->llcl_retry < llc_n2) {
                   1493:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1494:                        LLC_START_P_TIMER(linkp);
                   1495:                        LLC_START_REJ_TIMER(linkp);
                   1496:                        linkp->llcl_retry++;
                   1497:                        LLC_NEWSTATE(linkp, AWAIT_REJECT);
                   1498:                        action = 0;
                   1499:                }
                   1500:                break;
                   1501:        case LLC_ACK_TIMER_EXPIRED:
                   1502:        case LLC_BUSY_TIMER_EXPIRED:
                   1503:                if (LLC_GETFLAG(linkp, P) == 0 && linkp->llcl_retry < llc_n2) {
                   1504:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1505:                        LLC_START_P_TIMER(linkp);
                   1506:                        LLC_START_REJ_TIMER(linkp);
                   1507:                        linkp->llcl_retry++;
                   1508:                        /* 
                   1509:                         * I cannot locate the description of RESET_V(S)
                   1510:                         * in ISO 8802-2, table 7-1, state REJECT, last event,
                   1511:                         * and  assume they meant to set V(S) to 0 ...
                   1512:                         */
                   1513:                        linkp->llcl_vs = 0; /* XXX */
                   1514:                        LLC_NEWSTATE(linkp, AWAIT_REJECT);
                   1515:                        action = 0;
                   1516:                }
                   1517: 
                   1518:                break;
                   1519:        }
                   1520:        if (action == LLC_PASSITON)
                   1521:                action = llc_state_NBRAcore(linkp, frame, frame_kind, 
                   1522:                                            cmdrsp, pollfinal);
                   1523: 
                   1524:        return action;
                   1525: }
                   1526: 
                   1527: /*
                   1528:  * AWAIT --- A data link connection exists between the local LLC service access
                   1529:  *           point and the remote LLC service access point. The local LLC is
                   1530:  *           performing a timer recovery operation and has sent a command PDU
                   1531:  *           with the P bit set to ``1'', and is awaiting an acknowledgement
                   1532:  *           from the remote LLC. I PDUs may be received but not sent.
                   1533:  *           Supervisory PDUs may be both sent and received.
                   1534:  */
                   1535: int
                   1536: llc_state_AWAIT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                   1537:                int cmdrsp, int pollfinal)
                   1538: {
                   1539:        int action = LLC_PASSITON;
                   1540: 
                   1541:        switch(frame_kind + cmdrsp) {
                   1542:        case LLC_LOCAL_BUSY_DETECTED:
                   1543:                llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1544:                LLC_SETFLAG(linkp, DATA, 0);
                   1545:                LLC_NEWSTATE(linkp, AWAIT_BUSY);
                   1546:                action = 0;
                   1547:                break;
                   1548:        case LLC_INVALID_NS + LLC_CMD:
                   1549:        case LLC_INVALID_NS + LLC_RSP: {
                   1550:                register int p = LLC_GETFLAG(linkp, P);
                   1551:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1552:                
                   1553:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1554:                        llc_send(linkp, LLCFT_REJ, LLC_RSP, 1);
                   1555:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1556:                        LLC_START_REJ_TIMER(linkp);
                   1557:                        LLC_NEWSTATE(linkp, AWAIT_REJECT);
                   1558:                        action = 0;
                   1559:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1560:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
                   1561:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1562:                        linkp->llcl_vs = nr;
                   1563:                        LLC_STOP_P_TIMER(linkp);
                   1564:                        llc_resend(linkp, LLC_CMD, 0);
                   1565:                        LLC_START_REJ_TIMER(linkp);
                   1566:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1567:                        LLC_NEWSTATE(linkp, REJECT);
                   1568:                } else if (pollfinal == 0) {
                   1569:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
                   1570:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1571:                        LLC_START_REJ_TIMER(linkp);
                   1572:                        LLC_NEWSTATE(linkp, AWAIT_REJECT);
                   1573:                        action = 0;
                   1574:                }
                   1575:                break;
                   1576:        }
                   1577:        case LLCFT_INFO + LLC_RSP:
                   1578:        case LLCFT_INFO + LLC_CMD: {
                   1579:                register int p = LLC_GETFLAG(linkp, P);
                   1580:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1581:                
                   1582:                LLC_INC(linkp->llcl_vr);
                   1583:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1584:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1585:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1586:                        action = LLC_DATA_INDICATION;
                   1587:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1588:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1589:                        linkp->llcl_vs = nr;
                   1590:                        llc_resend(linkp, LLC_CMD, 1);
                   1591:                        LLC_START_P_TIMER(linkp);
                   1592:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1593:                        LLC_NEWSTATE(linkp, NORMAL);
                   1594:                        action = LLC_DATA_INDICATION;
                   1595:                } else if (pollfinal == 0) {
                   1596:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
                   1597:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1598:                        action = LLC_DATA_INDICATION;
                   1599:                }
                   1600:                break;
                   1601:        }
                   1602:        case LLCFT_RR + LLC_CMD:
                   1603:        case LLCFT_RR + LLC_RSP:
                   1604:        case LLCFT_REJ + LLC_CMD:
                   1605:        case LLCFT_REJ + LLC_RSP: {
                   1606:                register int p = LLC_GETFLAG(linkp, P);
                   1607:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1608:                
                   1609:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1610:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1611:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1612:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1613:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1614:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1615:                        linkp->llcl_vs = nr;
                   1616:                        LLC_STOP_P_TIMER(linkp);
                   1617:                        llc_resend(linkp, LLC_CMD, 0);
                   1618:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1619:                        LLC_NEWSTATE(linkp, NORMAL);
                   1620:                } else if (pollfinal == 0) {
                   1621:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1622:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1623:                }       
                   1624:                break;
                   1625:        }
                   1626:        case LLCFT_RNR + LLC_CMD:
                   1627:        case LLCFT_RNR + LLC_RSP: {
                   1628:                register int p = LLC_GETFLAG(linkp, P);
                   1629:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1630: 
                   1631:                if (pollfinal == 1 && cmdrsp == LLC_CMD) {
                   1632:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1633:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1634:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1635:                } else if (pollfinal == 1 && cmdrsp == LLC_RSP) {
                   1636:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1637:                        linkp->llcl_vs = nr;
                   1638:                        LLC_STOP_P_TIMER(linkp);
                   1639:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1640:                        LLC_NEWSTATE(linkp, NORMAL);
                   1641:                } else if (pollfinal == 0) {
                   1642:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1643:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1644:                }
                   1645:                break;
                   1646:        }
                   1647:        case LLC_P_TIMER_EXPIRED:
                   1648:                if (linkp->llcl_retry < llc_n2) {
                   1649:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 1);
                   1650:                        LLC_START_P_TIMER(linkp);
                   1651:                        linkp->llcl_retry++;
                   1652:                        action = 0;
                   1653:                }
                   1654:                break;
                   1655:        }
                   1656:        if (action == LLC_PASSITON)
                   1657:                action = llc_state_NBRAcore(linkp, frame, frame_kind, 
                   1658:                                            cmdrsp, pollfinal);
                   1659: 
                   1660:        return action;
                   1661: }
                   1662: 
                   1663: /*
                   1664:  * AWAIT_BUSY --- A data link connection exists between the local LLC service
                   1665:  *                access point and the remote LLC service access point. The
                   1666:  *                local LLC is performing a timer recovery operation and has
                   1667:  *                sent a command PDU with the P bit set to ``1'', and is
                   1668:  *                awaiting an acknowledgement from the remote LLC. I PDUs may
                   1669:  *                not be sent. Local conditions make it likely that the
                   1670:  *                information feld of receoved I PDUs will be ignored.
                   1671:  *                Supervisory PDUs may be both sent and received.
                   1672:  */
                   1673: int
                   1674: llc_state_AWAIT_BUSY(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                   1675:                     int cmdrsp, int pollfinal)
                   1676: {
                   1677:        int action = LLC_PASSITON;
                   1678: 
                   1679:        switch(frame_kind + cmdrsp) {
                   1680:        case LLC_LOCAL_BUSY_CLEARED:
                   1681:                switch (LLC_GETFLAG(linkp, DATA)) {
                   1682:                case 1:
                   1683:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 0);
                   1684:                        LLC_START_REJ_TIMER(linkp);
                   1685:                        LLC_NEWSTATE(linkp, AWAIT_REJECT);
                   1686:                        action = 0;
                   1687:                        break;
                   1688:                case 0:
                   1689:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
                   1690:                        LLC_NEWSTATE(linkp, AWAIT);
                   1691:                        action = 0;
                   1692:                        break;
                   1693:                case 2:
                   1694:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
                   1695:                        LLC_NEWSTATE(linkp, AWAIT_REJECT);
                   1696:                        action = 0;
                   1697:                        break;
                   1698:                }
                   1699:                break;
                   1700:        case LLC_INVALID_NS + LLC_CMD:
                   1701:        case LLC_INVALID_NS + LLC_RSP: {
                   1702:                register int p = LLC_GETFLAG(linkp, P);
                   1703:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1704: 
                   1705:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1706:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1707:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1708:                        LLC_SETFLAG(linkp, DATA, 1);
                   1709:                        action = 0;
                   1710:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1711:                        /* optionally */
                   1712:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1713:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1714:                        linkp->llcl_vs = nr;
                   1715:                        LLC_STOP_P_TIMER(linkp);
                   1716:                        LLC_SETFLAG(linkp, DATA, 1);
                   1717:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1718:                        llc_resend(linkp, LLC_CMD, 0);
                   1719:                        LLC_NEWSTATE(linkp, BUSY);
                   1720:                } else if (pollfinal == 0) {
                   1721:                        /* optionally */
                   1722:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1723:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1724:                        LLC_SETFLAG(linkp, DATA, 1);
                   1725:                        action = 0;
                   1726:                }
                   1727:        }
                   1728:        case LLCFT_INFO + LLC_CMD:
                   1729:        case LLCFT_INFO + LLC_RSP: {
                   1730:                register int p = LLC_GETFLAG(linkp, P);
                   1731:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1732:                
                   1733:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1734:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1735:                        LLC_INC(linkp->llcl_vr);
                   1736:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1737:                        LLC_SETFLAG(linkp, DATA, 0);
                   1738:                        action = LLC_DATA_INDICATION;
                   1739:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1740:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1741:                        LLC_INC(linkp->llcl_vr);
                   1742:                        LLC_START_P_TIMER(linkp);
                   1743:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1744:                        linkp->llcl_vs = nr;
                   1745:                        LLC_SETFLAG(linkp, DATA, 0);
                   1746:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1747:                        llc_resend(linkp, LLC_CMD, 0);
                   1748:                        LLC_NEWSTATE(linkp, BUSY);
                   1749:                        action = LLC_DATA_INDICATION;
                   1750:                } else if (pollfinal == 0) {
                   1751:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1752:                        LLC_INC(linkp->llcl_vr);
                   1753:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1754:                        LLC_SETFLAG(linkp, DATA, 0);
                   1755:                        action = LLC_DATA_INDICATION;
                   1756:                }
                   1757:                break;
                   1758:        }
                   1759:        case LLCFT_RR + LLC_CMD:
                   1760:        case LLCFT_REJ + LLC_CMD:
                   1761:        case LLCFT_RR + LLC_RSP:
                   1762:        case LLCFT_REJ + LLC_RSP: {
                   1763:                register int p = LLC_GETFLAG(linkp, P);
                   1764:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1765:                
                   1766:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1767:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1768:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1769:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1770:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1771:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1772:                        linkp->llcl_vs = nr;
                   1773:                        LLC_STOP_P_TIMER(linkp);
                   1774:                        llc_resend(linkp, LLC_CMD, 0);
                   1775:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1776:                        LLC_NEWSTATE(linkp, BUSY);
                   1777:                } else if (pollfinal == 0) {
                   1778:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1779:                        linkp->llcl_vs = nr;
                   1780:                        LLC_STOP_P_TIMER(linkp);
                   1781:                        llc_resend(linkp, LLC_CMD, 0);
                   1782:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1783:                }
                   1784:                break;
                   1785:        }
                   1786:        case LLCFT_RNR + LLC_CMD:
                   1787:        case LLCFT_RNR + LLC_RSP: {
                   1788:                register int p = LLC_GETFLAG(linkp, P);
                   1789:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1790:                
                   1791:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1792:                        llc_send(linkp, LLCFT_RNR, LLC_RSP, 1);
                   1793:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1794:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1795:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1796:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1797:                        linkp->llcl_vs = nr;
                   1798:                        LLC_STOP_P_TIMER(linkp);
                   1799:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1800:                        LLC_NEWSTATE(linkp, BUSY);
                   1801:                } else if (pollfinal == 0) {
                   1802:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1803:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1804:                }
                   1805:                break;
                   1806:        }
                   1807:        case LLC_P_TIMER_EXPIRED:
                   1808:                if (linkp->llcl_retry < llc_n2) {
                   1809:                        llc_send(linkp, LLCFT_RNR, LLC_CMD, 1);
                   1810:                        LLC_START_P_TIMER(linkp);
                   1811:                        linkp->llcl_retry++;
                   1812:                        action = 0;
                   1813:                }
                   1814:                break;
                   1815:        }
                   1816:        if (action == LLC_PASSITON)
                   1817:                action = llc_state_NBRAcore(linkp, frame, frame_kind, 
                   1818:                                            cmdrsp, pollfinal);
                   1819: 
                   1820:        return action;
                   1821: }
                   1822: 
                   1823: /*
                   1824:  * AWAIT_REJECT --- A data link connection exists between the local LLC service
                   1825:  *                  access point and the remote LLC service access point. The
                   1826:  *                  local connection component has requested that the remote
                   1827:  *                  connection component re-transmit a specific I PDU that the
                   1828:  *                  local connection component has detected as being out of
                   1829:  *                  sequence. Before the local LLC entered this state it was
                   1830:  *                  performing a timer recovery operation and had sent a
                   1831:  *                  command PDU with the P bit set to ``1'', and is still
                   1832:  *                  awaiting an acknowledgment from the remote LLC. I PDUs may
                   1833:  *                  be received but not transmitted. Supervisory PDUs may be
                   1834:  *                  both transmitted and received.
                   1835:  */
                   1836: int
                   1837: llc_state_AWAIT_REJECT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                   1838:                       int cmdrsp, int pollfinal)
                   1839: {
                   1840:        int action = LLC_PASSITON;
                   1841: 
                   1842:        switch(frame_kind + cmdrsp) {
                   1843:        case LLC_LOCAL_BUSY_DETECTED:
                   1844:                llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);
                   1845:                LLC_SETFLAG(linkp, DATA, 2);
                   1846:                LLC_NEWSTATE(linkp, AWAIT_BUSY);
                   1847:                action = 0;
                   1848:                break;
                   1849:        case LLC_INVALID_NS + LLC_CMD:
                   1850:        case LLC_INVALID_NS + LLC_RSP: {
                   1851:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1852:                
                   1853:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1854:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1855:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1856:                        action = 0;
                   1857:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1858:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1859:                        linkp->llcl_vs = nr;
                   1860:                        llc_resend(linkp, LLC_CMD, 1);
                   1861:                        LLC_START_P_TIMER(linkp);
                   1862:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1863:                        LLC_NEWSTATE(linkp, REJECT);
                   1864:                } else if (pollfinal == 0) {
                   1865:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1866:                        action = 0;     
                   1867:                }
                   1868:                break;
                   1869:        }
                   1870:        case LLCFT_INFO + LLC_CMD:
                   1871:        case LLCFT_INFO + LLC_RSP: {
                   1872:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1873: 
                   1874:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1875:                        LLC_INC(linkp->llcl_vr);
                   1876:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1877:                        LLC_STOP_REJ_TIMER(linkp);
                   1878:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1879:                        LLC_NEWSTATE(linkp, AWAIT);
                   1880:                        action = LLC_DATA_INDICATION;
                   1881:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1882:                        LLC_INC(linkp->llcl_vr);
                   1883:                        LLC_STOP_P_TIMER(linkp);
                   1884:                        LLC_STOP_REJ_TIMER(linkp);
                   1885:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1886:                        linkp->llcl_vs = nr;
                   1887:                        llc_resend(linkp, LLC_CMD, 0);
                   1888:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1889:                        LLC_NEWSTATE(linkp, NORMAL);
                   1890:                        action = LLC_DATA_INDICATION;
                   1891:                } else if (pollfinal == 0) {
                   1892:                        LLC_INC(linkp->llcl_vr);
                   1893:                        llc_send(linkp, LLCFT_RR, LLC_CMD, 0);
                   1894:                        LLC_STOP_REJ_TIMER(linkp);
                   1895:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1896:                        LLC_NEWSTATE(linkp, AWAIT);
                   1897:                        action = LLC_DATA_INDICATION;
                   1898:                }
                   1899:                break;
                   1900:        }
                   1901:        case LLCFT_RR + LLC_CMD:
                   1902:        case LLCFT_REJ + LLC_CMD:
                   1903:        case LLCFT_RR + LLC_RSP:
                   1904:        case LLCFT_REJ + LLC_RSP: {
                   1905:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1906:                
                   1907:                if (cmdrsp == LLC_CMD && pollfinal ==  1) {
                   1908:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1909:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1910:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1911:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1912:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1913:                        linkp->llcl_vs = nr;
                   1914:                        llc_resend(linkp, LLC_CMD, 1);
                   1915:                        LLC_START_P_TIMER(linkp);
                   1916:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1917:                        LLC_NEWSTATE(linkp, REJECT);
                   1918:                } else if (pollfinal == 0) {
                   1919:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1920:                        LLC_CLEAR_REMOTE_BUSY(linkp, action);
                   1921:                }
                   1922:                break;
                   1923:        }
                   1924:        case LLCFT_RNR + LLC_CMD:
                   1925:        case LLCFT_RNR + LLC_RSP: {
                   1926:                register int nr = LLCGBITS(frame->llc_control_ext, s_nr);
                   1927: 
                   1928:                if (cmdrsp == LLC_CMD && pollfinal == 1) {
                   1929:                        llc_send(linkp, LLCFT_RR, LLC_RSP, 1);
                   1930:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1931:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1932:                } else if (cmdrsp == LLC_RSP && pollfinal == 1) {
                   1933:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1934:                        linkp->llcl_vs = nr;
                   1935:                        LLC_STOP_P_TIMER(linkp);
                   1936:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1937:                        LLC_NEWSTATE(linkp, REJECT);
                   1938:                } else if (pollfinal == 0) {
                   1939:                        LLC_UPDATE_NR_RECEIVED(linkp, nr);
                   1940:                        LLC_SET_REMOTE_BUSY(linkp, action);
                   1941:                }
                   1942:                break;
                   1943:        }
                   1944:        case LLC_P_TIMER_EXPIRED:
                   1945:                if (linkp->llcl_retry < llc_n2) {
                   1946:                        llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);
                   1947:                        LLC_START_P_TIMER(linkp);
                   1948:                        linkp->llcl_retry++;
                   1949:                        action = 0;
                   1950:                }
                   1951:                break;
                   1952:        }
                   1953:        if (action == LLC_PASSITON)
                   1954:                action = llc_state_NBRAcore(linkp, frame, frame_kind, 
                   1955:                                            cmdrsp, pollfinal);
                   1956: 
                   1957:        return action;
                   1958: }
                   1959: 
                   1960: 
                   1961: /*
                   1962:  * llc_statehandler() --- Wrapper for llc_state_*() functions.
                   1963:  *                         Deals with action codes and checks for
                   1964:  *                         ``stuck'' links.
                   1965:  */
                   1966: 
                   1967: int
                   1968: llc_statehandler(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,
                   1969:                 int cmdrsp, int pollfinal)
                   1970: {
                   1971:        register int action = 0;
                   1972: 
                   1973:        /*
                   1974:         * To check for ``zombie'' links each time llc_statehandler() gets called
                   1975:         * the AGE timer of linkp is reset. If it expires llc_timer() will
                   1976:         * take care of the link --- i.e. kill it 8=)
                   1977:         */
                   1978:        LLC_STARTTIMER(linkp, AGE);
                   1979: 
                   1980:        /*
                   1981:         * Now call the current statehandler function.
                   1982:         */
                   1983:        action = (*linkp->llcl_statehandler)(linkp, frame, frame_kind, 
                   1984:                                             cmdrsp, pollfinal);
                   1985: once_more_and_again:
                   1986:        switch (action) {
                   1987:        case LLC_CONNECT_INDICATION: {
                   1988:                int naction;
                   1989: 
                   1990:                LLC_TRACE(linkp, LLCTR_INTERESTING, "CONNECT INDICATION");
                   1991:                linkp->llcl_nlnext = 
                   1992:                     (*linkp->llcl_sapinfo->si_ctlinput)
                   1993:                      (PRC_CONNECT_INDICATION,
                   1994:                       (struct sockaddr *) &linkp->llcl_addr, (caddr_t) linkp);
                   1995:                if (linkp->llcl_nlnext == 0)
                   1996:                        naction = NL_DISCONNECT_REQUEST;
                   1997:                else naction = NL_CONNECT_RESPONSE;
                   1998:                action = (*linkp->llcl_statehandler)(linkp, frame, naction, 0, 0);
                   1999:                goto once_more_and_again;
                   2000:        }
                   2001:        case LLC_CONNECT_CONFIRM:
                   2002:                /* llc_resend(linkp, LLC_CMD, 0); */
                   2003:                llc_start(linkp);
                   2004:                break;
                   2005:        case LLC_DISCONNECT_INDICATION:
                   2006:                LLC_TRACE(linkp, LLCTR_INTERESTING, "DISCONNECT INDICATION");
                   2007:                (*linkp->llcl_sapinfo->si_ctlinput)
                   2008:                  (PRC_DISCONNECT_INDICATION, 
                   2009:                   (struct sockaddr *) &linkp->llcl_addr, linkp->llcl_nlnext);
                   2010:                break;
                   2011:         /* internally visible only */
                   2012:        case LLC_RESET_CONFIRM:
                   2013:        case LLC_RESET_INDICATION_LOCAL:
                   2014:                /*
                   2015:                 * not much we can do here, the state machine either makes it or
                   2016:                 * brakes it ...
                   2017:                 */
                   2018:                break;
                   2019:        case LLC_RESET_INDICATION_REMOTE:
                   2020:                LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "RESET INDICATION (REMOTE)");
                   2021:                action = (*linkp->llcl_statehandler)(linkp, frame, 
                   2022:                                                     NL_RESET_RESPONSE, 0, 0);
                   2023:                goto once_more_and_again;
                   2024:        case LLC_FRMR_SENT:
                   2025:                LLC_TRACE(linkp, LLCTR_URGENT, "FRMR SENT");
                   2026:                break;
                   2027:        case LLC_FRMR_RECEIVED:
                   2028:                LLC_TRACE(linkp, LLCTR_URGEN, "FRMR RECEIVED");
                   2029:                action = (*linkp->llcl_statehandler)(linkp, frame,
                   2030:                                                     NL_RESET_REQUEST, 0, 0);
                   2031:                
                   2032:                goto once_more_and_again;
                   2033:        case LLC_REMOTE_BUSY:
                   2034:                LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "REMOTE BUSY");
                   2035:                break;
                   2036:        case LLC_REMOTE_NOT_BUSY:
                   2037:                LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "REMOTE BUSY CLEARED");
                   2038:                /*
                   2039:                 * try to get queued frames out
                   2040:                 */
                   2041:                llc_start(linkp);
                   2042:                break;
                   2043:        }               
                   2044: 
                   2045:        /*
                   2046:          * Only LLC_DATA_INDICATION is for the time being
                   2047:         * passed up to the network layer entity.
                   2048:         * The remaining action codes are for the time 
                   2049:         * being visible internally only.
                   2050:          * However, this can/may be changed if necessary.
                   2051:         */
                   2052: 
                   2053:        return action;
                   2054: }
                   2055: 
                   2056: 
                   2057: /*
                   2058:  * Core LLC2 routines
                   2059:  */ 
                   2060: 
                   2061: /*
                   2062:  * The INIT call. This routine is called once after the system is booted.
                   2063:  */
                   2064: 
                   2065: llc_init()
                   2066: {
                   2067:        llcintrq.ifq_maxlen = IFQ_MAXLEN;
                   2068: }
                   2069: 
                   2070: 
                   2071: /*
                   2072:  * In case of a link reset we need to shuffle the frames queued inside the
                   2073:  * LLC2 window.
                   2074:  */
                   2075: 
                   2076: void
                   2077: llc_resetwindow(struct llc_linkcb *linkp)
                   2078: {
                   2079:        register struct mbuf *mptr = (struct mbuf *) 0;
                   2080:        register struct mbuf *anchor = (struct mbuf *)0;
                   2081:        register short i;
                   2082: 
                   2083:        /* Pick up all queued frames and collect them in a linked mbuf list */
                   2084:        if (linkp->llcl_slotsfree != linkp->llcl_window) {
                   2085:                i = llc_seq2slot(linkp, linkp->llcl_nr_received);
                   2086:                anchor = mptr = linkp->llcl_output_buffers[i]; 
                   2087:                for (; i != linkp->llcl_freeslot; 
                   2088:                     i = llc_seq2slot(linkp, i+1)) {
                   2089:                        if (linkp->llcl_output_buffers[i]) {
                   2090:                                mptr->m_nextpkt = linkp->llcl_output_buffers[i];
                   2091:                                mptr = mptr->m_nextpkt;
                   2092:                        } else panic("LLC2 window broken");
                   2093:                }
                   2094:        }
                   2095:        /* clean closure */
                   2096:        if (mptr)
                   2097:                mptr->m_nextpkt = (struct mbuf *) 0;
                   2098: 
                   2099:        /* Now --- plug 'em in again */
                   2100:        if (anchor != (struct mbuf *)0) {
                   2101:                for (i = 0, mptr = anchor; mptr != (struct mbuf *) 0; i++) {
                   2102:                        linkp->llcl_output_buffers[i] = mptr;
                   2103:                        mptr = mptr->m_nextpkt;
                   2104:                        linkp->llcl_output_buffers[i]->m_nextpkt = (struct mbuf *)0;
                   2105:                }
                   2106:                linkp->llcl_freeslot = i;
                   2107:        } else linkp->llcl_freeslot = 0;
                   2108:        
                   2109:        /* We're resetting the link, the next frame to be acknowledged is 0 */
                   2110:        linkp->llcl_nr_received = 0;
                   2111: 
                   2112:        /* set distance between LLC2 sequence number and the top of window to 0 */
                   2113:        linkp->llcl_projvs = linkp->llcl_freeslot;
                   2114: 
                   2115:        return;
                   2116: }
                   2117:                        
                   2118: /*
                   2119:  * llc_newlink() --- We allocate enough memory to contain a link control block
                   2120:  *                   and initialize it properly. We don't intiate the actual
                   2121:  *                                      setup of the LLC2 link here.
                   2122:  */
                   2123: struct llc_linkcb *
                   2124: llc_newlink(struct sockaddr_dl *dst, struct ifnet *ifp, struct rtentry *nlrt, 
                   2125:            caddr_t nlnext, struct rtentry *llrt)
                   2126: {
                   2127:        struct llc_linkcb *nlinkp;
                   2128:        u_char sap = LLSAPADDR(dst);
                   2129:        short llcwindow;
                   2130: 
                   2131: 
                   2132:        /* allocate memory for link control block */
                   2133:        MALLOC(nlinkp, struct llc_linkcb *, sizeof(struct llc_linkcb),
                   2134:               M_PCB, M_NOWAIT);
                   2135:        if (nlinkp == 0)
                   2136:                return (NULL);
                   2137:        bzero((caddr_t)nlinkp, sizeof(struct llc_linkcb));
                   2138:        
                   2139:        /* copy link address */
                   2140:        sdl_copy(dst, &nlinkp->llcl_addr);
                   2141: 
                   2142:        /* hold on to the network layer route entry */
                   2143:        nlinkp->llcl_nlrt = nlrt;
                   2144: 
                   2145:        /* likewise the network layer control block */
                   2146:        nlinkp->llcl_nlnext = nlnext;
                   2147: 
                   2148:        /* jot down the link layer route entry */
                   2149:        nlinkp->llcl_llrt = llrt;
                   2150: 
                   2151:        /* reset writeq */
                   2152:        nlinkp->llcl_writeqh = nlinkp->llcl_writeqt = NULL;
                   2153: 
                   2154:        /* setup initial state handler function */
                   2155:        nlinkp->llcl_statehandler = llc_state_ADM;
                   2156:        
                   2157:        /* hold on to interface pointer */
                   2158:        nlinkp->llcl_if = ifp;
                   2159: 
                   2160:        /* get service access point information */
                   2161:        nlinkp->llcl_sapinfo = llc_getsapinfo(sap, ifp);
                   2162: 
                   2163:        /* get window size from SAP info block */
                   2164:        if ((llcwindow = nlinkp->llcl_sapinfo->si_window) == 0)
                   2165:                llcwindow = LLC_MAX_WINDOW;
                   2166: 
                   2167:        /* allocate memory for window buffer */
                   2168:        MALLOC(nlinkp->llcl_output_buffers, struct mbuf **, 
                   2169:               llcwindow*sizeof(struct mbuf *), M_PCB, M_NOWAIT);
                   2170:        if (nlinkp->llcl_output_buffers == 0) {
                   2171:                FREE(nlinkp, M_PCB);
                   2172:                return(NULL);
                   2173:        }
                   2174:        bzero((caddr_t)nlinkp->llcl_output_buffers, 
                   2175:              llcwindow*sizeof(struct mbuf *));
                   2176: 
                   2177:        /* set window size & slotsfree */
                   2178:        nlinkp->llcl_slotsfree = nlinkp->llcl_window = llcwindow;
                   2179: 
                   2180:        /* enter into linked listed of link control blocks */
                   2181:        insque(nlinkp, &llccb_q);
                   2182: 
                   2183:        return(nlinkp);
                   2184: }
                   2185: 
                   2186: /*
                   2187:  * llc_dellink() --- farewell to link control block
                   2188:  */
                   2189: llc_dellink(struct llc_linkcb *linkp)
                   2190: {
                   2191:        register struct mbuf *m;
                   2192:        register struct mbuf *n;
                   2193:        register struct npaidbentry *sapinfo = linkp->llcl_sapinfo;
                   2194:        register i;
                   2195: 
                   2196:        /* notify upper layer of imminent death */
                   2197:        if (linkp->llcl_nlnext && sapinfo->si_ctlinput)
                   2198:                (*sapinfo->si_ctlinput)
                   2199:                   (PRC_DISCONNECT_INDICATION, 
                   2200:                    (struct sockaddr *)&linkp->llcl_addr, linkp->llcl_nlnext);
                   2201: 
                   2202:        /* pull the plug */
                   2203:        if (linkp->llcl_llrt)
                   2204:                ((struct npaidbentry *)(linkp->llcl_llrt->rt_llinfo))->np_link 
                   2205:                        = (struct llc_linkcb *) 0;
                   2206: 
                   2207:        /* leave link control block queue */
                   2208:        remque(linkp);
                   2209: 
                   2210:        /* drop queued packets */
                   2211:        for (m = linkp->llcl_writeqh; m;) {
                   2212:                n = m->m_act;
                   2213:                m_freem(m);
                   2214:                m = n;
                   2215:        }
                   2216: 
                   2217:        /* drop packets in the window */
                   2218:        for(i = 0; i < linkp->llcl_window; i++)
                   2219:                if (linkp->llcl_output_buffers[i])
                   2220:                        m_freem(linkp->llcl_output_buffers[i]);
                   2221: 
                   2222:        /* return the window space */
                   2223:        FREE((caddr_t)linkp->llcl_output_buffers, M_PCB);
                   2224: 
                   2225:        /* return the control block space --- now it's gone ... */
                   2226:        FREE((caddr_t)linkp, M_PCB);
                   2227: }
                   2228: 
                   2229: llc_decode(struct llc* frame, struct llc_linkcb * linkp)
                   2230: {
                   2231:        register int ft = LLC_BAD_PDU;
                   2232: 
                   2233:        if ((frame->llc_control & 01) == 0) {
                   2234:                ft = LLCFT_INFO;
                   2235:        /* S or U frame ? */
                   2236:        } else switch (frame->llc_control) {
                   2237: 
                   2238:        /* U frames */
                   2239:        case LLC_UI:
                   2240:        case LLC_UI_P:     ft = LLC_UI; break;
                   2241:        case LLC_DM:
                   2242:        case LLC_DM_P:     ft =LLCFT_DM; break;
                   2243:        case LLC_DISC:
                   2244:        case LLC_DISC_P:   ft = LLCFT_DISC; break;
                   2245:        case LLC_UA:
                   2246:        case LLC_UA_P:     ft = LLCFT_UA; break;
                   2247:        case LLC_SABME:
                   2248:        case LLC_SABME_P:  ft = LLCFT_SABME; break;
                   2249:        case LLC_FRMR:
                   2250:        case LLC_FRMR_P:   ft = LLCFT_FRMR; break;
                   2251:        case LLC_XID:
                   2252:        case LLC_XID_P:    ft = LLCFT_XID; break;
                   2253:        case LLC_TEST:
                   2254:        case LLC_TEST_P:   ft = LLCFT_TEST; break;
                   2255: 
                   2256:        /* S frames */
                   2257:        case LLC_RR:       ft = LLCFT_RR; break;
                   2258:        case LLC_RNR:      ft = LLCFT_RNR; break;
                   2259:        case LLC_REJ:      ft = LLCFT_REJ; break;
                   2260:        } /* switch */
                   2261: 
                   2262:        if (linkp) {
                   2263:                switch (ft) {
                   2264:                case LLCFT_INFO:
                   2265:                        if (LLCGBITS(frame->llc_control, i_ns) != linkp->llcl_vr) {
                   2266:                                ft = LLC_INVALID_NS;
                   2267:                                break;
                   2268:                        }
                   2269:                        /* fall thru --- yeeeeeee */
                   2270:                case LLCFT_RR:
                   2271:                case LLCFT_RNR:
                   2272:                case LLCFT_REJ:
                   2273:                        /* splash! */
                   2274:                        if (LLC_NR_VALID(linkp, LLCGBITS(frame->llc_control_ext, 
                   2275:                                                         s_nr)) == 0)
                   2276:                                ft = LLC_INVALID_NR;
                   2277:                        break;
                   2278:                }
                   2279:        }
                   2280: 
                   2281:        return ft;
                   2282: }
                   2283: 
                   2284: /*
                   2285:  * llc_anytimersup() --- Checks if at least one timer is still up and running.
                   2286:  */
                   2287: int
                   2288: llc_anytimersup(struct llc_linkcb * linkp)
                   2289: {
                   2290:        register int i;
                   2291:        
                   2292:        FOR_ALL_LLC_TIMERS(i)
                   2293:                if (linkp->llcl_timers[i] > 0)
                   2294:                        break;
                   2295:        if (i == LLC_AGE_SHIFT)
                   2296:                return 0;
                   2297:        else return 1;
                   2298: }
                   2299: 
                   2300: /*
                   2301:  * llc_link_dump() - dump link info
                   2302:  */
                   2303: 
                   2304: #define SAL(s) ((struct sockaddr_dl *)&(s)->llcl_addr)
                   2305: #define CHECK(l, s) if (LLC_STATEEQ(l, s)) return #s
                   2306: 
                   2307: char *timer_names[] = {"ACK", "P", "BUSY", "REJ", "AGE"};
                   2308: 
                   2309: char *
                   2310: llc_getstatename(struct llc_linkcb *linkp)
                   2311: {
                   2312:        CHECK(linkp, ADM);
                   2313:        CHECK(linkp, CONN);
                   2314:        CHECK(linkp, RESET_WAIT);
                   2315:        CHECK(linkp, RESET_CHECK);
                   2316:        CHECK(linkp, SETUP);
                   2317:        CHECK(linkp, RESET);
                   2318:        CHECK(linkp, D_CONN);
                   2319:        CHECK(linkp, ERROR);
                   2320:        CHECK(linkp, NORMAL);
                   2321:        CHECK(linkp, BUSY);
                   2322:        CHECK(linkp, REJECT);
                   2323:        CHECK(linkp, AWAIT);
                   2324:        CHECK(linkp, AWAIT_BUSY);
                   2325:        CHECK(linkp, AWAIT_REJECT);
                   2326: 
                   2327:        return "UNKNOWN - eh?";
                   2328: }
                   2329: 
                   2330: void
                   2331: llc_link_dump(struct llc_linkcb* linkp, const char *message)
                   2332: {
                   2333:        register int i;
                   2334:        register char *state;
                   2335: 
                   2336:        /* print interface */
                   2337:        printf("if %s%d\n", linkp->llcl_if->if_name, linkp->llcl_if->if_unit);
                   2338:        
                   2339:        /* print message */
                   2340:        printf(">> %s <<\n", message);
                   2341: 
                   2342:        /* print MAC and LSAP */
                   2343:        printf("llc addr ");
                   2344:        for (i = 0; i < (SAL(linkp)->sdl_alen)-2; i++)
                   2345:                printf("%x:", (char)*(LLADDR(SAL(linkp))+i) & 0xff);
                   2346:        printf("%x,", (char)*(LLADDR(SAL(linkp))+i) & 0xff);
                   2347:        printf("%x\n", (char)*(LLADDR(SAL(linkp))+i+1) & 0xff);
                   2348: 
                   2349:        /* print state we're in and timers */
                   2350:         printf("state %s, ", llc_getstatename(linkp));
                   2351:         for (i = LLC_ACK_SHIFT; i < LLC_AGE_SHIFT; i++)
                   2352:                printf("%s-%c %d/", timer_names[i], 
                   2353:                       (linkp->llcl_timerflags & (1<<i) ? 'R' : 'S'),
                   2354:                       linkp->llcl_timers[i]);
                   2355:        printf("%s-%c %d\n", timer_names[i], (linkp->llcl_timerflags & (1<<i) ? 
                   2356:                                             'R' : 'S'), linkp->llcl_timers[i]);
                   2357: 
                   2358:        /* print flag values */
                   2359:        printf("flags P %d/F %d/S %d/DATA %d/REMOTE_BUSY %d\n",
                   2360:               LLC_GETFLAG(linkp, P), LLC_GETFLAG(linkp, S), 
                   2361:               LLC_GETFLAG(linkp, DATA), LLC_GETFLAG(linkp, REMOTE_BUSY));
                   2362: 
                   2363:        /* print send and receive state variables, ack, and window */
                   2364:        printf("V(R) %d/V(S) %d/N(R) received %d/window %d/freeslot %d\n",
                   2365:               linkp->llcl_vs, linkp->llcl_vr, linkp->llcl_nr_received,
                   2366:               linkp->llcl_window, linkp->llcl_freeslot);
                   2367: 
                   2368:        /* further expansions can follow here */
                   2369: 
                   2370: }
                   2371: 
                   2372: void
                   2373: llc_trace(struct llc_linkcb *linkp, int level, const char *message)
                   2374: {
                   2375:        if (linkp->llcl_sapinfo->si_trace && level > llc_tracelevel)
                   2376:                llc_link_dump(linkp, message);
                   2377: 
                   2378:        return;
                   2379: }

unix.superglobalmegacorp.com

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