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 43static 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 66static const char *const sscop_msigs[] = { 67 MKSTR(SSCOP_MDATA_request), 68 MKSTR(SSCOP_MDATA_indication), 69 MKSTR(SSCOP_MERROR_indication), 70}; 71 72static 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 86static 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 124static 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 144MEMINIT(); 145 146static void sscop_signal(struct sscop *, u_int, struct sscop_msg *); 147static void sscop_save_signal(struct sscop *, u_int, struct sscop_msg *); 148static void handle_sigs(struct sscop *); 149static 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 277TIMER_FUNC(cc, CC) 278TIMER_FUNC(nr, NR) 279TIMER_FUNC(ka, KA) 280TIMER_FUNC(poll, POLL) 281TIMER_FUNC(idle, IDLE) 282 283/************************************************************/ 284/* 285 * INSTANCE AND TYPE HANDLING. 286 */ 287#ifdef SSCOP_DEBUG 288static void 289sscop_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 */ 407static void 408sscop_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 421static void 422sscop_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 */ 450struct sscop * 451sscop_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 */ 502void 503sscop_destroy(struct sscop *sscop) 504{ 505 sscop_reset(sscop); 506 507 MEMFREE(sscop); 508} 509 510/* 511 * Reset the SSCOP instance. 512 */ 513void 514sscop_reset(struct sscop *sscop) 515{ 516 sscop_clear(sscop); 517 sscop_init(sscop); 518} 519 520void 521sscop_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 541int 542sscop_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 626enum sscop_state 627sscop_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 */ 641int 642sscop_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 */ 738int 739sscop_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 */ 779void 780sscop_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 */ 958u_int 959sscop_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 */ 968u_int 969sscop_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 984const char * 985sscop_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 997const char * 998sscop_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 1010const char * 1011sscop_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 */ 1032static void 1033m_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 */ 1044static void 1045m_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 */ 1063static void 1064m_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 */ 1081static void 1082m_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 */ 1095static void 1096m_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 */ 1125static void 1126m_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 */ 1143static void 1144m_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 */ 1175static int 1176m_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 */ 1192static void 1193m_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 */ 1204static void 1205m_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 */ 1216static void 1217m_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 */ 1226static void 1227m_initialize_mr(struct sscop *sscop) 1228{ 1229 sscop->vr_mr = sscop->mr; 1230} 1231 1232/************************************************************/ 1233/* 1234 * CONDITIONS 1235 */ 1236static int 1237c_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 */ 1255static void 1256send_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 */ 1291static void 1292send_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 */ 1324static void 1325send_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 */ 1358static void 1359send_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 */ 1383static void 1384send_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 */ 1401static void 1402send_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 */ 1419static void 1420send_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 */ 1453static void 1454send_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 */ 1497static void 1498send_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 */ 1524static void 1525send_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 */ 1551static void 1552send_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 */ 1576static void 1577send_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 */ 1600static void 1601send_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 */ 1625static void 1626send_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 */ 1664static void 1665send_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 */ 1692static void 1693sscop_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 */ 1719static void 1720sscop_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 */ 1776static void 1777sscop_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 */ 1786static void 1787sscop_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 */ 1797static void 1798sscop_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 */ 1810static void 1811sscop_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 */ 1822static void 1823sscop_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 */ 1835static void 1836sscop_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 */ 1848static void 1849sscop_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 */ 1861static void 1862sscop_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 */ 1874static void 1875sscop_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 */ 1887static void 1888sscop_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 */ 1900static void 1901sscop_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 */ 1913static void 1914sscop_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 */ 1930static void 1931sscop_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 */ 1942static void 1943sscop_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 */ 1964static void 1965sscop_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 */ 1983static void 1984sscop_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 */ 2005static void 2006sscop_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 */ 2022static void 2023sscop_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 */ 2056static void 2057sscop_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 */ 2077static void 2078sscop_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 */ 2091static void 2092sscop_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 */ 2114static void 2115sscop_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 */ 2125static void 2126sscop_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 */ 2141static void 2142sscop_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 */ 2153static void 2154sscop_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 */ 2169static void 2170sscop_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 */ 2188static void 2189sscop_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 */ 2207static void 2208sscop_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 */ 2226static void 2227sscop_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 */ 2245static void 2246sscop_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 */ 2256static void 2257sscop_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 */ 2267static void 2268sscop_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 */ 2279static void 2280sscop_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 */ 2300static void 2301sscop_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 */ 2321static void 2322sscop_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 */ 2342static void 2343sscop_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 */ 2361static void 2362sscop_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 */ 2379static void 2380sscop_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 */ 2408static void 2409sscop_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 */ 2435static void 2436sscop_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 */ 2449static void 2450sscop_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 */ 2464static void 2465sscop_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 */ 2482static void 2483sscop_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 */ 2502static void 2503sscop_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 */ 2518static void 2519sscop_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 */ 2545static void 2546sscop_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 */ 2565static void 2566sscop_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 */ 2580static void 2581sscop_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 */ 2595static void 2596sscop_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 */ 2608static void 2609sscop_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 */ 2621static void 2622sscop_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 */ 2639static void 2640sscop_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 */ 2650static void 2651sscop_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 */ 2675static void 2676sscop_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 */ 2690static void 2691sscop_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 */ 2705static void 2706sscop_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 */ 2720static void 2721sscop_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 */ 2735static void 2736sscop_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 */ 2746static void 2747sscop_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 */ 2757static void 2758sscop_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 */ 2776static void 2777sscop_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 */ 2788static void 2789sscop_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 */ 2803static void 2804sscop_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 */ 2815static void 2816sscop_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 */ 2837static void 2838sscop_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 */ 2859static void 2860sscop_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 */ 2876static void 2877sscop_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 */ 2893static void 2894sscop_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 */ 2914static void 2915sscop_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 */ 2932static void 2933sscop_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 */ 2952static void 2953sscop_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 */ 2980static void 2981sscop_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 */ 3008static void 3009sscop_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 */ 3018static void 3019sscop_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 */ 3029static void 3030sscop_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 */ 3054static void 3055sscop_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 */ 3067static void 3068sscop_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 */ 3086static void 3087sscop_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 */ 3099static void 3100sscop_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 */ 3112static void 3113sscop_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 */ 3128static void 3129sscop_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 */ 3140static void 3141sscop_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 */ 3164static void 3165sscop_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 */ 3180static void 3181sscop_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 */ 3199static void 3200sscop_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 */ 3209static void 3210sscop_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 */ 3229static void 3230sscop_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 */ 3254static void 3255sscop_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 */ 3269static void 3270sscop_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 */ 3284static void 3285sscop_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 */ 3302static void 3303sscop_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 */ 3312static void 3313sscop_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 */ 3329static void 3330sscop_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 */ 3347static void 3348sscop_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 */ 3367static void 3368sscop_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 */ 3380static void 3381sscop_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 */ 3393static void 3394sscop_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 */ 3408static void 3409sscop_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 */ 3423static void 3424sscop_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 */ 3438static void 3439sscop_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 */ 3453static void 3454sscop_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 */ 3464static void 3465sscop_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 */ 3488static void 3489sscop_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 */ 3507static void 3508sscop_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 */ 3533static void 3534sscop_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 */ 3545static void 3546sscop_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 */ 3556static void 3557sscop_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 */ 3577static void 3578sscop_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 */ 3595static void 3596sscop_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 */ 3623static void 3624sscop_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 */ 3653static void 3654sscop_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 */ 3668static void 3669sscop_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 */ 3683static void 3684sscop_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 */ 3710static void 3711sscop_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 */ 3730static void 3731sscop_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 */ 3742static void 3743sscop_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 */ 3754static void 3755sscop_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 */ 3768static void 3769sscop_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 */ 3784static void 3785sscop_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 */ 3796static void 3797sscop_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 */ 3865static void 3866sscop_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 */ 3884static void 3885sscop_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 */ 3966static void 3967sscop_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 */ 4043static void 4044sscop_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 */ 4138static void 4139sscop_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 */ 4310static void 4311sscop_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 */ 4321static void 4322sscop_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 */ 4332static void 4333sscop_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 */ 4350static void 4351sscop_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 */ 4368static void 4369sscop_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 */ 4386static void 4387sscop_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 */ 4409static void 4410sscop_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 */ 4427static 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 */ 4793static int 4794sig_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 */ 4830static void 4831sscop_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 */ 4856static void 4857handle_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 */ 4906static void 4907sscop_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 */ 4926static void 4927sscop_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 4937void 4938sscop_setdebug(struct sscop *sscop, u_int n) 4939{ 4940 sscop->debug = n; 4941} 4942 4943u_int 4944sscop_getdebug(const struct sscop *sscop) 4945{ 4946 return (sscop->debug); 4947} 4948