Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / netproto / atm / uni / sscop_sigcpcs.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/uni/sscop_sigcpcs.c,v 1.4 2000/01/17 20:49:52 mks Exp $
27  *
28  */
29
30 /*
31  * ATM Forum UNI Support
32  * ---------------------
33  *
34  * SSCOP Common - Process CPCS-signals (SSCOP PDUs)
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #include <netatm/uni/sscop.h>
41 #include <netatm/uni/sscop_misc.h>
42 #include <netatm/uni/sscop_pdu.h>
43 #include <netatm/uni/sscop_var.h>
44
45 #ifndef lint
46 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/sscop_sigcpcs.c,v 1.4 2000/01/17 20:49:52 mks Exp $");
47 #endif
48
49
50 /*
51  * No-op Processor
52  *
53  * Arguments:
54  *      sop     pointer to sscop connection block
55  *      m       pointer to PDU buffer (without trailer)
56  *      trlr    pointer to PDU trailer
57  *
58  * Returns:
59  *      none
60  *
61  */
62 void
63 sscop_noop(sop, m, trlr)
64         struct sscop    *sop;
65         KBuffer         *m;
66         caddr_t         trlr;
67 {
68         /*
69          * Just free PDU
70          */
71         KB_FREEALL(m);
72
73         return;
74 }
75
76
77 /*
78  * BGN PDU / SOS_IDLE Processor
79  *
80  * Arguments:
81  *      sop     pointer to sscop connection block
82  *      m       pointer to PDU buffer (without trailer)
83  *      trlr    pointer to PDU trailer
84  *
85  * Returns:
86  *      none
87  *
88  */
89 void
90 sscop_bgn_idle(sop, m, trlr)
91         struct sscop    *sop;
92         KBuffer         *m;
93         caddr_t         trlr;
94 {
95         struct bgn_pdu  *bp = (struct bgn_pdu *)trlr;
96         int             err, source;
97
98         if (sop->so_vers == SSCOP_VERS_Q2110) {
99                 /*
100                  * "Power-up Robustness" option
101                  *
102                  * Accept BGN regardless of BGN.N(SQ)
103                  */
104                 sop->so_rcvconn = bp->bgn_nsq;
105
106         } else {
107                 /*
108                  * If retransmitted BGN, reject it
109                  */
110                 if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
111                         KB_FREEALL(m);
112                         (void) sscop_send_bgrej(sop);
113                         return;
114                 }
115         }
116
117         if (sop->so_vers == SSCOP_VERS_QSAAL) {
118                 /*
119                  * Get Source value
120                  */
121                 if (bp->bgn_type & PT_SOURCE_SSCOP)
122                         source = SSCOP_SOURCE_SSCOP;
123                 else
124                         source = SSCOP_SOURCE_USER;
125
126                 /*
127                  * Reset receiver state variables
128                  */
129                 qsaal1_reset_rcvr(sop);
130         } else
131                 source = 0;
132
133         /*
134          * Set initial transmit window
135          */
136         SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
137
138         /*
139          * Pass connection request up to user
140          */
141         STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
142                 sop->so_connvc, (int)m, source, err);
143         if (err) {
144                 KB_FREEALL(m);
145                 sscop_abort(sop, "stack memory\n");
146                 return;
147         }
148
149         /*
150          * Wait for user's response
151          */
152         sop->so_state = SOS_INCONN;
153
154         return;
155 }
156
157
158 /*
159  * BGN PDU / SOS_OUTDISC Processor
160  *
161  * Arguments:
162  *      sop     pointer to sscop connection block
163  *      m       pointer to PDU buffer (without trailer)
164  *      trlr    pointer to PDU trailer
165  *
166  * Returns:
167  *      none
168  *
169  */
170 void
171 sscop_bgn_outdisc(sop, m, trlr)
172         struct sscop    *sop;
173         KBuffer         *m;
174         caddr_t         trlr;
175 {
176         struct bgn_pdu  *bp = (struct bgn_pdu *)trlr;
177         int             err, source;
178
179         /*
180          * If retransmitted BGN, ACK it and send new END
181          */
182         if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
183                 KB_FREEALL(m);
184                 (void) sscop_send_bgak(sop);
185                 (void) sscop_send_end(sop, SSCOP_SOURCE_LAST);
186                 return;
187         }
188
189         /*
190          * Stop retransmit timer
191          */
192         sop->so_timer[SSCOP_T_CC] = 0;
193
194         /*
195          * Initialize transmit window
196          */
197         SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
198
199         /*
200          * Notify user of connection termination
201          */
202         STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper, sop->so_toku,
203                 sop->so_connvc, 0, 0, err);
204         if (err) {
205                 KB_FREEALL(m);
206                 sscop_abort(sop, "stack memory\n");
207                 return;
208         }
209
210         if (sop->so_vers == SSCOP_VERS_QSAAL) {
211                 /*
212                  * Get Source value
213                  */
214                 if (bp->bgn_type & PT_SOURCE_SSCOP)
215                         source = SSCOP_SOURCE_SSCOP;
216                 else
217                         source = SSCOP_SOURCE_USER;
218
219                 /*
220                  * Reset receiver variables
221                  */
222                 qsaal1_reset_rcvr(sop);
223         
224         } else
225                 source = 0;
226
227         /*
228          * Tell user about incoming connection
229          */
230         STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
231                 sop->so_connvc, (int)m, source, err);
232         if (err) {
233                 KB_FREEALL(m);
234                 sscop_abort(sop, "stack memory\n");
235                 return;
236         }
237
238         /*
239          * Wait for user's response
240          */
241         sop->so_state = SOS_INCONN;
242
243         return;
244 }
245
246
247 /*
248  * BGN PDU / SOS_OUTRESYN Processor
249  *
250  * Arguments:
251  *      sop     pointer to sscop connection block
252  *      m       pointer to PDU buffer (without trailer)
253  *      trlr    pointer to PDU trailer
254  *
255  * Returns:
256  *      none
257  *
258  */
259 void
260 sscop_bgn_outresyn(sop, m, trlr)
261         struct sscop    *sop;
262         KBuffer         *m;
263         caddr_t         trlr;
264 {
265         struct bgn_pdu  *bp = (struct bgn_pdu *)trlr;
266         int             err, source;
267
268         /*
269          * If retransmitted BGN, ACK it and send new RS
270          */
271         if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
272                 KB_FREEALL(m);
273                 (void) sscop_send_bgak(sop);
274                 (void) sscop_send_rs(sop);
275                 return;
276         }
277
278         /*
279          * Stop retransmit timer
280          */
281         sop->so_timer[SSCOP_T_CC] = 0;
282
283         /*
284          * Initialize transmit window
285          */
286         SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
287
288         if (sop->so_vers == SSCOP_VERS_QSAAL) {
289                 /*
290                  * Get (possible) Source value
291                  */
292                 if (bp->bgn_type & PT_SOURCE_SSCOP)
293                         source = SSCOP_SOURCE_SSCOP;
294                 else
295                         source = SSCOP_SOURCE_USER;
296
297                 /*
298                  * Reset receiver variables
299                  */
300                 qsaal1_reset_rcvr(sop);
301         
302         } else
303                 source = SSCOP_SOURCE_USER;
304
305         /*
306          * Notify user of connection termination
307          */
308         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
309                 sop->so_connvc, SSCOP_UU_NULL, source, err);
310         if (err) {
311                 KB_FREEALL(m);
312                 sscop_abort(sop, "stack memory\n");
313                 return;
314         }
315
316         /*
317          * Now tell user of a "new" incoming connection
318          */
319         STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
320                 sop->so_connvc, (int)m, source, err);
321         if (err) {
322                 KB_FREEALL(m);
323                 sscop_abort(sop, "stack memory\n");
324                 return;
325         }
326
327         /*
328          * Wait for user's response
329          */
330         sop->so_state = SOS_INCONN;
331
332         return;
333 }
334
335
336 /*
337  * BGN PDU / SOS_INRESYN Processor
338  *
339  * Arguments:
340  *      sop     pointer to sscop connection block
341  *      m       pointer to PDU buffer (without trailer)
342  *      trlr    pointer to PDU trailer
343  *
344  * Returns:
345  *      none
346  *
347  */
348 void
349 sscop_bgn_inresyn(sop, m, trlr)
350         struct sscop    *sop;
351         KBuffer         *m;
352         caddr_t         trlr;
353 {
354         struct bgn_pdu  *bp = (struct bgn_pdu *)trlr;
355         int             err, source;
356
357         /*
358          * If retransmitted BGN, oops
359          */
360         if (sscop_is_rexmit(sop, bp->bgn_nsq)) {
361                 KB_FREEALL(m);
362                 sscop_maa_error(sop, 'B');
363                 return;
364         }
365
366         /*
367          * Stop data transfer timers
368          */
369         sop->so_timer[SSCOP_T_POLL] = 0;
370         sop->so_timer[SSCOP_T_NORESP] = 0;
371         sop->so_timer[SSCOP_T_IDLE] = 0;
372         sop->so_flags &= ~SOF_KEEPALIVE;
373
374         /*
375          * Initialize transmit window
376          */
377         SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
378
379         if (sop->so_vers == SSCOP_VERS_QSAAL) {
380                 /*
381                  * Get (possible) Source value
382                  */
383                 if (bp->bgn_type & PT_SOURCE_SSCOP)
384                         source = SSCOP_SOURCE_SSCOP;
385                 else
386                         source = SSCOP_SOURCE_USER;
387
388                 /*
389                  * Reset receiver variables
390                  */
391                 qsaal1_reset_rcvr(sop);
392
393         } else {
394                 /*
395                  * Stop possible retransmit timer
396                  */
397                 sop->so_timer[SSCOP_T_CC] = 0;
398
399                 /*
400                  * Drain receiver queues
401                  */
402                 sscop_rcvr_drain(sop);
403
404                 /*
405                  * Tell user current connection has been released
406                  */
407                 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
408                         sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_USER, err);
409                 if (err) {
410                         KB_FREEALL(m);
411                         sscop_abort(sop, "stack memory\n");
412                         return;
413                 }
414
415                 source = 0;
416         }
417
418         /*
419          * Tell user of incoming connection
420          */
421         STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
422                 sop->so_connvc, (int)m, source, err);
423         if (err) {
424                 KB_FREEALL(m);
425                 sscop_abort(sop, "stack memory\n");
426                 return;
427         }
428
429         /*
430          * Wait for user's response
431          */
432         sop->so_state = SOS_INCONN;
433
434         return;
435 }
436
437
438 /*
439  * BGAK PDU / Protocol Error
440  *
441  * Arguments:
442  *      sop     pointer to sscop connection block
443  *      m       pointer to PDU buffer (without trailer)
444  *      trlr    pointer to PDU trailer
445  *
446  * Returns:
447  *      none
448  *
449  */
450 void
451 sscop_bgak_error(sop, m, trlr)
452         struct sscop    *sop;
453         KBuffer         *m;
454         caddr_t         trlr;
455 {
456
457         /*
458          * Record error condition
459          */
460         sscop_maa_error(sop, 'C');
461         KB_FREEALL(m);
462
463         return;
464 }
465
466
467 /*
468  * BGAK PDU / SOS_IDLE Processor
469  *
470  * Arguments:
471  *      sop     pointer to sscop connection block
472  *      m       pointer to PDU buffer (without trailer)
473  *      trlr    pointer to PDU trailer
474  *
475  * Returns:
476  *      none
477  *
478  */
479 void
480 sscop_bgak_idle(sop, m, trlr)
481         struct sscop    *sop;
482         KBuffer         *m;
483         caddr_t         trlr;
484 {
485
486         /*
487          * Record error condition
488          */
489         sscop_bgak_error(sop, m, trlr);
490
491         /*
492          * Return an END to peer
493          */
494         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
495         return;
496 }
497
498
499 /*
500  * BGAK PDU / SOS_OUTCONN Processor
501  *
502  * Arguments:
503  *      sop     pointer to sscop connection block
504  *      m       pointer to PDU buffer (without trailer)
505  *      trlr    pointer to PDU trailer
506  *
507  * Returns:
508  *      none
509  *
510  */
511 void
512 sscop_bgak_outconn(sop, m, trlr)
513         struct sscop    *sop;
514         KBuffer         *m;
515         caddr_t         trlr;
516 {
517         struct bgak_pdu *bp = (struct bgak_pdu *)trlr;
518         int             err;
519
520         /*
521          * Stop retransmit timer
522          */
523         sop->so_timer[SSCOP_T_CC] = 0;
524
525         /*
526          * Initialize transmit window
527          */
528         SEQ_SET(sop->so_sendmax, ntohl(bp->bgak_nmr));
529
530         /*
531          * Notify user of connection establishment
532          */
533         if (sop->so_flags & SOF_REESTAB) {
534                 KB_FREEALL(m);
535                 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
536                         sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
537                 if (err) {
538                         sscop_abort(sop, "stack memory\n");
539                         return;
540                 }
541                 sop->so_flags &= ~SOF_REESTAB;
542         } else {
543                 STACK_CALL(SSCOP_ESTABLISH_CNF, sop->so_upper, sop->so_toku,
544                         sop->so_connvc, (int)m, 0, err);
545                 if (err) {
546                         KB_FREEALL(m);
547                         sscop_abort(sop, "stack memory\n");
548                         return;
549                 }
550         }
551
552         if (sop->so_vers == SSCOP_VERS_QSAAL) {
553                 /*
554                  * Reset receiver variables
555                  */
556                 qsaal1_reset_rcvr(sop);
557         
558                 /*
559                  * Start polling timer
560                  */
561                 sscop_set_poll(sop);
562
563                 /*
564                  * Start lost poll/stat timer
565                  */
566                 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
567
568         } else {
569                 /*
570                  * Initialize state variables
571                  */
572                 q2110_init_state(sop);
573
574                 /*
575                  * Start data transfer timers
576                  */
577                 sop->so_timer[SSCOP_T_POLL] = sop->so_parm.sp_timepoll;
578                 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
579         }
580
581         /*
582          * OK, we're ready for data
583          */
584         sop->so_state = SOS_READY;
585
586         /*
587          * See if transmit queues need servicing
588          */
589         if (sop->so_flags & SOF_XMITSRVC)
590                 sscop_service_xmit(sop);
591
592         return;
593 }
594
595
596 /*
597  * BGREJ PDU / Protocol Error
598  *
599  * Arguments:
600  *      sop     pointer to sscop connection block
601  *      m       pointer to PDU buffer (without trailer)
602  *      trlr    pointer to PDU trailer
603  *
604  * Returns:
605  *      none
606  *
607  */
608 void
609 sscop_bgrej_error(sop, m, trlr)
610         struct sscop    *sop;
611         KBuffer         *m;
612         caddr_t         trlr;
613 {
614
615         /*
616          * Record error condition
617          */
618         sscop_maa_error(sop, 'D');
619         KB_FREEALL(m);
620         return;
621 }
622
623
624 /*
625  * BGREJ PDU / SOS_OUTCONN Processor
626  *
627  * Arguments:
628  *      sop     pointer to sscop connection block
629  *      m       pointer to PDU buffer (without trailer)
630  *      trlr    pointer to PDU trailer
631  *
632  * Returns:
633  *      none
634  *
635  */
636 void
637 sscop_bgrej_outconn(sop, m, trlr)
638         struct sscop    *sop;
639         KBuffer         *m;
640         caddr_t         trlr;
641 {
642         int             source, uu, err;
643
644         /*
645          * Stop retransmit timer
646          */
647         sop->so_timer[SSCOP_T_CC] = 0;
648
649         if (sop->so_vers == SSCOP_VERS_QSAAL) {
650                 /*
651                  * Clear reestablishment flag
652                  */
653                 sop->so_flags &= ~SOF_REESTAB;
654
655                 KB_FREEALL(m);
656                 m = NULL;
657                 uu = SSCOP_UU_NULL;
658                 source = SSCOP_SOURCE_SSCOP;
659         } else {
660                 uu = (int)m;
661                 source = SSCOP_SOURCE_USER;
662         }
663
664         /*
665          * Notify user of connection failure
666          */
667         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
668                 sop->so_connvc, uu, source, err);
669         if (err) {
670                 KB_FREEALL(m);
671                 sscop_abort(sop, "stack memory\n");
672                 return;
673         }
674
675         /*
676          * Back to idle state
677          */
678         sop->so_state = SOS_IDLE;
679
680         return;
681 }
682
683
684 /*
685  * BGREJ PDU / SOS_INCONN Processor
686  *
687  * Arguments:
688  *      sop     pointer to sscop connection block
689  *      m       pointer to PDU buffer (without trailer)
690  *      trlr    pointer to PDU trailer
691  *
692  * Returns:
693  *      none
694  *
695  */
696 void
697 sscop_bgrej_inconn(sop, m, trlr)
698         struct sscop    *sop;
699         KBuffer         *m;
700         caddr_t         trlr;
701 {
702         int             err;
703
704         /*
705          * Report protocol error
706          */
707         sscop_bgrej_error(sop, m, trlr);
708
709         /*
710          * Notify user of connection failure
711          */
712         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
713                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
714         if (err) {
715                 sscop_abort(sop, "stack memory\n");
716                 return;
717         }
718
719         /*
720          * Back to idle state
721          */
722         sop->so_state = SOS_IDLE;
723
724         return;
725 }
726
727
728 /*
729  * BGREJ PDU / SOS_OUTRESYN Processor
730  *
731  * Arguments:
732  *      sop     pointer to sscop connection block
733  *      m       pointer to PDU buffer (without trailer)
734  *      trlr    pointer to PDU trailer
735  *
736  * Returns:
737  *      none
738  *
739  */
740 void
741 sscop_bgrej_outresyn(sop, m, trlr)
742         struct sscop    *sop;
743         KBuffer         *m;
744         caddr_t         trlr;
745 {
746         int             err;
747
748         /*
749          * Stop retransmit timer
750          */
751         sop->so_timer[SSCOP_T_CC] = 0;
752
753         /*
754          * Report protocol error
755          */
756         sscop_bgrej_error(sop, m, trlr);
757
758         /*
759          * Notify user of connection failure
760          */
761         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
762                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
763         if (err) {
764                 sscop_abort(sop, "stack memory\n");
765                 return;
766         }
767
768         if (sop->so_vers == SSCOP_VERS_QSAAL) {
769                 /*
770                  * Clear connection data
771                  */
772                 qsaal1_clear_connection(sop);
773         }
774
775         /*
776          * Back to idle state
777          */
778         sop->so_state = SOS_IDLE;
779
780         return;
781 }
782
783
784 /*
785  * BGREJ PDU / SOS_READY Processor
786  *
787  * Arguments:
788  *      sop     pointer to sscop connection block
789  *      m       pointer to PDU buffer (without trailer)
790  *      trlr    pointer to PDU trailer
791  *
792  * Returns:
793  *      none
794  *
795  */
796 void
797 sscop_bgrej_ready(sop, m, trlr)
798         struct sscop    *sop;
799         KBuffer         *m;
800         caddr_t         trlr;
801 {
802         int             err;
803
804         /*
805          * Stop data transfer timers
806          */
807         sop->so_timer[SSCOP_T_POLL] = 0;
808         sop->so_timer[SSCOP_T_NORESP] = 0;
809         sop->so_timer[SSCOP_T_IDLE] = 0;
810         sop->so_flags &= ~SOF_KEEPALIVE;
811
812         /*
813          * Report protocol error
814          */
815         sscop_bgrej_error(sop, m, trlr);
816
817         /*
818          * Notify user of connection failure
819          */
820         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
821                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
822         if (err) {
823                 sscop_abort(sop, "stack memory\n");
824                 return;
825         }
826
827         if (sop->so_vers == SSCOP_VERS_QSAAL) {
828                 /*
829                  * Clear connection data
830                  */
831                 qsaal1_clear_connection(sop);
832         } else {
833                 /*
834                  * Clear out appropriate queues
835                  */
836                 q2110_prep_retrieve(sop);
837         }
838
839         /*
840          * Back to idle state
841          */
842         sop->so_state = SOS_IDLE;
843
844         return;
845 }
846
847
848 /*
849  * END PDU / SOS_IDLE Processor
850  *
851  * Arguments:
852  *      sop     pointer to sscop connection block
853  *      m       pointer to PDU buffer (without trailer)
854  *      trlr    pointer to PDU trailer
855  *
856  * Returns:
857  *      none
858  *
859  */
860 void
861 sscop_end_idle(sop, m, trlr)
862         struct sscop    *sop;
863         KBuffer         *m;
864         caddr_t         trlr;
865 {
866
867         /*
868          * Free buffers
869          */
870         KB_FREEALL(m);
871
872         /*
873          * Return an ENDAK to peer
874          */
875         (void) sscop_send_endak(sop);
876
877         return;
878 }
879
880
881 /*
882  * END PDU / SOS_INCONN Processor
883  *
884  * Arguments:
885  *      sop     pointer to sscop connection block
886  *      m       pointer to PDU buffer (without trailer)
887  *      trlr    pointer to PDU trailer
888  *
889  * Returns:
890  *      none
891  *
892  */
893 void
894 sscop_end_inconn(sop, m, trlr)
895         struct sscop    *sop;
896         KBuffer         *m;
897         caddr_t         trlr;
898 {
899         struct end_pdu  *ep = (struct end_pdu *)trlr;
900         int             err, source;
901
902         /*
903          * Stop retransmit timer
904          */
905         sop->so_timer[SSCOP_T_CC] = 0;
906
907         /*
908          * Acknowledge END
909          */
910         (void) sscop_send_endak(sop);
911
912         /*
913          * Get Source value
914          */
915         if (ep->end_type & PT_SOURCE_SSCOP)
916                 source = SSCOP_SOURCE_SSCOP;
917         else
918                 source = SSCOP_SOURCE_USER;
919
920         /*
921          * Notify user of connection termination
922          */
923         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
924                 sop->so_connvc, (int)m, source, err);
925         if (err) {
926                 KB_FREEALL(m);
927                 sscop_abort(sop, "stack memory\n");
928                 return;
929         }
930
931         /*
932          * Back to idle state
933          */
934         sop->so_state = SOS_IDLE;
935
936         return;
937 }
938
939
940 /*
941  * END PDU / SOS_OUTDISC Processor
942  *
943  * Arguments:
944  *      sop     pointer to sscop connection block
945  *      m       pointer to PDU buffer (without trailer)
946  *      trlr    pointer to PDU trailer
947  *
948  * Returns:
949  *      none
950  *
951  */
952 void
953 sscop_end_outdisc(sop, m, trlr)
954         struct sscop    *sop;
955         KBuffer         *m;
956         caddr_t         trlr;
957 {
958         int             err;
959
960         /*
961          * Stop retransmit timer
962          */
963         sop->so_timer[SSCOP_T_CC] = 0;
964
965         /*
966          * Release buffers
967          */
968         KB_FREEALL(m);
969
970         /*
971          * Acknowledge END
972          */
973         (void) sscop_send_endak(sop);
974
975         /*
976          * Notify user of connection termination
977          */
978         STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper, sop->so_toku,
979                 sop->so_connvc, 0, 0, err);
980         if (err) {
981                 sscop_abort(sop, "stack memory\n");
982                 return;
983         }
984
985         /*
986          * Back to idle state
987          */
988         sop->so_state = SOS_IDLE;
989
990         return;
991 }
992
993
994 /*
995  * ENDAK PDU / Protocol Error
996  *
997  * Arguments:
998  *      sop     pointer to sscop connection block
999  *      m       pointer to PDU buffer (without trailer)
1000  *      trlr    pointer to PDU trailer
1001  *
1002  * Returns:
1003  *      none
1004  *
1005  */
1006 void
1007 sscop_endak_error(sop, m, trlr)
1008         struct sscop    *sop;
1009         KBuffer         *m;
1010         caddr_t         trlr;
1011 {
1012
1013         /*
1014          * Record error condition
1015          */
1016         sscop_maa_error(sop, 'F');
1017         KB_FREEALL(m);
1018
1019         return;
1020 }
1021
1022
1023 /*
1024  * ENDAK PDU / SOS_INCONN Processor
1025  *
1026  * Arguments:
1027  *      sop     pointer to sscop connection block
1028  *      m       pointer to PDU buffer (without trailer)
1029  *      trlr    pointer to PDU trailer
1030  *
1031  * Returns:
1032  *      none
1033  *
1034  */
1035 void
1036 sscop_endak_inconn(sop, m, trlr)
1037         struct sscop    *sop;
1038         KBuffer         *m;
1039         caddr_t         trlr;
1040 {
1041         int             err;
1042
1043         /*
1044          * Stop retransmit timer
1045          */
1046         sop->so_timer[SSCOP_T_CC] = 0;
1047
1048         /*
1049          * Report protocol error
1050          */
1051         sscop_endak_error(sop, m, trlr);
1052
1053         /*
1054          * Notify user of connection termination
1055          */
1056         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1057                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1058         if (err) {
1059                 sscop_abort(sop, "stack memory\n");
1060                 return;
1061         }
1062
1063         /*
1064          * Back to idle state
1065          */
1066         sop->so_state = SOS_IDLE;
1067
1068         return;
1069 }
1070
1071
1072 /*
1073  * ENDAK PDU / SOS_OUTDISC Processor
1074  *
1075  * Arguments:
1076  *      sop     pointer to sscop connection block
1077  *      m       pointer to PDU buffer (without trailer)
1078  *      trlr    pointer to PDU trailer
1079  *
1080  * Returns:
1081  *      none
1082  *
1083  */
1084 void
1085 sscop_endak_outdisc(sop, m, trlr)
1086         struct sscop    *sop;
1087         KBuffer         *m;
1088         caddr_t         trlr;
1089 {
1090         int             err;
1091
1092         /*
1093          * Stop retransmit timer
1094          */
1095         sop->so_timer[SSCOP_T_CC] = 0;
1096
1097         /*
1098          * Release buffers
1099          */
1100         KB_FREEALL(m);
1101
1102         /*
1103          * Notify user of connection termination
1104          */
1105         STACK_CALL(SSCOP_RELEASE_CNF, sop->so_upper, sop->so_toku,
1106                 sop->so_connvc, 0, 0, err);
1107         if (err) {
1108                 sscop_abort(sop, "stack memory\n");
1109                 return;
1110         }
1111
1112         /*
1113          * Back to idle state
1114          */
1115         sop->so_state = SOS_IDLE;
1116
1117         return;
1118 }
1119
1120
1121 /*
1122  * ENDAK PDU / SOS_READY Processor
1123  *
1124  * Arguments:
1125  *      sop     pointer to sscop connection block
1126  *      m       pointer to PDU buffer (without trailer)
1127  *      trlr    pointer to PDU trailer
1128  *
1129  * Returns:
1130  *      none
1131  *
1132  */
1133 void
1134 sscop_endak_ready(sop, m, trlr)
1135         struct sscop    *sop;
1136         KBuffer         *m;
1137         caddr_t         trlr;
1138 {
1139         int             err;
1140
1141         /*
1142          * Stop data transfer timers
1143          */
1144         sop->so_timer[SSCOP_T_POLL] = 0;
1145         sop->so_timer[SSCOP_T_NORESP] = 0;
1146         sop->so_timer[SSCOP_T_IDLE] = 0;
1147         sop->so_flags &= ~SOF_KEEPALIVE;
1148
1149         /*
1150          * Report protocol error
1151          */
1152         sscop_endak_error(sop, m, trlr);
1153
1154         /*
1155          * Notify user of connection failure
1156          */
1157         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1158                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1159         if (err) {
1160                 sscop_abort(sop, "stack memory\n");
1161                 return;
1162         }
1163
1164         if (sop->so_vers == SSCOP_VERS_QSAAL) {
1165                 /*
1166                  * Clear connection data
1167                  */
1168                 qsaal1_clear_connection(sop);
1169         } else {
1170                 /*
1171                  * Clear out appropriate queues
1172                  */
1173                 q2110_prep_retrieve(sop);
1174         }
1175
1176         /*
1177          * Back to idle state
1178          */
1179         sop->so_state = SOS_IDLE;
1180
1181         return;
1182 }
1183
1184
1185 /*
1186  * RS PDU / Protocol Error
1187  *
1188  * Arguments:
1189  *      sop     pointer to sscop connection block
1190  *      m       pointer to PDU buffer (without trailer)
1191  *      trlr    pointer to PDU trailer
1192  *
1193  * Returns:
1194  *      none
1195  *
1196  */
1197 void
1198 sscop_rs_error(sop, m, trlr)
1199         struct sscop    *sop;
1200         KBuffer         *m;
1201         caddr_t         trlr;
1202 {
1203
1204         /*
1205          * Record error condition
1206          */
1207         sscop_maa_error(sop, 'J');
1208         KB_FREEALL(m);
1209
1210         return;
1211 }
1212
1213
1214 /*
1215  * RS PDU / SOS_IDLE Processor
1216  *
1217  * Arguments:
1218  *      sop     pointer to sscop connection block
1219  *      m       pointer to PDU buffer (without trailer)
1220  *      trlr    pointer to PDU trailer
1221  *
1222  * Returns:
1223  *      none
1224  *
1225  */
1226 void
1227 sscop_rs_idle(sop, m, trlr)
1228         struct sscop    *sop;
1229         KBuffer         *m;
1230         caddr_t         trlr;
1231 {
1232
1233         /*
1234          * Report error condition
1235          */
1236         sscop_rs_error(sop, m, trlr);
1237
1238         /*
1239          * Return an END to peer
1240          */
1241         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1242
1243         return;
1244 }
1245
1246
1247 /*
1248  * RSAK PDU / Protocol Error
1249  *
1250  * Arguments:
1251  *      sop     pointer to sscop connection block
1252  *      m       pointer to PDU buffer (without trailer)
1253  *      trlr    pointer to PDU trailer
1254  *
1255  * Returns:
1256  *      none
1257  *
1258  */
1259 void
1260 sscop_rsak_error(sop, m, trlr)
1261         struct sscop    *sop;
1262         KBuffer         *m;
1263         caddr_t         trlr;
1264 {
1265
1266         /*
1267          * Record error condition
1268          */
1269         sscop_maa_error(sop, 'K');
1270         KB_FREEALL(m);
1271
1272         return;
1273 }
1274
1275
1276 /*
1277  * RSAK PDU / SOS_IDLE Processor
1278  *
1279  * Arguments:
1280  *      sop     pointer to sscop connection block
1281  *      m       pointer to PDU buffer (without trailer)
1282  *      trlr    pointer to PDU trailer
1283  *
1284  * Returns:
1285  *      none
1286  *
1287  */
1288 void
1289 sscop_rsak_idle(sop, m, trlr)
1290         struct sscop    *sop;
1291         KBuffer         *m;
1292         caddr_t         trlr;
1293 {
1294
1295         /*
1296          * Report error condition
1297          */
1298         sscop_rsak_error(sop, m, trlr);
1299
1300         /*
1301          * Return an END to peer
1302          */
1303         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1304         return;
1305 }
1306
1307
1308 /*
1309  * RSAK PDU / SOS_OUTRESYN Processor
1310  *
1311  * Arguments:
1312  *      sop     pointer to sscop connection block
1313  *      m       pointer to PDU buffer (without trailer)
1314  *      trlr    pointer to PDU trailer
1315  *
1316  * Returns:
1317  *      none
1318  *
1319  */
1320 void
1321 sscop_rsak_outresyn(sop, m, trlr)
1322         struct sscop    *sop;
1323         KBuffer         *m;
1324         caddr_t         trlr;
1325 {
1326         struct rsak_q2110_pdu   *rp = (struct rsak_q2110_pdu *)trlr;
1327         int             err;
1328
1329         /*
1330          * Stop retransmit timer
1331          */
1332         sop->so_timer[SSCOP_T_CC] = 0;
1333
1334         /*
1335          * Notify user of resynchronization completion
1336          */
1337         STACK_CALL(SSCOP_RESYNC_CNF, sop->so_upper, sop->so_toku,
1338                 sop->so_connvc, 0, 0, err);
1339         if (err) {
1340                 KB_FREEALL(m);
1341                 sscop_abort(sop, "stack memory\n");
1342                 return;
1343         }
1344
1345         if (sop->so_vers == SSCOP_VERS_QSAAL) {
1346                 /*
1347                  * Start the polling timer
1348                  */
1349                 sscop_set_poll(sop);
1350
1351                 /*
1352                  * Start lost poll/stat timer
1353                  */
1354                 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
1355         } else {
1356                 /*
1357                  * Initialize state variables
1358                  */
1359                 SEQ_SET(sop->so_sendmax, ntohl(rp->rsak_nmr));
1360                 q2110_init_state(sop);
1361
1362                 /*
1363                  * Start data transfer timers
1364                  */     
1365                 sop->so_timer[SSCOP_T_POLL] = sop->so_parm.sp_timepoll;
1366                 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
1367         }
1368
1369         /*
1370          * Free buffers
1371          */
1372         KB_FREEALL(m);
1373
1374         /*
1375          * Now go back to data transfer state
1376          */
1377         sop->so_state = SOS_READY;
1378
1379         /*
1380          * See if transmit queues need servicing
1381          */
1382         if (sop->so_flags & SOF_XMITSRVC)
1383                 sscop_service_xmit(sop);
1384
1385         return;
1386 }
1387
1388
1389 /*
1390  * SD PDU / Protocol Error
1391  *
1392  * Arguments:
1393  *      sop     pointer to sscop connection block
1394  *      m       pointer to PDU buffer (without trailer)
1395  *      trlr    pointer to PDU trailer
1396  *
1397  * Returns:
1398  *      none
1399  *
1400  */
1401 void
1402 sscop_sd_error(sop, m, trlr)
1403         struct sscop    *sop;
1404         KBuffer         *m;
1405         caddr_t         trlr;
1406 {
1407
1408         /*
1409          * Record error condition
1410          */
1411         sscop_maa_error(sop, 'A');
1412         KB_FREEALL(m);
1413
1414         return;
1415 }
1416
1417
1418 /*
1419  * SD PDU / SOS_IDLE Processor
1420  *
1421  * Arguments:
1422  *      sop     pointer to sscop connection block
1423  *      m       pointer to PDU buffer (without trailer)
1424  *      trlr    pointer to PDU trailer
1425  *
1426  * Returns:
1427  *      none
1428  *
1429  */
1430 void
1431 sscop_sd_idle(sop, m, trlr)
1432         struct sscop    *sop;
1433         KBuffer         *m;
1434         caddr_t         trlr;
1435 {
1436
1437         /*
1438          * Record error condition
1439          */
1440         sscop_sd_error(sop, m, trlr);
1441
1442         /*
1443          * Return an END to peer
1444          */
1445         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1446         return;
1447 }
1448
1449
1450 /*
1451  * SD PDU / SOS_INCONN Processor
1452  *
1453  * Arguments:
1454  *      sop     pointer to sscop connection block
1455  *      m       pointer to PDU buffer (without trailer)
1456  *      trlr    pointer to PDU trailer
1457  *
1458  * Returns:
1459  *      none
1460  *
1461  */
1462 void
1463 sscop_sd_inconn(sop, m, trlr)
1464         struct sscop    *sop;
1465         KBuffer         *m;
1466         caddr_t         trlr;
1467 {
1468         int             err;
1469
1470         /*
1471          * Record error condition
1472          */
1473         sscop_sd_error(sop, m, trlr);
1474
1475         /*
1476          * Return an END to peer
1477          */
1478         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1479
1480         /*
1481          * Notify user of connection failure
1482          */
1483         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1484                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1485         if (err) {
1486                 sscop_abort(sop, "stack memory\n");
1487                 return;
1488         }
1489
1490         /*
1491          * Go back to idle state
1492          */
1493         sop->so_state = SOS_IDLE;
1494
1495         return;
1496 }
1497
1498
1499 /*
1500  * POLL PDU / Protocol Error
1501  *
1502  * Arguments:
1503  *      sop     pointer to sscop connection block
1504  *      m       pointer to PDU buffer (without trailer)
1505  *      trlr    pointer to PDU trailer
1506  *
1507  * Returns:
1508  *      none
1509  *
1510  */
1511 void
1512 sscop_poll_error(sop, m, trlr)
1513         struct sscop    *sop;
1514         KBuffer         *m;
1515         caddr_t         trlr;
1516 {
1517
1518         /*
1519          * Record error condition
1520          */
1521         sscop_maa_error(sop, 'G');
1522         KB_FREEALL(m);
1523
1524         return;
1525 }
1526
1527
1528 /*
1529  * POLL PDU / SOS_IDLE Processor
1530  *
1531  * Arguments:
1532  *      sop     pointer to sscop connection block
1533  *      m       pointer to PDU buffer (without trailer)
1534  *      trlr    pointer to PDU trailer
1535  *
1536  * Returns:
1537  *      none
1538  *
1539  */
1540 void
1541 sscop_poll_idle(sop, m, trlr)
1542         struct sscop    *sop;
1543         KBuffer         *m;
1544         caddr_t         trlr;
1545 {
1546
1547         /*
1548          * Report error condition
1549          */
1550         sscop_poll_error(sop, m, trlr);
1551
1552         /*
1553          * Return an END to peer
1554          */
1555         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1556         return;
1557 }
1558
1559
1560 /*
1561  * POLL PDU / SOS_INCONN Processor
1562  *
1563  * Arguments:
1564  *      sop     pointer to sscop connection block
1565  *      m       pointer to PDU buffer (without trailer)
1566  *      trlr    pointer to PDU trailer
1567  *
1568  * Returns:
1569  *      none
1570  *
1571  */
1572 void
1573 sscop_poll_inconn(sop, m, trlr)
1574         struct sscop    *sop;
1575         KBuffer         *m;
1576         caddr_t         trlr;
1577 {
1578         int             err;
1579
1580         /*
1581          * Record error condition
1582          */
1583         sscop_poll_error(sop, m, trlr);
1584
1585         /*
1586          * Return an END to peer
1587          */
1588         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1589
1590         /*
1591          * Notify user of connection failure
1592          */
1593         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1594                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1595         if (err) {
1596                 sscop_abort(sop, "stack memory\n");
1597                 return;
1598         }
1599
1600         /*
1601          * Go back to idle state
1602          */
1603         sop->so_state = SOS_IDLE;
1604
1605         return;
1606 }
1607
1608
1609 /*
1610  * STAT PDU / Protocol Error
1611  *
1612  * Arguments:
1613  *      sop     pointer to sscop connection block
1614  *      m       pointer to PDU buffer (without trailer)
1615  *      trlr    pointer to PDU trailer
1616  *
1617  * Returns:
1618  *      none
1619  *
1620  */
1621 void
1622 sscop_stat_error(sop, m, trlr)
1623         struct sscop    *sop;
1624         KBuffer         *m;
1625         caddr_t         trlr;
1626 {
1627
1628         /*
1629          * Record error condition
1630          */
1631         sscop_maa_error(sop, 'H');
1632         KB_FREEALL(m);
1633
1634         return;
1635 }
1636
1637
1638 /*
1639  * STAT PDU / SOS_IDLE Processor
1640  *
1641  * Arguments:
1642  *      sop     pointer to sscop connection block
1643  *      m       pointer to PDU buffer (without trailer)
1644  *      trlr    pointer to PDU trailer
1645  *
1646  * Returns:
1647  *      none
1648  *
1649  */
1650 void
1651 sscop_stat_idle(sop, m, trlr)
1652         struct sscop    *sop;
1653         KBuffer         *m;
1654         caddr_t         trlr;
1655 {
1656
1657         /*
1658          * Report error condition
1659          */
1660         sscop_stat_error(sop, m, trlr);
1661
1662         /*
1663          * Return an END to peer
1664          */
1665         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1666         return;
1667 }
1668
1669
1670 /*
1671  * STAT PDU / SOS_INCONN Processor
1672  *
1673  * Arguments:
1674  *      sop     pointer to sscop connection block
1675  *      m       pointer to PDU buffer (without trailer)
1676  *      trlr    pointer to PDU trailer
1677  *
1678  * Returns:
1679  *      none
1680  *
1681  */
1682 void
1683 sscop_stat_inconn(sop, m, trlr)
1684         struct sscop    *sop;
1685         KBuffer         *m;
1686         caddr_t         trlr;
1687 {
1688         int             err;
1689
1690         /*
1691          * Record error condition
1692          */
1693         sscop_stat_error(sop, m, trlr);
1694
1695         /*
1696          * Return an END to peer
1697          */
1698         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1699
1700         /*
1701          * Notify user of connection failure
1702          */
1703         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1704                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1705         if (err) {
1706                 sscop_abort(sop, "stack memory\n");
1707                 return;
1708         }
1709
1710         /*
1711          * Go back to idle state
1712          */
1713         sop->so_state = SOS_IDLE;
1714
1715         return;
1716 }
1717
1718
1719 /*
1720  * STAT PDU / SOS_READY Processor
1721  *
1722  * Arguments:
1723  *      sop     pointer to sscop connection block
1724  *      m       pointer to PDU buffer (without trailer)
1725  *      trlr    pointer to PDU trailer
1726  *
1727  * Returns:
1728  *      none
1729  *
1730  */
1731 void
1732 sscop_stat_ready(sop, m, trlr)
1733         struct sscop    *sop;
1734         KBuffer         *m;
1735         caddr_t         trlr;
1736 {
1737         struct stat_pdu *sp = (struct stat_pdu *)trlr;
1738         struct pdu_hdr  *php;
1739         KBuffer         *m0 = m;
1740         sscop_seq       seq1, seq2, opa;
1741         int             cnt = 0;
1742
1743         NTOHL(sp->stat_nps);
1744         NTOHL(sp->stat_nmr);
1745         NTOHL(sp->stat_nr);
1746
1747         /*
1748          * Validate peer's received poll sequence number
1749          */
1750         if (SEQ_GT(sop->so_pollack, sp->stat_nps, sop->so_pollack) ||
1751             SEQ_GT(sp->stat_nps, sop->so_pollsend, sop->so_pollack)) {
1752                 /*
1753                  * Bad poll sequence number
1754                  */
1755                 sscop_maa_error(sop, 'R');
1756                 goto goterr;
1757         }
1758
1759         /*
1760          * Validate peer's current receive data sequence number
1761          */
1762         if (SEQ_GT(sop->so_ack, sp->stat_nr, sop->so_ack) ||
1763             SEQ_GT(sp->stat_nr, sop->so_send, sop->so_ack)) {
1764                 /*
1765                  * Bad data sequence number
1766                  */
1767                 sscop_maa_error(sop, 'S');
1768                 goto goterr;
1769         }
1770
1771         /*
1772          * Free acknowledged PDUs
1773          */
1774         for (seq1 = sop->so_ack, SEQ_SET(seq2, sp->stat_nr);
1775                         SEQ_LT(seq1, seq2, sop->so_ack);
1776                         SEQ_INCR(seq1, 1)) {
1777                 sscop_pack_free(sop, seq1);
1778         }
1779
1780         /*
1781          * Update transmit state variables
1782          */
1783         opa = sop->so_pollack;
1784         sop->so_ack = seq2;
1785         SEQ_SET(sop->so_pollack, sp->stat_nps);
1786         SEQ_SET(sop->so_sendmax, sp->stat_nmr);
1787
1788         /*
1789          * Get first element in STAT list
1790          */
1791         while (m && (KB_LEN(m) == 0))
1792                 m = KB_NEXT(m);
1793         if (m == NULL)
1794                 goto done;
1795         m = sscop_stat_getelem(m, &seq1);
1796
1797         /*
1798          * Make sure there's a second element too
1799          */
1800         if (m == NULL)
1801                 goto done;
1802
1803         /*
1804          * Validate first element (start of missing pdus)
1805          */
1806         if (SEQ_GT(sop->so_ack, seq1, sop->so_ack) ||
1807             SEQ_GEQ(seq1, sop->so_send, sop->so_ack)) {
1808                 /*
1809                  * Bad element sequence number
1810                  */
1811                 sscop_maa_error(sop, 'S');
1812                 goto goterr;
1813         }
1814
1815         /*
1816          * Loop thru all STAT elements in list
1817          */
1818         while (m) {
1819                 /*
1820                  * Get next even element (start of received pdus)
1821                  */
1822                 m = sscop_stat_getelem(m, &seq2);
1823
1824                 /*
1825                  * Validate seqence number
1826                  */
1827                 if (SEQ_GEQ(seq1, seq2, sop->so_ack) ||
1828                     SEQ_GT(seq2, sop->so_send, sop->so_ack)) {
1829                         /*
1830                          * Bad element sequence number
1831                          */
1832                         sscop_maa_error(sop, 'S');
1833                         goto goterr;
1834                 }
1835
1836                 /*
1837                  * Process each missing sequence number in this gap
1838                  */
1839                 while (SEQ_LT(seq1, seq2, sop->so_ack)) {
1840                         /*
1841                          * Find corresponding SD PDU on pending ack queue
1842                          */
1843                         php = sscop_pack_locate(sop, seq1);
1844                         if (php == NULL) {
1845                                 sscop_maa_error(sop, 'S');
1846                                 goto goterr;
1847                         }
1848
1849                         /*
1850                          * Retransmit this SD PDU only if it was last sent
1851                          * during an earlier poll sequence and it's not
1852                          * already scheduled for retranmission.
1853                          */
1854                         if (SEQ_LT(php->ph_nps, sp->stat_nps, opa) &&
1855                             (php->ph_rexmit_lk == NULL) &&
1856                             (sop->so_rexmit_tl != php)) {
1857                                 /*
1858                                  * Put PDU on retransmit queue and schedule
1859                                  * transmit servicing
1860                                  */
1861                                 sscop_rexmit_insert(sop, php);
1862                                 sop->so_flags |= SOF_XMITSRVC;
1863                                 cnt++;
1864                         }
1865
1866                         /*
1867                          * Bump to next sequence number
1868                          */
1869                         SEQ_INCR(seq1, 1);
1870                 }
1871
1872                 /*
1873                  * Now process series of acknowledged PDUs
1874                  *
1875                  * Get next odd element (start of missing pdus),
1876                  * but make sure there is one and that it's valid
1877                  */
1878                 if (m == NULL)
1879                         goto done;
1880                 m = sscop_stat_getelem(m, &seq2);
1881                 if (SEQ_GEQ(seq1, seq2, sop->so_ack) ||
1882                     SEQ_GT(seq2, sop->so_send, sop->so_ack)) {
1883                         /*
1884                          * Bad element sequence number
1885                          */
1886                         sscop_maa_error(sop, 'S');
1887                         goto goterr;
1888                 }
1889
1890                 /*
1891                  * Process each acked sequence number
1892                  */
1893                 while (SEQ_LT(seq1, seq2, sop->so_ack)) {
1894                         /*
1895                          * Can we clear transmit buffers ??
1896                          */
1897                         if ((sop->so_flags & SOF_NOCLRBUF) == 0) {
1898                                 /*
1899                                  * Yes, free acked buffers
1900                                  */
1901                                 sscop_pack_free(sop, seq1);
1902                         }
1903
1904                         /*
1905                          * Bump to next sequence number
1906                          */
1907                         SEQ_INCR(seq1, 1);
1908                 }
1909         }
1910
1911 done:
1912         /*
1913          * Free PDU buffer chain
1914          */
1915         KB_FREEALL(m0);
1916
1917         /*
1918          * Report retransmitted PDUs
1919          */
1920         if (cnt)
1921                 sscop_maa_error(sop, 'V');
1922
1923         /*
1924          * Record transmit window closed transitions
1925          */
1926         if (SEQ_LT(sop->so_send, sop->so_sendmax, sop->so_ack)) {
1927                 if (sop->so_flags & SOF_NOCREDIT) {
1928                         sop->so_flags &= ~SOF_NOCREDIT;
1929                         sscop_maa_error(sop, 'X');
1930                 }
1931         } else {
1932                 if ((sop->so_flags & SOF_NOCREDIT) == 0) {
1933                         sop->so_flags |= SOF_NOCREDIT;
1934                         sscop_maa_error(sop, 'W');
1935                 }
1936         }
1937
1938         if (sop->so_vers == SSCOP_VERS_QSAAL)
1939                 /*
1940                  * Restart lost poll/stat timer
1941                  */
1942                 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
1943         else {
1944                 /*
1945                  * Determine new polling phase
1946                  */
1947                 if ((sop->so_timer[SSCOP_T_POLL] != 0) &&
1948                     ((sop->so_flags & SOF_KEEPALIVE) == 0)) {
1949                         /*
1950                          * Remain in active phase - reset NO-RESPONSE timer
1951                          */
1952                         sop->so_timer[SSCOP_T_NORESP] =
1953                                         sop->so_parm.sp_timeresp;
1954
1955                 } else if (sop->so_timer[SSCOP_T_IDLE] == 0) {
1956                         /*
1957                          * Go from transient to idle phase
1958                          */
1959                         sop->so_timer[SSCOP_T_POLL] = 0;
1960                         sop->so_flags &= ~SOF_KEEPALIVE;
1961                         sop->so_timer[SSCOP_T_NORESP] = 0;
1962                         sop->so_timer[SSCOP_T_IDLE] = sop->so_parm.sp_timeidle;
1963                 }
1964         }
1965
1966         /*
1967          * See if transmit queues need servicing
1968          */
1969         if (sop->so_flags & SOF_XMITSRVC)
1970                 sscop_service_xmit(sop);
1971
1972         return;
1973
1974 goterr:
1975         /*
1976          * Protocol/parameter error encountered
1977          */
1978
1979         /*
1980          * Free PDU buffer chain
1981          */
1982         KB_FREEALL(m0);
1983
1984         if (sop->so_vers == SSCOP_VERS_QSAAL)
1985                 /*
1986                  * Reestablish a new connection
1987                  */
1988                 qsaal1_reestablish(sop);
1989         else
1990                 /*
1991                  * Initiate error recovery
1992                  */
1993                 q2110_error_recovery(sop);
1994
1995         return;
1996 }
1997
1998
1999 /*
2000  * USTAT PDU / Protocol Error
2001  *
2002  * Arguments:
2003  *      sop     pointer to sscop connection block
2004  *      m       pointer to PDU buffer (without trailer)
2005  *      trlr    pointer to PDU trailer
2006  *
2007  * Returns:
2008  *      none
2009  *
2010  */
2011 void
2012 sscop_ustat_error(sop, m, trlr)
2013         struct sscop    *sop;
2014         KBuffer         *m;
2015         caddr_t         trlr;
2016 {
2017
2018         /*
2019          * Record error condition
2020          */
2021         sscop_maa_error(sop, 'I');
2022         KB_FREEALL(m);
2023
2024         return;
2025 }
2026
2027
2028 /*
2029  * USTAT PDU / SOS_IDLE Processor
2030  *
2031  * Arguments:
2032  *      sop     pointer to sscop connection block
2033  *      m       pointer to PDU buffer (without trailer)
2034  *      trlr    pointer to PDU trailer
2035  *
2036  * Returns:
2037  *      none
2038  *
2039  */
2040 void
2041 sscop_ustat_idle(sop, m, trlr)
2042         struct sscop    *sop;
2043         KBuffer         *m;
2044         caddr_t         trlr;
2045 {
2046
2047         /*
2048          * Report error condition
2049          */
2050         sscop_ustat_error(sop, m, trlr);
2051
2052         /*
2053          * Return an END to peer
2054          */
2055         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
2056         return;
2057 }
2058
2059
2060 /*
2061  * USTAT PDU / SOS_INCONN Processor
2062  *
2063  * Arguments:
2064  *      sop     pointer to sscop connection block
2065  *      m       pointer to PDU buffer (without trailer)
2066  *      trlr    pointer to PDU trailer
2067  *
2068  * Returns:
2069  *      none
2070  *
2071  */
2072 void
2073 sscop_ustat_inconn(sop, m, trlr)
2074         struct sscop    *sop;
2075         KBuffer         *m;
2076         caddr_t         trlr;
2077 {
2078         int             err;
2079
2080         /*
2081          * Record error condition
2082          */
2083         sscop_ustat_error(sop, m, trlr);
2084
2085         /*
2086          * Return an END to peer
2087          */
2088         (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
2089
2090         /*
2091          * Notify user of connection failure
2092          */
2093         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
2094                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
2095         if (err) {
2096                 sscop_abort(sop, "stack memory\n");
2097                 return;
2098         }
2099
2100         /*
2101          * Go back to idle state
2102          */
2103         sop->so_state = SOS_IDLE;
2104
2105         return;
2106 }
2107
2108
2109 /*
2110  * USTAT PDU / SOS_READY Processor
2111  *
2112  * Arguments:
2113  *      sop     pointer to sscop connection block
2114  *      m       pointer to PDU buffer (without trailer)
2115  *      trlr    pointer to PDU trailer
2116  *
2117  * Returns:
2118  *      none
2119  *
2120  */
2121 void
2122 sscop_ustat_ready(sop, m, trlr)
2123         struct sscop    *sop;
2124         KBuffer         *m;
2125         caddr_t         trlr;
2126 {
2127         struct ustat_pdu        *up = (struct ustat_pdu *)trlr;
2128         struct pdu_hdr  *php;
2129         sscop_seq       seq1, seq2;
2130
2131         NTOHL(up->ustat_nmr);
2132         NTOHL(up->ustat_nr);
2133
2134         /*
2135          * Validate peer's current receive data sequence number
2136          */
2137         if (SEQ_GT(sop->so_ack, up->ustat_nr, sop->so_ack) ||
2138             SEQ_GEQ(up->ustat_nr, sop->so_send, sop->so_ack)) {
2139                 /*
2140                  * Bad data sequence number
2141                  */
2142                 goto goterr;
2143         }
2144
2145         /*
2146          * Free acknowledged PDUs
2147          */
2148         for (seq1 = sop->so_ack, SEQ_SET(seq2, up->ustat_nr);
2149                         SEQ_LT(seq1, seq2, sop->so_ack);
2150                         SEQ_INCR(seq1, 1)) {
2151                 sscop_pack_free(sop, seq1);
2152         }
2153
2154         /*
2155          * Update transmit state variables
2156          */
2157         sop->so_ack = seq2;
2158         SEQ_SET(sop->so_sendmax, up->ustat_nmr);
2159
2160         /*
2161          * Get USTAT list elements
2162          */
2163         SEQ_SET(seq1, ntohl(up->ustat_le1));
2164         SEQ_SET(seq2, ntohl(up->ustat_le2));
2165
2166         /*
2167          * Validate elements
2168          */
2169         if (SEQ_GT(sop->so_ack, seq1, sop->so_ack) ||
2170             SEQ_GEQ(seq1, seq2, sop->so_ack) ||
2171             SEQ_GEQ(seq2, sop->so_send, sop->so_ack)) {
2172                 /*
2173                  * Bad element sequence number
2174                  */
2175                 goto goterr;
2176         }
2177
2178         /*
2179          * Process each missing sequence number in this gap
2180          */
2181         while (SEQ_LT(seq1, seq2, sop->so_ack)) {
2182                 /*
2183                  * Find corresponding SD PDU on pending ack queue
2184                  */
2185                 php = sscop_pack_locate(sop, seq1);
2186                 if (php == NULL) {
2187                         goto goterr;
2188                 }
2189
2190                 /*
2191                  * Retransmit this SD PDU if it's not
2192                  * already scheduled for retranmission.
2193                  */
2194                 if ((php->ph_rexmit_lk == NULL) &&
2195                     (sop->so_rexmit_tl != php)) {
2196                         /*
2197                          * Put PDU on retransmit queue and schedule
2198                          * transmit servicing
2199                          */
2200                         sscop_rexmit_insert(sop, php);
2201                         sop->so_flags |= SOF_XMITSRVC;
2202                 }
2203
2204                 /*
2205                  * Bump to next sequence number
2206                  */
2207                 SEQ_INCR(seq1, 1);
2208         }
2209
2210         /*
2211          * Report retransmitted PDUs
2212          */
2213         sscop_maa_error(sop, 'V');
2214
2215         /*
2216          * Free PDU buffer chain
2217          */
2218         KB_FREEALL(m);
2219
2220         /*
2221          * See if transmit queues need servicing
2222          */
2223         if (sop->so_flags & SOF_XMITSRVC)
2224                 sscop_service_xmit(sop);
2225
2226         return;
2227
2228 goterr:
2229         /*
2230          * Protocol/parameter error encountered
2231          */
2232         sscop_maa_error(sop, 'T');
2233
2234         /*
2235          * Free PDU buffer chain
2236          */
2237         KB_FREEALL(m);
2238
2239         if (sop->so_vers == SSCOP_VERS_QSAAL)
2240                 /*
2241                  * Reestablish a new connection
2242                  */
2243                 qsaal1_reestablish(sop);
2244         else
2245                 /*
2246                  * Initiate error recovery
2247                  */
2248                 q2110_error_recovery(sop);
2249
2250         return;
2251 }
2252
2253
2254 /*
2255  * UD PDU / SOS_* Processor
2256  *
2257  * Arguments:
2258  *      sop     pointer to sscop connection block
2259  *      m       pointer to PDU buffer (without trailer)
2260  *      trlr    pointer to PDU trailer
2261  *
2262  * Returns:
2263  *      none
2264  *
2265  */
2266 void
2267 sscop_ud_all(sop, m, trlr)
2268         struct sscop    *sop;
2269         KBuffer         *m;
2270         caddr_t         trlr;
2271 {
2272         int             err;
2273
2274         /*
2275          * Pass data up to user
2276          */
2277         STACK_CALL(SSCOP_UNITDATA_IND, sop->so_upper, sop->so_toku,
2278                 sop->so_connvc, (int)m, 0, err);
2279         if (err)
2280                 KB_FREEALL(m);
2281         return;
2282 }
2283
2284
2285 /*
2286  * MD PDU / SOS_* Processor
2287  *
2288  * Arguments:
2289  *      sop     pointer to sscop connection block
2290  *      m       pointer to PDU buffer (without trailer)
2291  *      trlr    pointer to PDU trailer
2292  *
2293  * Returns:
2294  *      none
2295  *
2296  */
2297 void
2298 sscop_md_all(sop, m, trlr)
2299         struct sscop    *sop;
2300         KBuffer         *m;
2301         caddr_t         trlr;
2302 {
2303
2304         /*
2305          * We don't support MD PDUs
2306          */
2307         KB_FREEALL(m);
2308         return;
2309 }
2310