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
TIMER_FUNC(cc,CC)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
sscop_init(struct sscop * sscop)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
sscop_clear(struct sscop * sscop)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 *
sscop_create(void * a,const struct sscop_funcs * funcs)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
sscop_destroy(struct sscop * sscop)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
sscop_reset(struct sscop * sscop)514 sscop_reset(struct sscop *sscop)
515 {
516 sscop_clear(sscop);
517 sscop_init(sscop);
518 }
519
520 void
sscop_getparam(const struct sscop * sscop,struct sscop_param * p)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
sscop_setparam(struct sscop * sscop,struct sscop_param * p,u_int * pmask)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
sscop_getstate(const struct sscop * sscop)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
sscop_aasig(struct sscop * sscop,enum sscop_aasig sig,struct SSCOP_MBUF_T * m,u_int arg)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
sscop_maasig(struct sscop * sscop,enum sscop_maasig sig,struct SSCOP_MBUF_T * m)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
sscop_input(struct sscop * sscop,struct SSCOP_MBUF_T * m)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
sscop_window(struct sscop * sscop,u_int n)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
sscop_setbusy(struct sscop * sscop,int busy)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 *
sscop_signame(enum sscop_aasig sig)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 *
sscop_msigname(enum sscop_maasig sig)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 *
sscop_statename(enum sscop_state s)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
m_release_buffers(struct sscop * sscop)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
m_prepare_retrieval(struct sscop * sscop)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
m_prepare_recovery(struct sscop * sscop)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
m_clear_transmitter(struct sscop * sscop)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
m_deliver_data(struct sscop * sscop)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
m_initialize_state(struct sscop * sscop)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
m_data_retrieval(struct sscop * sscop,u_int rn)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
m_detect_retransmission(struct sscop * sscop,struct sscop_msg * msg)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
m_set_poll_timer(struct sscop * sscop)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
m_reset_data_xfer_timers(struct sscop * sscop)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
m_set_data_xfer_timers(struct sscop * sscop)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
m_initialize_mr(struct sscop * sscop)1227 m_initialize_mr(struct sscop *sscop)
1228 {
1229 sscop->vr_mr = sscop->mr;
1230 }
1231
1232 /************************************************************/
1233 /*
1234 * CONDITIONS
1235 */
1236 static int
c_ready_pduq(struct sscop * sscop)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
send_bgn(struct sscop * sscop,struct SSCOP_MBUF_T * uu)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
send_bgrej(struct sscop * sscop,struct SSCOP_MBUF_T * uu)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
send_bgak(struct sscop * sscop,struct SSCOP_MBUF_T * uu)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
send_sd(struct sscop * sscop,struct SSCOP_MBUF_T * m,u_int seqno)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
send_ud(struct sscop * sscop,struct SSCOP_MBUF_T * m)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
send_md(struct sscop * sscop,struct SSCOP_MBUF_T * m)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
send_end(struct sscop * sscop,int src,struct SSCOP_MBUF_T * uu)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
send_ustat(struct sscop * sscop,...)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
send_er(struct sscop * sscop)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
send_poll(struct sscop * sscop)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
send_stat(struct sscop * sscop,u_int nps,struct SSCOP_MBUF_T * m)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
send_endak(struct sscop * sscop)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
send_erak(struct sscop * sscop)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
send_rs(struct sscop * sscop,int resend,struct SSCOP_MBUF_T * uu)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
send_rsak(struct sscop * sscop)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
sscop_idle_establish_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_idle_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ignore_pdu(struct sscop * sscop __unused,struct sscop_msg * msg)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
sscop_idle_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_poll(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_sd(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_erak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_stat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_ustat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_idle_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_flush_pduq(struct sscop * sscop __unused,struct sscop_msg * unused __unused)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
sscop_outpend_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outpend_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outpend_tcc(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_outpend_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_outpend_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_establish_resp(struct sscop * sscop,struct sscop_msg * uu)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
sscop_inpend_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_inpend_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_sd(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_ustat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_stat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_poll(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_erak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inpend_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outdis_establish_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_outdis_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outdis_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outdis_cc(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_outdis_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outsync_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outsync_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outsync_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outsync_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outsync_cc(struct sscop * sscop,struct sscop_msg * msg __unused)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
sscop_outsync_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_outsync_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outsync_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_sync_resp(struct sscop * sscop,struct sscop_msg * noarg __unused)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
sscop_insync_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_insync_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_sd(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_poll(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_stat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_ustat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_erak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_insync_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_userdata(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_erak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_cc(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_outrec_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_outrec_sync_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_outrec_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_pduq(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_outrec_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_rec_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_recover(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_rec_sync_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_rec_pduq(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_stat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_rec_ustat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_recover(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_inrec_pduq(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_inrec_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_sync_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_inrec_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_ustat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_stat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_poll(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_sd(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_rsak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_bgak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_inrec_erak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_sync_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_ready_release_req(struct sscop * sscop,struct sscop_msg * uu)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
sscop_ready_er(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_bgn(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_endak(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_bgrej(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_rs(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_end(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_tpoll(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_ready_tka(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_ready_tidle(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_ready_nr(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_ready_userdata(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_pduq(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_recover(struct sscop * sscop)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
sscop_ready_sd(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_poll(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_ustat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ready_stat(struct sscop * sscop,struct sscop_msg * msg)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
sscop_udata_req(struct sscop * sscop,struct sscop_msg * msg)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
sscop_mdata_req(struct sscop * sscop,struct sscop_msg * msg)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
sscop_upduq(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_mpduq(struct sscop * sscop,struct sscop_msg * unused __unused)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
sscop_md(struct sscop * sscop,struct sscop_msg * msg)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
sscop_ud(struct sscop * sscop,struct sscop_msg * msg)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
sscop_retrieve(struct sscop * sscop,struct sscop_msg * msg)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
sig_exec(struct sscop * sscop,u_int sig,struct sscop_msg * msg)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
sscop_signal(struct sscop * sscop,u_int sig,struct sscop_msg * msg)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
handle_sigs(struct sscop * sscop)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
sscop_save_signal(struct sscop * sscop,u_int sig,struct sscop_msg * msg)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
sscop_set_state(struct sscop * sscop,u_int nstate)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
sscop_setdebug(struct sscop * sscop,u_int n)4938 sscop_setdebug(struct sscop *sscop, u_int n)
4939 {
4940 sscop->debug = n;
4941 }
4942
4943 u_int
sscop_getdebug(const struct sscop * sscop)4944 sscop_getdebug(const struct sscop *sscop)
4945 {
4946 return (sscop->debug);
4947 }
4948