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