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