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