The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netccitt/llc_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: e4e296b3e8732134715edf8b1328b460


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.