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.5 2003/08/23 10:06:22 rob 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(cmd, tok, arg1, arg2)
190 struct sscop *sop = (struct sscop *)tok;
191 void (**ptab) (struct sscop *, KBuffer *, caddr_t);
192 void (*func) (struct sscop *, KBuffer *, caddr_t);
196 ATM_DEBUG5("sscop_upper: cmd=0x%x, sop=%p, state=%d, arg1=0x%x, arg2=0x%x\n",
197 cmd, sop, sop->so_state, arg1, arg2);
201 case CPCS_UNITDATA_SIG:
203 * Decode/validate received PDU
205 trlr = sscop_pdu_receive((KBuffer *)arg1, sop, &type);
211 * Validate sscop state
213 if (sop->so_state > SOS_MAXSTATE) {
215 "sscop_upper: invalid state sop=%p, state=%d\n",
217 KB_FREEALL((KBuffer *)arg1);
222 * Call event processing function
224 ptab = sop->so_vers == SSCOP_VERS_QSAAL ?
225 sscop_qsaal_pdutab[type]:
226 sscop_q2110_pdutab[type];
227 func = ptab[sop->so_state];
230 "sscop_upper: unsupported pdu=%d, state=%d\n",
231 type, sop->so_state);
234 (*func)(sop, (KBuffer *)arg1, trlr);
238 log(LOG_ERR, "sscop_upper: unknown cmd 0x%x, sop=%p\n",
247 * Decode and Validate Received PDU
249 * This function will process all received SSCOP PDUs. The PDU type will be
250 * determined and PDU format validation will be performed. If the PDU is
251 * successfully decoded and validated, the buffer chain will have the PDU
252 * trailer removed, but any resultant zero-length buffers will NOT be freed.
253 * If the PDU fails validation, then the buffer chain will be freed.
256 * m pointer to PDU buffer chain
257 * sop pointer to sscop connection block
258 * typep address to store PDU type
261 * addr pointer to (contiguous) PDU trailer
262 * 0 invalid PDU, buffer chain freed
266 sscop_pdu_receive(m, sop, typep)
271 KBuffer *m0, *ml, *mn;
273 int len, tlen, type, plen;
276 * Calculate PDU length and find the last two buffers in the chain
279 for (m0 = m, ml = mn = NULL; m0; m0 = KB_NEXT(m0)) {
286 * Make sure we've got a minimum sized PDU
288 if (len < PDU_MIN_LEN)
294 if (KB_LEN(ml) >= PDU_MIN_LEN) {
295 KB_DATAEND(ml, tp, caddr_t);
298 KB_DATAEND(mn, tp, caddr_t);
299 tp -= (PDU_MIN_LEN - KB_LEN(ml));
301 *typep = type = *tp & PT_TYPE_MASK;
304 * Check up on PDU length
306 if (sop->so_vers == SSCOP_VERS_QSAAL) {
307 if ((len < (tlen = qsaal_pdulen[type].min)) ||
308 (len > qsaal_pdulen[type].max) ||
309 (len & PDU_LEN_MASK))
312 if ((len < (tlen = q2110_pdulen[type].min)) ||
313 (len > q2110_pdulen[type].max) ||
314 (len & PDU_LEN_MASK))
319 * Get a contiguous, aligned PDU trailer and adjust buffer
320 * controls to remove trailer
322 if (KB_LEN(ml) >= tlen) {
324 * Trailer is contained in last buffer
326 KB_TAILADJ(ml, -tlen);
327 KB_DATAEND(ml, cp, caddr_t);
328 if ((int)cp & PDU_ADDR_MASK) {
330 * Trailer not aligned in buffer, use local memory
332 KM_COPY(cp, (caddr_t)&sscop_trailer, tlen);
333 cp = (caddr_t)&sscop_trailer;
337 * Trailer is split across buffers, use local memory
340 int off = tlen - KB_LEN(ml);
342 cp = (caddr_t)&sscop_trailer;
345 * Ensure trailer is within last two buffers
347 if ((mn == NULL) || (KB_LEN(mn) < off))
350 KB_DATASTART(ml, cp1, caddr_t);
351 KM_COPY(cp1, cp + off, KB_LEN(ml));
353 KB_TAILADJ(mn, -off);
354 KB_DATAEND(mn, cp1, caddr_t);
355 KM_COPY(cp1, cp, off);
359 * Get possible PDU Pad Length
361 if (sop->so_vers == SSCOP_VERS_QSAAL) {
362 if (qsaal_padlen[type])
363 plen = (*tp & PT_PAD_MASK) >> PT_PAD_SHIFT;
367 if (q2110_padlen[type])
368 plen = (*tp & PT_PAD_MASK) >> PT_PAD_SHIFT;
374 * Perform Pad Length adjustments
377 if (KB_LEN(ml) >= plen) {
379 * All pad bytes in last buffer
381 KB_TAILADJ(ml, -plen);
384 * Pad bytes split between buffers
387 if ((mn == NULL) || (KB_LEN(mn) < plen))
390 KB_TAILADJ(mn, -plen);
398 * This MAA Error is only supposed to be for a PDU length violation,
399 * but we use it for any PDU format error.
401 sscop_maa_error(sop, 'U');
402 sscop_pdu_print(sop, m, "badpdu received");