3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
31 * ATM Forum UNI Support
32 * ---------------------
34 * ITU-T Q.SAAL1 - Process CPCS-signals (SSCOP PDUs)
38 #include <netatm/kern_include.h>
40 #include <netatm/uni/sscop.h>
41 #include <netatm/uni/sscop_misc.h>
42 #include <netatm/uni/sscop_pdu.h>
43 #include <netatm/uni/sscop_var.h>
46 __RCSID("@(#) $FreeBSD$");
53 static void sscop_bgn_outconn __P((struct sscop *, KBuffer *, caddr_t));
54 static void sscop_end_outresyn __P((struct sscop *, KBuffer *, caddr_t));
55 static void sscop_end_conresyn __P((struct sscop *, KBuffer *, caddr_t));
56 static void sscop_end_ready __P((struct sscop *, KBuffer *, caddr_t));
57 static void sscop_endak_outresyn __P((struct sscop *, KBuffer *, caddr_t));
58 static void sscop_rs_outresyn __P((struct sscop *, KBuffer *, caddr_t));
59 static void sscop_rs_ready __P((struct sscop *, KBuffer *, caddr_t));
60 static void sscop_rsak_conresyn __P((struct sscop *, KBuffer *, caddr_t));
61 static void sscop_sd_inresyn __P((struct sscop *, KBuffer *, caddr_t));
62 static void sscop_sd_conresyn __P((struct sscop *, KBuffer *, caddr_t));
63 static void sscop_sd_process __P((struct sscop *, KBuffer *, caddr_t, int));
64 static void sscop_sd_ready __P((struct sscop *, KBuffer *, caddr_t));
65 static void sscop_sdp_ready __P((struct sscop *, KBuffer *, caddr_t));
66 static void sscop_poll_inresyn __P((struct sscop *, KBuffer *, caddr_t));
67 static void sscop_poll_conresyn __P((struct sscop *, KBuffer *, caddr_t));
68 static void sscop_poll_ready __P((struct sscop *, KBuffer *, caddr_t));
69 static void sscop_stat_conresyn __P((struct sscop *, KBuffer *, caddr_t));
70 static void sscop_ustat_conresyn __P((struct sscop *, KBuffer *, caddr_t));
74 * PDU type state lookup tables
77 static void (*sscop_bgn_tab[SOS_NUMSTATES])
78 __P((struct sscop *, KBuffer *, caddr_t)) = {
80 sscop_bgn_idle, /* SOS_IDLE */
81 sscop_bgn_outconn, /* SOS_OUTCONN */
82 sscop_noop, /* SOS_INCONN */
83 sscop_bgn_outdisc, /* SOS_OUTDISC */
84 sscop_bgn_outresyn, /* SOS_OUTRESYN */
85 sscop_bgn_inresyn, /* SOS_INRESYN */
86 sscop_bgn_outresyn, /* SOS_CONRESYN */
89 sscop_bgn_inresyn, /* SOS_READY */
90 sscop_noop /* SOS_TERM */
94 static void (*sscop_bgak_tab[SOS_NUMSTATES])
95 __P((struct sscop *, KBuffer *, caddr_t)) = {
97 sscop_bgak_idle, /* SOS_IDLE */
98 sscop_bgak_outconn, /* SOS_OUTCONN */
99 sscop_bgak_error, /* SOS_INCONN */
100 sscop_noop, /* SOS_OUTDISC */
101 sscop_bgak_error, /* SOS_OUTRESYN */
102 sscop_bgak_error, /* SOS_INRESYN */
103 sscop_bgak_error, /* SOS_CONRESYN */
106 sscop_noop, /* SOS_READY */
107 sscop_noop /* SOS_TERM */
111 static void (*sscop_bgrej_tab[SOS_NUMSTATES])
112 __P((struct sscop *, KBuffer *, caddr_t)) = {
114 sscop_bgrej_error, /* SOS_IDLE */
115 sscop_bgrej_outconn, /* SOS_OUTCONN */
116 sscop_bgrej_inconn, /* SOS_INCONN */
117 sscop_noop, /* SOS_OUTDISC */
118 sscop_bgrej_outresyn, /* SOS_OUTRESYN */
119 sscop_bgrej_ready, /* SOS_INRESYN */
120 sscop_bgrej_outresyn, /* SOS_CONRESYN */
123 sscop_bgrej_ready, /* SOS_READY */
124 sscop_noop /* SOS_TERM */
128 static void (*sscop_end_tab[SOS_NUMSTATES])
129 __P((struct sscop *, KBuffer *, caddr_t)) = {
131 sscop_end_idle, /* SOS_IDLE */
132 sscop_noop, /* SOS_OUTCONN */
133 sscop_end_inconn, /* SOS_INCONN */
134 sscop_end_outdisc, /* SOS_OUTDISC */
135 sscop_end_outresyn, /* SOS_OUTRESYN */
136 sscop_end_ready, /* SOS_INRESYN */
137 sscop_end_conresyn, /* SOS_CONRESYN */
140 sscop_end_ready, /* SOS_READY */
141 sscop_noop /* SOS_TERM */
145 static void (*sscop_endak_tab[SOS_NUMSTATES])
146 __P((struct sscop *, KBuffer *, caddr_t)) = {
148 sscop_noop, /* SOS_IDLE */
149 sscop_noop, /* SOS_OUTCONN */
150 sscop_endak_inconn, /* SOS_INCONN */
151 sscop_endak_outdisc, /* SOS_OUTDISC */
152 sscop_endak_outresyn, /* SOS_OUTRESYN */
153 sscop_endak_ready, /* SOS_INRESYN */
154 sscop_endak_outresyn, /* SOS_CONRESYN */
157 sscop_endak_ready, /* SOS_READY */
158 sscop_noop /* SOS_TERM */
162 static void (*sscop_rs_tab[SOS_NUMSTATES])
163 __P((struct sscop *, KBuffer *, caddr_t)) = {
165 sscop_rs_idle, /* SOS_IDLE */
166 sscop_noop, /* SOS_OUTCONN */
167 sscop_rs_error, /* SOS_INCONN */
168 sscop_noop, /* SOS_OUTDISC */
169 sscop_rs_outresyn, /* SOS_OUTRESYN */
170 sscop_noop, /* SOS_INRESYN */
171 sscop_noop, /* SOS_CONRESYN */
174 sscop_rs_ready, /* SOS_READY */
175 sscop_noop /* SOS_TERM */
179 static void (*sscop_rsak_tab[SOS_NUMSTATES])
180 __P((struct sscop *, KBuffer *, caddr_t)) = {
182 sscop_rsak_idle, /* SOS_IDLE */
183 sscop_noop, /* SOS_OUTCONN */
184 sscop_rsak_error, /* SOS_INCONN */
185 sscop_noop, /* SOS_OUTDISC */
186 sscop_rsak_outresyn, /* SOS_OUTRESYN */
187 sscop_rsak_error, /* SOS_INRESYN */
188 sscop_rsak_conresyn, /* SOS_CONRESYN */
191 sscop_rsak_error, /* SOS_READY */
192 sscop_noop /* SOS_TERM */
196 static void (*sscop_sd_tab[SOS_NUMSTATES])
197 __P((struct sscop *, KBuffer *, caddr_t)) = {
199 sscop_sd_idle, /* SOS_IDLE */
200 sscop_noop, /* SOS_OUTCONN */
201 sscop_sd_inconn, /* SOS_INCONN */
202 sscop_noop, /* SOS_OUTDISC */
203 sscop_sd_ready, /* SOS_OUTRESYN */
204 sscop_sd_inresyn, /* SOS_INRESYN */
205 sscop_sd_conresyn, /* SOS_CONRESYN */
208 sscop_sd_ready, /* SOS_READY */
209 sscop_noop /* SOS_TERM */
213 static void (*sscop_sdp_tab[SOS_NUMSTATES])
214 __P((struct sscop *, KBuffer *, caddr_t)) = {
216 sscop_sd_idle, /* SOS_IDLE */
217 sscop_noop, /* SOS_OUTCONN */
218 sscop_sd_inconn, /* SOS_INCONN */
219 sscop_noop, /* SOS_OUTDISC */
220 sscop_sdp_ready, /* SOS_OUTRESYN */
221 sscop_sd_inresyn, /* SOS_INRESYN */
222 sscop_sd_conresyn, /* SOS_CONRESYN */
225 sscop_sdp_ready, /* SOS_READY */
226 sscop_noop /* SOS_TERM */
230 static void (*sscop_poll_tab[SOS_NUMSTATES])
231 __P((struct sscop *, KBuffer *, caddr_t)) = {
233 sscop_poll_idle, /* SOS_IDLE */
234 sscop_noop, /* SOS_OUTCONN */
235 sscop_poll_inconn, /* SOS_INCONN */
236 sscop_noop, /* SOS_OUTDISC */
237 sscop_poll_ready, /* SOS_OUTRESYN */
238 sscop_poll_inresyn, /* SOS_INRESYN */
239 sscop_poll_conresyn, /* SOS_CONRESYN */
242 sscop_poll_ready, /* SOS_READY */
243 sscop_noop /* SOS_TERM */
247 static void (*sscop_stat_tab[SOS_NUMSTATES])
248 __P((struct sscop *, KBuffer *, caddr_t)) = {
250 sscop_stat_idle, /* SOS_IDLE */
251 sscop_noop, /* SOS_OUTCONN */
252 sscop_stat_inconn, /* SOS_INCONN */
253 sscop_noop, /* SOS_OUTDISC */
254 sscop_noop, /* SOS_OUTRESYN */
255 sscop_stat_ready, /* SOS_INRESYN */
256 sscop_stat_conresyn, /* SOS_CONRESYN */
259 sscop_stat_ready, /* SOS_READY */
260 sscop_noop /* SOS_TERM */
264 static void (*sscop_ustat_tab[SOS_NUMSTATES])
265 __P((struct sscop *, KBuffer *, caddr_t)) = {
267 sscop_ustat_idle, /* SOS_IDLE */
268 sscop_noop, /* SOS_OUTCONN */
269 sscop_ustat_inconn, /* SOS_INCONN */
270 sscop_noop, /* SOS_OUTDISC */
271 sscop_noop, /* SOS_OUTRESYN */
272 sscop_ustat_ready, /* SOS_INRESYN */
273 sscop_ustat_conresyn, /* SOS_CONRESYN */
276 sscop_ustat_ready, /* SOS_READY */
277 sscop_noop /* SOS_TERM */
281 static void (*sscop_ud_tab[SOS_NUMSTATES])
282 __P((struct sscop *, KBuffer *, caddr_t)) = {
284 sscop_ud_all, /* SOS_IDLE */
285 sscop_ud_all, /* SOS_OUTCONN */
286 sscop_ud_all, /* SOS_INCONN */
287 sscop_ud_all, /* SOS_OUTDISC */
288 sscop_ud_all, /* SOS_OUTRESYN */
289 sscop_ud_all, /* SOS_INRESYN */
290 sscop_ud_all, /* SOS_CONRESYN */
293 sscop_ud_all, /* SOS_READY */
294 sscop_noop /* SOS_TERM */
298 static void (*sscop_md_tab[SOS_NUMSTATES])
299 __P((struct sscop *, KBuffer *, caddr_t)) = {
301 sscop_md_all, /* SOS_IDLE */
302 sscop_md_all, /* SOS_OUTCONN */
303 sscop_md_all, /* SOS_INCONN */
304 sscop_md_all, /* SOS_OUTDISC */
305 sscop_md_all, /* SOS_OUTRESYN */
306 sscop_md_all, /* SOS_INRESYN */
307 sscop_md_all, /* SOS_CONRESYN */
310 sscop_md_all, /* SOS_READY */
311 sscop_noop /* SOS_TERM */
316 * PDU type lookup table
318 void (*(*sscop_qsaal_pdutab[]))
319 __P((struct sscop *, KBuffer *, caddr_t)) = {
340 * BGN PDU / SOS_OUTCONN Processor
343 * sop pointer to sscop connection block
344 * m pointer to PDU buffer (without trailer)
345 * trlr pointer to PDU trailer
352 sscop_bgn_outconn(sop, m, trlr)
357 struct bgn_pdu *bp = (struct bgn_pdu *)trlr;
361 * Initialize transmit window
363 SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
366 * Notify user of connection establishment
368 if (sop->so_flags & SOF_REESTAB) {
370 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku,
371 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
373 sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
376 sop->so_flags &= ~SOF_REESTAB;
378 STACK_CALL(SSCOP_ESTABLISH_CNF, sop->so_upper, sop->so_toku,
379 sop->so_connvc, (int)m, 0, err);
382 sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
388 * Return an ACK to peer
390 (void) sscop_send_bgak(sop);
393 * Stop retransmit timer
395 sop->so_timer[SSCOP_T_CC] = 0;
398 * Reset receiver variables
400 qsaal1_reset_rcvr(sop);
403 * Start polling timer
408 * Start lost poll/stat timer
410 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
413 * OK, we're ready for data
415 sop->so_state = SOS_READY;
418 * See if transmit queues need servicing
420 if (sop->so_flags & SOF_XMITSRVC)
421 sscop_service_xmit(sop);
428 * END PDU / SOS_OUTRESYN Processor
431 * sop pointer to sscop connection block
432 * m pointer to PDU buffer (without trailer)
433 * trlr pointer to PDU trailer
440 sscop_end_outresyn(sop, m, trlr)
445 struct end_pdu *ep = (struct end_pdu *)trlr;
449 * Stop retransmit timer
451 sop->so_timer[SSCOP_T_CC] = 0;
456 (void) sscop_send_endak(sop);
461 if (ep->end_type & PT_SOURCE_SSCOP)
462 source = SSCOP_SOURCE_SSCOP;
464 source = SSCOP_SOURCE_USER;
467 * Notify user of connection termination
469 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
470 sop->so_connvc, (int)m, source, err);
473 sscop_abort(sop, "sscop_end_outresyn: stack memory\n");
478 * Clear connection data
480 qsaal1_clear_connection(sop);
485 sop->so_state = SOS_IDLE;
492 * END PDU / SOS_CONRESYN Processor
495 * sop pointer to sscop connection block
496 * m pointer to PDU buffer (without trailer)
497 * trlr pointer to PDU trailer
504 sscop_end_conresyn(sop, m, trlr)
512 * Stop retransmit timer
514 sop->so_timer[SSCOP_T_CC] = 0;
524 (void) sscop_send_endak(sop);
527 * Notify user of connection termination
529 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
530 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
532 sscop_abort(sop, "sscop_end_conresyn: stack memory\n");
537 * Clear connection data
539 qsaal1_clear_connection(sop);
544 sop->so_state = SOS_IDLE;
551 * END PDU / SOS_READY Processor
554 * sop pointer to sscop connection block
555 * m pointer to PDU buffer (without trailer)
556 * trlr pointer to PDU trailer
563 sscop_end_ready(sop, m, trlr)
568 struct end_pdu *ep = (struct end_pdu *)trlr;
574 sop->so_timer[SSCOP_T_POLL] = 0;
575 sop->so_flags &= ~SOF_KEEPALIVE;
578 * Stop lost poll/stat timer
580 sop->so_timer[SSCOP_T_NORESP] = 0;
585 (void) sscop_send_endak(sop);
590 if (ep->end_type & PT_SOURCE_SSCOP)
591 source = SSCOP_SOURCE_SSCOP;
593 source = SSCOP_SOURCE_USER;
596 * Notify user of connection termination
598 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
599 sop->so_connvc, (int)m, source, err);
602 sscop_abort(sop, "sscop_end_ready: stack memory\n");
607 * Clear connection data
609 qsaal1_clear_connection(sop);
614 sop->so_state = SOS_IDLE;
621 * ENDAK PDU / SOS_OUTRESYN Processor
624 * sop pointer to sscop connection block
625 * m pointer to PDU buffer (without trailer)
626 * trlr pointer to PDU trailer
633 sscop_endak_outresyn(sop, m, trlr)
641 * Stop retransmit timer
643 sop->so_timer[SSCOP_T_CC] = 0;
646 * Report protocol error
648 sscop_endak_error(sop, m, trlr);
651 * Notify user of connection failure
653 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
654 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
656 sscop_abort(sop, "sscop_endak_outresyn: stack memory\n");
661 * Clear connection data
663 qsaal1_clear_connection(sop);
668 sop->so_state = SOS_IDLE;
675 * RS PDU / SOS_OUTRESYN Processor
678 * sop pointer to sscop connection block
679 * m pointer to PDU buffer (without trailer)
680 * trlr pointer to PDU trailer
687 sscop_rs_outresyn(sop, m, trlr)
695 * Notify user of resynchronization
697 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
698 sop->so_connvc, (int)m, 0, err);
701 sscop_abort(sop, "sscop_rs_outresyn: stack memory\n");
706 * Reset receiver state variables
708 qsaal1_reset_rcvr(sop);
711 * Wait for both peer and user responses
713 sop->so_state = SOS_CONRESYN;
720 * RS PDU / SOS_READY Processor
723 * sop pointer to sscop connection block
724 * m pointer to PDU buffer (without trailer)
725 * trlr pointer to PDU trailer
732 sscop_rs_ready(sop, m, trlr)
740 * Notify user of resynchronization
742 STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku,
743 sop->so_connvc, (int)m, 0, err);
746 sscop_abort(sop, "sscop_rs_ready: stack memory\n");
751 * Reset receiver state variables
753 qsaal1_reset_rcvr(sop);
756 * Wait for user response
758 sop->so_state = SOS_INRESYN;
765 * RSAK PDU / SOS_CONRESYN Processor
768 * sop pointer to sscop connection block
769 * m pointer to PDU buffer (without trailer)
770 * trlr pointer to PDU trailer
777 sscop_rsak_conresyn(sop, m, trlr)
785 * Stop retransmit timer
787 sop->so_timer[SSCOP_T_CC] = 0;
795 * Notify user of resynchronization completion
797 STACK_CALL(SSCOP_RESYNC_CNF, sop->so_upper, sop->so_toku,
798 sop->so_connvc, 0, 0, err);
800 sscop_abort(sop, "sscop_rsak_conresyn: stack memory\n");
805 * Start the polling timer
810 * Start lost poll/stat timer
812 sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
815 * Continue waiting for user response
817 sop->so_state = SOS_INRESYN;
820 * See if transmit queues need servicing
822 if (sop->so_flags & SOF_XMITSRVC)
823 sscop_service_xmit(sop);
830 * SD PDU / SOS_INRESYN Processor
833 * sop pointer to sscop connection block
834 * m pointer to PDU buffer (without trailer)
835 * trlr pointer to PDU trailer
842 sscop_sd_inresyn(sop, m, trlr)
852 sop->so_timer[SSCOP_T_POLL] = 0;
853 sop->so_flags &= ~SOF_KEEPALIVE;
856 * Stop lost poll/stat timer
858 sop->so_timer[SSCOP_T_NORESP] = 0;
861 * Record error condition
863 sscop_sd_error(sop, m, trlr);
866 * Return an END to peer
868 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
871 * Notify user of connection failure
873 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
874 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
876 sscop_abort(sop, "sscop_sd_inresyn: stack memory\n");
881 * Clear connection data
883 qsaal1_clear_connection(sop);
886 * Go back to idle state
888 sop->so_state = SOS_IDLE;
895 * SD PDU / SOS_CONRESYN Processor
898 * sop pointer to sscop connection block
899 * m pointer to PDU buffer (without trailer)
900 * trlr pointer to PDU trailer
907 sscop_sd_conresyn(sop, m, trlr)
915 * Stop retransmit timer
917 sop->so_timer[SSCOP_T_CC] = 0;
920 * Record error condition
922 sscop_sd_error(sop, m, trlr);
925 * Return an END to peer
927 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
930 * Notify user of connection failure
932 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
933 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
935 sscop_abort(sop, "sscop_sd_conresyn: stack memory\n");
940 * Clear connection data
942 qsaal1_clear_connection(sop);
945 * Go back to idle state
947 sop->so_state = SOS_IDLE;
954 * SD/SDP PDU Common Processor
957 * sop pointer to sscop connection block
958 * m pointer to PDU user data buffer chain
959 * trlr pointer to PDU trailer
960 * type PDU type (SD or SDP)
967 sscop_sd_process(sop, m, trlr, type)
975 struct poll_pdu poll;
982 * Get PDU sequence number(s)
985 sp = (struct sd_pdu *)trlr;
986 SEQ_SET(ns, ntohl(sp->sd_ns));
989 spp = (struct sdp_pdu *)trlr;
990 SEQ_SET(ns, ntohl(spp->sdp_ns));
991 SEQ_SET(nps, ntohl(spp->sdp_nps));
995 * Ensure that the sequence number fits within the window
997 if (SEQ_GEQ(ns, sop->so_rcvmax, sop->so_rcvnext)) {
1003 * If this is the next in-sequence PDU, hand it to user
1005 if (ns == sop->so_rcvnext) {
1006 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1007 sop->so_connvc, (int)m, ns, err);
1014 * Bump next expected sequence number
1016 SEQ_INCR(sop->so_rcvnext, 1);
1019 * Slide receive window down
1021 SEQ_INCR(sop->so_rcvmax, 1);
1024 * Is this the highest sequence PDU we've received??
1026 if (ns == sop->so_rcvhigh) {
1028 * Yes, bump the limit and exit
1030 sop->so_rcvhigh = sop->so_rcvnext;
1037 * This is a retransmitted PDU, so see if we have
1038 * more in-sequence PDUs already queued up
1040 while ((php = sop->so_recv_hd) &&
1041 (php->ph_ns == sop->so_rcvnext)) {
1044 * Yup we do, so remove next PDU from queue and
1045 * pass it up to the user as well
1047 sop->so_recv_hd = php->ph_recv_lk;
1048 if (sop->so_recv_hd == NULL)
1049 sop->so_recv_tl = NULL;
1050 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1051 sop->so_connvc, (int)php->ph_buf, php->ph_ns,
1055 * Should never happen, but...
1057 KB_FREEALL(php->ph_buf);
1059 "sscop_sd_process: stack memory\n");
1064 * Bump next expected sequence number
1066 SEQ_INCR(sop->so_rcvnext, 1);
1069 * Slide receive window down
1071 SEQ_INCR(sop->so_rcvmax, 1);
1075 * Finished with data...see if we need to poll
1083 * We're gonna have to queue this PDU, so find space
1084 * for the PDU header
1086 KB_HEADROOM(m, space);
1089 * If there's not enough room in the received buffer,
1090 * allocate & link a new buffer for the header
1092 if (space < sizeof(struct pdu_hdr)) {
1094 KB_ALLOC(n, sizeof(struct pdu_hdr), KB_F_NOWAIT, KB_T_HEADER);
1099 KB_HEADSET(n, sizeof(struct pdu_hdr));
1108 * We can at least assume/require that the start of
1109 * the user data is aligned. Also note that we don't
1110 * include this header in the buffer len/offset fields.
1112 KB_DATASTART(m, php, struct pdu_hdr *);
1118 * Insert PDU into the receive queue
1120 if (sscop_recv_insert(sop, php)) {
1122 * Oops, a duplicate sequence number PDU is already on
1123 * the queue, somethings wrong here.
1125 sscop_maa_error(sop, 'Q');
1133 * Reestablish a new connection
1135 qsaal1_reestablish(sop);
1141 * Are we at the high-water mark??
1143 if (ns == sop->so_rcvhigh) {
1145 * Yes, just bump the mark
1147 SEQ_INCR(sop->so_rcvhigh, 1);
1155 * Are we beyond the high-water mark??
1157 if (SEQ_GT(ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1159 * Yes, then there's a missing PDU, so inform the transmitter
1162 (void) sscop_send_ustat(sop, ns);
1165 * Update high-water mark
1167 sop->so_rcvhigh = SEQ_ADD(ns, 1);
1175 * Do the "poll" part of an SDP PDU
1177 poll.poll_nps = htonl(nps);
1178 poll.poll_ns = htonl((PT_POLL << PT_TYPE_SHIFT) | ns);
1179 sscop_poll_ready(sop, NULL, (caddr_t)&poll);
1185 * SD PDU / SOS_READY Processor
1188 * sop pointer to sscop connection block
1189 * m pointer to PDU buffer (without trailer)
1190 * trlr pointer to PDU trailer
1197 sscop_sd_ready(sop, m, trlr)
1203 * Just call common SD/SDP processor
1205 sscop_sd_process(sop, m, trlr, PT_SD);
1212 * SDP PDU / SOS_READY Processor
1215 * sop pointer to sscop connection block
1216 * m pointer to PDU buffer (without trailer)
1217 * trlr pointer to PDU trailer
1224 sscop_sdp_ready(sop, m, trlr)
1230 * Just call common SD/SDP processor
1232 sscop_sd_process(sop, m, trlr, PT_SDP);
1239 * POLL PDU / SOS_INRESYN Processor
1242 * sop pointer to sscop connection block
1243 * m pointer to PDU buffer (without trailer)
1244 * trlr pointer to PDU trailer
1251 sscop_poll_inresyn(sop, m, trlr)
1261 sop->so_timer[SSCOP_T_POLL] = 0;
1262 sop->so_flags &= ~SOF_KEEPALIVE;
1265 * Stop lost poll/stat timer
1267 sop->so_timer[SSCOP_T_NORESP] = 0;
1270 * Report protocol error
1272 sscop_poll_error(sop, m, trlr);
1275 * Return an END to peer
1277 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1280 * Notify user of connection failure
1282 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1283 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1285 sscop_abort(sop, "sscop_poll_inresyn: stack memory\n");
1290 * Clear connection data
1292 qsaal1_clear_connection(sop);
1295 * Back to idle state
1297 sop->so_state = SOS_IDLE;
1304 * POLL PDU / SOS_CONRESYN Processor
1307 * sop pointer to sscop connection block
1308 * m pointer to PDU buffer (without trailer)
1309 * trlr pointer to PDU trailer
1316 sscop_poll_conresyn(sop, m, trlr)
1324 * Stop retransmit timer
1326 sop->so_timer[SSCOP_T_CC] = 0;
1329 * Record error condition
1331 sscop_poll_error(sop, m, trlr);
1334 * Return an END to peer
1336 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1339 * Notify user of connection failure
1341 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1342 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1344 sscop_abort(sop, "sscop_poll_conresyn: stack memory\n");
1349 * Clear connection data
1351 qsaal1_clear_connection(sop);
1354 * Go back to idle state
1356 sop->so_state = SOS_IDLE;
1363 * POLL PDU / SOS_READY Processor
1366 * sop pointer to sscop connection block
1367 * m pointer to PDU buffer (without trailer)
1368 * trlr pointer to PDU trailer
1375 sscop_poll_ready(sop, m, trlr)
1380 struct poll_pdu *pp = (struct poll_pdu *)trlr;
1386 * If the poll sequence number is less than highest number
1387 * we've already seen, something's wrong - so attempt to
1388 * reestablish a new connection.
1390 if (SEQ_LT(pp->poll_ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1392 * Record error condition
1394 sscop_maa_error(sop, 'Q');
1402 * Reestablish a new connection
1404 qsaal1_reestablish(sop);
1410 * Set a new "next highest" sequence number expected
1412 if (SEQ_LT(pp->poll_ns, sop->so_rcvmax, sop->so_rcvnext))
1413 SEQ_SET(sop->so_rcvhigh, pp->poll_ns);
1415 sop->so_rcvhigh = sop->so_rcvmax;
1418 * Return a STAT PDU to peer
1420 SEQ_SET(nps, ntohl(pp->poll_nps));
1422 (void) sscop_send_stat(sop, nps);
1429 * STAT PDU / SOS_CONRESYN Processor
1432 * sop pointer to sscop connection block
1433 * m pointer to PDU buffer (without trailer)
1434 * trlr pointer to PDU trailer
1441 sscop_stat_conresyn(sop, m, trlr)
1449 * Stop retransmit timer
1451 sop->so_timer[SSCOP_T_CC] = 0;
1454 * Record error condition
1456 sscop_stat_error(sop, m, trlr);
1459 * Return an END to peer
1461 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1464 * Notify user of connection failure
1466 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1467 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1469 sscop_abort(sop, "sscop_stat_conresyn: stack memory\n");
1474 * Clear connection data
1476 qsaal1_clear_connection(sop);
1479 * Go back to idle state
1481 sop->so_state = SOS_IDLE;
1488 * USTAT PDU / SOS_CONRESYN Processor
1491 * sop pointer to sscop connection block
1492 * m pointer to PDU buffer (without trailer)
1493 * trlr pointer to PDU trailer
1500 sscop_ustat_conresyn(sop, m, trlr)
1508 * Stop retransmit timer
1510 sop->so_timer[SSCOP_T_CC] = 0;
1513 * Record error condition
1515 sscop_ustat_error(sop, m, trlr);
1518 * Return an END to peer
1520 (void) sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1523 * Notify user of connection failure
1525 STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku,
1526 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1528 sscop_abort(sop, "sscop_ustat_conresyn: stack memory\n");
1533 * Clear connection data
1535 qsaal1_clear_connection(sop);
1538 * Go back to idle state
1540 sop->so_state = SOS_IDLE;