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