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