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 $
31 * ATM Forum UNI Support
32 * ---------------------
34 * SSCOP - CPCS SAP interface processing
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: src/sys/netatm/uni/sscop_upper.c,v 1.5 2000/01/17 20:49:54 mks Exp $");
53 static caddr_t sscop_pdu_receive __P((KBuffer *, struct sscop *, int *));
61 struct bgak_pdu t_bgak;
63 struct endak_q2110_pdu t_endak_q2110;
64 struct endak_qsaal_pdu t_endak_qsaal;
66 struct rsak_q2110_pdu t_rsak_q2110;
67 struct rsak_qsaal_pdu t_rsak_qsaal;
68 struct bgrej_pdu t_bgrej;
72 struct poll_pdu t_poll;
73 struct stat_pdu t_stat;
74 struct ustat_pdu t_ustat;
77 struct erak_pdu t_erak;
82 * PDU length validation table
89 static struct pdulen qsaal_pdulen[] = {
91 {sizeof(struct bgn_pdu), sizeof(struct bgn_pdu)},
92 {sizeof(struct bgak_pdu), sizeof(struct bgak_pdu)},
93 {sizeof(struct end_pdu), sizeof(struct end_pdu)},
94 {sizeof(struct endak_qsaal_pdu),sizeof(struct endak_qsaal_pdu)},
95 {sizeof(struct rs_pdu), sizeof(struct rs_pdu)},
96 {sizeof(struct rsak_qsaal_pdu), sizeof(struct rsak_qsaal_pdu)},
97 {sizeof(struct bgrej_pdu), sizeof(struct bgrej_pdu)},
98 {sizeof(struct sd_pdu), sizeof(struct sd_pdu) + PDU_MAX_INFO},
99 {sizeof(struct sdp_pdu), sizeof(struct sdp_pdu) + PDU_MAX_INFO},
100 {sizeof(struct poll_pdu), sizeof(struct poll_pdu)},
101 {sizeof(struct stat_pdu), sizeof(struct stat_pdu) + PDU_MAX_STAT},
102 {sizeof(struct ustat_pdu), sizeof(struct ustat_pdu)},
103 {sizeof(struct ud_pdu), sizeof(struct ud_pdu) + PDU_MAX_INFO},
104 {sizeof(struct md_pdu), sizeof(struct md_pdu) + PDU_MAX_INFO},
108 static struct pdulen q2110_pdulen[] = {
110 {sizeof(struct bgn_pdu), sizeof(struct bgn_pdu) + PDU_MAX_UU},
111 {sizeof(struct bgak_pdu), sizeof(struct bgak_pdu) + PDU_MAX_UU},
112 {sizeof(struct end_pdu), sizeof(struct end_pdu) + PDU_MAX_UU},
113 {sizeof(struct endak_q2110_pdu),sizeof(struct endak_q2110_pdu)},
114 {sizeof(struct rs_pdu), sizeof(struct rs_pdu) + PDU_MAX_UU},
115 {sizeof(struct rsak_q2110_pdu), sizeof(struct rsak_q2110_pdu)},
116 {sizeof(struct bgrej_pdu), sizeof(struct bgrej_pdu) + PDU_MAX_UU},
117 {sizeof(struct sd_pdu), sizeof(struct sd_pdu) + PDU_MAX_INFO},
118 {sizeof(struct er_pdu), sizeof(struct er_pdu)},
119 {sizeof(struct poll_pdu), sizeof(struct poll_pdu)},
120 {sizeof(struct stat_pdu), sizeof(struct stat_pdu) + PDU_MAX_STAT},
121 {sizeof(struct ustat_pdu), sizeof(struct ustat_pdu)},
122 {sizeof(struct ud_pdu), sizeof(struct ud_pdu) + PDU_MAX_INFO},
123 {sizeof(struct md_pdu), sizeof(struct md_pdu) + PDU_MAX_INFO},
124 {sizeof(struct erak_pdu), sizeof(struct erak_pdu)}
129 * PDUs with Pad Length Fields
131 static u_char qsaal_padlen[] = {
150 static u_char q2110_padlen[] = {
171 * SSCOP Upper Stack Command Handler
173 * This function will receive all of the stack commands issued from the
174 * layer below SSCOP (ie. CPCS). Currently, only incoming PDUs will be
175 * received here. The appropriate processing function will be determined
176 * based on the received PDU type and the current sscop control block state.
179 * cmd stack command code
181 * arg1 command specific argument
182 * arg2 command specific argument
189 sscop_upper(cmd, tok, arg1, arg2)
195 struct sscop *sop = (struct sscop *)tok;
196 void (**ptab) __P((struct sscop *, KBuffer *, caddr_t));
197 void (*func) __P((struct sscop *, KBuffer *, caddr_t));
201 ATM_DEBUG5("sscop_upper: cmd=0x%x, sop=%p, state=%d, arg1=0x%x, arg2=0x%x\n",
202 cmd, sop, sop->so_state, arg1, arg2);
206 case CPCS_UNITDATA_SIG:
208 * Decode/validate received PDU
210 trlr = sscop_pdu_receive((KBuffer *)arg1, sop, &type);
216 * Validate sscop state
218 if (sop->so_state > SOS_MAXSTATE) {
220 "sscop_upper: invalid state sop=%p, state=%d\n",
222 KB_FREEALL((KBuffer *)arg1);
227 * Call event processing function
229 ptab = sop->so_vers == SSCOP_VERS_QSAAL ?
230 sscop_qsaal_pdutab[type]:
231 sscop_q2110_pdutab[type];
232 func = ptab[sop->so_state];
235 "sscop_upper: unsupported pdu=%d, state=%d\n",
236 type, sop->so_state);
239 (*func)(sop, (KBuffer *)arg1, trlr);
243 log(LOG_ERR, "sscop_upper: unknown cmd 0x%x, sop=%p\n",
252 * Decode and Validate Received PDU
254 * This function will process all received SSCOP PDUs. The PDU type will be
255 * determined and PDU format validation will be performed. If the PDU is
256 * successfully decoded and validated, the buffer chain will have the PDU
257 * trailer removed, but any resultant zero-length buffers will NOT be freed.
258 * If the PDU fails validation, then the buffer chain will be freed.
261 * m pointer to PDU buffer chain
262 * sop pointer to sscop connection block
263 * typep address to store PDU type
266 * addr pointer to (contiguous) PDU trailer
267 * 0 invalid PDU, buffer chain freed
271 sscop_pdu_receive(m, sop, typep)
276 KBuffer *m0, *ml, *mn;
278 int len, tlen, type, plen;
281 * Calculate PDU length and find the last two buffers in the chain
284 for (m0 = m, ml = mn = NULL; m0; m0 = KB_NEXT(m0)) {
291 * Make sure we've got a minimum sized PDU
293 if (len < PDU_MIN_LEN)
299 if (KB_LEN(ml) >= PDU_MIN_LEN) {
300 KB_DATAEND(ml, tp, caddr_t);
303 KB_DATAEND(mn, tp, caddr_t);
304 tp -= (PDU_MIN_LEN - KB_LEN(ml));
306 *typep = type = *tp & PT_TYPE_MASK;
309 * Check up on PDU length
311 if (sop->so_vers == SSCOP_VERS_QSAAL) {
312 if ((len < (tlen = qsaal_pdulen[type].min)) ||
313 (len > qsaal_pdulen[type].max) ||
314 (len & PDU_LEN_MASK))
317 if ((len < (tlen = q2110_pdulen[type].min)) ||
318 (len > q2110_pdulen[type].max) ||
319 (len & PDU_LEN_MASK))
324 * Get a contiguous, aligned PDU trailer and adjust buffer
325 * controls to remove trailer
327 if (KB_LEN(ml) >= tlen) {
329 * Trailer is contained in last buffer
331 KB_TAILADJ(ml, -tlen);
332 KB_DATAEND(ml, cp, caddr_t);
333 if ((int)cp & PDU_ADDR_MASK) {
335 * Trailer not aligned in buffer, use local memory
337 KM_COPY(cp, (caddr_t)&sscop_trailer, tlen);
338 cp = (caddr_t)&sscop_trailer;
342 * Trailer is split across buffers, use local memory
345 int off = tlen - KB_LEN(ml);
347 cp = (caddr_t)&sscop_trailer;
350 * Ensure trailer is within last two buffers
352 if ((mn == NULL) || (KB_LEN(mn) < off))
355 KB_DATASTART(ml, cp1, caddr_t);
356 KM_COPY(cp1, cp + off, KB_LEN(ml));
358 KB_TAILADJ(mn, -off);
359 KB_DATAEND(mn, cp1, caddr_t);
360 KM_COPY(cp1, cp, off);
364 * Get possible PDU Pad Length
366 if (sop->so_vers == SSCOP_VERS_QSAAL) {
367 if (qsaal_padlen[type])
368 plen = (*tp & PT_PAD_MASK) >> PT_PAD_SHIFT;
372 if (q2110_padlen[type])
373 plen = (*tp & PT_PAD_MASK) >> PT_PAD_SHIFT;
379 * Perform Pad Length adjustments
382 if (KB_LEN(ml) >= plen) {
384 * All pad bytes in last buffer
386 KB_TAILADJ(ml, -plen);
389 * Pad bytes split between buffers
392 if ((mn == NULL) || (KB_LEN(mn) < plen))
395 KB_TAILADJ(mn, -plen);
403 * This MAA Error is only supposed to be for a PDU length violation,
404 * but we use it for any PDU format error.
406 sscop_maa_error(sop, 'U');
407 sscop_pdu_print(sop, m, "badpdu received");