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.
26 * @(#) $FreeBSD: src/sys/netatm/uni/sscop_upper.c,v 1.5 2000/01/17 20:49:54 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/sscop_upper.c,v 1.6 2006/01/14 13:36:39 swildner Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * SSCOP - CPCS SAP interface processing
38 #include <netproto/atm/kern_include.h>
41 #include "sscop_misc.h"
42 #include "sscop_pdu.h"
43 #include "sscop_var.h"
48 static caddr_t
sscop_pdu_receive (KBuffer
*, struct sscop
*, int *);
56 struct bgak_pdu t_bgak
;
58 struct endak_q2110_pdu t_endak_q2110
;
59 struct endak_qsaal_pdu t_endak_qsaal
;
61 struct rsak_q2110_pdu t_rsak_q2110
;
62 struct rsak_qsaal_pdu t_rsak_qsaal
;
63 struct bgrej_pdu t_bgrej
;
67 struct poll_pdu t_poll
;
68 struct stat_pdu t_stat
;
69 struct ustat_pdu t_ustat
;
72 struct erak_pdu t_erak
;
77 * PDU length validation table
84 static struct pdulen qsaal_pdulen
[] = {
86 {sizeof(struct bgn_pdu
), sizeof(struct bgn_pdu
)},
87 {sizeof(struct bgak_pdu
), sizeof(struct bgak_pdu
)},
88 {sizeof(struct end_pdu
), sizeof(struct end_pdu
)},
89 {sizeof(struct endak_qsaal_pdu
),sizeof(struct endak_qsaal_pdu
)},
90 {sizeof(struct rs_pdu
), sizeof(struct rs_pdu
)},
91 {sizeof(struct rsak_qsaal_pdu
), sizeof(struct rsak_qsaal_pdu
)},
92 {sizeof(struct bgrej_pdu
), sizeof(struct bgrej_pdu
)},
93 {sizeof(struct sd_pdu
), sizeof(struct sd_pdu
) + PDU_MAX_INFO
},
94 {sizeof(struct sdp_pdu
), sizeof(struct sdp_pdu
) + PDU_MAX_INFO
},
95 {sizeof(struct poll_pdu
), sizeof(struct poll_pdu
)},
96 {sizeof(struct stat_pdu
), sizeof(struct stat_pdu
) + PDU_MAX_STAT
},
97 {sizeof(struct ustat_pdu
), sizeof(struct ustat_pdu
)},
98 {sizeof(struct ud_pdu
), sizeof(struct ud_pdu
) + PDU_MAX_INFO
},
99 {sizeof(struct md_pdu
), sizeof(struct md_pdu
) + PDU_MAX_INFO
},
103 static struct pdulen q2110_pdulen
[] = {
105 {sizeof(struct bgn_pdu
), sizeof(struct bgn_pdu
) + PDU_MAX_UU
},
106 {sizeof(struct bgak_pdu
), sizeof(struct bgak_pdu
) + PDU_MAX_UU
},
107 {sizeof(struct end_pdu
), sizeof(struct end_pdu
) + PDU_MAX_UU
},
108 {sizeof(struct endak_q2110_pdu
),sizeof(struct endak_q2110_pdu
)},
109 {sizeof(struct rs_pdu
), sizeof(struct rs_pdu
) + PDU_MAX_UU
},
110 {sizeof(struct rsak_q2110_pdu
), sizeof(struct rsak_q2110_pdu
)},
111 {sizeof(struct bgrej_pdu
), sizeof(struct bgrej_pdu
) + PDU_MAX_UU
},
112 {sizeof(struct sd_pdu
), sizeof(struct sd_pdu
) + PDU_MAX_INFO
},
113 {sizeof(struct er_pdu
), sizeof(struct er_pdu
)},
114 {sizeof(struct poll_pdu
), sizeof(struct poll_pdu
)},
115 {sizeof(struct stat_pdu
), sizeof(struct stat_pdu
) + PDU_MAX_STAT
},
116 {sizeof(struct ustat_pdu
), sizeof(struct ustat_pdu
)},
117 {sizeof(struct ud_pdu
), sizeof(struct ud_pdu
) + PDU_MAX_INFO
},
118 {sizeof(struct md_pdu
), sizeof(struct md_pdu
) + PDU_MAX_INFO
},
119 {sizeof(struct erak_pdu
), sizeof(struct erak_pdu
)}
124 * PDUs with Pad Length Fields
126 static u_char qsaal_padlen
[] = {
145 static u_char q2110_padlen
[] = {
166 * SSCOP Upper Stack Command Handler
168 * This function will receive all of the stack commands issued from the
169 * layer below SSCOP (ie. CPCS). Currently, only incoming PDUs will be
170 * received here. The appropriate processing function will be determined
171 * based on the received PDU type and the current sscop control block state.
174 * cmd stack command code
176 * arg1 command specific argument
177 * arg2 command specific argument
184 sscop_upper(int cmd
, void *tok
, int arg1
, int arg2
)
186 struct sscop
*sop
= (struct sscop
*)tok
;
187 void (**ptab
) (struct sscop
*, KBuffer
*, caddr_t
);
188 void (*func
) (struct sscop
*, KBuffer
*, caddr_t
);
192 ATM_DEBUG5("sscop_upper: cmd=0x%x, sop=%p, state=%d, arg1=0x%x, arg2=0x%x\n",
193 cmd
, sop
, sop
->so_state
, arg1
, arg2
);
197 case CPCS_UNITDATA_SIG
:
199 * Decode/validate received PDU
201 trlr
= sscop_pdu_receive((KBuffer
*)arg1
, sop
, &type
);
207 * Validate sscop state
209 if (sop
->so_state
> SOS_MAXSTATE
) {
211 "sscop_upper: invalid state sop=%p, state=%d\n",
213 KB_FREEALL((KBuffer
*)arg1
);
218 * Call event processing function
220 ptab
= sop
->so_vers
== SSCOP_VERS_QSAAL
?
221 sscop_qsaal_pdutab
[type
]:
222 sscop_q2110_pdutab
[type
];
223 func
= ptab
[sop
->so_state
];
226 "sscop_upper: unsupported pdu=%d, state=%d\n",
227 type
, sop
->so_state
);
230 (*func
)(sop
, (KBuffer
*)arg1
, trlr
);
234 log(LOG_ERR
, "sscop_upper: unknown cmd 0x%x, sop=%p\n",
243 * Decode and Validate Received PDU
245 * This function will process all received SSCOP PDUs. The PDU type will be
246 * determined and PDU format validation will be performed. If the PDU is
247 * successfully decoded and validated, the buffer chain will have the PDU
248 * trailer removed, but any resultant zero-length buffers will NOT be freed.
249 * If the PDU fails validation, then the buffer chain will be freed.
252 * m pointer to PDU buffer chain
253 * sop pointer to sscop connection block
254 * typep address to store PDU type
257 * addr pointer to (contiguous) PDU trailer
258 * 0 invalid PDU, buffer chain freed
262 sscop_pdu_receive(KBuffer
*m
, struct sscop
*sop
, int *typep
)
264 KBuffer
*m0
, *ml
, *mn
;
266 int len
, tlen
, type
, plen
;
269 * Calculate PDU length and find the last two buffers in the chain
272 for (m0
= m
, ml
= mn
= NULL
; m0
; m0
= KB_NEXT(m0
)) {
279 * Make sure we've got a minimum sized PDU
281 if (len
< PDU_MIN_LEN
)
287 if (KB_LEN(ml
) >= PDU_MIN_LEN
) {
288 KB_DATAEND(ml
, tp
, caddr_t
);
291 KB_DATAEND(mn
, tp
, caddr_t
);
292 tp
-= (PDU_MIN_LEN
- KB_LEN(ml
));
294 *typep
= type
= *tp
& PT_TYPE_MASK
;
297 * Check up on PDU length
299 if (sop
->so_vers
== SSCOP_VERS_QSAAL
) {
300 if ((len
< (tlen
= qsaal_pdulen
[type
].min
)) ||
301 (len
> qsaal_pdulen
[type
].max
) ||
302 (len
& PDU_LEN_MASK
))
305 if ((len
< (tlen
= q2110_pdulen
[type
].min
)) ||
306 (len
> q2110_pdulen
[type
].max
) ||
307 (len
& PDU_LEN_MASK
))
312 * Get a contiguous, aligned PDU trailer and adjust buffer
313 * controls to remove trailer
315 if (KB_LEN(ml
) >= tlen
) {
317 * Trailer is contained in last buffer
319 KB_TAILADJ(ml
, -tlen
);
320 KB_DATAEND(ml
, cp
, caddr_t
);
321 if ((int)cp
& PDU_ADDR_MASK
) {
323 * Trailer not aligned in buffer, use local memory
325 KM_COPY(cp
, (caddr_t
)&sscop_trailer
, tlen
);
326 cp
= (caddr_t
)&sscop_trailer
;
330 * Trailer is split across buffers, use local memory
333 int off
= tlen
- KB_LEN(ml
);
335 cp
= (caddr_t
)&sscop_trailer
;
338 * Ensure trailer is within last two buffers
340 if ((mn
== NULL
) || (KB_LEN(mn
) < off
))
343 KB_DATASTART(ml
, cp1
, caddr_t
);
344 KM_COPY(cp1
, cp
+ off
, KB_LEN(ml
));
346 KB_TAILADJ(mn
, -off
);
347 KB_DATAEND(mn
, cp1
, caddr_t
);
348 KM_COPY(cp1
, cp
, off
);
352 * Get possible PDU Pad Length
354 if (sop
->so_vers
== SSCOP_VERS_QSAAL
) {
355 if (qsaal_padlen
[type
])
356 plen
= (*tp
& PT_PAD_MASK
) >> PT_PAD_SHIFT
;
360 if (q2110_padlen
[type
])
361 plen
= (*tp
& PT_PAD_MASK
) >> PT_PAD_SHIFT
;
367 * Perform Pad Length adjustments
370 if (KB_LEN(ml
) >= plen
) {
372 * All pad bytes in last buffer
374 KB_TAILADJ(ml
, -plen
);
377 * Pad bytes split between buffers
380 if ((mn
== NULL
) || (KB_LEN(mn
) < plen
))
383 KB_TAILADJ(mn
, -plen
);
391 * This MAA Error is only supposed to be for a PDU length violation,
392 * but we use it for any PDU format error.
394 sscop_maa_error(sop
, 'U');
395 sscop_pdu_print(sop
, m
, "badpdu received");