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/contrib/ngatm/netnatm/saal/saal_sscop.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 /*
    2  * Copyright (c) 1996-2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * Author: Hartmut Brandt <harti@freebsd.org>
   28  *
   29  * $Begemot: libunimsg/netnatm/saal/saal_sscop.c,v 1.11 2004/07/08 08:22:13 brandt Exp $
   30  *
   31  * Core SSCOP code (ITU-T Q.2110)
   32  */
   33 
   34 #include <netnatm/saal/sscop.h>
   35 #include <netnatm/saal/sscoppriv.h>
   36 
   37 #ifndef FAILURE
   38 #define FAILURE(S)
   39 #endif
   40 
   41 #define MKSTR(S)        #S
   42 
   43 static const char *const sscop_sigs[] = {
   44         MKSTR(SSCOP_ESTABLISH_request),
   45         MKSTR(SSCOP_ESTABLISH_indication),
   46         MKSTR(SSCOP_ESTABLISH_response),
   47         MKSTR(SSCOP_ESTABLISH_confirm),
   48         MKSTR(SSCOP_RELEASE_request),
   49         MKSTR(SSCOP_RELEASE_indication),
   50         MKSTR(SSCOP_RELEASE_confirm),
   51         MKSTR(SSCOP_DATA_request),
   52         MKSTR(SSCOP_DATA_indication),
   53         MKSTR(SSCOP_UDATA_request),
   54         MKSTR(SSCOP_UDATA_indication),
   55         MKSTR(SSCOP_RECOVER_indication),
   56         MKSTR(SSCOP_RECOVER_response),
   57         MKSTR(SSCOP_RESYNC_request),
   58         MKSTR(SSCOP_RESYNC_indication),
   59         MKSTR(SSCOP_RESYNC_response),
   60         MKSTR(SSCOP_RESYNC_confirm),
   61         MKSTR(SSCOP_RETRIEVE_request),
   62         MKSTR(SSCOP_RETRIEVE_indication),
   63         MKSTR(SSCOP_RETRIEVE_COMPL_indication),
   64 };
   65 
   66 static const char *const sscop_msigs[] = {
   67         MKSTR(SSCOP_MDATA_request),
   68         MKSTR(SSCOP_MDATA_indication),
   69         MKSTR(SSCOP_MERROR_indication),
   70 };
   71 
   72 static const char *const states[] = {
   73         MKSTR(SSCOP_IDLE),
   74         MKSTR(SSCOP_OUT_PEND),
   75         MKSTR(SSCOP_IN_PEND),
   76         MKSTR(SSCOP_OUT_DIS_PEND),
   77         MKSTR(SSCOP_OUT_RESYNC_PEND),
   78         MKSTR(SSCOP_IN_RESYNC_PEND),
   79         MKSTR(SSCOP_OUT_REC_PEND),
   80         MKSTR(SSCOP_REC_PEND),
   81         MKSTR(SSCOP_IN_REC_PEND),
   82         MKSTR(SSCOP_READY),
   83 };
   84 
   85 #ifdef SSCOP_DEBUG
   86 static const char *const events[] = {
   87         MKSTR(SIG_BGN),
   88         MKSTR(SIG_BGAK),
   89         MKSTR(SIG_END),
   90         MKSTR(SIG_ENDAK),
   91         MKSTR(SIG_RS),
   92         MKSTR(SIG_RSAK),
   93         MKSTR(SIG_BGREJ),
   94         MKSTR(SIG_SD),
   95         MKSTR(SIG_ER),
   96         MKSTR(SIG_POLL),
   97         MKSTR(SIG_STAT),
   98         MKSTR(SIG_USTAT),
   99         MKSTR(SIG_UD),
  100         MKSTR(SIG_MD),
  101         MKSTR(SIG_ERAK),
  102 
  103         MKSTR(SIG_T_CC),
  104         MKSTR(SIG_T_POLL),
  105         MKSTR(SIG_T_KA),
  106         MKSTR(SIG_T_NR),
  107         MKSTR(SIG_T_IDLE),
  108 
  109         MKSTR(SIG_PDU_Q),
  110         MKSTR(SIG_USER_DATA),
  111         MKSTR(SIG_ESTAB_REQ),
  112         MKSTR(SIG_ESTAB_RESP),
  113         MKSTR(SIG_RELEASE_REQ),
  114         MKSTR(SIG_RECOVER),
  115         MKSTR(SIG_SYNC_REQ),
  116         MKSTR(SIG_SYNC_RESP),
  117         MKSTR(SIG_UDATA),
  118         MKSTR(SIG_MDATA),
  119         MKSTR(SIG_UPDU_Q),
  120         MKSTR(SIG_MPDU_Q),
  121         MKSTR(SIG_RETRIEVE),
  122 };
  123 
  124 static const char *const pdus[] = {
  125         "illegale PDU type 0",          /* no PDU type 0 */
  126         MKSTR(PDU_BGN),
  127         MKSTR(PDU_BGAK),
  128         MKSTR(PDU_END),
  129         MKSTR(PDU_ENDAK),
  130         MKSTR(PDU_RS),
  131         MKSTR(PDU_RSAK),
  132         MKSTR(PDU_BGREJ),
  133         MKSTR(PDU_SD),
  134         MKSTR(PDU_ER),
  135         MKSTR(PDU_POLL),
  136         MKSTR(PDU_STAT),
  137         MKSTR(PDU_USTAT),
  138         MKSTR(PDU_UD),
  139         MKSTR(PDU_MD),
  140         MKSTR(PDU_ERAK),
  141 };
  142 #endif
  143 
  144 MEMINIT();
  145 
  146 static void sscop_signal(struct sscop *, u_int, struct sscop_msg *);
  147 static void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *);
  148 static void handle_sigs(struct sscop *);
  149 static void sscop_set_state(struct sscop *, u_int);
  150 
  151 /************************************************************/
  152 
  153 
  154 /************************************************************/
  155 /*
  156  * Queue macros
  157  */
  158 #define SSCOP_MSG_FREE(MSG)                                             \
  159     do {                                                                \
  160         if(MSG) {                                                       \
  161                 MBUF_FREE((MSG)->m);                                    \
  162                 MSG_FREE((MSG));                                        \
  163         }                                                               \
  164     } while(0)
  165 
  166 static inline struct sscop_msg *QFIND(sscop_msgq_head_t *q, u_int rn)
  167 {
  168         struct sscop_msg *msg = NULL, *m;
  169         MSGQ_FOREACH(m, q) {
  170                 if(m->seqno == rn) {
  171                         msg = m;
  172                         break;
  173                 }
  174         }
  175         return msg;
  176 }
  177 
  178 #define QINSERT(Q,M)                                                    \
  179     do {                                                                \
  180         struct sscop_msg *_msg = NULL, *_m;                             \
  181         MSGQ_FOREACH(_m, (Q)) {                                         \
  182                 if (_m->seqno > (M)->seqno) {                           \
  183                         _msg = _m;                                      \
  184                         break;                                          \
  185                 }                                                       \
  186         }                                                               \
  187         if (_msg != NULL)                                                       \
  188                 MSGQ_INSERT_BEFORE(_msg, (M));                          \
  189         else                                                            \
  190                 MSGQ_APPEND((Q), (M));                                  \
  191     } while (0)
  192 
  193 
  194 /*
  195  * Send an error indication to the management plane.
  196  */
  197 #define MAAL_ERROR(S,E,C)                                               \
  198     do {                                                                \
  199         VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,                     \
  200             "MAA-Signal %s in state %s",                                \
  201             sscop_msigs[SSCOP_MERROR_indication], states[(S)->state])); \
  202         (S)->funcs->send_manage((S), (S)->aarg,                         \
  203             SSCOP_MERROR_indication, NULL, (E), (C));                   \
  204     } while(0)
  205 
  206 #define MAAL_DATA(S,M)                                                  \
  207     do {                                                                \
  208         VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,                     \
  209             "MAA-Signal %s in state %s",                                \
  210             sscop_msigs[SSCOP_MDATA_indication], states[(S)->state]));  \
  211         (S)->funcs->send_manage((S), (S)->aarg,                         \
  212             SSCOP_MDATA_indication, (M), 0, 0);                         \
  213     } while(0)
  214 
  215 #define AAL_DATA(S,D,M,N)                                               \
  216     do {                                                                \
  217         VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,                     \
  218             "AA-Signal %s in state %s",                                 \
  219             sscop_sigs[D], states[(S)->state]));                        \
  220         (S)->funcs->send_upper((S), (S)->aarg, (D), (M), (N));          \
  221     } while(0)
  222 
  223 #define AAL_SIG(S,D)                                                    \
  224     do {                                                                \
  225         VERBOSE(S, SSCOP_DBG_USIG, ((S), (S)->aarg,                     \
  226             "AA-Signal %s in state %s",                                 \
  227             sscop_sigs[D], states[(S)->state]));                        \
  228         (S)->funcs->send_upper((S), (S)->aarg, (D), NULL, 0);           \
  229     } while(0)
  230 
  231 #ifdef SSCOP_DEBUG
  232 #define AAL_SEND(S,M) do {                                              \
  233         if (ISVERBOSE(S, SSCOP_DBG_PDU))                                \
  234                 sscop_dump_pdu(S, "tx", (M));                           \
  235         (S)->funcs->send_lower((S), (S)->aarg, (M));                    \
  236     } while(0)
  237 #else
  238 #define AAL_SEND(S,M) (S)->funcs->send_lower((S), (S)->aarg, (M))
  239 #endif
  240 
  241 
  242 /*
  243  * Free a save user-to-user data buffer and set the pointer to zero
  244  * to signal, that it is free.
  245  */
  246 #define FREE_UU(F)                                                      \
  247         do {                                                            \
  248                 if(sscop->F) {                                          \
  249                         MBUF_FREE(sscop->F);                            \
  250                         sscop->F = NULL;                                \
  251                 }                                                       \
  252         } while(0)
  253 
  254 #define SET_UU(F,U)                                                     \
  255         do {                                                            \
  256                 FREE_UU(F);                                             \
  257                 sscop->F = U->m;                                        \
  258                 U->m = NULL;                                            \
  259                 SSCOP_MSG_FREE(U);                                      \
  260         } while(0)
  261 
  262 #define AAL_UU_SIGNAL(S, SIG, M, PL, SN)                                \
  263         do {                                                            \
  264                 if(MBUF_LEN((M)->m) > 0) {                              \
  265                         MBUF_UNPAD((M)->m,(PL));                        \
  266                         AAL_DATA((S), (SIG), (M)->m, (SN));             \
  267                         (M)->m = NULL;                                  \
  268                 } else {                                                \
  269                         AAL_DATA((S), (SIG), NULL, (SN));               \
  270                 }                                                       \
  271                 SSCOP_MSG_FREE((M));                                    \
  272         } while(0)
  273 
  274 
  275 
  276 TIMER_FUNC(cc, CC)
  277 TIMER_FUNC(nr, NR)
  278 TIMER_FUNC(ka, KA)
  279 TIMER_FUNC(poll, POLL)
  280 TIMER_FUNC(idle, IDLE)
  281 
  282 /************************************************************/
  283 /*
  284  * INSTANCE AND TYPE HANDLING.
  285  */
  286 #ifdef SSCOP_DEBUG
  287 static void
  288 sscop_dump_pdu(struct sscop *sscop, const char *dir,
  289     const struct SSCOP_MBUF_T *m)
  290 {
  291         u_int32_t v1, v2, v3, v4;
  292         u_int size = MBUF_LEN(m);
  293         u_int n, i;
  294 
  295         if (size < 8)
  296                 return;
  297 
  298         v1 = MBUF_TRAIL32(m, -1);
  299         v2 = MBUF_TRAIL32(m, -2);
  300 
  301         switch ((v1 >> 24) & 0xf) {
  302 
  303           case 0:
  304                 return;
  305 
  306           case PDU_BGN:
  307                 sscop->funcs->verbose(sscop, sscop->aarg,
  308                     "%s BGN n(mr)=%u n(sq)=%u pl=%u",
  309                     dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
  310                 return;
  311 
  312           case PDU_BGAK:
  313                 sscop->funcs->verbose(sscop, sscop->aarg,
  314                     "%s BGAK n(mr)=%u pl=%u",
  315                     dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
  316                 return;
  317 
  318           case PDU_END:
  319                 sscop->funcs->verbose(sscop, sscop->aarg,
  320                     "%s END r=%u s=%u pl=%u",
  321                     dir, (v1 >> 29) & 1, (v1 >> 28) & 1, (v1 >> 30) & 0x3);
  322                 return;
  323 
  324           case PDU_ENDAK:
  325                 sscop->funcs->verbose(sscop, sscop->aarg, "%s ENDAK", dir);
  326                 return;
  327 
  328           case PDU_RS:
  329                 sscop->funcs->verbose(sscop, sscop->aarg,
  330                     "%s RS n(mr)=%u n(sq)=%u pl=%u",
  331                     dir, v1 & 0xffffff, v2 & 0xff, (v1 >> 30) & 0x3);
  332                 return;
  333 
  334           case PDU_RSAK:
  335                 sscop->funcs->verbose(sscop, sscop->aarg, "%s RSAK n(mr)=%u",
  336                     dir, v1 & 0xffffff);
  337                 return;
  338 
  339           case PDU_BGREJ:
  340                 sscop->funcs->verbose(sscop, sscop->aarg, "%s BGREJ pl=%u",
  341                     dir, (v1 >> 30) & 0x3);
  342                 return;
  343 
  344           case PDU_SD:
  345                 sscop->funcs->verbose(sscop, sscop->aarg, "%s SD n(s)=%u pl=%u",
  346                     dir, v1 & 0xffffff, (v1 >> 30) & 0x3);
  347                 return;
  348 
  349           case PDU_ER:
  350                 sscop->funcs->verbose(sscop, sscop->aarg, "%s ER n(mr)=%u n(sq)=%u",
  351                     dir, v1 & 0xffffff, v2 & 0xff);
  352                 return;
  353 
  354           case PDU_POLL:
  355                 sscop->funcs->verbose(sscop, sscop->aarg, "%s POLL n(s)=%u n(ps)=%u",
  356                     dir, v1 & 0xffffff, v2 & 0xffffff);
  357                 return;
  358 
  359           case PDU_STAT:
  360                 if (size < 12)
  361                         return;
  362                 v3 = MBUF_TRAIL32(m, -3);
  363                 sscop->funcs->verbose(sscop, sscop->aarg,
  364                     "%s STAT n(r)=%u n(mr)=%u n(ps)=%u",
  365                     dir, v1 & 0xffffff, v2 & 0xffffff, v3 & 0xffffff);
  366                 n = (size - 12) / 4;
  367                 for (i = 0; i < (size - 12) / 4; i++, n--) {
  368                         v4 = MBUF_TRAIL32(m, -4 - (int)i);
  369                         sscop->funcs->verbose(sscop, sscop->aarg,
  370                             "   LE(%u)=%u", n, v4 & 0xffffff);
  371                 }
  372                 return;
  373 
  374           case PDU_USTAT:
  375                 if (size < 16)
  376                         return;
  377                 sscop->funcs->verbose(sscop, sscop->aarg,
  378                     "%s STAT n(r)=%u n(mr)=%u LE1=%u LE2=%u",
  379                     dir, v1 & 0xffffff, v2 & 0xffffff,
  380                     MBUF_TRAIL32(m, -4) & 0xffffff,
  381                     MBUF_TRAIL32(m, -3) & 0xffffff);
  382                 return;
  383 
  384           case PDU_UD:
  385                 sscop->funcs->verbose(sscop, sscop->aarg,
  386                     "%s UD pl=%u", dir, (v1 >> 30) & 0x3);
  387                 return;
  388 
  389           case PDU_MD:
  390                 sscop->funcs->verbose(sscop, sscop->aarg,
  391                     "%s MD pl=%u", dir, (v1 >> 30) & 0x3);
  392                 return;
  393 
  394           case PDU_ERAK:
  395                 sscop->funcs->verbose(sscop, sscop->aarg,
  396                     "%s ERAK n(mr)=%u", dir, v1 & 0xffffff);
  397                 return;
  398         }
  399 }
  400 #endif
  401 
  402 
  403 /*
  404  * Initialize state of variables
  405  */
  406 static void
  407 sscop_init(struct sscop *sscop)
  408 {
  409         sscop->state = SSCOP_IDLE;
  410 
  411         sscop->vt_sq = 0;
  412         sscop->vr_sq = 0;
  413         sscop->clear_buffers = 1;
  414 
  415         sscop->ll_busy = 0;
  416 
  417         sscop->rxq = 0;
  418 }
  419 
  420 static void
  421 sscop_clear(struct sscop *sscop)
  422 {
  423         TIMER_STOP(sscop, cc);
  424         TIMER_STOP(sscop, ka);
  425         TIMER_STOP(sscop, nr);
  426         TIMER_STOP(sscop, idle);
  427         TIMER_STOP(sscop, poll);
  428 
  429         FREE_UU(uu_bgn);
  430         FREE_UU(uu_bgak);
  431         FREE_UU(uu_bgrej);
  432         FREE_UU(uu_end);
  433         FREE_UU(uu_rs);
  434 
  435         MSGQ_CLEAR(&sscop->xq);
  436         MSGQ_CLEAR(&sscop->uxq);
  437         MSGQ_CLEAR(&sscop->mxq);
  438         MSGQ_CLEAR(&sscop->xbuf);
  439         MSGQ_CLEAR(&sscop->rbuf);
  440 
  441         SIGQ_CLEAR(&sscop->sigs);
  442         SIGQ_CLEAR(&sscop->saved_sigs);
  443 }
  444 
  445 
  446 /*
  447  * Allocate instance memory, initialize the state of all variables.
  448  */
  449 struct sscop *
  450 sscop_create(void *a, const struct sscop_funcs *funcs)
  451 {
  452         struct sscop *sscop;
  453 
  454         MEMZALLOC(sscop, struct sscop *, sizeof(struct sscop));
  455         if (sscop == NULL)
  456                 return (NULL);
  457 
  458         if (a == NULL)
  459                 sscop->aarg = sscop;
  460         else
  461                 sscop->aarg = a;
  462         sscop->funcs = funcs;
  463 
  464         sscop->maxk = MAXK;
  465         sscop->maxj = MAXJ;
  466         sscop->maxcc = MAXCC;
  467         sscop->maxpd = MAXPD;
  468         sscop->maxstat = MAXSTAT;
  469         sscop->timercc = TIMERCC;
  470         sscop->timerka = TIMERKA;
  471         sscop->timernr = TIMERNR;
  472         sscop->timerpoll = TIMERPOLL;
  473         sscop->timeridle = TIMERIDLE;
  474         sscop->robustness = 0;
  475         sscop->poll_after_rex = 0;
  476         sscop->mr = MAXMR;
  477 
  478         TIMER_INIT(sscop, cc);
  479         TIMER_INIT(sscop, nr);
  480         TIMER_INIT(sscop, ka);
  481         TIMER_INIT(sscop, poll);
  482         TIMER_INIT(sscop, idle);
  483 
  484         MSGQ_INIT(&sscop->xq);
  485         MSGQ_INIT(&sscop->uxq);
  486         MSGQ_INIT(&sscop->mxq);
  487         MSGQ_INIT(&sscop->rbuf);
  488         MSGQ_INIT(&sscop->xbuf);
  489 
  490         SIGQ_INIT(&sscop->sigs);
  491         SIGQ_INIT(&sscop->saved_sigs);
  492 
  493         sscop_init(sscop);
  494 
  495         return (sscop);
  496 }
  497 
  498 /*
  499  * Free all resources in a sscop instance
  500  */
  501 void
  502 sscop_destroy(struct sscop *sscop)
  503 {
  504         sscop_reset(sscop);
  505 
  506         MEMFREE(sscop);
  507 }
  508 
  509 /*
  510  * Reset the SSCOP instance.
  511  */
  512 void
  513 sscop_reset(struct sscop *sscop)
  514 {
  515         sscop_clear(sscop);
  516         sscop_init(sscop);
  517 }
  518 
  519 void
  520 sscop_getparam(const struct sscop *sscop, struct sscop_param *p)
  521 {
  522         p->timer_cc = sscop->timercc;
  523         p->timer_poll = sscop->timerpoll;
  524         p->timer_keep_alive = sscop->timerka;
  525         p->timer_no_response = sscop->timernr;
  526         p->timer_idle = sscop->timeridle;
  527         p->maxk = sscop->maxk;
  528         p->maxj = sscop->maxj;
  529         p->maxcc = sscop->maxcc;
  530         p->maxpd = sscop->maxpd;
  531         p->maxstat = sscop->maxstat;
  532         p->mr = sscop->mr;
  533         p->flags = 0;
  534         if(sscop->robustness)
  535                 p->flags |= SSCOP_ROBUST;
  536         if(sscop->poll_after_rex)
  537                 p->flags |= SSCOP_POLLREX;
  538 }
  539 
  540 int
  541 sscop_setparam(struct sscop *sscop, struct sscop_param *p, u_int *pmask)
  542 {
  543         u_int mask = *pmask;
  544 
  545         /* can change only in idle state */
  546         if (sscop->state != SSCOP_IDLE)
  547                 return (EISCONN);
  548 
  549         *pmask = 0;
  550 
  551         /*
  552          * first check all parameters
  553          */
  554         if ((mask & SSCOP_SET_TCC) && p->timer_cc == 0)
  555                 *pmask |= SSCOP_SET_TCC;
  556         if ((mask & SSCOP_SET_TPOLL) && p->timer_poll == 0)
  557                 *pmask |= SSCOP_SET_TPOLL;
  558         if ((mask & SSCOP_SET_TKA) && p->timer_keep_alive == 0)
  559                 *pmask |= SSCOP_SET_TKA;
  560         if ((mask & SSCOP_SET_TNR) && p->timer_no_response == 0)
  561                 *pmask |= SSCOP_SET_TNR;
  562         if ((mask & SSCOP_SET_TIDLE) && p->timer_idle == 0)
  563                 *pmask |= SSCOP_SET_TIDLE;
  564         if ((mask & SSCOP_SET_MAXK) && p->maxk > MAXMAXK)
  565                 *pmask |= SSCOP_SET_MAXK;
  566         if ((mask & SSCOP_SET_MAXJ) && p->maxj > MAXMAXJ)
  567                 *pmask |= SSCOP_SET_MAXJ;
  568         if ((mask & SSCOP_SET_MAXCC) && p->maxcc > 255)
  569                 *pmask |= SSCOP_SET_MAXCC;
  570         if ((mask & SSCOP_SET_MAXPD) && p->maxpd >= (1 << 24))
  571                 *pmask |= SSCOP_SET_MAXPD;
  572         if ((mask & SSCOP_SET_MAXSTAT) && 
  573             ((p->maxstat & 1) == 0 || p->maxstat == 1 || p->maxstat == 2 ||
  574             p->maxstat * 4 > MAXMAXK - 8))
  575                 *pmask |= SSCOP_SET_MAXSTAT;
  576         if ((mask & SSCOP_SET_MR) && p->mr >= (1 << 24) - 1)
  577                 *pmask |= SSCOP_SET_MR;
  578 
  579         if (*pmask)
  580                 return (EINVAL);
  581 
  582 
  583         /*
  584          * now set it
  585          */
  586         if (mask & SSCOP_SET_TCC)
  587                 sscop->timercc = p->timer_cc;
  588 
  589         if (mask & SSCOP_SET_TPOLL)
  590                 sscop->timerpoll = p->timer_poll;
  591 
  592         if (mask & SSCOP_SET_TKA)
  593                 sscop->timerka = p->timer_keep_alive;
  594 
  595         if (mask & SSCOP_SET_TNR)
  596                 sscop->timernr = p->timer_no_response;
  597 
  598         if (mask & SSCOP_SET_TIDLE)
  599                 sscop->timeridle = p->timer_idle;
  600 
  601         if (mask & SSCOP_SET_MAXK)
  602                 sscop->maxk = p->maxk;
  603         if (mask & SSCOP_SET_MAXJ)
  604                 sscop->maxj = p->maxj;
  605 
  606         if (mask & SSCOP_SET_MAXCC)
  607                 sscop->maxcc = p->maxcc;
  608         if (mask & SSCOP_SET_MAXPD)
  609                 sscop->maxpd = p->maxpd;
  610         if (mask & SSCOP_SET_MAXSTAT)
  611                 sscop->maxstat = p->maxstat;
  612 
  613         if (mask & SSCOP_SET_MR)
  614                 sscop->mr = p->mr;
  615 
  616         if (mask & SSCOP_SET_ROBUST)
  617                 sscop->robustness = ((p->flags & SSCOP_ROBUST) != 0);
  618 
  619         if (mask & SSCOP_SET_POLLREX)
  620                 sscop->poll_after_rex = ((p->flags & SSCOP_POLLREX) != 0);
  621 
  622         return (0);
  623 }
  624 
  625 enum sscop_state
  626 sscop_getstate(const struct sscop *sscop)
  627 {
  628         return (sscop->state);
  629 }
  630 
  631 
  632 /************************************************************/
  633 /*
  634  * EXTERNAL INPUT SIGNAL MAPPING
  635  */
  636 
  637 /*
  638  * Map AA signal to SSCOP internal signal
  639  */
  640 int
  641 sscop_aasig(struct sscop *sscop, enum sscop_aasig sig,
  642     struct SSCOP_MBUF_T *m, u_int arg)
  643 {
  644         struct sscop_msg *msg;
  645 
  646         if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
  647                 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
  648                     "AA-Signal %u - bad signal", sig));
  649                 MBUF_FREE(m);
  650                 return (EINVAL);
  651         }
  652         VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
  653             "AA-Signal %s in state %s with%s message",
  654             sscop_sigs[sig], states[sscop->state], m ? "" : "out"));
  655 
  656         MSG_ALLOC(msg);
  657         if (msg == NULL) {
  658                 FAILURE("sscop: cannot allocate aasig");
  659                 MBUF_FREE(m);
  660                 return (ENOMEM);
  661         }
  662 
  663         switch(sig) {
  664 
  665           case SSCOP_ESTABLISH_request:
  666                 msg->m = m;
  667                 msg->rexmit = arg;
  668                 sscop_signal(sscop, SIG_ESTAB_REQ, msg);
  669                 break;
  670 
  671           case SSCOP_ESTABLISH_response:
  672                 msg->m = m;
  673                 msg->rexmit = arg;
  674                 sscop_signal(sscop, SIG_ESTAB_RESP, msg);
  675                 break;
  676 
  677           case SSCOP_RELEASE_request:
  678                 msg->m = m;
  679                 sscop_signal(sscop, SIG_RELEASE_REQ, msg);
  680                 break;
  681 
  682           case SSCOP_DATA_request:
  683                 msg->m = m;
  684                 sscop_signal(sscop, SIG_USER_DATA, msg);
  685                 break;
  686 
  687           case SSCOP_UDATA_request:
  688                 msg->m = m;
  689                 sscop_signal(sscop, SIG_UDATA, msg);
  690                 break;
  691 
  692           case SSCOP_RECOVER_response:
  693                 MBUF_FREE(m);
  694                 MSG_FREE(msg);
  695                 sscop_signal(sscop, SIG_RECOVER, NULL);
  696                 break;
  697 
  698           case SSCOP_RESYNC_request:
  699                 msg->m = m;
  700                 sscop_signal(sscop, SIG_SYNC_REQ, msg);
  701                 break;
  702 
  703           case SSCOP_RESYNC_response:
  704                 MBUF_FREE(m);
  705                 MSG_FREE(msg);
  706                 sscop_signal(sscop, SIG_SYNC_RESP, NULL);
  707                 break;
  708 
  709           case SSCOP_RETRIEVE_request:
  710                 MBUF_FREE(m);
  711                 msg->rexmit = arg;
  712                 sscop_signal(sscop, SIG_RETRIEVE, msg);
  713                 break;
  714 
  715           case SSCOP_ESTABLISH_indication:
  716           case SSCOP_ESTABLISH_confirm:
  717           case SSCOP_RELEASE_indication:
  718           case SSCOP_RELEASE_confirm:
  719           case SSCOP_DATA_indication:
  720           case SSCOP_UDATA_indication:
  721           case SSCOP_RECOVER_indication:
  722           case SSCOP_RESYNC_indication:
  723           case SSCOP_RESYNC_confirm:
  724           case SSCOP_RETRIEVE_indication:
  725           case SSCOP_RETRIEVE_COMPL_indication:
  726                 MBUF_FREE(m);
  727                 MSG_FREE(msg);
  728                 return EINVAL;
  729         }
  730 
  731         return 0;
  732 }
  733 
  734 /*
  735  * Signal from layer management.
  736  */
  737 int
  738 sscop_maasig(struct sscop *sscop, enum sscop_maasig sig, struct SSCOP_MBUF_T *m)
  739 {
  740         struct sscop_msg *msg;
  741 
  742         if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
  743                 VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
  744                     "MAA-Signal %u - bad signal", sig));
  745                 MBUF_FREE(m);
  746                 return (EINVAL);
  747         }
  748         VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
  749             "MAA-Signal %s in state %s with%s message",
  750             sscop_msigs[sig], states[sscop->state], m ? "" : "out"));
  751 
  752         MSG_ALLOC(msg);
  753         if (msg == NULL) {
  754                 FAILURE("sscop: cannot allocate maasig");
  755                 MBUF_FREE(m);
  756                 return (ENOMEM);
  757         }
  758 
  759         switch (sig) {
  760 
  761           case SSCOP_MDATA_request:
  762                 msg->m = m;
  763                 sscop_signal(sscop, SIG_MDATA, msg);
  764                 break;
  765 
  766           case SSCOP_MDATA_indication:
  767           case SSCOP_MERROR_indication:
  768                 MBUF_FREE(m);
  769                 MSG_FREE(msg);
  770                 return (EINVAL);
  771         }
  772         return (0);
  773 }
  774 
  775 /*
  776  * Map PDU to SSCOP signal.
  777  */
  778 void
  779 sscop_input(struct sscop *sscop, struct SSCOP_MBUF_T *m)
  780 {
  781         struct sscop_msg *msg;
  782         union pdu pdu;
  783         u_int size;
  784 
  785         MSG_ALLOC(msg);
  786         if(msg == NULL) {
  787                 FAILURE("sscop: cannot allocate in pdu msg");
  788                 MBUF_FREE(m);
  789                 return;
  790         }
  791 
  792         msg->m = m;
  793         msg->rexmit = 0;
  794 
  795         size = MBUF_LEN(m);
  796 
  797         if(size % 4 != 0 || size < 4)
  798                 goto err;
  799 
  800         pdu.sscop_null = MBUF_TRAIL32(m, -1);
  801 
  802         VERBOSE(sscop, SSCOP_DBG_PDU, (sscop, sscop->aarg,
  803             "got %s, size=%u", pdus[pdu.sscop_type], size));
  804 
  805 #ifdef SSCOP_DEBUG
  806 #define ENSURE(C,F)     if(!(C)) { VERBOSE(sscop, SSCOP_DBG_PDU, F); goto err; }
  807 #else
  808 #define ENSURE(C,F)     if(!(C)) goto err
  809 #endif
  810 
  811 #ifdef SSCOP_DEBUG
  812         if (ISVERBOSE(sscop, SSCOP_DBG_PDU))
  813                 sscop_dump_pdu(sscop, "rx", m);
  814 #endif
  815 
  816         switch(pdu.sscop_type) {
  817 
  818           default:
  819                 ENSURE(0, (sscop, sscop->aarg,
  820                     "Bad PDU type %u", pdu.sscop_type));
  821                 break;
  822 
  823           case PDU_BGN:
  824                 ENSURE(size >= 8U, (sscop, sscop->aarg,
  825                         "PDU_BGN size=%u", size));
  826                 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
  827                         "PDU_BGN size=%u pl=%u", size, pdu.sscop_pl));
  828                 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
  829                         "PDU_BGN size=%u", size));
  830                 sscop_signal(sscop, SIG_BGN, msg);
  831                 break;
  832 
  833           case PDU_BGAK:
  834                 ENSURE(size >= 8U, (sscop, sscop->aarg,
  835                         "PDU_BGAK size=%u", size));
  836                 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
  837                         "PDU_BGAK size=%u pl=%u", size, pdu.sscop_pl));
  838                 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
  839                         "PDU_BGAK size=%u", size));
  840                 sscop_signal(sscop, SIG_BGAK, msg);
  841                 break;
  842 
  843           case PDU_END:
  844                 ENSURE(size >= 8U, (sscop, sscop->aarg,
  845                         "PDU_END size=%u", size));
  846                 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
  847                         "PDU_END size=%u pl=%u", size, pdu.sscop_pl));
  848                 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
  849                         "PDU_END size=%u", size));
  850                 sscop_signal(sscop, SIG_END, msg);
  851                 break;
  852 
  853           case PDU_ENDAK:
  854                 ENSURE(size == 8U, (sscop, sscop->aarg,
  855                         "PDU_ENDAK size=%u", size));
  856                 sscop_signal(sscop, SIG_ENDAK, msg);
  857                 break;
  858 
  859           case PDU_BGREJ:
  860                 ENSURE(size >= 8U, (sscop, sscop->aarg,
  861                         "PDU_BGREJ size=%u", size));
  862                 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
  863                         "PDU_BGREJ size=%u pl=%u", size, pdu.sscop_pl));
  864                 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
  865                         "PDU_BGREJ size=%u", size));
  866                 sscop_signal(sscop, SIG_BGREJ, msg);
  867                 break;
  868 
  869           case PDU_SD:
  870                 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
  871                         "PDU_SD size=%u pl=%u", size, pdu.sscop_pl));
  872                 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
  873                         "PDU_SD size=%u", size));
  874                 sscop_signal(sscop, SIG_SD, msg);
  875                 break;
  876 
  877           case PDU_UD:
  878                 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
  879                         "PDU_UD size=%u pl=%u", size, pdu.sscop_pl));
  880                 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
  881                         "PDU_UD size=%u", size));
  882                 sscop_signal(sscop, SIG_UD, msg);
  883                 break;
  884 
  885           case PDU_MD:
  886                 ENSURE(size >= 4U + pdu.sscop_pl, (sscop, sscop->aarg,
  887                         "PDU_MD size=%u pl=%u", size, pdu.sscop_pl));
  888                 ENSURE(size <= 4U + sscop->maxk, (sscop, sscop->aarg,
  889                         "PDU_MD size=%u", size));
  890                 sscop_signal(sscop, SIG_MD, msg);
  891                 break;
  892 
  893           case PDU_POLL:
  894                 ENSURE(size == 8U, (sscop, sscop->aarg,
  895                         "PDU_POLL size=%u", size));
  896                 sscop_signal(sscop, SIG_POLL, msg);
  897                 break;
  898 
  899           case PDU_STAT:
  900                 ENSURE(size >= 12U, (sscop, sscop->aarg,
  901                         "PDU_STAT size=%u", size));
  902                 ENSURE(size <= 12U + 4 * sscop->maxstat, (sscop, sscop->aarg,
  903                         "PDU_STAT size=%u", size));
  904                 sscop_signal(sscop, SIG_STAT, msg);
  905                 break;
  906 
  907           case PDU_RS:
  908                 ENSURE(size >= 8U, (sscop, sscop->aarg,
  909                         "PDU_RS size=%u", size));
  910                 ENSURE(size >= 8U + pdu.sscop_pl, (sscop, sscop->aarg,
  911                         "PDU_RS size=%u pl=%u", size, pdu.sscop_pl));
  912                 ENSURE(size <= 8U + sscop->maxj, (sscop, sscop->aarg,
  913                         "PDU_RS size=%u", size));
  914                 sscop_signal(sscop, SIG_RS, msg);
  915                 break;
  916 
  917           case PDU_RSAK:
  918                 ENSURE(size == 8U, (sscop, sscop->aarg,
  919                         "PDU_RSAK size=%u", size));
  920                 sscop_signal(sscop, SIG_RSAK, msg);
  921                 break;
  922 
  923           case PDU_ER:
  924                 ENSURE(size == 8U, (sscop, sscop->aarg,
  925                         "PDU_ER size=%u", size));
  926                 sscop_signal(sscop, SIG_ER, msg);
  927                 break;
  928 
  929           case PDU_ERAK:
  930                 ENSURE(size == 8U, (sscop, sscop->aarg,
  931                         "PDU_ERAK size=%u", size));
  932                 sscop_signal(sscop, SIG_ERAK, msg);
  933                 break;
  934 
  935           case PDU_USTAT:
  936                 ENSURE(size == 16U, (sscop, sscop->aarg,
  937                         "PDU_ERAK size=%u", size));
  938                 sscop_signal(sscop, SIG_USTAT, msg);
  939                 break;
  940         }
  941 #undef ENSURE
  942         return;
  943 
  944   err:
  945         MAAL_ERROR(sscop, 'U', 0);
  946         SSCOP_MSG_FREE(msg);
  947 }
  948 
  949 /************************************************************/
  950 /*
  951  * UTILITIES
  952  */
  953 
  954 /*
  955  * Move the receiver window by N packets
  956  */
  957 u_int
  958 sscop_window(struct sscop *sscop, u_int n)
  959 {
  960         sscop->vr_mr += n;
  961         return (SEQNO_DIFF(sscop->vr_mr, sscop->vr_r));
  962 }
  963 
  964 /*
  965  * Lower layer busy handling
  966  */
  967 u_int
  968 sscop_setbusy(struct sscop *sscop, int busy)
  969 {
  970         u_int old = sscop->ll_busy;
  971 
  972         if (busy > 0)
  973                 sscop->ll_busy = 1;
  974         else if (busy == 0) {
  975                 sscop->ll_busy = 0;
  976                 if(old)
  977                         handle_sigs(sscop);
  978         }
  979 
  980         return (old);
  981 }
  982 
  983 const char *
  984 sscop_signame(enum sscop_aasig sig)
  985 {
  986         static char str[40];
  987 
  988         if (sig >= sizeof(sscop_sigs)/sizeof(sscop_sigs[0])) {
  989                 sprintf(str, "BAD SSCOP_AASIG %u", sig);
  990                 return (str);
  991         } else {
  992                 return (sscop_sigs[sig]);
  993         }
  994 }
  995 
  996 const char *
  997 sscop_msigname(enum sscop_maasig sig)
  998 {
  999         static char str[40];
 1000 
 1001         if (sig >= sizeof(sscop_msigs)/sizeof(sscop_msigs[0])) {
 1002                 sprintf(str, "BAD SSCOP_MAASIG %u", sig);
 1003                 return (str);
 1004         } else {
 1005                 return (sscop_msigs[sig]);
 1006         }
 1007 }
 1008 
 1009 const char *
 1010 sscop_statename(enum sscop_state s)
 1011 {
 1012         static char str[40];
 1013 
 1014         if (s >= sizeof(states)/sizeof(states[0])) {
 1015                 sprintf(str, "BAD SSCOP_STATE %u", s);
 1016                 return (str);
 1017         } else {
 1018                 return (states[s]);
 1019         }
 1020 }
 1021 
 1022 
 1023 /************************************************************/
 1024 /*
 1025  * MACROS
 1026  */
 1027 
 1028 /*
 1029  * p 75: release buffers
 1030  */
 1031 static void
 1032 m_release_buffers(struct sscop *sscop)
 1033 {
 1034         MSGQ_CLEAR(&sscop->xq);
 1035         MSGQ_CLEAR(&sscop->xbuf);
 1036         sscop->rxq = 0;
 1037         MSGQ_CLEAR(&sscop->rbuf);
 1038 }
 1039 
 1040 /*
 1041  * P 75: Prepare retrival
 1042  */
 1043 static void
 1044 m_prepare_retrieval(struct sscop *sscop)
 1045 {
 1046         struct sscop_msg *msg;
 1047 
 1048         if (sscop->clear_buffers) {
 1049                 MSGQ_CLEAR(&sscop->xq);
 1050                 MSGQ_CLEAR(&sscop->xbuf);
 1051         }
 1052         MSGQ_FOREACH(msg, &sscop->xbuf)
 1053                 msg->rexmit = 0;
 1054         sscop->rxq = 0;
 1055 
 1056         MSGQ_CLEAR(&sscop->rbuf);
 1057 }
 1058 
 1059 /*
 1060  * P 75: Prepare retrival
 1061  */
 1062 static void
 1063 m_prepare_recovery(struct sscop *sscop)
 1064 {
 1065         struct sscop_msg *msg;
 1066 
 1067         if(sscop->clear_buffers) {
 1068                 MSGQ_CLEAR(&sscop->xq);
 1069                 MSGQ_CLEAR(&sscop->xbuf);
 1070         }
 1071         MSGQ_FOREACH(msg, &sscop->xbuf)
 1072                 msg->rexmit = 0;
 1073         sscop->rxq = 0;
 1074 }
 1075 
 1076 
 1077 /*
 1078  * P 75: Clear transmitter
 1079  */
 1080 static void
 1081 m_clear_transmitter(struct sscop *sscop)
 1082 {
 1083         if(!sscop->clear_buffers) {
 1084                 MSGQ_CLEAR(&sscop->xq);
 1085                 MSGQ_CLEAR(&sscop->xbuf);
 1086         }
 1087 }
 1088 
 1089 
 1090 /*
 1091  * p 75: Deliver data
 1092  * Freeing the message is the responibility of the handler function.
 1093  */
 1094 static void
 1095 m_deliver_data(struct sscop *sscop)
 1096 {
 1097         struct sscop_msg *msg;
 1098         u_int sn;
 1099 
 1100         if ((msg = MSGQ_GET(&sscop->rbuf)) == NULL)
 1101                 return;
 1102 
 1103         if (sscop->clear_buffers) {
 1104                 MSGQ_CLEAR(&sscop->rbuf);
 1105                 return;
 1106         }
 1107 
 1108         sn = msg->seqno + 1;
 1109         AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
 1110         MSG_FREE(msg);
 1111 
 1112         while ((msg = MSGQ_GET(&sscop->rbuf)) != NULL) {
 1113                 ASSERT(msg->seqno == sn);
 1114                 if (++sn == SSCOP_MAXSEQNO)
 1115                         sn = 0;
 1116                 AAL_DATA(sscop, SSCOP_DATA_indication, msg->m, msg->seqno);
 1117                 MSG_FREE(msg);
 1118         }
 1119 }
 1120 
 1121 /*
 1122  * P 75: Initialize state variables
 1123  */
 1124 static void
 1125 m_initialize_state(struct sscop *sscop)
 1126 {
 1127         sscop->vt_s = 0;
 1128         sscop->vt_ps = 0;
 1129         sscop->vt_a = 0;
 1130 
 1131         sscop->vt_pa = 1;
 1132         sscop->vt_pd = 0;
 1133         sscop->credit = 1;
 1134 
 1135         sscop->vr_r = 0;
 1136         sscop->vr_h = 0;
 1137 }
 1138 
 1139 /*
 1140  * p 76: Data retrieval
 1141  */
 1142 static void
 1143 m_data_retrieval(struct sscop *sscop, u_int rn)
 1144 {
 1145         struct sscop_msg *s;
 1146 
 1147         if (rn != SSCOP_RETRIEVE_UNKNOWN) {
 1148                 if(rn >= SSCOP_RETRIEVE_TOTAL)
 1149                         rn = sscop->vt_a;
 1150                 else
 1151                         rn++;
 1152                 while(rn >= sscop->vt_a && rn < sscop->vt_s) {
 1153                         if(rn == SSCOP_MAXSEQNO) rn = 0;
 1154                         if((s = QFIND(&sscop->xbuf, rn)) != NULL) {
 1155                                 MSGQ_REMOVE(&sscop->xbuf, s);
 1156                                 AAL_DATA(sscop, SSCOP_RETRIEVE_indication,
 1157                                         s->m, 0);
 1158                                 MSG_FREE(s);
 1159                         }
 1160                         rn++;
 1161                 }
 1162         }
 1163 
 1164         while((s = MSGQ_GET(&sscop->xq)) != NULL) {
 1165                 AAL_DATA(sscop, SSCOP_RETRIEVE_indication, s->m, 0);
 1166                 MSG_FREE(s);
 1167         }
 1168         AAL_SIG(sscop, SSCOP_RETRIEVE_COMPL_indication);
 1169 }
 1170 
 1171 /*
 1172  * P 76: Detect retransmission. PDU type must already be stripped.
 1173  */
 1174 static int
 1175 m_detect_retransmission(struct sscop *sscop, struct sscop_msg *msg)
 1176 {
 1177         union bgn bgn;
 1178 
 1179         bgn.sscop_null = MBUF_TRAIL32(msg->m, -1);
 1180 
 1181         if (sscop->vr_sq == bgn.sscop_bgns)
 1182                 return (1);
 1183 
 1184         sscop->vr_sq = bgn.sscop_bgns;
 1185         return (0);
 1186 }
 1187 
 1188 /*
 1189  * P 76: Set POLL timer
 1190  */
 1191 static void
 1192 m_set_poll_timer(struct sscop *sscop)
 1193 {
 1194         if(MSGQ_EMPTY(&sscop->xq) && sscop->vt_s == sscop->vt_a)
 1195                 TIMER_RESTART(sscop, ka);
 1196         else
 1197                 TIMER_RESTART(sscop, poll);
 1198 }
 1199 
 1200 /*
 1201  * P 77: Reset data transfer timers
 1202  */
 1203 static void
 1204 m_reset_data_xfer_timers(struct sscop *sscop)
 1205 {
 1206         TIMER_STOP(sscop, ka);
 1207         TIMER_STOP(sscop, nr);
 1208         TIMER_STOP(sscop, idle);
 1209         TIMER_STOP(sscop, poll);
 1210 }
 1211 
 1212 /*
 1213  * P 77: Set data transfer timers
 1214  */
 1215 static void
 1216 m_set_data_xfer_timers(struct sscop *sscop)
 1217 {
 1218         TIMER_RESTART(sscop, poll);
 1219         TIMER_RESTART(sscop, nr);
 1220 }
 1221 
 1222 /*
 1223  * P 77: Initialize VR(MR)
 1224  */
 1225 static void
 1226 m_initialize_mr(struct sscop *sscop)
 1227 {
 1228         sscop->vr_mr = sscop->mr;
 1229 }
 1230 
 1231 /************************************************************/
 1232 /*
 1233  * CONDITIONS
 1234  */
 1235 static int
 1236 c_ready_pduq(struct sscop *sscop)
 1237 {
 1238         if (!sscop->ll_busy &&
 1239             (sscop->rxq != 0 ||
 1240             sscop->vt_s < sscop->vt_ms ||
 1241             TIMER_ISACT(sscop, idle)))
 1242                 return (1);
 1243         return (0);
 1244 }
 1245 
 1246 /************************************************************/
 1247 /*
 1248  * SEND PDUS
 1249  */
 1250 
 1251 /*
 1252  * Send BG PDU.
 1253  */
 1254 static void
 1255 send_bgn(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
 1256 {
 1257         union pdu pdu;
 1258         union bgn bgn;
 1259         struct SSCOP_MBUF_T *m;
 1260 
 1261         pdu.sscop_null = 0;
 1262         pdu.sscop_type = PDU_BGN;
 1263         pdu.sscop_ns = sscop->vr_mr;
 1264 
 1265         bgn.sscop_null = 0;
 1266         bgn.sscop_bgns = sscop->vt_sq;
 1267 
 1268         if(uu) {
 1269                 if ((m = MBUF_DUP(uu)) == NULL) {
 1270                         FAILURE("sscop: cannot allocate BGN");
 1271                         return;
 1272                 }
 1273                 pdu.sscop_pl += MBUF_PAD4(m);
 1274         } else {
 1275                 if ((m = MBUF_ALLOC(8)) == NULL) {
 1276                         FAILURE("sscop: cannot allocate BGN");
 1277                         return;
 1278                 }
 1279         }
 1280 
 1281         MBUF_APPEND32(m, bgn.sscop_null);
 1282         MBUF_APPEND32(m, pdu.sscop_null);
 1283 
 1284         AAL_SEND(sscop, m);
 1285 }
 1286 
 1287 /*
 1288  * Send BGREJ PDU.
 1289  */
 1290 static void
 1291 send_bgrej(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
 1292 {
 1293         union pdu pdu;
 1294         union bgn bgn;
 1295         struct SSCOP_MBUF_T *m;
 1296 
 1297         pdu.sscop_null = 0;
 1298         pdu.sscop_type = PDU_BGREJ;
 1299         bgn.sscop_null = 0;
 1300 
 1301         if(uu) {
 1302                 if((m = MBUF_DUP(uu)) == NULL) {
 1303                         FAILURE("sscop: cannot allocate BGREJ");
 1304                         return;
 1305                 }
 1306                 pdu.sscop_pl += MBUF_PAD4(m);
 1307         } else {
 1308                 if((m = MBUF_ALLOC(8)) == NULL) {
 1309                         FAILURE("sscop: cannot allocate BGREJ");
 1310                         return;
 1311                 }
 1312         }
 1313 
 1314         MBUF_APPEND32(m, bgn.sscop_null);
 1315         MBUF_APPEND32(m, pdu.sscop_null);
 1316 
 1317         AAL_SEND(sscop, m);
 1318 }
 1319 
 1320 /*
 1321  * Send BGAK PDU.
 1322  */
 1323 static void
 1324 send_bgak(struct sscop *sscop, struct SSCOP_MBUF_T *uu)
 1325 {
 1326         union pdu pdu;
 1327         union bgn bgn;
 1328         struct SSCOP_MBUF_T *m;
 1329 
 1330         pdu.sscop_null = 0;
 1331         pdu.sscop_type = PDU_BGAK;
 1332         pdu.sscop_ns = sscop->vr_mr;
 1333         bgn.sscop_null = 0;
 1334 
 1335         if(uu) {
 1336                 if((m = MBUF_DUP(uu)) == NULL) {
 1337                         FAILURE("sscop: cannot allocate BGAK");
 1338                         return;
 1339                 }
 1340                 pdu.sscop_pl += MBUF_PAD4(m);
 1341         } else {
 1342                 if((m = MBUF_ALLOC(8)) == NULL) {
 1343                         FAILURE("sscop: cannot allocate BGAK");
 1344                         return;
 1345                 }
 1346         }
 1347 
 1348         MBUF_APPEND32(m, bgn.sscop_null);
 1349         MBUF_APPEND32(m, pdu.sscop_null);
 1350 
 1351         AAL_SEND(sscop, m);
 1352 }
 1353 
 1354 /*
 1355  * Send SD PDU. The function makes a duplicate of the message.
 1356  */
 1357 static void
 1358 send_sd(struct sscop *sscop, struct SSCOP_MBUF_T *m, u_int seqno)
 1359 {
 1360         union pdu pdu;
 1361 
 1362         if((m = MBUF_DUP(m)) == NULL) {
 1363                 FAILURE("sscop: cannot allocate SD");
 1364                 return;
 1365         }
 1366 
 1367         pdu.sscop_null = 0;
 1368         pdu.sscop_pl = 0;
 1369         pdu.sscop_type = PDU_SD;
 1370         pdu.sscop_ns = seqno;
 1371 
 1372         pdu.sscop_pl += MBUF_PAD4(m);
 1373 
 1374         MBUF_APPEND32(m, pdu.sscop_null);
 1375 
 1376         AAL_SEND(sscop, m);
 1377 }
 1378 
 1379 /*
 1380  * Send a UD PDU. The caller must free the sscop msg part.
 1381  */
 1382 static void
 1383 send_ud(struct sscop *sscop, struct SSCOP_MBUF_T *m)
 1384 {
 1385         union pdu pdu;
 1386 
 1387         pdu.sscop_null = 0;
 1388         pdu.sscop_type = PDU_UD;
 1389 
 1390         pdu.sscop_pl += MBUF_PAD4(m);
 1391 
 1392         MBUF_APPEND32(m, pdu.sscop_null);
 1393 
 1394         AAL_SEND(sscop, m);
 1395 }
 1396 
 1397 /*
 1398  * Send a MD PDU. The caller must free the sscop msg part.
 1399  */
 1400 static void
 1401 send_md(struct sscop *sscop, struct SSCOP_MBUF_T *m)
 1402 {
 1403         union pdu pdu;
 1404 
 1405         pdu.sscop_null = 0;
 1406         pdu.sscop_type = PDU_MD;
 1407 
 1408         pdu.sscop_pl += MBUF_PAD4(m);
 1409 
 1410         MBUF_APPEND32(m, pdu.sscop_null);
 1411 
 1412         AAL_SEND(sscop, m);
 1413 }
 1414 
 1415 /*
 1416  * Send END PDU.
 1417  */
 1418 static void
 1419 send_end(struct sscop *sscop, int src, struct SSCOP_MBUF_T *uu)
 1420 {
 1421         union pdu pdu;
 1422         struct SSCOP_MBUF_T *m;
 1423 
 1424         sscop->last_end_src = src;
 1425 
 1426         pdu.sscop_null = 0;
 1427         pdu.sscop_s = src;
 1428         pdu.sscop_type = PDU_END;
 1429 
 1430         if(uu) {
 1431                 if((m = MBUF_DUP(uu)) == NULL) {
 1432                         FAILURE("sscop: cannot allocate END");
 1433                         return;
 1434                 }
 1435                 pdu.sscop_pl += MBUF_PAD4(m);
 1436         } else {
 1437                 if((m = MBUF_ALLOC(8)) == NULL) {
 1438                         FAILURE("sscop: cannot allocate END");
 1439                         return;
 1440                 }
 1441         }
 1442 
 1443         MBUF_APPEND32(m, 0);
 1444         MBUF_APPEND32(m, pdu.sscop_null);
 1445 
 1446         AAL_SEND(sscop, m);
 1447 }
 1448 
 1449 /*
 1450  * Send USTAT PDU. List must be terminated by -1.
 1451  */
 1452 static void
 1453 send_ustat(struct sscop *sscop, ...)
 1454 {
 1455         va_list ap;
 1456         int f;
 1457         u_int n;
 1458         union pdu pdu;
 1459         union seqno seqno;
 1460         struct SSCOP_MBUF_T *m;
 1461 
 1462         va_start(ap, sscop);
 1463         n = 0;
 1464         while((f = va_arg(ap, int)) >= 0)
 1465                 n++;
 1466         va_end(ap);
 1467 
 1468         if((m = MBUF_ALLOC(n * 4 + 8)) == NULL) {
 1469                 FAILURE("sscop: cannot allocate USTAT");
 1470                 return;
 1471         }
 1472 
 1473         va_start(ap, sscop);
 1474         while((f = va_arg(ap, int)) >= 0) {
 1475                 seqno.sscop_null = 0;
 1476                 seqno.sscop_n = f;
 1477                 MBUF_APPEND32(m, seqno.sscop_null);
 1478         }
 1479         va_end(ap);
 1480 
 1481         seqno.sscop_null = 0;
 1482         seqno.sscop_n = sscop->vr_mr;
 1483         MBUF_APPEND32(m, seqno.sscop_null);
 1484 
 1485         pdu.sscop_null = 0;
 1486         pdu.sscop_type = PDU_USTAT;
 1487         pdu.sscop_ns = sscop->vr_r;
 1488         MBUF_APPEND32(m, pdu.sscop_null);
 1489 
 1490         AAL_SEND(sscop, m);
 1491 }
 1492 
 1493 /*
 1494  * Send ER PDU.
 1495  */
 1496 static void
 1497 send_er(struct sscop *sscop)
 1498 {
 1499         union pdu pdu;
 1500         union bgn bgn;
 1501         struct SSCOP_MBUF_T *m;
 1502 
 1503         pdu.sscop_null = 0;
 1504         pdu.sscop_type = PDU_ER;
 1505         pdu.sscop_ns = sscop->vr_mr;
 1506 
 1507         bgn.sscop_null = 0;
 1508         bgn.sscop_bgns = sscop->vt_sq;
 1509 
 1510         if((m = MBUF_ALLOC(8)) == NULL) {
 1511                 FAILURE("sscop: cannot allocate ER");
 1512                 return;
 1513         }
 1514         MBUF_APPEND32(m, bgn.sscop_null);
 1515         MBUF_APPEND32(m, pdu.sscop_null);
 1516 
 1517         AAL_SEND(sscop, m);
 1518 }
 1519 
 1520 /*
 1521  * Send POLL PDU.
 1522  */
 1523 static void
 1524 send_poll(struct sscop *sscop)
 1525 {
 1526         union pdu pdu;
 1527         union seqno seqno;
 1528         struct SSCOP_MBUF_T *m;
 1529 
 1530         seqno.sscop_null = 0;
 1531         seqno.sscop_n = sscop->vt_ps;
 1532 
 1533         pdu.sscop_null = 0;
 1534         pdu.sscop_ns = sscop->vt_s;
 1535         pdu.sscop_type = PDU_POLL;
 1536 
 1537         if((m = MBUF_ALLOC(8)) == NULL) {
 1538                 FAILURE("sscop: cannot allocate POLL");
 1539                 return;
 1540         }
 1541         MBUF_APPEND32(m, seqno.sscop_null);
 1542         MBUF_APPEND32(m, pdu.sscop_null);
 1543 
 1544         AAL_SEND(sscop, m);
 1545 }
 1546 
 1547 /*
 1548  * Send STAT PDU. List is already in buffer.
 1549  */
 1550 static void
 1551 send_stat(struct sscop *sscop, u_int nps, struct SSCOP_MBUF_T *m)
 1552 {
 1553         union pdu pdu;
 1554         union seqno seqno;
 1555 
 1556         seqno.sscop_null = 0;
 1557         seqno.sscop_n = nps;
 1558         MBUF_APPEND32(m, seqno.sscop_null);
 1559 
 1560         seqno.sscop_null = 0;
 1561         seqno.sscop_n = sscop->vr_mr;
 1562         MBUF_APPEND32(m, seqno.sscop_null);
 1563 
 1564         pdu.sscop_null = 0;
 1565         pdu.sscop_type = PDU_STAT;
 1566         pdu.sscop_ns = sscop->vr_r;
 1567         MBUF_APPEND32(m, pdu.sscop_null);
 1568 
 1569         AAL_SEND(sscop, m);
 1570 }
 1571 
 1572 /*
 1573  * Send ENDAK PDU.
 1574  */
 1575 static void
 1576 send_endak(struct sscop *sscop)
 1577 {
 1578         union pdu pdu;
 1579         union seqno seqno;
 1580         struct SSCOP_MBUF_T *m;
 1581 
 1582         seqno.sscop_null = 0;
 1583         pdu.sscop_null = 0;
 1584         pdu.sscop_type = PDU_ENDAK;
 1585 
 1586         if((m = MBUF_ALLOC(8)) == NULL) {
 1587                 FAILURE("sscop: cannot allocate ENDAK");
 1588                 return;
 1589         }
 1590         MBUF_APPEND32(m, seqno.sscop_null);
 1591         MBUF_APPEND32(m, pdu.sscop_null);
 1592 
 1593         AAL_SEND(sscop, m);
 1594 }
 1595 
 1596 /*
 1597  * Send ERAK PDU.
 1598  */
 1599 static void
 1600 send_erak(struct sscop *sscop)
 1601 {
 1602         union pdu pdu;
 1603         union seqno seqno;
 1604         struct SSCOP_MBUF_T *m;
 1605 
 1606         seqno.sscop_null = 0;
 1607         pdu.sscop_null = 0;
 1608         pdu.sscop_type = PDU_ERAK;
 1609         pdu.sscop_ns = sscop->vr_mr;
 1610 
 1611         if((m = MBUF_ALLOC(8)) == NULL) {
 1612                 FAILURE("sscop: cannot allocate ERAK");
 1613                 return;
 1614         }
 1615         MBUF_APPEND32(m, seqno.sscop_null);
 1616         MBUF_APPEND32(m, pdu.sscop_null);
 1617 
 1618         AAL_SEND(sscop, m);
 1619 }
 1620 
 1621 /*
 1622  * Send RS PDU
 1623  */
 1624 static void
 1625 send_rs(struct sscop *sscop, int resend, struct SSCOP_MBUF_T *uu)
 1626 {
 1627         union pdu pdu;
 1628         union bgn bgn;
 1629         struct SSCOP_MBUF_T *m;
 1630 
 1631         pdu.sscop_null = 0;
 1632         pdu.sscop_type = PDU_RS;
 1633         pdu.sscop_ns = resend ? sscop->rs_mr : sscop->vr_mr;
 1634 
 1635         bgn.sscop_null = 0;
 1636         bgn.sscop_bgns = resend ? sscop->rs_sq : sscop->vt_sq;
 1637 
 1638         sscop->rs_mr = pdu.sscop_ns;
 1639         sscop->rs_sq = bgn.sscop_bgns;
 1640 
 1641         if(uu) {
 1642                 if((m = MBUF_DUP(uu)) == NULL) {
 1643                         FAILURE("sscop: cannot allocate RS");
 1644                         return;
 1645                 }
 1646                 pdu.sscop_pl += MBUF_PAD4(m);
 1647         } else {
 1648                 if((m = MBUF_ALLOC(8)) == NULL) {
 1649                         FAILURE("sscop: cannot allocate RS");
 1650                         return;
 1651                 }
 1652         }
 1653 
 1654         MBUF_APPEND32(m, bgn.sscop_null);
 1655         MBUF_APPEND32(m, pdu.sscop_null);
 1656 
 1657         AAL_SEND(sscop, m);
 1658 }
 1659 
 1660 /*
 1661  * Send RSAK pdu
 1662  */
 1663 static void
 1664 send_rsak(struct sscop *sscop)
 1665 {
 1666         union pdu pdu;
 1667         union seqno seqno;
 1668         struct SSCOP_MBUF_T *m;
 1669 
 1670         seqno.sscop_null = 0;
 1671         pdu.sscop_null = 0;
 1672         pdu.sscop_type = PDU_RSAK;
 1673         pdu.sscop_ns = sscop->vr_mr;
 1674 
 1675         if((m = MBUF_ALLOC(8)) == NULL) {
 1676                 FAILURE("sscop: cannot allocate RSAK");
 1677                 return;
 1678         }
 1679 
 1680         MBUF_APPEND32(m, seqno.sscop_null);
 1681         MBUF_APPEND32(m, pdu.sscop_null);
 1682 
 1683         AAL_SEND(sscop, m);
 1684 }
 1685 
 1686 /************************************************************/
 1687 /*
 1688  * P 31; IDLE && AA-ESTABLISH-request
 1689  *      arg is UU data (opt).
 1690  */
 1691 static void
 1692 sscop_idle_establish_req(struct sscop *sscop, struct sscop_msg *uu)
 1693 {
 1694         u_int br = uu->rexmit;
 1695 
 1696         SET_UU(uu_bgn, uu);
 1697 
 1698         m_clear_transmitter(sscop);
 1699 
 1700         sscop->clear_buffers = br;
 1701 
 1702         sscop->vt_cc = 1;
 1703         sscop->vt_sq++;
 1704 
 1705         m_initialize_mr(sscop);
 1706 
 1707         send_bgn(sscop, sscop->uu_bgn);
 1708 
 1709         TIMER_RESTART(sscop, cc);
 1710 
 1711         sscop_set_state(sscop, SSCOP_OUT_PEND);
 1712 }
 1713 
 1714 /*
 1715  * P 31: IDLE && BGN PDU
 1716  *      arg is the received PDU (freed).
 1717  */
 1718 static void
 1719 sscop_idle_bgn(struct sscop *sscop, struct sscop_msg *msg)
 1720 {
 1721         union pdu pdu;
 1722         union bgn bgn;
 1723 
 1724         pdu.sscop_null = MBUF_STRIP32(msg->m);
 1725 
 1726         if(sscop->robustness) {
 1727                 bgn.sscop_null = MBUF_STRIP32(msg->m);
 1728                 sscop->vr_sq = bgn.sscop_bgns;
 1729         } else {
 1730                 if(m_detect_retransmission(sscop, msg)) {
 1731                         send_bgrej(sscop, sscop->uu_bgrej);
 1732                         SSCOP_MSG_FREE(msg);
 1733                         return;
 1734                 }
 1735                 (void)MBUF_STRIP32(msg->m);
 1736         }
 1737 
 1738         sscop->vt_ms = pdu.sscop_ns;
 1739         sscop_set_state(sscop, SSCOP_IN_PEND);
 1740 
 1741         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
 1742 }
 1743 
 1744 /*
 1745  * p 31: IDLE && ENDAK PDU
 1746  * p 34: OUT_PEND && ENDAK PDU
 1747  * p 34: OUT_PEND && SD PDU
 1748  * p 34: OUT_PEND && ERAK PDU
 1749  * p 34: OUT_PEND && END PDU
 1750  * p 34: OUT_PEND && STAT PDU
 1751  * p 34: OUT_PEND && USTAT PDU
 1752  * p 34: OUT_PEND && POLL PDU
 1753  * p 36: OUT_PEND && RS PDU
 1754  * p 36: OUT_PEND && RSAK PDU
 1755  * p 40: OUTGOING_DISCONNECT_PENDING && SD PDU
 1756  * p 40: OUTGOING_DISCONNECT_PENDING && BGAK PDU
 1757  * p 40: OUTGOING_DISCONNECT_PENDING && POLL PDU
 1758  * p 40: OUTGOING_DISCONNECT_PENDING && STAT PDU
 1759  * p 40: OUTGOING_DISCONNECT_PENDING && USTAT PDU
 1760  * p 41: OUTGOING_DISCONNECT_PENDING && ERAK PDU
 1761  * p 42: OUTGOING_DISCONNECT_PENDING && ER PDU
 1762  * p 42: OUTGOING_DISCONNECT_PENDING && RS PDU
 1763  * p 42: OUTGOING_DISCONNECT_PENDING && RSAK PDU
 1764  * p 43: OUTGOING_RESYNC && ER PDU
 1765  * p 43: OUTGOING_RESYNC && POLL PDU
 1766  * p 44: OUTGOING_RESYNC && STAT PDU
 1767  * p 44: OUTGOING_RESYNC && USTAT PDU
 1768  * p 45: OUTGOING_RESYNC && BGAK PDU
 1769  * p 45: OUTGOING_RESYNC && SD PDU
 1770  * p 45: OUTGOING_RESYNC && ERAK PDU
 1771  * P 60: READY && BGAK PDU
 1772  * P 60: READY && ERAK PDU
 1773  *      arg is pdu (freed).
 1774  */
 1775 static void
 1776 sscop_ignore_pdu(struct sscop *sscop __unused, struct sscop_msg *msg)
 1777 {
 1778         SSCOP_MSG_FREE(msg);
 1779 }
 1780 
 1781 /*
 1782  * p 31: IDLE && END PDU
 1783  *      arg is pdu (freed).
 1784  */
 1785 static void
 1786 sscop_idle_end(struct sscop *sscop, struct sscop_msg *msg)
 1787 {
 1788         SSCOP_MSG_FREE(msg);
 1789         send_endak(sscop);
 1790 }
 1791 
 1792 /*
 1793  * p 31: IDLE && ER PDU
 1794  *      arg is pdu (freed).
 1795  */
 1796 static void
 1797 sscop_idle_er(struct sscop *sscop, struct sscop_msg *msg)
 1798 {
 1799         SSCOP_MSG_FREE(msg);
 1800         MAAL_ERROR(sscop, 'L', 0);
 1801         FREE_UU(uu_end);
 1802         send_end(sscop, 1, NULL);
 1803 }
 1804 
 1805 /*
 1806  * p 31: IDLE && BGREJ PDU
 1807  *      arg is pdu (freed).
 1808  */
 1809 static void
 1810 sscop_idle_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 1811 {
 1812         SSCOP_MSG_FREE(msg);
 1813         MAAL_ERROR(sscop, 'D', 0);
 1814         FREE_UU(uu_end);
 1815 }
 1816 
 1817 /*
 1818  * p 32: IDLE && POLL PDU
 1819  *      arg is pdu (freed).
 1820  */
 1821 static void
 1822 sscop_idle_poll(struct sscop *sscop, struct sscop_msg *msg)
 1823 {
 1824         SSCOP_MSG_FREE(msg);
 1825         MAAL_ERROR(sscop, 'G', 0);
 1826         FREE_UU(uu_end);
 1827         send_end(sscop, 1, NULL);
 1828 }
 1829 
 1830 /*
 1831  * p 32: IDLE && SD PDU
 1832  *      arg is pdu (freed).
 1833  */
 1834 static void
 1835 sscop_idle_sd(struct sscop *sscop, struct sscop_msg *msg)
 1836 {
 1837         SSCOP_MSG_FREE(msg);
 1838         MAAL_ERROR(sscop, 'A', 0);
 1839         FREE_UU(uu_end);
 1840         send_end(sscop, 1, NULL);
 1841 }
 1842 
 1843 /*
 1844  * p 32: IDLE && BGAK PDU
 1845  *      arg is pdu (freed).
 1846  */
 1847 static void
 1848 sscop_idle_bgak(struct sscop *sscop, struct sscop_msg *msg)
 1849 {
 1850         SSCOP_MSG_FREE(msg);
 1851         MAAL_ERROR(sscop, 'C', 0);
 1852         FREE_UU(uu_end);
 1853         send_end(sscop, 1, NULL);
 1854 }
 1855 
 1856 /*
 1857  * p 32: IDLE && ERAK PDU
 1858  *      arg is pdu (freed).
 1859  */
 1860 static void
 1861 sscop_idle_erak(struct sscop *sscop, struct sscop_msg *msg)
 1862 {
 1863         SSCOP_MSG_FREE(msg);
 1864         MAAL_ERROR(sscop, 'M', 0);
 1865         FREE_UU(uu_end);
 1866         send_end(sscop, 1, NULL);
 1867 }
 1868 
 1869 /*
 1870  * p 32: IDLE && STAT PDU
 1871  *      arg is pdu (freed).
 1872  */
 1873 static void
 1874 sscop_idle_stat(struct sscop *sscop, struct sscop_msg *msg)
 1875 {
 1876         SSCOP_MSG_FREE(msg);
 1877         MAAL_ERROR(sscop, 'H', 0);
 1878         FREE_UU(uu_end);
 1879         send_end(sscop, 1, NULL);
 1880 }
 1881 
 1882 /*
 1883  * p 32: IDLE && USTAT PDU
 1884  *      arg is pdu (freed).
 1885  */
 1886 static void
 1887 sscop_idle_ustat(struct sscop *sscop, struct sscop_msg *msg)
 1888 {
 1889         SSCOP_MSG_FREE(msg);
 1890         MAAL_ERROR(sscop, 'I', 0);
 1891         FREE_UU(uu_end);
 1892         send_end(sscop, 1, NULL);
 1893 }
 1894 
 1895 /*
 1896  * p 33: IDLE & RS PDU
 1897  *      arg is pdu (freed).
 1898  */
 1899 static void
 1900 sscop_idle_rs(struct sscop *sscop, struct sscop_msg *msg)
 1901 {
 1902         SSCOP_MSG_FREE(msg);
 1903         MAAL_ERROR(sscop, 'J', 0);
 1904         FREE_UU(uu_end);
 1905         send_end(sscop, 1, NULL);
 1906 }
 1907 
 1908 /*
 1909  * p 33: IDLE & RSAK PDU
 1910  *      arg is pdu (freed).
 1911  */
 1912 static void
 1913 sscop_idle_rsak(struct sscop *sscop, struct sscop_msg *msg)
 1914 {
 1915         SSCOP_MSG_FREE(msg);
 1916         MAAL_ERROR(sscop, 'K', 0);
 1917         FREE_UU(uu_end);
 1918         send_end(sscop, 1, NULL);
 1919 }
 1920 
 1921 /*
 1922  * p 33: IDLE && PDU_Q
 1923  * p XX: OUTPEND && PDU_Q
 1924  * p 39: IN_PEND && PDU_Q
 1925  * p 45: OUT_RESYNC_PEND && PDU_Q
 1926  * p 48: IN_RESYNC_PEND && PDU_Q
 1927  *      no arg
 1928  */
 1929 static void
 1930 sscop_flush_pduq(struct sscop *sscop __unused, struct sscop_msg *unused __unused)
 1931 {
 1932 #if 0
 1933         MSGQ_CLEAR(&sscop->xq);
 1934 #endif
 1935 }
 1936 
 1937 /*
 1938  * p 34: OUT_PEND && BGAK PDU
 1939  *      arg is pdu (freed).
 1940  */
 1941 static void
 1942 sscop_outpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
 1943 {
 1944         union pdu pdu;
 1945 
 1946         pdu.sscop_null = MBUF_STRIP32(msg->m);
 1947         (void)MBUF_STRIP32(msg->m);
 1948 
 1949         TIMER_STOP(sscop, cc);
 1950         sscop->vt_ms = pdu.sscop_ns;
 1951 
 1952         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
 1953 
 1954         m_initialize_state(sscop);
 1955         m_set_data_xfer_timers(sscop);
 1956 
 1957         sscop_set_state(sscop, SSCOP_READY);
 1958 }
 1959 
 1960 /*
 1961  * P 34: OUT_PEND && BGREJ PDU
 1962  */
 1963 static void
 1964 sscop_outpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 1965 {
 1966         union pdu pdu;
 1967 
 1968         pdu.sscop_null = MBUF_STRIP32(msg->m);
 1969         (void)MBUF_STRIP32(msg->m);
 1970 
 1971         TIMER_STOP(sscop, cc);
 1972 
 1973         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl, 0);
 1974 
 1975         sscop_set_state(sscop, SSCOP_IDLE);
 1976 }
 1977 
 1978 /*
 1979  * P 35: OUT_PEND && TIMER_CC expiry
 1980  *      no arg
 1981  */
 1982 static void
 1983 sscop_outpend_tcc(struct sscop *sscop, struct sscop_msg *unused __unused)
 1984 {
 1985         if(sscop->vt_cc >= sscop->maxcc) {
 1986                 MAAL_ERROR(sscop, 'O', 0);
 1987                 FREE_UU(uu_end);
 1988                 send_end(sscop, 1, NULL);
 1989 
 1990                 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 1991 
 1992                 sscop_set_state(sscop, SSCOP_IDLE);
 1993         } else {
 1994                 sscop->vt_cc++;
 1995                 send_bgn(sscop, sscop->uu_bgn);
 1996                 TIMER_RESTART(sscop, cc);
 1997         }
 1998 }
 1999 
 2000 /*
 2001  * P 35: OUT_PEND && RELEASE_REQ
 2002  *      arg is UU
 2003  */
 2004 static void
 2005 sscop_outpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
 2006 {
 2007         SET_UU(uu_end, uu);
 2008 
 2009         TIMER_STOP(sscop, cc);
 2010         sscop->vt_cc = 1;
 2011         send_end(sscop, 0, sscop->uu_end);
 2012         TIMER_RESTART(sscop, cc);
 2013 
 2014         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 2015 }
 2016 
 2017 /*
 2018  * P 36: OUT_PEND && BGN PDU
 2019  *      arg is the received PDU (freed).
 2020  */
 2021 static void
 2022 sscop_outpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
 2023 {
 2024         union pdu pdu;
 2025 
 2026         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2027 
 2028         if(m_detect_retransmission(sscop, msg)) {
 2029                 SSCOP_MSG_FREE(msg);
 2030                 return;
 2031         }
 2032         (void)MBUF_STRIP32(msg->m);
 2033 
 2034         TIMER_STOP(sscop, cc);
 2035 
 2036         sscop->vt_ms = pdu.sscop_ns;
 2037 
 2038         m_initialize_mr(sscop);
 2039 
 2040         send_bgak(sscop, sscop->uu_bgak);
 2041  
 2042         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_confirm, msg, pdu.sscop_pl, 0);
 2043 
 2044         m_initialize_state(sscop);
 2045 
 2046         m_set_data_xfer_timers(sscop);
 2047 
 2048         sscop_set_state(sscop, SSCOP_READY);
 2049 }
 2050 
 2051 /*
 2052  * p 37: IN_PEND && AA-ESTABLISH.response
 2053  *      arg is UU
 2054  */
 2055 static void
 2056 sscop_inpend_establish_resp(struct sscop *sscop, struct sscop_msg *uu)
 2057 {
 2058         u_int br = uu->rexmit;
 2059 
 2060         SET_UU(uu_bgak, uu);
 2061 
 2062         m_clear_transmitter(sscop);
 2063         sscop->clear_buffers = br;
 2064         m_initialize_mr(sscop);
 2065         send_bgak(sscop, sscop->uu_bgak);
 2066         m_initialize_state(sscop);
 2067         m_set_data_xfer_timers(sscop);
 2068 
 2069         sscop_set_state(sscop, SSCOP_READY);
 2070 }
 2071 
 2072 /*
 2073  * p 37: IN_PEND && AA-RELEASE.request
 2074  *      arg is uu.
 2075  */
 2076 static void
 2077 sscop_inpend_release_req(struct sscop *sscop, struct sscop_msg *uu)
 2078 {
 2079         SET_UU(uu_bgrej, uu);
 2080 
 2081         send_bgrej(sscop, sscop->uu_bgrej);
 2082 
 2083         sscop_set_state(sscop, SSCOP_IDLE);
 2084 }
 2085 
 2086 /*
 2087  * p 37: IN_PEND && BGN PDU
 2088  *      arg is pdu. (freed)
 2089  */
 2090 static void
 2091 sscop_inpend_bgn(struct sscop *sscop, struct sscop_msg *msg)
 2092 {
 2093         union pdu pdu;
 2094 
 2095         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2096 
 2097         if(m_detect_retransmission(sscop, msg)) {
 2098                 SSCOP_MSG_FREE(msg);
 2099                 return;
 2100         }
 2101         (void)MBUF_STRIP32(msg->m);
 2102 
 2103         sscop->vt_ms = pdu.sscop_ns;
 2104 
 2105         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 2106         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
 2107 }
 2108 
 2109 /*
 2110  * p 37: IN_PEND && ER PDU
 2111  *      arg is pdu (freed).
 2112  */
 2113 static void
 2114 sscop_inpend_er(struct sscop *sscop, struct sscop_msg *msg)
 2115 {
 2116         MAAL_ERROR(sscop, 'L', 0);
 2117         SSCOP_MSG_FREE(msg);
 2118 }
 2119 
 2120 /*
 2121  * p 37: IN_PEND && ENDAK PDU
 2122  *      arg is pdu (freed).
 2123  */
 2124 static void
 2125 sscop_inpend_endak(struct sscop *sscop, struct sscop_msg *msg)
 2126 {
 2127         MAAL_ERROR(sscop, 'F', 0);
 2128 
 2129         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2130 
 2131         sscop_set_state(sscop, SSCOP_IDLE);
 2132 
 2133         SSCOP_MSG_FREE(msg);
 2134 }
 2135 
 2136 /*
 2137  * p 38: IN_PEND && BGAK PDU
 2138  *      arg is pdu (freed).
 2139  */
 2140 static void
 2141 sscop_inpend_bgak(struct sscop *sscop, struct sscop_msg *msg)
 2142 {
 2143         MAAL_ERROR(sscop, 'C', 0);
 2144 
 2145         SSCOP_MSG_FREE(msg);
 2146 }
 2147 
 2148 /*
 2149  * p 38: IN_PEND && BGREJ PDU
 2150  *      arg is pdu (freed).
 2151  */
 2152 static void
 2153 sscop_inpend_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 2154 {
 2155         MAAL_ERROR(sscop, 'D', 0);
 2156 
 2157         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2158 
 2159         SSCOP_MSG_FREE(msg);
 2160 
 2161         sscop_set_state(sscop, SSCOP_IDLE);
 2162 }
 2163 
 2164 /*
 2165  * p 38: IN_PEND && SD PDU
 2166  *      arg is pdu (freed).
 2167  */
 2168 static void
 2169 sscop_inpend_sd(struct sscop *sscop, struct sscop_msg *msg)
 2170 {
 2171         MAAL_ERROR(sscop, 'A', 0);
 2172 
 2173         SSCOP_MSG_FREE(msg);
 2174 
 2175         FREE_UU(uu_end);
 2176         send_end(sscop, 1, NULL);
 2177 
 2178         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2179 
 2180         sscop_set_state(sscop, SSCOP_IDLE);
 2181 }
 2182 
 2183 /*
 2184  * p 38: IN_PEND && USTAT PDU
 2185  *      arg is pdu (freed).
 2186  */
 2187 static void
 2188 sscop_inpend_ustat(struct sscop *sscop, struct sscop_msg *msg)
 2189 {
 2190         MAAL_ERROR(sscop, 'I', 0);
 2191 
 2192         SSCOP_MSG_FREE(msg);
 2193 
 2194         FREE_UU(uu_end);
 2195         send_end(sscop, 1, NULL);
 2196 
 2197         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2198 
 2199         sscop_set_state(sscop, SSCOP_IDLE);
 2200 }
 2201 
 2202 /*
 2203  * p 38: IN_PEND && STAT PDU
 2204  *      arg is pdu (freed).
 2205  */
 2206 static void
 2207 sscop_inpend_stat(struct sscop *sscop, struct sscop_msg *msg)
 2208 {
 2209         MAAL_ERROR(sscop, 'H', 0);
 2210 
 2211         SSCOP_MSG_FREE(msg);
 2212 
 2213         FREE_UU(uu_end);
 2214         send_end(sscop, 1, NULL);
 2215 
 2216         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2217 
 2218         sscop_set_state(sscop, SSCOP_IDLE);
 2219 }
 2220 
 2221 /*
 2222  * p 38: IN_PEND && POLL PDU
 2223  *      arg is pdu (freed).
 2224  */
 2225 static void
 2226 sscop_inpend_poll(struct sscop *sscop, struct sscop_msg *msg)
 2227 {
 2228         MAAL_ERROR(sscop, 'G', 0);
 2229 
 2230         SSCOP_MSG_FREE(msg);
 2231 
 2232         FREE_UU(uu_end);
 2233         send_end(sscop, 1, NULL);
 2234 
 2235         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2236 
 2237         sscop_set_state(sscop, SSCOP_IDLE);
 2238 }
 2239 
 2240 /*
 2241  * p 39: IN_PEND && ERAK PDU
 2242  *      arg is pdu (freed).
 2243  */
 2244 static void
 2245 sscop_inpend_erak(struct sscop *sscop, struct sscop_msg *msg)
 2246 {
 2247         SSCOP_MSG_FREE(msg);
 2248         MAAL_ERROR(sscop, 'M', 0);
 2249 }
 2250 
 2251 /*
 2252  * p 39: IN_PEND & RS PDU
 2253  *      arg is pdu (freed).
 2254  */
 2255 static void
 2256 sscop_inpend_rs(struct sscop *sscop, struct sscop_msg *msg)
 2257 {
 2258         SSCOP_MSG_FREE(msg);
 2259         MAAL_ERROR(sscop, 'J', 0);
 2260 }
 2261 
 2262 /*
 2263  * p 39: IN_PEND & RSAK PDU
 2264  *      arg is pdu (freed).
 2265  */
 2266 static void
 2267 sscop_inpend_rsak(struct sscop *sscop, struct sscop_msg *msg)
 2268 {
 2269         SSCOP_MSG_FREE(msg);
 2270         MAAL_ERROR(sscop, 'K', 0);
 2271 }
 2272 
 2273 /*
 2274  * p 39: IN_PEND && END PDU
 2275  *      arg is pdu (freed).
 2276  *      no uui
 2277  */
 2278 static void
 2279 sscop_inpend_end(struct sscop *sscop, struct sscop_msg *msg)
 2280 {
 2281         union pdu pdu;
 2282 
 2283         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2284         (void)MBUF_STRIP32(msg->m);
 2285 
 2286         send_endak(sscop);
 2287 
 2288         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
 2289                 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
 2290 
 2291         sscop_set_state(sscop, SSCOP_IDLE);
 2292 }
 2293 
 2294 /*
 2295  * p 40: OUT_DIS_PEND && SSCOP_ESTABLISH_request
 2296  *      no arg.
 2297  *      no uui.
 2298  */
 2299 static void
 2300 sscop_outdis_establish_req(struct sscop *sscop, struct sscop_msg *uu)
 2301 {
 2302         SET_UU(uu_bgn, uu);
 2303 
 2304         TIMER_STOP(sscop, cc);
 2305         m_clear_transmitter(sscop);
 2306         sscop->clear_buffers = 1;
 2307         sscop->vt_cc = 1;
 2308         sscop->vt_sq++;
 2309         m_initialize_mr(sscop);
 2310         send_bgn(sscop, sscop->uu_bgn);
 2311         TIMER_RESTART(sscop, cc);
 2312 
 2313         sscop_set_state(sscop, SSCOP_OUT_PEND);
 2314 }
 2315 
 2316 /*
 2317  * p 41: OUT_DIS_PEND && END PDU
 2318  *      arg is pdu (freed).
 2319  */
 2320 static void
 2321 sscop_outdis_end(struct sscop *sscop, struct sscop_msg *msg)
 2322 {
 2323         union pdu pdu;
 2324 
 2325         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2326         (void)MBUF_STRIP32(msg->m);
 2327 
 2328         TIMER_STOP(sscop, cc);
 2329         send_endak(sscop);
 2330 
 2331         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
 2332 
 2333         sscop_set_state(sscop, SSCOP_IDLE);
 2334 }
 2335 
 2336 /*
 2337  * p 41: OUT_DIS_PEND && ENDAK PDU
 2338  * p 41: OUT_DIS_PEND && BGREJ PDU
 2339  *      arg is pdu (freed)
 2340  */
 2341 static void
 2342 sscop_outdis_endak(struct sscop *sscop, struct sscop_msg *msg)
 2343 {
 2344         union pdu pdu;
 2345 
 2346         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2347         (void)MBUF_STRIP32(msg->m);
 2348 
 2349         TIMER_STOP(sscop, cc);
 2350 
 2351         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_confirm, msg, pdu.sscop_pl, 0);
 2352 
 2353         sscop_set_state(sscop, SSCOP_IDLE);
 2354 }
 2355 
 2356 /*
 2357  * p 41: OUT_DIS_PEND && TIMER CC expiry
 2358  *      no arg
 2359  */
 2360 static void
 2361 sscop_outdis_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
 2362 {
 2363         if(sscop->vt_cc >= sscop->maxcc) {
 2364                 MAAL_ERROR(sscop, 'O', 0);
 2365                 AAL_SIG(sscop, SSCOP_RELEASE_confirm);
 2366                 sscop_set_state(sscop, SSCOP_IDLE);
 2367         } else {
 2368                 sscop->vt_cc++;
 2369                 send_end(sscop, sscop->last_end_src, sscop->uu_end);
 2370                 TIMER_RESTART(sscop, cc);
 2371         }
 2372 }
 2373 
 2374 /*
 2375  * p 42: OUT_DIS_PEND && BGN PDU
 2376  *      arg is pdu (freed).
 2377  */
 2378 static void
 2379 sscop_outdis_bgn(struct sscop *sscop, struct sscop_msg *msg)
 2380 {
 2381         union pdu pdu;
 2382 
 2383         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2384 
 2385         if(m_detect_retransmission(sscop, msg)) {
 2386                 FREE_UU(uu_bgak);
 2387                 send_bgak(sscop, NULL);
 2388                 send_end(sscop, sscop->last_end_src, sscop->uu_end);
 2389                 SSCOP_MSG_FREE(msg);
 2390 
 2391         } else {
 2392                 (void)MBUF_STRIP32(msg->m);
 2393 
 2394                 TIMER_STOP(sscop, cc);
 2395                 sscop->vt_ms = pdu.sscop_ns;
 2396                 AAL_SIG(sscop, SSCOP_RELEASE_confirm);
 2397                 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
 2398                         msg, pdu.sscop_pl, 0);
 2399                 sscop_set_state(sscop, SSCOP_IN_PEND);
 2400         }
 2401 }
 2402 
 2403 /*
 2404  * p 43: OUT_RESYNC_PEND && BGN PDU
 2405  *      arg is pdu (freed).
 2406  */
 2407 static void
 2408 sscop_outsync_bgn(struct sscop *sscop, struct sscop_msg *msg)
 2409 {
 2410         union pdu pdu;
 2411 
 2412         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2413 
 2414         if(m_detect_retransmission(sscop, msg)) {
 2415                 send_bgak(sscop, sscop->uu_bgak);
 2416                 send_rs(sscop, 1, sscop->uu_rs);
 2417                 SSCOP_MSG_FREE(msg);
 2418         } else {
 2419                 (void)MBUF_STRIP32(msg->m);
 2420 
 2421                 TIMER_STOP(sscop, cc);
 2422                 sscop->vt_ms = pdu.sscop_ns;
 2423                 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 2424                 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
 2425                         msg, pdu.sscop_pl, 0);
 2426                 sscop_set_state(sscop, SSCOP_IN_PEND);
 2427         }
 2428 }
 2429 
 2430 /*
 2431  * p 43: OUT_RESYNC_PEND && ENDAK PDU
 2432  *      arg is pdu (freed).
 2433  */
 2434 static void
 2435 sscop_outsync_endak(struct sscop *sscop, struct sscop_msg *msg)
 2436 {
 2437         SSCOP_MSG_FREE(msg);
 2438         TIMER_STOP(sscop, cc);
 2439         MAAL_ERROR(sscop, 'F', 0);
 2440         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2441         sscop_set_state(sscop, SSCOP_IDLE);
 2442 }
 2443 
 2444 /*
 2445  * p 43: OUT_RESYNC_PEND && BGREJ PDU
 2446  *      arg is pdu (freed).
 2447  */
 2448 static void
 2449 sscop_outsync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 2450 {
 2451         SSCOP_MSG_FREE(msg);
 2452         TIMER_STOP(sscop, cc);
 2453         MAAL_ERROR(sscop, 'D', 0);
 2454         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2455         sscop_set_state(sscop, SSCOP_IDLE);
 2456 }
 2457 
 2458 /*
 2459  * p 43: OUT_RESYNC_PEND && END PDU
 2460  *      arg is pdu (freed).
 2461  *      no UU-data
 2462  */
 2463 static void
 2464 sscop_outsync_end(struct sscop *sscop, struct sscop_msg *msg)
 2465 {
 2466         union pdu pdu;
 2467 
 2468         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2469         (void)MBUF_STRIP32(msg->m);
 2470 
 2471         TIMER_STOP(sscop, cc);
 2472         send_endak(sscop);
 2473         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication, msg, pdu.sscop_pl,
 2474                 (u_int)pdu.sscop_s);
 2475         sscop_set_state(sscop, SSCOP_IDLE);
 2476 }
 2477 
 2478 /*
 2479  * p 44: OUT_RESYNC && TIMER CC expiry
 2480  */
 2481 static void
 2482 sscop_outsync_cc(struct sscop *sscop, struct sscop_msg *msg __unused)
 2483 {
 2484         if(sscop->vt_cc == sscop->maxcc) {
 2485                 MAAL_ERROR(sscop, 'O', 0);
 2486                 FREE_UU(uu_end);
 2487                 send_end(sscop, 1, NULL);
 2488                 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2489                 sscop_set_state(sscop, SSCOP_IDLE);
 2490         } else {
 2491                 sscop->vt_cc++;
 2492                 send_rs(sscop, 1, sscop->uu_rs);
 2493                 TIMER_RESTART(sscop, cc);
 2494         }
 2495 }
 2496 
 2497 /*
 2498  * p 44: OUT_RESYNC && AA-RELEASE.request
 2499  *      arg is UU
 2500  */
 2501 static void
 2502 sscop_outsync_release_req(struct sscop *sscop, struct sscop_msg *uu)
 2503 {
 2504         SET_UU(uu_end, uu);
 2505 
 2506         TIMER_STOP(sscop, cc);
 2507         sscop->vt_cc = 1;
 2508         send_end(sscop, 0, sscop->uu_end);
 2509         TIMER_RESTART(sscop, cc);
 2510         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 2511 }
 2512 
 2513 /*
 2514  * p 45: OUT_RESYNC && RS PDU
 2515  *      arg is pdu (freed).
 2516  */
 2517 static void
 2518 sscop_outsync_rs(struct sscop *sscop, struct sscop_msg *msg)
 2519 {
 2520         union pdu pdu;
 2521 
 2522         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2523 
 2524         if(m_detect_retransmission(sscop, msg)) {
 2525                 SSCOP_MSG_FREE(msg);
 2526                 return;
 2527         }
 2528         (void)MBUF_STRIP32(msg->m);
 2529 
 2530         TIMER_STOP(sscop, cc);
 2531         sscop->vt_ms = pdu.sscop_ns;
 2532         m_initialize_mr(sscop);
 2533         send_rsak(sscop);
 2534         AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_confirm, msg, pdu.sscop_pl, 0);
 2535         m_initialize_state(sscop);
 2536         m_set_data_xfer_timers(sscop);
 2537         sscop_set_state(sscop, SSCOP_READY);
 2538 }
 2539 
 2540 /*
 2541  * p 45: OUT_RESYNC && RSAK PDU
 2542  *      arg is pdu (freed).
 2543  */
 2544 static void
 2545 sscop_outsync_rsak(struct sscop *sscop, struct sscop_msg *msg)
 2546 {
 2547         union pdu pdu;
 2548 
 2549         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2550 
 2551         SSCOP_MSG_FREE(msg);
 2552 
 2553         TIMER_STOP(sscop, cc);
 2554         sscop->vt_ms = pdu.sscop_ns;
 2555         AAL_SIG(sscop, SSCOP_RESYNC_confirm);
 2556         m_initialize_state(sscop);
 2557         m_set_data_xfer_timers(sscop);
 2558         sscop_set_state(sscop, SSCOP_READY);
 2559 }
 2560 
 2561 /*
 2562  * p 46: IN_RESYNC_PEND && AA-RESYNC.response
 2563  */
 2564 static void
 2565 sscop_insync_sync_resp(struct sscop *sscop, struct sscop_msg *noarg __unused)
 2566 {
 2567         m_initialize_mr(sscop);
 2568         send_rsak(sscop);
 2569         m_clear_transmitter(sscop);
 2570         m_initialize_state(sscop);
 2571         m_set_data_xfer_timers(sscop);
 2572         sscop_set_state(sscop, SSCOP_READY);
 2573 }
 2574 
 2575 /*
 2576  * p 46: IN_RESYNC_PEND && AA-RELEASE.request
 2577  *      arg is uu
 2578  */
 2579 static void
 2580 sscop_insync_release_req(struct sscop *sscop, struct sscop_msg *uu)
 2581 {
 2582         SET_UU(uu_end, uu);
 2583 
 2584         sscop->vt_cc = 1;
 2585         send_end(sscop, 0, sscop->uu_end);
 2586         TIMER_RESTART(sscop, cc);
 2587         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 2588 }
 2589 
 2590 /*
 2591  * p 46: IN_RESYNC_PEND && ENDAK PDU
 2592  *      arg is pdu (freed).
 2593  */
 2594 static void
 2595 sscop_insync_endak(struct sscop *sscop, struct sscop_msg *msg)
 2596 {
 2597         SSCOP_MSG_FREE(msg);
 2598         MAAL_ERROR(sscop, 'F', 0);
 2599         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2600         sscop_set_state(sscop, SSCOP_IDLE);
 2601 }
 2602 
 2603 /*
 2604  * p 46: IN_RESYNC_PEND && BGREJ PDU
 2605  *      arg is pdu (freed).
 2606  */
 2607 static void
 2608 sscop_insync_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 2609 {
 2610         SSCOP_MSG_FREE(msg);
 2611         MAAL_ERROR(sscop, 'D', 0);
 2612         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2613         sscop_set_state(sscop, SSCOP_IDLE);
 2614 }
 2615 
 2616 /*
 2617  * p 46: IN_RESYNC_PEND && END PDU
 2618  *      arg is pdu (freed).
 2619  */
 2620 static void
 2621 sscop_insync_end(struct sscop *sscop, struct sscop_msg *msg)
 2622 {
 2623         union pdu pdu;
 2624 
 2625         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2626         (void)MBUF_STRIP32(msg->m);
 2627 
 2628         send_endak(sscop);
 2629         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
 2630                 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
 2631         sscop_set_state(sscop, SSCOP_IDLE);
 2632 }
 2633 
 2634 /*
 2635  * p 47: IN_RESYNC_PEND && ER PDU
 2636  *      arg is pdu (freed).
 2637  */
 2638 static void
 2639 sscop_insync_er(struct sscop *sscop, struct sscop_msg *msg)
 2640 {
 2641         SSCOP_MSG_FREE(msg);
 2642         MAAL_ERROR(sscop, 'L', 0);
 2643 }
 2644 
 2645 /*
 2646  * p 47: IN_RESYNC_PEND && BGN PDU
 2647  *      arg is pdu (freed).
 2648  */
 2649 static void
 2650 sscop_insync_bgn(struct sscop *sscop, struct sscop_msg *msg)
 2651 {
 2652         union pdu pdu;
 2653 
 2654         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2655 
 2656         if(m_detect_retransmission(sscop, msg)) {
 2657                 MAAL_ERROR(sscop, 'B', 0);
 2658                 SSCOP_MSG_FREE(msg);
 2659                 return;
 2660         }
 2661         (void)MBUF_STRIP32(msg->m);
 2662 
 2663         sscop->vt_ms = pdu.sscop_ns;
 2664         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 2665         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
 2666 
 2667         sscop_set_state(sscop, SSCOP_IN_PEND);
 2668 }
 2669 
 2670 /*
 2671  * p 47: IN_RESYNC_PEND && SD PDU
 2672  *      arg is pdu (freed).
 2673  */
 2674 static void
 2675 sscop_insync_sd(struct sscop *sscop, struct sscop_msg *msg)
 2676 {
 2677         SSCOP_MSG_FREE(msg);
 2678         MAAL_ERROR(sscop, 'A', 0);
 2679         FREE_UU(uu_end);
 2680         send_end(sscop, 1, NULL);
 2681         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2682         sscop_set_state(sscop, SSCOP_IDLE);
 2683 }
 2684 
 2685 /*
 2686  * p 47: IN_RESYNC_PEND && POLL PDU
 2687  *      arg is pdu (freed).
 2688  */
 2689 static void
 2690 sscop_insync_poll(struct sscop *sscop, struct sscop_msg *msg)
 2691 {
 2692         SSCOP_MSG_FREE(msg);
 2693         MAAL_ERROR(sscop, 'G', 0);
 2694         FREE_UU(uu_end);
 2695         send_end(sscop, 1, NULL);
 2696         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2697         sscop_set_state(sscop, SSCOP_IDLE);
 2698 }
 2699 
 2700 /*
 2701  * p 47: IN_RESYNC_PEND && STAT PDU
 2702  *      arg is pdu (freed).
 2703  */
 2704 static void
 2705 sscop_insync_stat(struct sscop *sscop, struct sscop_msg *msg)
 2706 {
 2707         SSCOP_MSG_FREE(msg);
 2708         MAAL_ERROR(sscop, 'H', 0);
 2709         FREE_UU(uu_end);
 2710         send_end(sscop, 1, NULL);
 2711         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2712         sscop_set_state(sscop, SSCOP_IDLE);
 2713 }
 2714 
 2715 /*
 2716  * p 47: IN_RESYNC_PEND && USTAT PDU
 2717  *      arg is pdu (freed).
 2718  */
 2719 static void
 2720 sscop_insync_ustat(struct sscop *sscop, struct sscop_msg *msg)
 2721 {
 2722         SSCOP_MSG_FREE(msg);
 2723         MAAL_ERROR(sscop, 'I', 0);
 2724         FREE_UU(uu_end);
 2725         send_end(sscop, 1, NULL);
 2726         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2727         sscop_set_state(sscop, SSCOP_IDLE);
 2728 }
 2729 
 2730 /*
 2731  * p 48: IN_RESYNC_PEND && BGAK PDU
 2732  *      arg is pdu (freed).
 2733  */
 2734 static void
 2735 sscop_insync_bgak(struct sscop *sscop, struct sscop_msg *msg)
 2736 {
 2737         MAAL_ERROR(sscop, 'C', 0);
 2738         SSCOP_MSG_FREE(msg);
 2739 }
 2740 
 2741 /*
 2742  * p 48: IN_RESYNC_PEND && ERAK PDU
 2743  *      arg is pdu (freed).
 2744  */
 2745 static void
 2746 sscop_insync_erak(struct sscop *sscop, struct sscop_msg *msg)
 2747 {
 2748         MAAL_ERROR(sscop, 'M', 0);
 2749         SSCOP_MSG_FREE(msg);
 2750 }
 2751 
 2752 /*
 2753  * p 48: IN_RESYNC_PEND && RS PDU
 2754  *      arg is pdu (freed).
 2755  */
 2756 static void
 2757 sscop_insync_rs(struct sscop *sscop, struct sscop_msg *msg)
 2758 {
 2759         union pdu pdu;
 2760 
 2761         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2762 
 2763         if(m_detect_retransmission(sscop, msg)) {
 2764                 SSCOP_MSG_FREE(msg);
 2765                 return;
 2766         }
 2767         SSCOP_MSG_FREE(msg);
 2768         MAAL_ERROR(sscop, 'J', 0);
 2769 }
 2770 
 2771 /*
 2772  * p 48: IN_RESYNC_PEND && RSAK PDU
 2773  *      arg is pdu (freed).
 2774  */
 2775 static void
 2776 sscop_insync_rsak(struct sscop *sscop, struct sscop_msg *msg)
 2777 {
 2778         MAAL_ERROR(sscop, 'K', 0);
 2779         SSCOP_MSG_FREE(msg);
 2780 }
 2781 
 2782 
 2783 /*
 2784  * p 49: OUT_REC_PEND && AA-DATA.request
 2785  *      arg is message (queued).
 2786  */
 2787 static void
 2788 sscop_outrec_userdata(struct sscop *sscop, struct sscop_msg *msg)
 2789 {
 2790         if(!sscop->clear_buffers) {
 2791                 MSGQ_APPEND(&sscop->xq, msg);
 2792                 sscop_signal(sscop, SIG_PDU_Q, msg);
 2793         } else {
 2794                 SSCOP_MSG_FREE(msg);
 2795         }
 2796 }
 2797 
 2798 /*
 2799  * p 49: OUT_REC_PEND && BGAK PDU
 2800  *      arg is pdu (freed)
 2801  */
 2802 static void
 2803 sscop_outrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
 2804 {
 2805         MAAL_ERROR(sscop, 'C', 0);
 2806 
 2807         SSCOP_MSG_FREE(msg);
 2808 }
 2809 
 2810 /*
 2811  * p 49: OUT_REC_PEND && ERAK PDU
 2812  *      arg is pdu (freed)
 2813  */
 2814 static void
 2815 sscop_outrec_erak(struct sscop *sscop, struct sscop_msg *msg)
 2816 {
 2817         union pdu pdu;
 2818 
 2819         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2820 
 2821         TIMER_STOP(sscop, cc);
 2822         sscop->vt_ms = pdu.sscop_ns;
 2823         m_deliver_data(sscop);
 2824 
 2825         AAL_SIG(sscop, SSCOP_RECOVER_indication);
 2826 
 2827         sscop_set_state(sscop, SSCOP_REC_PEND);
 2828 
 2829         SSCOP_MSG_FREE(msg);
 2830 }
 2831 
 2832 /*
 2833  * p 49: OUT_REC_PEND && END PDU
 2834  *      arg is pdu (freed)
 2835  */
 2836 static void
 2837 sscop_outrec_end(struct sscop *sscop, struct sscop_msg *msg)
 2838 {
 2839         union pdu pdu;
 2840 
 2841         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2842         (void)MBUF_STRIP32(msg->m);
 2843 
 2844         TIMER_STOP(sscop, cc);
 2845         send_endak(sscop);
 2846         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
 2847                 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
 2848 
 2849         MSGQ_CLEAR(&sscop->rbuf);
 2850 
 2851         sscop_set_state(sscop, SSCOP_IDLE);
 2852 }
 2853 
 2854 /*
 2855  * p 49: OUT_REC_PEND && ENDAK PDU
 2856  *      arg is pdu (freed)
 2857  */
 2858 static void
 2859 sscop_outrec_endak(struct sscop *sscop, struct sscop_msg *msg)
 2860 {
 2861         MAAL_ERROR(sscop, 'F', 0);
 2862         TIMER_STOP(sscop, cc);
 2863         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2864         MSGQ_CLEAR(&sscop->rbuf);
 2865 
 2866         sscop_set_state(sscop, SSCOP_IDLE);
 2867 
 2868         SSCOP_MSG_FREE(msg);
 2869 }
 2870 
 2871 /*
 2872  * p 49: OUT_REC_PEND && BGREJ PDU
 2873  *      arg is pdu (freed)
 2874  */
 2875 static void
 2876 sscop_outrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 2877 {
 2878         MAAL_ERROR(sscop, 'D', 0);
 2879         TIMER_STOP(sscop, cc);
 2880         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2881         MSGQ_CLEAR(&sscop->rbuf);
 2882 
 2883         sscop_set_state(sscop, SSCOP_IDLE);
 2884 
 2885         SSCOP_MSG_FREE(msg);
 2886 }
 2887 
 2888 /*
 2889  * p 50: OUT_REC_PEND && TIMER CC expiry
 2890  *      no arg.
 2891  */
 2892 static void
 2893 sscop_outrec_cc(struct sscop *sscop, struct sscop_msg *unused __unused)
 2894 {
 2895         if(sscop->vt_cc >= sscop->maxcc) {
 2896                 MAAL_ERROR(sscop, 'O', 0);
 2897                 FREE_UU(uu_end);
 2898                 send_end(sscop, 1, NULL);
 2899                 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 2900                 MSGQ_CLEAR(&sscop->rbuf);
 2901                 sscop_set_state(sscop, SSCOP_IDLE);
 2902         } else {
 2903                 sscop->vt_cc++;
 2904                 send_er(sscop);
 2905                 TIMER_RESTART(sscop, cc);
 2906         }
 2907 }
 2908 
 2909 /*
 2910  * p 50: OUT_REC_PEND && SSCOP_RELEASE_request
 2911  *      arg is UU
 2912  */
 2913 static void
 2914 sscop_outrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
 2915 {
 2916         SET_UU(uu_end, uu);
 2917 
 2918         TIMER_STOP(sscop, cc);
 2919         sscop->vt_cc = 1;
 2920         send_end(sscop, 0, sscop->uu_end);
 2921         MSGQ_CLEAR(&sscop->rbuf);
 2922         TIMER_RESTART(sscop, cc);
 2923 
 2924         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 2925 }
 2926 
 2927 /*
 2928  * p 51: OUT_REC_PEND && AA-RESYNC.request
 2929  *      arg is uu
 2930  */
 2931 static void
 2932 sscop_outrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
 2933 {
 2934         SET_UU(uu_rs, uu);
 2935 
 2936         TIMER_STOP(sscop, cc);
 2937         sscop->vt_cc = 1;
 2938         sscop->vt_sq++;
 2939         m_initialize_mr(sscop);
 2940         send_rs(sscop, 0, sscop->uu_rs);
 2941         m_clear_transmitter(sscop);
 2942         MSGQ_CLEAR(&sscop->rbuf);
 2943         TIMER_RESTART(sscop, cc);
 2944 }
 2945 
 2946 /*
 2947  * p 51: OUT_REC_PEND && BGN PDU
 2948  *      arg is pdu (freed).
 2949  *      no uui
 2950  */
 2951 static void
 2952 sscop_outrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
 2953 {
 2954         union pdu pdu;
 2955 
 2956         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2957 
 2958         if(m_detect_retransmission(sscop, msg)) {
 2959                 MAAL_ERROR(sscop, 'B', 0);
 2960                 SSCOP_MSG_FREE(msg);
 2961         } else {
 2962                 (void)MBUF_STRIP32(msg->m);
 2963 
 2964                 TIMER_STOP(sscop, cc);
 2965                 sscop->vt_ms = pdu.sscop_ns;
 2966                 AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 2967                 AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication,
 2968                         msg, pdu.sscop_pl, 0);
 2969                 MSGQ_CLEAR(&sscop->rbuf);
 2970 
 2971                 sscop_set_state(sscop, SSCOP_IN_PEND);
 2972         }
 2973 }
 2974 
 2975 /*
 2976  * p 51: OUT_REC_PEND && ER PDU
 2977  *      arg is pdu (freed).
 2978  */
 2979 static void
 2980 sscop_outrec_er(struct sscop *sscop, struct sscop_msg *msg)
 2981 {
 2982         union pdu pdu;
 2983 
 2984         pdu.sscop_null = MBUF_STRIP32(msg->m);
 2985 
 2986         if(m_detect_retransmission(sscop, msg)) {
 2987                 MAAL_ERROR(sscop, 'L', 0);
 2988         } else {
 2989                 TIMER_STOP(sscop, cc);
 2990                 sscop->vt_ms = pdu.sscop_ns;
 2991                 m_initialize_mr(sscop);
 2992                 send_erak(sscop);
 2993                 m_deliver_data(sscop);
 2994 
 2995                 AAL_SIG(sscop, SSCOP_RECOVER_indication);
 2996 
 2997                 sscop_set_state(sscop, SSCOP_REC_PEND);
 2998         }
 2999 
 3000         SSCOP_MSG_FREE(msg);
 3001 }
 3002 
 3003 /*
 3004  * p 52: OUT_REC_PEND && SD PDU queued
 3005  *      no arg.
 3006  */
 3007 static void
 3008 sscop_outrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
 3009 {
 3010         sscop_save_signal(sscop, SIG_PDU_Q, msg);
 3011 }
 3012 
 3013 /*
 3014  * p 52: OUT_REC_PEND && RSAK PDU
 3015  *      arg is pdu (freed).
 3016  */
 3017 static void
 3018 sscop_outrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
 3019 {
 3020         SSCOP_MSG_FREE(msg);
 3021         MAAL_ERROR(sscop, 'K', 0);
 3022 }
 3023 
 3024 /*
 3025  * p 52: OUT_REC_PEND && RS PDU
 3026  *      arg is pdu (freed).
 3027  */
 3028 static void
 3029 sscop_outrec_rs(struct sscop *sscop, struct sscop_msg *msg)
 3030 {
 3031         union pdu pdu;
 3032 
 3033         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3034 
 3035         if(m_detect_retransmission(sscop, msg)) {
 3036                 SSCOP_MSG_FREE(msg);
 3037                 MAAL_ERROR(sscop, 'J', 0);
 3038                 return;
 3039         }
 3040         (void)MBUF_STRIP32(msg->m);
 3041 
 3042         TIMER_STOP(sscop, cc);
 3043         sscop->vt_ms = pdu.sscop_ns;
 3044         AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
 3045         MSGQ_CLEAR(&sscop->rbuf);
 3046         sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
 3047 }
 3048 
 3049 /*
 3050  * p 53: REC_PEND && BGAK PDU
 3051  *      arg is pdu (freed)
 3052  */
 3053 static void
 3054 sscop_rec_bgak(struct sscop *sscop, struct sscop_msg *msg)
 3055 {
 3056         MAAL_ERROR(sscop, 'C', 0);
 3057 
 3058         SSCOP_MSG_FREE(msg);
 3059 }
 3060 
 3061 /*
 3062  * p 53: REC_PEND && END PDU
 3063  *      arg is pdu (freed)
 3064  *      no uui
 3065  */
 3066 static void
 3067 sscop_rec_end(struct sscop *sscop, struct sscop_msg *msg)
 3068 {
 3069         union pdu pdu;
 3070 
 3071         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3072         (void)MBUF_STRIP32(msg->m);
 3073 
 3074         send_endak(sscop);
 3075         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
 3076                 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
 3077 
 3078         sscop_set_state(sscop, SSCOP_IDLE);
 3079 }
 3080 
 3081 /*
 3082  * p 53: REC_PEND && ENDAK PDU
 3083  *      arg is pdu (freed)
 3084  */
 3085 static void
 3086 sscop_rec_endak(struct sscop *sscop, struct sscop_msg *msg)
 3087 {
 3088         MAAL_ERROR(sscop, 'F', 0);
 3089         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3090         sscop_set_state(sscop, SSCOP_IDLE);
 3091         SSCOP_MSG_FREE(msg);
 3092 }
 3093 
 3094 /*
 3095  * p 53: REC_PEND && BGREJ PDU
 3096  *      arg is pdu (freed)
 3097  */
 3098 static void
 3099 sscop_rec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 3100 {
 3101         MAAL_ERROR(sscop, 'D', 0);
 3102         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3103         sscop_set_state(sscop, SSCOP_IDLE);
 3104         SSCOP_MSG_FREE(msg);
 3105 }
 3106 
 3107 /*
 3108  * p 54: REC_PEND && RELEASE
 3109  *      arg is UU
 3110  */
 3111 static void
 3112 sscop_rec_release_req(struct sscop *sscop, struct sscop_msg *uu)
 3113 {
 3114         SET_UU(uu_end, uu);
 3115 
 3116         sscop->vt_cc = 1;
 3117         send_end(sscop, 0, sscop->uu_end);
 3118         TIMER_RESTART(sscop, cc);
 3119 
 3120         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 3121 }
 3122 
 3123 /*
 3124  * p 54: REC_PEND && RSAK PDU
 3125  *      arg is pdu (freed).
 3126  */
 3127 static void
 3128 sscop_rec_rsak(struct sscop *sscop, struct sscop_msg *msg)
 3129 {
 3130         MAAL_ERROR(sscop, 'K', 0);
 3131         SSCOP_MSG_FREE(msg);
 3132 }
 3133 
 3134 
 3135 /*
 3136  * p 54: REC_PEND && RS PDU
 3137  *      arg is pdu (freed).
 3138  */
 3139 static void
 3140 sscop_rec_rs(struct sscop *sscop, struct sscop_msg *msg)
 3141 {
 3142         union pdu pdu;
 3143 
 3144         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3145 
 3146         if(m_detect_retransmission(sscop, msg)) {
 3147                 SSCOP_MSG_FREE(msg);
 3148                 MAAL_ERROR(sscop, 'J', 0);
 3149                 return;
 3150         }
 3151         (void)MBUF_STRIP32(msg->m);
 3152 
 3153         sscop->vt_ms = pdu.sscop_ns;
 3154         AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
 3155 
 3156         sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
 3157 }
 3158 
 3159 /*
 3160  * p 54: REC_PEND && RECOVER response
 3161  *      no arg
 3162  */
 3163 static void
 3164 sscop_rec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
 3165 {
 3166         if(!sscop->clear_buffers) {
 3167                 MSGQ_CLEAR(&sscop->xbuf);
 3168         }
 3169         m_initialize_state(sscop);
 3170         m_set_data_xfer_timers(sscop);
 3171 
 3172         sscop_set_state(sscop, SSCOP_READY);
 3173 }
 3174 
 3175 /*
 3176  * p 54: REC_PEND && RESYNC request
 3177  *      arg is uu
 3178  */
 3179 static void
 3180 sscop_rec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
 3181 {
 3182         SET_UU(uu_rs, uu);
 3183 
 3184         m_clear_transmitter(sscop);
 3185         sscop->vt_cc = 1;
 3186         sscop->vt_sq++;
 3187         m_initialize_mr(sscop);
 3188         send_rs(sscop, 0, sscop->uu_rs);
 3189         TIMER_RESTART(sscop, cc);
 3190 
 3191         sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
 3192 }
 3193 
 3194 /*
 3195  * p 55: REC_PEND && SD PDU queued
 3196  *      no arg
 3197  */
 3198 static void
 3199 sscop_rec_pduq(struct sscop *sscop, struct sscop_msg *msg)
 3200 {
 3201         sscop_save_signal(sscop, SIG_PDU_Q, msg);
 3202 }
 3203 
 3204 /*
 3205  * p 55: REC_PEND && ER PDU
 3206  *      arg is pdu (freed).
 3207  */
 3208 static void
 3209 sscop_rec_er(struct sscop *sscop, struct sscop_msg *msg)
 3210 {
 3211         union pdu pdu;
 3212 
 3213         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3214 
 3215         if(m_detect_retransmission(sscop, msg)) {
 3216                 send_erak(sscop);
 3217         } else {
 3218                 MAAL_ERROR(sscop, 'L', 0);
 3219         }
 3220         SSCOP_MSG_FREE(msg);
 3221 }
 3222 
 3223 /*
 3224  * p 55: REC_PEND && BGN PDU
 3225  *      arg is pdu (freed)
 3226  *      no uui
 3227  */
 3228 static void
 3229 sscop_rec_bgn(struct sscop *sscop, struct sscop_msg *msg)
 3230 {
 3231         union pdu pdu;
 3232 
 3233         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3234 
 3235         if(m_detect_retransmission(sscop, msg)) {
 3236                 MAAL_ERROR(sscop, 'B', 0);
 3237                 SSCOP_MSG_FREE(msg);
 3238                 return;
 3239         }
 3240         (void)MBUF_STRIP32(msg->m);
 3241 
 3242         sscop->vt_ms = pdu.sscop_ns;
 3243         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 3244         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
 3245 
 3246         sscop_set_state(sscop, SSCOP_IN_PEND);
 3247 }
 3248 
 3249 /*
 3250  * p 55: REC_PEND && STAT PDU
 3251  *      arg is pdu (freed)
 3252  */
 3253 static void
 3254 sscop_rec_stat(struct sscop *sscop, struct sscop_msg *msg)
 3255 {
 3256         MAAL_ERROR(sscop, 'H', 0);
 3257         FREE_UU(uu_end);
 3258         send_end(sscop, 1, NULL);
 3259         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3260         sscop_set_state(sscop, SSCOP_IDLE);
 3261         SSCOP_MSG_FREE(msg);
 3262 }
 3263 
 3264 /*
 3265  * p 55: REC_PEND && USTAT PDU
 3266  *      arg is pdu (freed)
 3267  */
 3268 static void
 3269 sscop_rec_ustat(struct sscop *sscop, struct sscop_msg *msg)
 3270 {
 3271         MAAL_ERROR(sscop, 'I', 0);
 3272         FREE_UU(uu_end);
 3273         send_end(sscop, 1, NULL);
 3274         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3275         sscop_set_state(sscop, SSCOP_IDLE);
 3276         SSCOP_MSG_FREE(msg);
 3277 }
 3278 
 3279 /*
 3280  * p 56: IN_REC_PEND && AA-RECOVER.response
 3281  *      no arg
 3282  */
 3283 static void
 3284 sscop_inrec_recover(struct sscop *sscop, struct sscop_msg *unused __unused)
 3285 {
 3286         if(!sscop->clear_buffers) {
 3287                 MSGQ_CLEAR(&sscop->xbuf);
 3288         }
 3289         m_initialize_mr(sscop);
 3290         send_erak(sscop);
 3291         m_initialize_state(sscop);
 3292         m_set_data_xfer_timers(sscop);
 3293 
 3294         sscop_set_state(sscop, SSCOP_READY);
 3295 }
 3296 
 3297 /*
 3298  * p 56: IN_REC_PEND && SD PDU queued
 3299  *      no arg
 3300  */
 3301 static void
 3302 sscop_inrec_pduq(struct sscop *sscop, struct sscop_msg *msg)
 3303 {
 3304         sscop_save_signal(sscop, SIG_PDU_Q, msg);
 3305 }
 3306 
 3307 /*
 3308  * p 56: IN_REC_PEND && AA-RELEASE.request
 3309  *      arg is UU
 3310  */
 3311 static void
 3312 sscop_inrec_release_req(struct sscop *sscop, struct sscop_msg *uu)
 3313 {
 3314         SET_UU(uu_end, uu);
 3315 
 3316         sscop->vt_cc = 1;
 3317         send_end(sscop, 0, sscop->uu_end);
 3318         TIMER_RESTART(sscop, cc);
 3319 
 3320         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 3321 }
 3322 
 3323 /*
 3324  * p 56: IN_REC_PEND && END PDU
 3325  *      arg is pdu (freed).
 3326  *      no uui
 3327  */
 3328 static void
 3329 sscop_inrec_end(struct sscop *sscop, struct sscop_msg *msg)
 3330 {
 3331         union pdu pdu;
 3332 
 3333         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3334         (void)MBUF_STRIP32(msg->m);
 3335 
 3336         send_endak(sscop);
 3337         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
 3338                 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
 3339 
 3340         sscop_set_state(sscop, SSCOP_IDLE);
 3341 }
 3342 
 3343 /*
 3344  * p 56: IN_REC_PEND && RESYNC_REQ
 3345  */
 3346 static void
 3347 sscop_inrec_sync_req(struct sscop *sscop, struct sscop_msg *uu)
 3348 {
 3349         SET_UU(uu_rs, uu);
 3350 
 3351         m_clear_transmitter(sscop);
 3352         sscop->vt_cc = 1;
 3353         sscop->vt_sq++;
 3354         m_initialize_mr(sscop);
 3355         send_rs(sscop, 0, sscop->uu_rs);
 3356         TIMER_RESTART(sscop, cc);
 3357 
 3358         sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
 3359 }
 3360 
 3361 
 3362 /*
 3363  * p 57: IN_REC_PEND && ENDAK PDU
 3364  *      arg is pdu (freed)
 3365  */
 3366 static void
 3367 sscop_inrec_endak(struct sscop *sscop, struct sscop_msg *msg)
 3368 {
 3369         MAAL_ERROR(sscop, 'F', 0);
 3370         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3371         SSCOP_MSG_FREE(msg);
 3372         sscop_set_state(sscop, SSCOP_IDLE);
 3373 }
 3374 
 3375 /*
 3376  * p 57: IN_REC_PEND && BGREJ PDU
 3377  *      arg is pdu (freed)
 3378  */
 3379 static void
 3380 sscop_inrec_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 3381 {
 3382         MAAL_ERROR(sscop, 'D', 0);
 3383         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3384         SSCOP_MSG_FREE(msg);
 3385         sscop_set_state(sscop, SSCOP_IDLE);
 3386 }
 3387 
 3388 /*
 3389  * p 57: IN_REC_PEND && USTAT PDU
 3390  *      arg is pdu (freed)
 3391  */
 3392 static void
 3393 sscop_inrec_ustat(struct sscop *sscop, struct sscop_msg *msg)
 3394 {
 3395         MAAL_ERROR(sscop, 'I', 0);
 3396         FREE_UU(uu_end);
 3397         send_end(sscop, 1, NULL);
 3398         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3399         SSCOP_MSG_FREE(msg);
 3400         sscop_set_state(sscop, SSCOP_IDLE);
 3401 }
 3402 
 3403 /*
 3404  * p 57: IN_REC_PEND && STAT PDU
 3405  *      arg is pdu (freed)
 3406  */
 3407 static void
 3408 sscop_inrec_stat(struct sscop *sscop, struct sscop_msg *msg)
 3409 {
 3410         MAAL_ERROR(sscop, 'H', 0);
 3411         FREE_UU(uu_end);
 3412         send_end(sscop, 1, NULL);
 3413         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3414         SSCOP_MSG_FREE(msg);
 3415         sscop_set_state(sscop, SSCOP_IDLE);
 3416 }
 3417 
 3418 /*
 3419  * p 57: IN_REC_PEND && POLL PDU
 3420  *      arg is pdu (freed)
 3421  */
 3422 static void
 3423 sscop_inrec_poll(struct sscop *sscop, struct sscop_msg *msg)
 3424 {
 3425         MAAL_ERROR(sscop, 'G', 0);
 3426         FREE_UU(uu_end);
 3427         send_end(sscop, 1, NULL);
 3428         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3429         SSCOP_MSG_FREE(msg);
 3430         sscop_set_state(sscop, SSCOP_IDLE);
 3431 }
 3432 
 3433 /*
 3434  * p 57: IN_REC_PEND && SD PDU
 3435  *      arg is pdu (freed)
 3436  */
 3437 static void
 3438 sscop_inrec_sd(struct sscop *sscop, struct sscop_msg *msg)
 3439 {
 3440         MAAL_ERROR(sscop, 'A', 0);
 3441         FREE_UU(uu_end);
 3442         send_end(sscop, 1, NULL);
 3443         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3444         SSCOP_MSG_FREE(msg);
 3445         sscop_set_state(sscop, SSCOP_IDLE);
 3446 }
 3447 
 3448 /*
 3449  * p 58: IN_REC_PEND && RSAK PDU
 3450  *      arg is pdu (freed).
 3451  */
 3452 static void
 3453 sscop_inrec_rsak(struct sscop *sscop, struct sscop_msg *msg)
 3454 {
 3455         SSCOP_MSG_FREE(msg);
 3456         MAAL_ERROR(sscop, 'K', 0);
 3457 }
 3458 
 3459 /*
 3460  * p 58: IN_REC_PEND && RS PDU
 3461  *      arg is pdu (freed).
 3462  */
 3463 static void
 3464 sscop_inrec_rs(struct sscop *sscop, struct sscop_msg *msg)
 3465 {
 3466         union pdu pdu;
 3467 
 3468         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3469 
 3470         if(m_detect_retransmission(sscop, msg)) {
 3471                 SSCOP_MSG_FREE(msg);
 3472                 MAAL_ERROR(sscop, 'J', 0);
 3473                 return;
 3474         }
 3475         (void)MBUF_STRIP32(msg->m);
 3476 
 3477         sscop->vt_ms = pdu.sscop_ns;
 3478         AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
 3479 
 3480         sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
 3481 }
 3482 
 3483 /*
 3484  * p 59: IN_REC_PEND && ER PDU
 3485  *      arg is pdu (freed)
 3486  */
 3487 static void
 3488 sscop_inrec_er(struct sscop *sscop, struct sscop_msg *msg)
 3489 {
 3490         union pdu pdu;
 3491 
 3492         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3493 
 3494         if(!m_detect_retransmission(sscop, msg)) {
 3495                 MAAL_ERROR(sscop, 'L', 0);
 3496         }
 3497 
 3498         SSCOP_MSG_FREE(msg);
 3499 }
 3500 
 3501 /*
 3502  * p 59: IN_REC_PEND && BGN PDU
 3503  *      arg is pdu (freed).
 3504  *      no uui
 3505  */
 3506 static void
 3507 sscop_inrec_bgn(struct sscop *sscop, struct sscop_msg *msg)
 3508 {
 3509         union pdu pdu;
 3510 
 3511         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3512 
 3513         if(m_detect_retransmission(sscop, msg)) {
 3514                 MAAL_ERROR(sscop, 'B', 0);
 3515                 SSCOP_MSG_FREE(msg);
 3516                 return;
 3517         }
 3518         (void)MBUF_STRIP32(msg->m);
 3519 
 3520         sscop->vt_ms = pdu.sscop_ns;
 3521         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 3522         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
 3523 
 3524         sscop_set_state(sscop, SSCOP_IN_PEND);
 3525 }
 3526 
 3527 /*
 3528  * p 59: IN_REC_PEND && BGAK PDU
 3529  *      arg is pdu (freed)
 3530  *      no uui
 3531  */
 3532 static void
 3533 sscop_inrec_bgak(struct sscop *sscop, struct sscop_msg *msg)
 3534 {
 3535         MAAL_ERROR(sscop, 'C', 0);
 3536         SSCOP_MSG_FREE(msg);
 3537 }
 3538 
 3539 /*
 3540  * p 59: IN_REC_PEND && ERAK PDU
 3541  *      arg is pdu (freed)
 3542  *      no uui
 3543  */
 3544 static void
 3545 sscop_inrec_erak(struct sscop *sscop, struct sscop_msg *msg)
 3546 {
 3547         MAAL_ERROR(sscop, 'M', 0);
 3548         SSCOP_MSG_FREE(msg);
 3549 }
 3550 
 3551 /*
 3552  * p 60: READY && RESYNC request
 3553  *      arg is UU
 3554  */
 3555 static void
 3556 sscop_ready_sync_req(struct sscop *sscop, struct sscop_msg *uu)
 3557 {
 3558         SET_UU(uu_rs, uu);
 3559 
 3560         m_reset_data_xfer_timers(sscop);
 3561         sscop->vt_cc = 1;
 3562         sscop->vt_sq++;
 3563         m_initialize_mr(sscop);
 3564         send_rs(sscop, 0, sscop->uu_rs);
 3565         m_release_buffers(sscop);
 3566         TIMER_RESTART(sscop, cc);
 3567 
 3568         sscop_set_state(sscop, SSCOP_OUT_RESYNC_PEND);
 3569 }
 3570 
 3571 
 3572 /*
 3573  * p 60: READY && AA-RELEASE.request
 3574  *      arg is uu.
 3575  */
 3576 static void
 3577 sscop_ready_release_req(struct sscop *sscop, struct sscop_msg *uu)
 3578 {
 3579         SET_UU(uu_end, uu);
 3580 
 3581         m_reset_data_xfer_timers(sscop);
 3582         sscop->vt_cc = 1;
 3583         send_end(sscop, 0, sscop->uu_end);
 3584         m_prepare_retrieval(sscop);
 3585         TIMER_RESTART(sscop, cc);
 3586 
 3587         sscop_set_state(sscop, SSCOP_OUT_DIS_PEND);
 3588 }
 3589 
 3590 /*
 3591  * p 61: READY && ER PDU
 3592  *      arg is pdu (freed).
 3593  */
 3594 static void
 3595 sscop_ready_er(struct sscop *sscop, struct sscop_msg *msg)
 3596 {
 3597         union pdu pdu;
 3598 
 3599         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3600 
 3601         if(m_detect_retransmission(sscop, msg)) {
 3602                 TIMER_RESTART(sscop, nr);
 3603                 send_erak(sscop);
 3604         } else {
 3605                 m_reset_data_xfer_timers(sscop);
 3606                 sscop->vt_ms = pdu.sscop_ns;
 3607                 m_prepare_recovery(sscop);
 3608                 m_deliver_data(sscop);
 3609 
 3610                 AAL_SIG(sscop, SSCOP_RECOVER_indication);
 3611 
 3612                 sscop_set_state(sscop, SSCOP_IN_REC_PEND);
 3613         }
 3614 
 3615         SSCOP_MSG_FREE(msg);
 3616 }
 3617 
 3618 /*
 3619  * p 61: READY && BGN PDU
 3620  *      arg is pdu (freed)
 3621  */
 3622 static void
 3623 sscop_ready_bgn(struct sscop *sscop, struct sscop_msg *msg)
 3624 {
 3625         union pdu pdu;
 3626 
 3627         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3628 
 3629         if(m_detect_retransmission(sscop, msg)) {
 3630                 TIMER_RESTART(sscop, nr);
 3631                 send_bgak(sscop, sscop->uu_bgak);
 3632                 SSCOP_MSG_FREE(msg);
 3633                 return;
 3634         }
 3635         (void)MBUF_STRIP32(msg->m);
 3636 
 3637         m_reset_data_xfer_timers(sscop);
 3638         sscop->vt_ms = pdu.sscop_ns;
 3639 
 3640         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 0);
 3641         AAL_UU_SIGNAL(sscop, SSCOP_ESTABLISH_indication, msg, pdu.sscop_pl, 0);
 3642 
 3643         m_prepare_retrieval(sscop);
 3644 
 3645         sscop_set_state(sscop, SSCOP_IN_PEND);
 3646 }
 3647 
 3648 /*
 3649  * p 62: READY && ENDAK PDU
 3650  *      arg is pdu (freed)
 3651  */
 3652 static void
 3653 sscop_ready_endak(struct sscop *sscop, struct sscop_msg *msg)
 3654 {
 3655         m_reset_data_xfer_timers(sscop);
 3656         MAAL_ERROR(sscop, 'F', 0);
 3657         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3658         m_prepare_retrieval(sscop);
 3659         SSCOP_MSG_FREE(msg);
 3660         sscop_set_state(sscop, SSCOP_IDLE);
 3661 }
 3662 
 3663 /*
 3664  * p 62: READY && BGREJ PDU
 3665  *      arg is pdu (freed)
 3666  */
 3667 static void
 3668 sscop_ready_bgrej(struct sscop *sscop, struct sscop_msg *msg)
 3669 {
 3670         m_reset_data_xfer_timers(sscop);
 3671         MAAL_ERROR(sscop, 'D', 0);
 3672         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3673         m_prepare_retrieval(sscop);
 3674         SSCOP_MSG_FREE(msg);
 3675         sscop_set_state(sscop, SSCOP_IDLE);
 3676 }
 3677 
 3678 /*
 3679  * p 62: READY && RS PDU
 3680  *      arg is pdu (freed)
 3681  */
 3682 static void
 3683 sscop_ready_rs(struct sscop *sscop, struct sscop_msg *msg)
 3684 {
 3685         union pdu pdu;
 3686 
 3687         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3688 
 3689         if(m_detect_retransmission(sscop, msg)) {
 3690                 SSCOP_MSG_FREE(msg);
 3691                 TIMER_RESTART(sscop, nr);
 3692                 send_rsak(sscop);
 3693                 return;
 3694         }
 3695         (void)MBUF_STRIP32(msg->m);
 3696 
 3697         m_reset_data_xfer_timers(sscop);
 3698         sscop->vt_ms = pdu.sscop_ns;
 3699         AAL_UU_SIGNAL(sscop, SSCOP_RESYNC_indication, msg, pdu.sscop_pl, 0);
 3700         m_prepare_retrieval(sscop);
 3701 
 3702         sscop_set_state(sscop, SSCOP_IN_RESYNC_PEND);
 3703 }
 3704 
 3705 /*
 3706  * p 62: READY && END PDU
 3707  *      arg is pdu (freed)
 3708  */
 3709 static void
 3710 sscop_ready_end(struct sscop *sscop, struct sscop_msg *msg)
 3711 {
 3712         union pdu pdu;
 3713 
 3714         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3715         (void)MBUF_STRIP32(msg->m);
 3716 
 3717         m_reset_data_xfer_timers(sscop);
 3718         send_endak(sscop);
 3719         AAL_UU_SIGNAL(sscop, SSCOP_RELEASE_indication,
 3720                 msg, pdu.sscop_pl, (u_int)pdu.sscop_s);
 3721         m_prepare_retrieval(sscop);
 3722 
 3723         sscop_set_state(sscop, SSCOP_IDLE);
 3724 }
 3725 
 3726 /*
 3727  * p 63: READY && POLL expiry
 3728  */
 3729 static void
 3730 sscop_ready_tpoll(struct sscop *sscop, struct sscop_msg *unused __unused)
 3731 {
 3732         sscop->vt_ps++;
 3733         send_poll(sscop);
 3734         sscop->vt_pd = 0;
 3735         m_set_poll_timer(sscop);
 3736 }
 3737 
 3738 /*
 3739  * p 63: READY && KEEP_ALIVE expiry
 3740  */
 3741 static void
 3742 sscop_ready_tka(struct sscop *sscop, struct sscop_msg *unused __unused)
 3743 {
 3744         sscop->vt_ps++;
 3745         send_poll(sscop);
 3746         sscop->vt_pd = 0;
 3747         m_set_poll_timer(sscop);
 3748 }
 3749 
 3750 /*
 3751  * p 63: READY && IDLE expiry
 3752  */
 3753 static void
 3754 sscop_ready_tidle(struct sscop *sscop, struct sscop_msg *unused __unused)
 3755 {
 3756         TIMER_RESTART(sscop, nr);
 3757         sscop->vt_ps++;
 3758         send_poll(sscop);
 3759         sscop->vt_pd = 0;
 3760         m_set_poll_timer(sscop);
 3761 }
 3762 
 3763 /*
 3764  * p 63: READY && NO_RESPONSE expiry
 3765  *      no arg
 3766  */
 3767 static void
 3768 sscop_ready_nr(struct sscop *sscop, struct sscop_msg *unused __unused)
 3769 {
 3770         m_reset_data_xfer_timers(sscop);
 3771         MAAL_ERROR(sscop, 'P', 0);
 3772         FREE_UU(uu_end);
 3773         send_end(sscop, 1, NULL);
 3774         AAL_DATA(sscop, SSCOP_RELEASE_indication, NULL, 1);
 3775         m_prepare_retrieval(sscop);
 3776         sscop_set_state(sscop, SSCOP_IDLE);
 3777 }
 3778 
 3779 /*
 3780  * p 63: READY && AA-DATA.request
 3781  *      arg is message (queued).
 3782  */
 3783 static void
 3784 sscop_ready_userdata(struct sscop *sscop, struct sscop_msg *msg)
 3785 {
 3786         MSGQ_APPEND(&sscop->xq, msg);
 3787 
 3788         sscop_signal(sscop, SIG_PDU_Q, msg);
 3789 }
 3790 
 3791 /*
 3792  * p 64: READY && SD PDU queued up
 3793  *      arg is unused.
 3794  */
 3795 static void
 3796 sscop_ready_pduq(struct sscop *sscop, struct sscop_msg *unused __unused)
 3797 {
 3798         struct sscop_msg *msg;
 3799 
 3800         if(sscop->rxq != 0) {
 3801                 TAILQ_FOREACH(msg, &sscop->xbuf, link)
 3802                         if(msg->rexmit)
 3803                                 break;
 3804                 ASSERT(msg != NULL);
 3805                 msg->rexmit = 0;
 3806                 sscop->rxq--;
 3807                 send_sd(sscop, msg->m, msg->seqno);
 3808                 msg->poll_seqno = sscop->vt_ps;
 3809                 if(sscop->poll_after_rex && sscop->rxq == 0)
 3810                         goto poll;                      /* -> A */
 3811                 else
 3812                         goto maybe_poll;                /* -> B */
 3813 
 3814         }
 3815         if(MSGQ_EMPTY(&sscop->xq))
 3816                 return;
 3817 
 3818         if(sscop->vt_s >= sscop->vt_ms) {
 3819                 /* Send windows closed */
 3820                 TIMER_STOP(sscop, idle);
 3821                 TIMER_RESTART(sscop, nr);
 3822                 goto poll;                      /* -> A */
 3823 
 3824         } else {
 3825                 msg = MSGQ_GET(&sscop->xq);
 3826                 msg->seqno = sscop->vt_s;
 3827                 send_sd(sscop, msg->m, msg->seqno);
 3828                 msg->poll_seqno = sscop->vt_ps;
 3829                 sscop->vt_s++;
 3830                 MSGQ_APPEND(&sscop->xbuf, msg);
 3831                 goto maybe_poll;                /* -> B */
 3832         }
 3833 
 3834         /*
 3835          * p 65: Poll handling
 3836          */
 3837   maybe_poll:                                   /* label B */
 3838         sscop->vt_pd++;
 3839         if(TIMER_ISACT(sscop, poll)) {
 3840                 if(sscop->vt_pd < sscop->maxpd)
 3841                         return;
 3842         } else {
 3843                  if(TIMER_ISACT(sscop, idle)) {
 3844                         TIMER_STOP(sscop, idle);
 3845                         TIMER_RESTART(sscop, nr);
 3846                 } else {
 3847                         TIMER_STOP(sscop, ka);
 3848                 }
 3849                 if(sscop->vt_pd < sscop->maxpd) {
 3850                         TIMER_RESTART(sscop, poll);
 3851                         return;
 3852                 }
 3853         }
 3854   poll:                                         /* label A */
 3855         sscop->vt_ps++;
 3856         send_poll(sscop);
 3857         sscop->vt_pd = 0;
 3858         TIMER_RESTART(sscop, poll);
 3859 }
 3860 
 3861 /*
 3862  * p 67: common recovery start
 3863  */
 3864 static void
 3865 sscop_recover(struct sscop *sscop)
 3866 {
 3867         sscop->vt_cc = 1;
 3868         sscop->vt_sq++;
 3869 
 3870         m_initialize_mr(sscop);
 3871         send_er(sscop);
 3872         m_prepare_recovery(sscop);
 3873 
 3874         TIMER_RESTART(sscop, cc);
 3875 
 3876         sscop_set_state(sscop, SSCOP_OUT_REC_PEND);
 3877 }
 3878 
 3879 /*
 3880  * p 66: READY && SD PDU
 3881  *      arg is received message.
 3882  */
 3883 static void
 3884 sscop_ready_sd(struct sscop *sscop, struct sscop_msg *msg)
 3885 {
 3886         union pdu pdu;
 3887         u_int sn;
 3888 
 3889         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3890         msg->seqno = pdu.sscop_ns;
 3891 
 3892         /* Fix padding */
 3893         MBUF_UNPAD(msg->m, pdu.sscop_pl);
 3894 
 3895         if(msg->seqno >= sscop->vr_mr) {
 3896                 /* message outside window */
 3897                 if(sscop->vr_h < sscop->vr_mr) {
 3898                         send_ustat(sscop, sscop->vr_h, sscop->vr_mr, -1);
 3899                         sscop->vr_h = sscop->vr_mr;
 3900                 }
 3901                 SSCOP_MSG_FREE(msg);
 3902                 return;
 3903         }
 3904 
 3905         if(msg->seqno == sscop->vr_r) {
 3906                 if(msg->seqno == sscop->vr_h) {
 3907                         sscop->vr_r = msg->seqno + 1;
 3908                         sscop->vr_h = msg->seqno + 1;
 3909 
 3910                         AAL_DATA(sscop, SSCOP_DATA_indication,
 3911                                 msg->m, msg->seqno);
 3912                         msg->m = NULL;
 3913                         SSCOP_MSG_FREE(msg);
 3914 
 3915                         return;
 3916                 }
 3917                 for(;;) {
 3918                         AAL_DATA(sscop, SSCOP_DATA_indication,
 3919                                 msg->m, msg->seqno);
 3920                         msg->m = NULL;
 3921                         SSCOP_MSG_FREE(msg);
 3922 
 3923                         sscop->vr_r++;
 3924                         if((msg = MSGQ_PEEK(&sscop->rbuf)) == NULL)
 3925                                 break;
 3926                         sn = msg->seqno;
 3927                         ASSERT(sn >= sscop->vr_r);
 3928                         if(sn != sscop->vr_r)
 3929                                 break;
 3930                         msg = MSGQ_GET(&sscop->rbuf);
 3931                 }
 3932                 return;
 3933         }
 3934 
 3935         /* Messages were lost */
 3936 
 3937         /* XXX Flow control */
 3938         if(msg->seqno == sscop->vr_h) {
 3939                 QINSERT(&sscop->rbuf, msg);
 3940                 sscop->vr_h++;
 3941                 return;
 3942         }
 3943         if(sscop->vr_h < msg->seqno) {
 3944                 QINSERT(&sscop->rbuf, msg);
 3945                 send_ustat(sscop, sscop->vr_h, msg->seqno, -1);
 3946                 sscop->vr_h = msg->seqno + 1;
 3947                 return;
 3948         }
 3949 
 3950         if(QFIND(&sscop->rbuf, msg->seqno) == NULL) {
 3951                 QINSERT(&sscop->rbuf, msg);
 3952                 return;
 3953         }
 3954 
 3955         /* error: start recovery */
 3956         SSCOP_MSG_FREE(msg);
 3957         m_reset_data_xfer_timers(sscop);
 3958         MAAL_ERROR(sscop, 'Q', 0);
 3959         sscop_recover(sscop);
 3960 }
 3961 
 3962 /*
 3963  * p 67: READY && POLL PDU
 3964  */
 3965 static void
 3966 sscop_ready_poll(struct sscop *sscop, struct sscop_msg *msg)
 3967 {
 3968         union pdu pdu;
 3969         union seqno seqno;
 3970         u_int sn, nps;
 3971         struct SSCOP_MBUF_T *m;
 3972 
 3973         pdu.sscop_null = MBUF_STRIP32(msg->m);
 3974         seqno.sscop_null = MBUF_STRIP32(msg->m);
 3975 
 3976         if((u_int)pdu.sscop_ns < sscop->vr_h) {
 3977                 SSCOP_MSG_FREE(msg);
 3978                 m_reset_data_xfer_timers(sscop);
 3979                 MAAL_ERROR(sscop, 'Q', 0);
 3980                 sscop_recover(sscop);
 3981                 return;
 3982         }
 3983         nps = seqno.sscop_n;
 3984 
 3985         if((u_int)pdu.sscop_ns > sscop->vr_mr)
 3986                 sscop->vr_h = sscop->vr_mr;
 3987         else
 3988                 sscop->vr_h = pdu.sscop_ns;
 3989 
 3990         SSCOP_MSG_FREE(msg);
 3991 
 3992         /* build stat pdu */
 3993         if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
 3994                 FAILURE("sscop: cannot allocate STAT");
 3995                 return;
 3996         }
 3997         sn = sscop->vr_r;
 3998 
 3999         while(sn != sscop->vr_h) {
 4000                 /* loop through burst we already have */
 4001                 for(;;) {
 4002                         if(sn >= sscop->vr_h) {
 4003                                 seqno.sscop_null = 0;
 4004                                 seqno.sscop_n = sn;
 4005                                 MBUF_APPEND32(m, seqno.sscop_null);
 4006                                 goto out;
 4007                         }
 4008                         if(QFIND(&sscop->rbuf, sn) == NULL)
 4009                                 break;
 4010                         sn++;
 4011                 }
 4012 
 4013                 /* start of a hole */
 4014                 seqno.sscop_null = 0;
 4015                 seqno.sscop_n = sn;
 4016                 MBUF_APPEND32(m, seqno.sscop_null);
 4017                 if(MBUF_LEN(m)/4 >= sscop->maxstat) {
 4018                         send_stat(sscop, nps, m);
 4019                         if((m = MBUF_ALLOC(sscop->maxstat * 4 + 12)) == NULL) {
 4020                                 FAILURE("sscop: cannot allocate STAT");
 4021                                 return;
 4022                         }
 4023                         seqno.sscop_null = 0;
 4024                         seqno.sscop_n = sn;
 4025                         MBUF_APPEND32(m, seqno.sscop_null);
 4026                 }
 4027                 do {
 4028                         sn++;
 4029                 } while(sn < sscop->vr_h && !QFIND(&sscop->rbuf, sn));
 4030                 seqno.sscop_null = 0;
 4031                 seqno.sscop_n = sn;
 4032                 MBUF_APPEND32(m, seqno.sscop_null);
 4033         }
 4034   out:
 4035         send_stat(sscop, nps, m);
 4036 }
 4037 
 4038 /*
 4039  * p 69: READY && USTAT PDU
 4040  *      arg is msg (freed)
 4041  */
 4042 static void
 4043 sscop_ready_ustat(struct sscop *sscop, struct sscop_msg *msg)
 4044 {
 4045         union pdu pdu;
 4046         union seqno nmr, sq1, sq2;
 4047         u_int cnt;
 4048 
 4049         pdu.sscop_null = MBUF_STRIP32(msg->m);
 4050         nmr.sscop_null = MBUF_STRIP32(msg->m);
 4051         sq2.sscop_null = MBUF_STRIP32(msg->m);
 4052         sq1.sscop_null = MBUF_STRIP32(msg->m);
 4053 
 4054         SSCOP_MSG_FREE(msg);
 4055 
 4056         cnt = sq1.sscop_n - sq2.sscop_n;
 4057 
 4058         if((u_int)pdu.sscop_ns < sscop->vt_a || (u_int)pdu.sscop_ns >= sscop->vt_s) {
 4059                 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
 4060                     "USTAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
 4061                     "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
 4062                 goto err_f;
 4063         }
 4064 
 4065         /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
 4066          * next in sequence-SD-number of the receiver and means, it has all
 4067          * messages below N(R). Remove all message below N(R) from the
 4068          * transmission buffer. It may already be removed because of an
 4069          * earlier selective ACK in a STAT message.
 4070          */
 4071         while((msg = MSGQ_PEEK(&sscop->xbuf)) != NULL && msg->seqno < (u_int)pdu.sscop_ns) {
 4072                 ASSERT(msg->seqno >= sscop->vt_a);
 4073                 MSGQ_REMOVE(&sscop->xbuf, msg);
 4074                 SSCOP_MSG_FREE(msg);
 4075         }
 4076 
 4077         /* Update the in-sequence acknowledge and the send window */
 4078         sscop->vt_a = pdu.sscop_ns;
 4079         sscop->vt_ms = nmr.sscop_n;
 4080 
 4081         /* check, that the range of requested re-transmissions is between
 4082          * the in-sequence-ack and the highest up-to-now transmitted SD
 4083          */
 4084         if(sq1.sscop_n >= sq2.sscop_n
 4085             || (u_int)sq1.sscop_n < sscop->vt_a
 4086             || (u_int)sq2.sscop_n >= sscop->vt_s) {
 4087                 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
 4088                     "USTAT: seq1 or seq2 outside VT(A)...VT(S)-1 or seq1>=seq2:"
 4089                     " seq1=%u seq2=%u VT(A)=%u VT(S)=%u",
 4090                     sq1.sscop_n, sq2.sscop_n, sscop->vt_a, sscop->vt_s));
 4091                 goto err_f;
 4092         }
 4093 
 4094         /*
 4095          * Retransmit all messages from seq1 to seq2-1
 4096          */
 4097         do {
 4098                 /*
 4099                  * The message may not be in the transmit buffer if it was
 4100                  * already acked by a STAT. This means, the receiver is
 4101                  * confused.
 4102                  */
 4103                 if((msg = QFIND(&sscop->xbuf, sq1.sscop_n)) == NULL) {
 4104                         VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
 4105                             "USTAT: message %u not found in xmit buffer",
 4106                             sq1.sscop_n));
 4107                         goto err_f;
 4108                 }
 4109 
 4110                 /*
 4111                  * If it is not yet in the re-transmission queue, put it there
 4112                  */
 4113                 if(!msg->rexmit) {
 4114                         msg->rexmit = 1;
 4115                         sscop->rxq++;
 4116                         sscop_signal(sscop, SIG_PDU_Q, msg);
 4117                 }
 4118                 sq1.sscop_n++;
 4119         } while(sq1.sscop_n != sq2.sscop_n);
 4120 
 4121         /*
 4122          * report the re-transmission to the management
 4123          */
 4124         MAAL_ERROR(sscop, 'V', cnt);
 4125         return;
 4126 
 4127   err_f:
 4128         m_reset_data_xfer_timers(sscop);
 4129         MAAL_ERROR(sscop, 'T', 0);
 4130         sscop_recover(sscop);
 4131 }
 4132 
 4133 /*
 4134  * p 70: READY && STAT PDU
 4135  *      arg is msg (freed).
 4136  */
 4137 static void
 4138 sscop_ready_stat(struct sscop *sscop, struct sscop_msg *msg)
 4139 {
 4140         union pdu pdu;
 4141         union seqno nps, nmr;
 4142         u_int len, seq1, seq2, cnt;
 4143         struct sscop_msg *m;
 4144 
 4145         pdu.sscop_null = MBUF_STRIP32(msg->m);
 4146         nmr.sscop_null = MBUF_STRIP32(msg->m);
 4147         nps.sscop_null = MBUF_STRIP32(msg->m);
 4148 
 4149         len = MBUF_LEN(msg->m) / 4;
 4150 
 4151         if((u_int)nps.sscop_n < sscop->vt_pa
 4152             || (u_int)nps.sscop_n > sscop->vt_ps) {
 4153                 SSCOP_MSG_FREE(msg);
 4154                 m_reset_data_xfer_timers(sscop);
 4155                 MAAL_ERROR(sscop, 'R', 0);
 4156                 sscop_recover(sscop);
 4157                 return;
 4158         }
 4159 
 4160         if((u_int)pdu.sscop_ns < sscop->vt_a
 4161             || (u_int)pdu.sscop_ns > sscop->vt_s) {
 4162                 /*
 4163                  * The in-sequence acknowledge, i.e. the receivers's next
 4164                  * expected in-sequence msg is outside the window between
 4165                  * the transmitters in-sequence ack and highest seqno -
 4166                  * the receiver seems to be confused.
 4167                  */
 4168                 VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
 4169                     "STAT: N(R) outside VT(A)...VT(S)-1: N(R)=%u VT(A)=%u "
 4170                     "VT(S)=%u", (u_int)pdu.sscop_ns, sscop->vt_a, sscop->vt_s));
 4171   err_H:
 4172                 SSCOP_MSG_FREE(msg);
 4173                 m_reset_data_xfer_timers(sscop);
 4174                 MAAL_ERROR(sscop, 'S', 0);
 4175                 sscop_recover(sscop);
 4176                 return;
 4177         }
 4178 
 4179         /* Acknowledge all messages between VT(A) and N(R)-1. N(R) is the new
 4180          * next in sequence-SD-number of the receiver and means, it has all
 4181          * messages below N(R). Remove all message below N(R) from the
 4182          * transmission buffer. It may already be removed because of an
 4183          * earlier selective ACK in a STAT message.
 4184          */
 4185         while((m = MSGQ_PEEK(&sscop->xbuf)) != NULL
 4186             && m->seqno < (u_int)pdu.sscop_ns) {
 4187                 ASSERT(m->seqno >= sscop->vt_a);
 4188                 MSGQ_REMOVE(&sscop->xbuf, m);
 4189                 SSCOP_MSG_FREE(m);
 4190         }
 4191 
 4192         /*
 4193          * Update in-sequence ack, poll-ack and send window.
 4194          */
 4195         sscop->vt_a = pdu.sscop_ns;
 4196         sscop->vt_pa = nps.sscop_n;
 4197         sscop->vt_ms = nmr.sscop_n;
 4198 
 4199         cnt = 0;
 4200         if(len > 1) {
 4201                 seq1 = MBUF_GET32(msg->m);
 4202                 len--;
 4203                 if(seq1 >= sscop->vt_s) {
 4204                         VERBERR(sscop, SSCOP_DBG_ERR, (sscop, sscop->aarg,
 4205                             "STAT: seq1 >= VT(S): seq1=%u VT(S)=%u",
 4206                             seq1, sscop->vt_s));
 4207                         goto err_H;
 4208                 }
 4209 
 4210                 for(;;) {
 4211                         seq2 = MBUF_GET32(msg->m);
 4212                         len--;
 4213                         if(seq1 >= seq2 || seq2 > sscop->vt_s) {
 4214                                 VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
 4215                                     sscop->aarg, "STAT: seq1 >= seq2 or "
 4216                                     "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
 4217                                     seq1, seq2, sscop->vt_s));
 4218                                 goto err_H;
 4219                         }
 4220 
 4221                         do {
 4222                                 /*
 4223                                  * The receiver requests the re-transmission
 4224                                  * of some message, but has acknowledged it
 4225                                  * already in an earlier STAT (it isn't in the
 4226                                  * transmitt buffer anymore).
 4227                                  */
 4228                                 if((m = QFIND(&sscop->xbuf, seq1)) == NULL) {
 4229                                         VERBERR(sscop, SSCOP_DBG_ERR,
 4230                                             (sscop, sscop->aarg, "STAT: message"
 4231                                             " %u not found in xmit buffer",
 4232                                             seq1));
 4233                                         goto err_H;
 4234                                 }
 4235                                 if(m->poll_seqno < (u_int)nps.sscop_n
 4236                                     && (u_int)nps.sscop_n <= sscop->vt_ps)
 4237                                         if(!m->rexmit) {
 4238                                                 m->rexmit = 1;
 4239                                                 sscop->rxq++;
 4240                                                 cnt++;
 4241                                                 sscop_signal(sscop, SIG_PDU_Q, msg);
 4242                                         }
 4243                         } while(++seq1 < seq2);
 4244 
 4245                         if(len == 0)
 4246                                 break;
 4247 
 4248                         seq2 = MBUF_GET32(msg->m);
 4249                         len--;
 4250 
 4251                         if(seq1 >= seq2 || seq2 > sscop->vt_s) {
 4252                                 VERBERR(sscop, SSCOP_DBG_ERR, (sscop,
 4253                                     sscop->aarg, "STAT: seq1 >= seq2 or "
 4254                                     "seq2 > VT(S): seq1=%u seq2=%u VT(S)=%u",
 4255                                     seq1, seq2, sscop->vt_s));
 4256                                 goto err_H;
 4257                         }
 4258 
 4259                         /* OK now the sucessful transmitted messages. Note, that
 4260                          * some messages may already be out of the buffer because
 4261                          * of earlier STATS */
 4262                         do {
 4263                                 if(sscop->clear_buffers) {
 4264                                         if((m = QFIND(&sscop->xbuf, seq1)) != NULL) {
 4265                                                 MSGQ_REMOVE(&sscop->xbuf, m);
 4266                                                 SSCOP_MSG_FREE(m);
 4267                                         }
 4268                                 }
 4269                         } while(++seq1 != seq2);
 4270 
 4271                         if(len == 0)
 4272                                 break;
 4273                 }
 4274                 MAAL_ERROR(sscop, 'V', cnt);
 4275         }
 4276         SSCOP_MSG_FREE(msg);
 4277 
 4278         /* label L: */
 4279         if(sscop->vt_s >= sscop->vt_ms) {
 4280                 /*
 4281                  * The receiver has closed the window: report to management
 4282                  */
 4283                 if(sscop->credit) {
 4284                         sscop->credit = 0;
 4285                         MAAL_ERROR(sscop, 'W', 0);
 4286                 }
 4287         } else if(!sscop->credit) {
 4288                 /*
 4289                  * The window was forcefully closed above, but
 4290                  * now re-opened. Report to management.
 4291                  */
 4292                 sscop->credit = 1;
 4293                 MAAL_ERROR(sscop, 'X', 0);
 4294         }
 4295 
 4296         if(TIMER_ISACT(sscop, poll)) {
 4297                 TIMER_RESTART(sscop, nr);
 4298         } else if(!TIMER_ISACT(sscop, idle)) {
 4299                 TIMER_STOP(sscop, ka);
 4300                 TIMER_STOP(sscop, nr);
 4301                 TIMER_RESTART(sscop, idle);
 4302         }
 4303 }
 4304 
 4305 /*
 4306  * P. 73: any state & UDATA_REQUEST
 4307  *      arg is pdu (queued)
 4308  */
 4309 static void
 4310 sscop_udata_req(struct sscop *sscop, struct sscop_msg *msg)
 4311 {
 4312         MSGQ_APPEND(&sscop->uxq, msg);
 4313         sscop_signal(sscop, SIG_UPDU_Q, msg);
 4314 }
 4315 
 4316 /*
 4317  * P. 73: any state & MDATA_REQUEST
 4318  *      arg is pdu (queued)
 4319  */
 4320 static void
 4321 sscop_mdata_req(struct sscop *sscop, struct sscop_msg *msg)
 4322 {
 4323         MSGQ_APPEND(&sscop->mxq, msg);
 4324         sscop_signal(sscop, SIG_MPDU_Q, msg);
 4325 }
 4326 
 4327 /*
 4328  * P. 74: any state & UDATA queued
 4329  *      no arg.
 4330  */
 4331 static void
 4332 sscop_upduq(struct sscop *sscop, struct sscop_msg *unused __unused)
 4333 {
 4334         struct sscop_msg *msg;
 4335 
 4336         if(sscop->ll_busy)
 4337                 return;
 4338         while((msg = MSGQ_GET(&sscop->uxq)) != NULL) {
 4339                 send_ud(sscop, msg->m);
 4340                 msg->m = NULL;
 4341                 SSCOP_MSG_FREE(msg);
 4342         }
 4343 }
 4344 
 4345 /*
 4346  * P. 74: any state & MDATA queued
 4347  *      no arg.
 4348  */
 4349 static void
 4350 sscop_mpduq(struct sscop *sscop, struct sscop_msg *unused __unused)
 4351 {
 4352         struct sscop_msg *msg;
 4353 
 4354         if(sscop->ll_busy)
 4355                 return;
 4356         while((msg = MSGQ_GET(&sscop->mxq)) != NULL) {
 4357                 send_md(sscop, msg->m);
 4358                 msg->m = NULL;
 4359                 SSCOP_MSG_FREE(msg);
 4360         }
 4361 }
 4362 
 4363 /*
 4364  * p 73: MD PDU
 4365  *      arg is PDU
 4366  */
 4367 static void
 4368 sscop_md(struct sscop *sscop, struct sscop_msg *msg)
 4369 {
 4370         union pdu pdu;
 4371 
 4372         pdu.sscop_null = MBUF_STRIP32(msg->m);
 4373 
 4374         MBUF_UNPAD(msg->m, pdu.sscop_pl);
 4375 
 4376         MAAL_DATA(sscop, msg->m);
 4377         msg->m = NULL;
 4378         SSCOP_MSG_FREE(msg);
 4379 }
 4380 
 4381 /*
 4382  * p 73: UD PDU
 4383  *      arg is PDU
 4384  */
 4385 static void
 4386 sscop_ud(struct sscop *sscop, struct sscop_msg *msg)
 4387 {
 4388         union pdu pdu;
 4389 
 4390         pdu.sscop_null = MBUF_STRIP32(msg->m);
 4391 
 4392         MBUF_UNPAD(msg->m, pdu.sscop_pl);
 4393 
 4394         AAL_DATA(sscop, SSCOP_UDATA_indication, msg->m, 0);
 4395         msg->m = NULL;
 4396         SSCOP_MSG_FREE(msg);
 4397 }
 4398 
 4399 
 4400 /*
 4401  * p 33: IDLE & RETRIEVE
 4402  * p 39: IN_PEND & RETRIEVE
 4403  * p 42: OUT_DIS_PEND & RETRIEVE
 4404  * p 48: IN_RESYNC_PEND & RETRIEVE
 4405  * p 53: REC_PEND & RETRIEVE
 4406  * p 58: IN_REC_PEND & RETRIEVE
 4407  */
 4408 static void
 4409 sscop_retrieve(struct sscop *sscop, struct sscop_msg *msg)
 4410 {
 4411         m_data_retrieval(sscop, msg->rexmit);
 4412         SSCOP_MSG_FREE(msg);
 4413 }
 4414 
 4415 /************************************************************/
 4416 /*
 4417  * GENERAL EVENT HANDLING
 4418  */
 4419 
 4420 /*
 4421  * State/event matrix.
 4422  *
 4423  * Entries marked with Z are not specified in Q.2110, but are added for
 4424  * the sake of stability.
 4425  */
 4426 static struct {
 4427         void    (*func)(struct sscop *, struct sscop_msg *);
 4428         int     (*cond)(struct sscop *);
 4429 } state_matrix[SSCOP_NSTATES][SIG_NUM] = {
 4430         /* SSCOP_IDLE */ {
 4431                 /* SIG_BGN */           { sscop_idle_bgn, NULL },
 4432                 /* SIG_BGAK */          { sscop_idle_bgak, NULL },
 4433                 /* SIG_END */           { sscop_idle_end, NULL },
 4434                 /* SIG_ENDAK */         { sscop_ignore_pdu, NULL },
 4435                 /* SIG_RS */            { sscop_idle_rs, NULL },
 4436                 /* SIG_RSAK */          { sscop_idle_rsak, NULL },
 4437                 /* SIG_BGREJ */         { sscop_idle_bgrej, NULL },
 4438                 /* SIG_SD */            { sscop_idle_sd, NULL },
 4439                 /* SIG_ER */            { sscop_idle_er, NULL },
 4440                 /* SIG_POLL */          { sscop_idle_poll, NULL },
 4441                 /* SIG_STAT */          { sscop_idle_stat, NULL },
 4442                 /* SIG_USTAT */         { sscop_idle_ustat, NULL },
 4443                 /* SIG_UD */            { sscop_ud, NULL },
 4444                 /* SIG_MD */            { sscop_md, NULL },
 4445                 /* SIG_ERAK */          { sscop_idle_erak, NULL },
 4446                 /* SIG_T_CC */          { NULL, NULL },
 4447                 /* SIG_T_POLL */        { NULL, NULL },
 4448                 /* SIG_T_KA */          { NULL, NULL },
 4449                 /* SIG_T_NR */          { NULL, NULL },
 4450                 /* SIG_T_IDLE */        { NULL, NULL },
 4451                 /* SIG_PDU_Q */         { sscop_flush_pduq, NULL },
 4452                 /* SIG_USER_DATA */     { NULL, NULL },
 4453                 /* SIG_ESTAB_REQ */     { sscop_idle_establish_req, NULL },
 4454                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4455                 /* SIG_RELEASE_REQ */   { NULL, NULL },
 4456                 /* SIG_RECOVER */       { NULL, NULL },
 4457                 /* SIG_SYNC_REQ */      { NULL, NULL },
 4458                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4459                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4460                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4461                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4462                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4463                 /* SIG_RETRIEVE */      { sscop_retrieve, NULL },
 4464         },
 4465         /* SSCOP_OUT_PEND */ {
 4466                 /* SIG_BGN */           { sscop_outpend_bgn, NULL },
 4467                 /* SIG_BGAK */          { sscop_outpend_bgak, NULL },
 4468                 /* SIG_END */           { sscop_ignore_pdu, NULL },
 4469                 /* SIG_ENDAK */         { sscop_ignore_pdu, NULL },
 4470                 /* SIG_RS */            { sscop_ignore_pdu, NULL },
 4471                 /* SIG_RSAK */          { sscop_ignore_pdu, NULL },
 4472                 /* SIG_BGREJ */         { sscop_outpend_bgrej, NULL },
 4473                 /* SIG_SD */            { sscop_ignore_pdu, NULL },
 4474                 /* SIG_ER */            { sscop_ignore_pdu, NULL },
 4475                 /* SIG_POLL */          { sscop_ignore_pdu, NULL },
 4476                 /* SIG_STAT */          { sscop_ignore_pdu, NULL },
 4477                 /* SIG_USTAT */         { sscop_ignore_pdu, NULL },
 4478                 /* SIG_UD */            { sscop_ud, NULL },
 4479                 /* SIG_MD */            { sscop_md, NULL },
 4480                 /* SIG_ERAK */          { sscop_ignore_pdu, NULL },
 4481                 /* SIG_T_CC */          { sscop_outpend_tcc, NULL },
 4482                 /* SIG_T_POLL */        { NULL, NULL },
 4483                 /* SIG_T_KA */          { NULL, NULL },
 4484                 /* SIG_T_NR */          { NULL, NULL },
 4485                 /* SIG_T_IDLE */        { NULL, NULL },
 4486                 /* SIG_PDU_Q */         { sscop_flush_pduq, NULL },
 4487                 /* SIG_USER_DATA */     { NULL, NULL },
 4488                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4489                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4490                 /* SIG_RELEASE_REQ */   { sscop_outpend_release_req, NULL },
 4491                 /* SIG_RECOVER */       { NULL, NULL },
 4492                 /* SIG_SYNC_REQ */      { NULL, NULL },
 4493                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4494                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4495                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4496                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4497                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4498                 /* SIG_RETRIEVE */      { NULL, NULL },
 4499         },
 4500         /* SSCOP_IN_PEND */ {
 4501                 /* SIG_BGN */           { sscop_inpend_bgn, NULL },
 4502                 /* SIG_BGAK */          { sscop_inpend_bgak, NULL },
 4503                 /* SIG_END */           { sscop_inpend_end, NULL },
 4504                 /* SIG_ENDAK */         { sscop_inpend_endak, NULL },
 4505                 /* SIG_RS */            { sscop_inpend_rs, NULL },
 4506                 /* SIG_RSAK */          { sscop_inpend_rsak, NULL },
 4507                 /* SIG_BGREJ */         { sscop_inpend_bgrej, NULL },
 4508                 /* SIG_SD */            { sscop_inpend_sd, NULL },
 4509                 /* SIG_ER */            { sscop_inpend_er, NULL },
 4510                 /* SIG_POLL */          { sscop_inpend_poll, NULL },
 4511                 /* SIG_STAT */          { sscop_inpend_stat, NULL },
 4512                 /* SIG_USTAT */         { sscop_inpend_ustat, NULL },
 4513                 /* SIG_UD */            { sscop_ud, NULL },
 4514                 /* SIG_MD */            { sscop_md, NULL },
 4515                 /* SIG_ERAK */          { sscop_inpend_erak, NULL },
 4516                 /* SIG_T_CC */          { NULL, NULL },
 4517                 /* SIG_T_POLL */        { NULL, NULL },
 4518                 /* SIG_T_KA */          { NULL, NULL },
 4519                 /* SIG_T_NR */          { NULL, NULL },
 4520                 /* SIG_T_IDLE */        { NULL, NULL },
 4521                 /* SIG_PDU_Q */         { sscop_flush_pduq, NULL },
 4522                 /* SIG_USER_DATA */     { NULL, NULL },
 4523                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4524                 /* SIG_ESTAB_RESP */    { sscop_inpend_establish_resp, NULL },
 4525                 /* SIG_RELEASE_REQ */   { sscop_inpend_release_req, NULL },
 4526                 /* SIG_RECOVER */       { NULL, NULL },
 4527                 /* SIG_SYNC_REQ */      { NULL, NULL },
 4528                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4529                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4530                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4531                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4532                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4533                 /* SIG_RETRIEVE */      { sscop_retrieve, NULL },
 4534         },
 4535         /* SSCOP_OUT_DIS_PEND */ {
 4536                 /* SIG_BGN */           { sscop_outdis_bgn, NULL },
 4537                 /* SIG_BGAK */          { sscop_ignore_pdu, NULL },
 4538                 /* SIG_END */           { sscop_outdis_end, NULL },
 4539                 /* SIG_ENDAK */         { sscop_outdis_endak, NULL },
 4540                 /* SIG_RS */            { sscop_ignore_pdu, NULL },
 4541                 /* SIG_RSAK */          { sscop_ignore_pdu, NULL },
 4542                 /* SIG_BGREJ */         { sscop_outdis_endak, NULL },
 4543                 /* SIG_SD */            { sscop_ignore_pdu, NULL },
 4544                 /* SIG_ER */            { sscop_ignore_pdu, NULL },
 4545                 /* SIG_POLL */          { sscop_ignore_pdu, NULL },
 4546                 /* SIG_STAT */          { sscop_ignore_pdu, NULL },
 4547                 /* SIG_USTAT */         { sscop_ignore_pdu, NULL },
 4548                 /* SIG_UD */            { sscop_ud, NULL },
 4549                 /* SIG_MD */            { sscop_md, NULL },
 4550                 /* SIG_ERAK */          { sscop_ignore_pdu, NULL },
 4551                 /* SIG_T_CC */          { sscop_outdis_cc, NULL },
 4552                 /* SIG_T_POLL */        { NULL, NULL },
 4553                 /* SIG_T_KA */          { NULL, NULL },
 4554                 /* SIG_T_NR */          { NULL, NULL },
 4555                 /* SIG_T_IDLE */        { NULL, NULL },
 4556                 /* SIG_PDU_Q */         { sscop_flush_pduq, NULL },
 4557                 /* SIG_USER_DATA */     { NULL, NULL },
 4558                 /* SIG_ESTAB_REQ */     { sscop_outdis_establish_req, NULL },
 4559                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4560                 /* SIG_RELEASE_REQ */   { NULL, NULL },
 4561                 /* SIG_RECOVER */       { NULL, NULL },
 4562                 /* SIG_SYNC_REQ */      { NULL, NULL },
 4563                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4564                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4565                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4566                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4567                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4568                 /* SIG_RETRIEVE */      { sscop_retrieve, NULL },
 4569         },
 4570         /* SSCOP_OUT_RESYNC_PEND */ {
 4571                 /* SIG_BGN */           { sscop_outsync_bgn, NULL },
 4572                 /* SIG_BGAK */          { sscop_ignore_pdu, NULL },
 4573                 /* SIG_END */           { sscop_outsync_end, NULL },
 4574                 /* SIG_ENDAK */         { sscop_outsync_endak, NULL },
 4575                 /* SIG_RS */            { sscop_outsync_rs, NULL },
 4576                 /* SIG_RSAK */          { sscop_outsync_rsak, NULL },
 4577                 /* SIG_BGREJ */         { sscop_outsync_bgrej, NULL },
 4578                 /* SIG_SD */            { sscop_ignore_pdu, NULL },
 4579                 /* SIG_ER */            { sscop_ignore_pdu, NULL },
 4580                 /* SIG_POLL */          { sscop_ignore_pdu, NULL },
 4581                 /* SIG_STAT */          { sscop_ignore_pdu, NULL },
 4582                 /* SIG_USTAT */         { sscop_ignore_pdu, NULL },
 4583                 /* SIG_UD */            { sscop_ud, NULL },
 4584                 /* SIG_MD */            { sscop_md, NULL },
 4585                 /* SIG_ERAK */          { sscop_ignore_pdu, NULL },
 4586                 /* SIG_T_CC */          { sscop_outsync_cc, NULL },
 4587                 /* SIG_T_POLL */        { NULL, NULL },
 4588                 /* SIG_T_KA */          { NULL, NULL },
 4589                 /* SIG_T_NR */          { NULL, NULL },
 4590                 /* SIG_T_IDLE */        { NULL, NULL },
 4591                 /* SIG_PDU_Q */         { sscop_flush_pduq, NULL },
 4592                 /* SIG_USER_DATA */     { NULL, NULL },
 4593                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4594                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4595                 /* SIG_RELEASE_REQ */   { sscop_outsync_release_req, NULL },
 4596                 /* SIG_RECOVER */       { NULL, NULL },
 4597                 /* SIG_SYNC_REQ */      { NULL, NULL },
 4598                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4599                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4600                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4601                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4602                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4603                 /* SIG_RETRIEVE */      { NULL, NULL },
 4604         },
 4605         /* SSCOP_IN_RESYNC_PEND */ {
 4606                 /* SIG_BGN */           { sscop_insync_bgn, NULL },
 4607                 /* SIG_BGAK */          { sscop_insync_bgak, NULL },
 4608                 /* SIG_END */           { sscop_insync_end, NULL },
 4609                 /* SIG_ENDAK */         { sscop_insync_endak, NULL },
 4610                 /* SIG_RS */            { sscop_insync_rs, NULL },
 4611                 /* SIG_RSAK */          { sscop_insync_rsak, NULL },
 4612                 /* SIG_BGREJ */         { sscop_insync_bgrej, NULL },
 4613                 /* SIG_SD */            { sscop_insync_sd, NULL },
 4614                 /* SIG_ER */            { sscop_insync_er, NULL },
 4615                 /* SIG_POLL */          { sscop_insync_poll, NULL },
 4616                 /* SIG_STAT */          { sscop_insync_stat, NULL },
 4617                 /* SIG_USTAT */         { sscop_insync_ustat, NULL },
 4618                 /* SIG_UD */            { sscop_ud, NULL },
 4619                 /* SIG_MD */            { sscop_md, NULL },
 4620                 /* SIG_ERAK */          { sscop_insync_erak, NULL },
 4621                 /* SIG_T_CC */          { NULL, NULL },
 4622                 /* SIG_T_POLL */        { NULL, NULL },
 4623                 /* SIG_T_KA */          { NULL, NULL },
 4624                 /* SIG_T_NR */          { NULL, NULL },
 4625                 /* SIG_T_IDLE */        { NULL, NULL },
 4626                 /* SIG_PDU_Q */         { sscop_flush_pduq, NULL },
 4627                 /* SIG_USER_DATA */     { NULL, NULL },
 4628                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4629                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4630                 /* SIG_RELEASE_REQ */   { sscop_insync_release_req, NULL },
 4631                 /* SIG_RECOVER */       { NULL, NULL },
 4632                 /* SIG_SYNC_REQ */      { NULL, NULL },
 4633                 /* SIG_SYNC_RESP */     { sscop_insync_sync_resp, NULL },
 4634                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4635                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4636                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4637                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4638                 /* SIG_RETRIEVE */      { sscop_retrieve, NULL },
 4639         },
 4640         /* SSCOP_OUT_REC_PEND */ {
 4641                 /* SIG_BGN */           { sscop_outrec_bgn, NULL },
 4642                 /* SIG_BGAK */          { sscop_outrec_bgak, NULL },
 4643                 /* SIG_END */           { sscop_outrec_end, NULL },
 4644                 /* SIG_ENDAK */         { sscop_outrec_endak, NULL },
 4645                 /* SIG_RS */            { sscop_outrec_rs, NULL },
 4646                 /* SIG_RSAK */          { sscop_outrec_rsak, NULL },
 4647                 /* SIG_BGREJ */         { sscop_outrec_bgrej, NULL },
 4648                 /* SIG_SD */            { sscop_ignore_pdu, NULL },
 4649                 /* SIG_ER */            { sscop_outrec_er, NULL },
 4650                 /* SIG_POLL */          { sscop_ignore_pdu, NULL },
 4651                 /* SIG_STAT */          { sscop_ignore_pdu, NULL },
 4652                 /* SIG_USTAT */         { sscop_ignore_pdu, NULL },
 4653                 /* SIG_UD */            { sscop_ud, NULL },
 4654                 /* SIG_MD */            { sscop_md, NULL },
 4655                 /* SIG_ERAK */          { sscop_outrec_erak, NULL },
 4656                 /* SIG_T_CC */          { sscop_outrec_cc, NULL },
 4657                 /* SIG_T_POLL */        { NULL, NULL },
 4658                 /* SIG_T_KA */          { NULL, NULL },
 4659                 /* SIG_T_NR */          { NULL, NULL },
 4660                 /* SIG_T_IDLE */        { NULL, NULL },
 4661                 /* SIG_PDU_Q */         { sscop_outrec_pduq, NULL },
 4662                 /* SIG_USER_DATA */     { sscop_outrec_userdata, NULL },
 4663                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4664                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4665                 /* SIG_RELEASE_REQ */   { sscop_outrec_release_req, NULL },
 4666                 /* SIG_RECOVER */       { NULL, NULL },
 4667                 /* SIG_SYNC_REQ */      { sscop_outrec_sync_req, NULL },
 4668                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4669                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4670                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4671                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4672                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4673                 /* SIG_RETRIEVE */      { NULL, NULL },
 4674         },
 4675         /* SSCOP_REC_PEND */ {
 4676                 /* SIG_BGN */           { sscop_rec_bgn, NULL },
 4677                 /* SIG_BGAK */          { sscop_rec_bgak, NULL },
 4678                 /* SIG_END */           { sscop_rec_end, NULL },
 4679                 /* SIG_ENDAK */         { sscop_rec_endak, NULL },
 4680                 /* SIG_RS */            { sscop_rec_rs, NULL },
 4681                 /* SIG_RSAK */          { sscop_rec_rsak, NULL },
 4682                 /* SIG_BGREJ */         { sscop_rec_bgrej, NULL },
 4683                 /* SIG_SD */            { sscop_ignore_pdu, NULL },
 4684                 /* SIG_ER */            { sscop_rec_er, NULL },
 4685                 /* SIG_POLL */          { sscop_ignore_pdu, NULL },
 4686                 /* SIG_STAT */          { sscop_rec_stat, NULL },
 4687                 /* SIG_USTAT */         { sscop_rec_ustat, NULL },
 4688                 /* SIG_UD */            { sscop_ud, NULL },
 4689                 /* SIG_MD */            { sscop_md, NULL },
 4690                 /* SIG_ERAK */          { sscop_ignore_pdu, NULL },
 4691                 /* SIG_T_CC */          { NULL, NULL },
 4692                 /* SIG_T_POLL */        { NULL, NULL },
 4693                 /* SIG_T_KA */          { NULL, NULL },
 4694                 /* SIG_T_NR */          { NULL, NULL },
 4695                 /* SIG_T_IDLE */        { NULL, NULL },
 4696                 /* SIG_PDU_Q */         { sscop_rec_pduq, NULL },
 4697                 /* SIG_USER_DATA */     { NULL, NULL },
 4698                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4699                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4700                 /* SIG_RELEASE_REQ */   { sscop_rec_release_req, NULL },
 4701                 /* SIG_RECOVER */       { sscop_rec_recover, NULL },
 4702                 /* SIG_SYNC_REQ */      { sscop_rec_sync_req, NULL },
 4703                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4704                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4705                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4706                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4707                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4708                 /* SIG_RETRIEVE */      { sscop_retrieve, NULL },
 4709         },
 4710         /* SSCOP_IN_REC_PEND */ {
 4711                 /* SIG_BGN */           { sscop_inrec_bgn, NULL },
 4712                 /* SIG_BGAK */          { sscop_inrec_bgak, NULL },
 4713                 /* SIG_END */           { sscop_inrec_end, NULL },
 4714                 /* SIG_ENDAK */         { sscop_inrec_endak, NULL },
 4715                 /* SIG_RS */            { sscop_inrec_rs, NULL },
 4716                 /* SIG_RSAK */          { sscop_inrec_rsak, NULL },
 4717                 /* SIG_BGREJ */         { sscop_inrec_bgrej, NULL },
 4718                 /* SIG_SD */            { sscop_inrec_sd, NULL },
 4719                 /* SIG_ER */            { sscop_inrec_er, NULL },
 4720                 /* SIG_POLL */          { sscop_inrec_poll, NULL },
 4721                 /* SIG_STAT */          { sscop_inrec_stat, NULL },
 4722                 /* SIG_USTAT */         { sscop_inrec_ustat, NULL },
 4723                 /* SIG_UD */            { sscop_ud, NULL },
 4724                 /* SIG_MD */            { sscop_md, NULL },
 4725                 /* SIG_ERAK */          { sscop_inrec_erak, NULL },
 4726                 /* SIG_T_CC */          { NULL, NULL },
 4727                 /* SIG_T_POLL */        { NULL, NULL },
 4728                 /* SIG_T_KA */          { NULL, NULL },
 4729                 /* SIG_T_NR */          { NULL, NULL },
 4730                 /* SIG_T_IDLE */        { NULL, NULL },
 4731                 /* SIG_PDU_Q */         { sscop_inrec_pduq, NULL },
 4732                 /* SIG_USER_DATA */     { NULL, NULL },
 4733                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4734                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4735                 /* SIG_RELEASE_REQ */   { sscop_inrec_release_req, NULL },
 4736                 /* SIG_RECOVER */       { sscop_inrec_recover, NULL },
 4737                 /* SIG_SYNC_REQ */      { sscop_inrec_sync_req, NULL },
 4738                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4739                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4740                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4741                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4742                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4743                 /* SIG_RETRIEVE */      { sscop_retrieve, NULL },
 4744         },
 4745         /* SSCOP_READY */ {
 4746                 /* SIG_BGN */           { sscop_ready_bgn, NULL },
 4747                 /* SIG_BGAK */          { sscop_ignore_pdu, NULL },
 4748                 /* SIG_END */           { sscop_ready_end, NULL },
 4749                 /* SIG_ENDAK */         { sscop_ready_endak, NULL },
 4750                 /* SIG_RS */            { sscop_ready_rs, NULL },
 4751                 /* SIG_RSAK */          { sscop_ignore_pdu, NULL },
 4752                 /* SIG_BGREJ */         { sscop_ready_bgrej, NULL },
 4753                 /* SIG_SD */            { sscop_ready_sd, NULL },
 4754                 /* SIG_ER */            { sscop_ready_er, NULL },
 4755                 /* SIG_POLL */          { sscop_ready_poll, NULL },
 4756                 /* SIG_STAT */          { sscop_ready_stat, NULL },
 4757                 /* SIG_USTAT */         { sscop_ready_ustat, NULL },
 4758                 /* SIG_UD */            { sscop_ud, NULL },
 4759                 /* SIG_MD */            { sscop_md, NULL },
 4760                 /* SIG_ERAK */          { sscop_ignore_pdu, NULL },
 4761                 /* SIG_T_CC */          { NULL, NULL },
 4762                 /* SIG_T_POLL */        { sscop_ready_tpoll, NULL },
 4763                 /* SIG_T_KA */          { sscop_ready_tka, NULL },
 4764                 /* SIG_T_NR */          { sscop_ready_nr, NULL },
 4765                 /* SIG_T_IDLE */        { sscop_ready_tidle, NULL },
 4766                 /* SIG_PDU_Q */         { sscop_ready_pduq, c_ready_pduq },
 4767                 /* SIG_USER_DATA */     { sscop_ready_userdata, NULL },
 4768                 /* SIG_ESTAB_REQ */     { NULL, NULL },
 4769                 /* SIG_ESTAB_RESP */    { NULL, NULL },
 4770                 /* SIG_RELEASE_REQ */   { sscop_ready_release_req, NULL },
 4771                 /* SIG_RECOVER */       { NULL, NULL },
 4772                 /* SIG_SYNC_REQ */      { sscop_ready_sync_req, NULL },
 4773                 /* SIG_SYNC_RESP */     { NULL, NULL },
 4774                 /* SIG_UDATA */         { sscop_udata_req, NULL },
 4775                 /* SIG_MDATA */         { sscop_mdata_req, NULL },
 4776                 /* SIG_UPDU_Q */        { sscop_upduq, NULL },
 4777                 /* SIG_MPDU_Q */        { sscop_mpduq, NULL },
 4778                 /* SIG_RETRIEVE */      { NULL, NULL },
 4779         }
 4780 };
 4781 
 4782 /*
 4783  * Try to execute a signal. It is executed if
 4784  *   - it is illegal (in this case it is effectively ignored)
 4785  *   - it has no condition
 4786  *   - its condition is true
 4787  * If it has a condition and that is false, the function does nothing and
 4788  * returns 0.
 4789  * If the signal gets executed, the signal function is responsible to release
 4790  * the message (if any).
 4791  */
 4792 static int
 4793 sig_exec(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
 4794 {
 4795         void (*func)(struct sscop *, struct sscop_msg *);
 4796         int (*cond)(struct sscop *);
 4797 
 4798         func = state_matrix[sscop->state][sig].func;
 4799         cond = state_matrix[sscop->state][sig].cond;
 4800 
 4801         if(func == NULL) {
 4802                 VERBOSE(sscop, SSCOP_DBG_BUG, (sscop, sscop->aarg,
 4803                     "no handler for %s in state %s - ignored",
 4804                     events[sig], states[sscop->state]));
 4805                 SSCOP_MSG_FREE(msg);
 4806                 return 1;
 4807         }
 4808         if(cond == NULL || (*cond)(sscop)) {
 4809                 VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
 4810                     "executing %s in %s", events[sig],
 4811                     states[sscop->state]));
 4812                 (*func)(sscop, msg);
 4813                 return 1;
 4814         }
 4815         VERBOSE(sscop, SSCOP_DBG_EXEC, (sscop, sscop->aarg,
 4816             "delaying %s in %s", events[sig],
 4817             states[sscop->state]));
 4818 
 4819         return 0;
 4820 }
 4821 
 4822 /*
 4823  * Deliver a signal to the given sscop
 4824  * If it is delivered from inside a signal handler - queue it. If not,
 4825  * execute it. After execution loop through the queue and execute all
 4826  * pending signals. Signals, that cannot be executed because of entry
 4827  * conditions are skipped.
 4828  */
 4829 static void
 4830 sscop_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
 4831 {
 4832         struct sscop_sig *s;
 4833 
 4834         VERBOSE(sscop, SSCOP_DBG_INSIG, (sscop, sscop->aarg,
 4835             "got signal %s in state %s%s", events[sig],
 4836             states[sscop->state], sscop->in_sig ? " -- queuing" : ""));
 4837 
 4838         SIG_ALLOC(s);
 4839         if(s == NULL) {
 4840                 FAILURE("sscop: cannot allocate signal");
 4841                 SSCOP_MSG_FREE(msg);
 4842                 return;
 4843         }
 4844         s->sig = sig;
 4845         s->msg = msg;
 4846         SIGQ_APPEND(&sscop->sigs, s);
 4847 
 4848         if(!sscop->in_sig)
 4849                 handle_sigs(sscop);
 4850 }
 4851 
 4852 /*
 4853  * Loop through the signal queue until we can't execute any signals.
 4854  */
 4855 static void
 4856 handle_sigs(struct sscop *sscop)
 4857 {
 4858         struct sscop_sig *s;
 4859         sscop_sigq_head_t dsigs, q;
 4860         int exec;
 4861 
 4862         sscop->in_sig++;
 4863  
 4864         /*
 4865          * Copy the current signal queue to the local one and empty
 4866          * the signal queue. Then loop through the signals. After one
 4867          * pass we have a list of delayed signals because of entry
 4868          * conditions and a new list of signals. Merge them. Repeat until
 4869          * the signal queue is either empty or contains only delayed signals.
 4870          */
 4871         SIGQ_INIT(&q);
 4872         SIGQ_INIT(&dsigs);
 4873         do {
 4874                 exec = 0;
 4875 
 4876                 /*
 4877                  * Copy signal list and make sscop list empty
 4878                  */
 4879                 SIGQ_MOVE(&sscop->sigs, &q);
 4880 
 4881                 /*
 4882                  * Loop through the list
 4883                  */
 4884                 while((s = SIGQ_GET(&q)) != NULL) {
 4885                         if(sig_exec(sscop, s->sig, s->msg)) {
 4886                                 exec = 1;
 4887                                 SIG_FREE(s);
 4888                         } else {
 4889                                 SIGQ_APPEND(&dsigs, s);
 4890                         }
 4891                 }
 4892 
 4893                 /*
 4894                  * Merge lists by inserting delayed signals in front of
 4895                  * the signal list. preserving the order.
 4896                  */
 4897                 SIGQ_PREPEND(&dsigs, &sscop->sigs);
 4898         } while(exec);
 4899         sscop->in_sig--;
 4900 }
 4901 
 4902 /*
 4903  * Save a signal that should be executed only if state changes.
 4904  */
 4905 static void
 4906 sscop_save_signal(struct sscop *sscop, u_int sig, struct sscop_msg *msg)
 4907 {
 4908         struct sscop_sig *s;
 4909 
 4910         SIG_ALLOC(s);
 4911         if(s == NULL) {
 4912                 FAILURE("sscop: cannot allocate signal");
 4913                 SSCOP_MSG_FREE(msg);
 4914                 return;
 4915         }
 4916         s->sig = sig;
 4917         s->msg = msg;
 4918         SIGQ_APPEND(&sscop->saved_sigs, s);
 4919 }
 4920 
 4921 /*
 4922  * Set a new state. If signals are waiting for a state change - append them to
 4923  * the signal queue, so they get executed.
 4924  */
 4925 static void
 4926 sscop_set_state(struct sscop *sscop, u_int nstate)
 4927 {
 4928         VERBOSE(sscop, SSCOP_DBG_STATE, (sscop, sscop->aarg,
 4929             "changing state from %s to %s",
 4930             states[sscop->state], states[nstate]));
 4931 
 4932         sscop->state = nstate;
 4933         SIGQ_MOVE(&sscop->saved_sigs, &sscop->sigs);
 4934 }
 4935 
 4936 void
 4937 sscop_setdebug(struct sscop *sscop, u_int n)
 4938 {
 4939         sscop->debug = n;
 4940 }
 4941 
 4942 u_int
 4943 sscop_getdebug(const struct sscop *sscop)
 4944 {
 4945         return (sscop->debug);
 4946 }

Cache object: b17071b7673f54bb59b2f2f86298bd76


[ 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.