010586ed3aa9ebe83753020bd7a5ae51f69fdcd5
[dragonfly.git] / sys / netproto / atm / uni / unisig_decode.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/unisig_decode.c,v 1.5 2000/01/17 20:49:56 mks Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_decode.c,v 1.6 2006/01/14 13:36:39 swildner Exp $
28  */
29
30 /*
31  * ATM Forum UNI 3.0/3.1 Signalling Manager
32  * ----------------------------------------
33  *
34  * Message formatting module
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "unisig_var.h"
41 #include "unisig_msg.h"
42 #include "unisig_mbuf.h"
43 #include "unisig_decode.h"
44
45 #define ALLOC_IE(ie)                                            \
46         (ie) = (struct ie_generic *) atm_allocate(&unisig_iepool); \
47         if (!ie)                                                \
48                 return(ENOMEM);
49
50
51 /*
52  * Local functions
53  */
54 static int      usf_dec_ie (struct usfmt *, struct unisig_msg *, struct ie_generic *);
55 static int      usf_dec_ie_hdr (struct usfmt *, struct ie_generic *);
56 static int      usf_dec_ie_aalp (struct usfmt *, struct ie_generic *);
57 static int      usf_dec_ie_clrt (struct usfmt *, struct ie_generic *);
58 static int      usf_dec_ie_bbcp (struct usfmt *, struct ie_generic *);
59 static int      usf_dec_ie_bhli (struct usfmt *, struct ie_generic *);
60 static int      usf_dec_ie_blli (struct usfmt *, struct ie_generic *);
61 static int      usf_dec_ie_clst (struct usfmt *, struct ie_generic *);
62 static int      usf_dec_ie_cdad (struct usfmt *, struct ie_generic *);
63 static int      usf_dec_ie_cdsa (struct usfmt *, struct ie_generic *);
64 static int      usf_dec_ie_cgad (struct usfmt *, struct ie_generic *);
65 static int      usf_dec_ie_cgsa (struct usfmt *, struct ie_generic *);
66 static int      usf_dec_ie_caus (struct usfmt *, struct ie_generic *);
67 static int      usf_dec_ie_cnid (struct usfmt *, struct ie_generic *);
68 static int      usf_dec_ie_qosp (struct usfmt *, struct ie_generic *);
69 static int      usf_dec_ie_brpi (struct usfmt *, struct ie_generic *);
70 static int      usf_dec_ie_rsti (struct usfmt *, struct ie_generic *);
71 static int      usf_dec_ie_bsdc (struct usfmt *, struct ie_generic *);
72 static int      usf_dec_ie_trnt (struct usfmt *, struct ie_generic *);
73 static int      usf_dec_ie_uimp (struct usfmt *, struct ie_generic *);
74 static int      usf_dec_ie_ident (struct usfmt *, struct ie_generic *,
75                         struct ie_decode_tbl *);
76 static int      usf_dec_atm_addr (struct usfmt *, Atm_addr *, int);
77
78
79 /*
80  * Table associating IE type with IE vector index
81  */
82 u_char unisig_ie_ident_vec[] = {
83         UNI_IE_AALP,
84         UNI_IE_CLRT,
85         UNI_IE_BBCP,
86         UNI_IE_BHLI,
87         UNI_IE_BLLI,
88         UNI_IE_CLST,
89         UNI_IE_CDAD,
90         UNI_IE_CDSA,
91         UNI_IE_CGAD,
92         UNI_IE_CGSA,
93         UNI_IE_CAUS,
94         UNI_IE_CNID,
95         UNI_IE_QOSP,
96         UNI_IE_BRPI,
97         UNI_IE_RSTI,
98         UNI_IE_BLSH,
99         UNI_IE_BNSH,
100         UNI_IE_BSDC,
101         UNI_IE_TRNT,
102         UNI_IE_EPRF,
103         UNI_IE_EPST
104 };
105
106
107 /*
108  * Tables specifying which IEs are mandatory, optional, and
109  * not allowed for each Q.2931 message type
110  */
111 static u_char uni_calp_ie_tbl[] = {
112         IE_NA,          /* ATM AAL Parameters */
113         IE_NA,          /* ATM User Cell Rate */
114         IE_NA,          /* Broadband Bearer Capability */
115         IE_NA,          /* Broadband High Layer Information */
116         IE_NA,          /* Broadband Low Layer Information */
117         IE_NA,          /* Call State */
118         IE_NA,          /* Called Party Number */
119         IE_NA,          /* Called Party Subaddress */
120         IE_NA,          /* Calling Party Number */
121         IE_NA,          /* Calling Party Subaddress */
122         IE_NA,          /* Cause */
123         IE_OPT,         /* Connection Identifier */
124         IE_NA,          /* Quality of Service Parameters */
125         IE_NA,          /* Broadband Repeat Indicator */
126         IE_NA,          /* Restart Indicator */
127         IE_NA,          /* Broadband Locking Shift */
128         IE_NA,          /* Broadband Non-locking Shift */
129         IE_NA,          /* Broadband Sending Complete */
130         IE_NA,          /* Transit Net */
131         IE_OPT,         /* Endpoint Reference */
132         IE_NA           /* Endpoint State */
133 };
134
135 static u_char uni_conn_ie_tbl[] = {
136         IE_OPT,         /* ATM AAL Parameters */
137         IE_NA,          /* ATM User Cell Rate */
138         IE_NA,          /* Broadband Bearer Capability */
139         IE_NA,          /* Broadband High Layer Information */
140         IE_OPT,         /* Broadband Low Layer Information */
141         IE_NA,          /* Call State */
142         IE_NA,          /* Called Party Number */
143         IE_NA,          /* Called Party Subaddress */
144         IE_NA,          /* Calling Party Number */
145         IE_NA,          /* Calling Party Subaddress */
146         IE_NA,          /* Cause */
147         IE_OPT,         /* Connection Identifier */
148         IE_NA,          /* Quality of Service Parameters */
149         IE_NA,          /* Broadband Repeat Indicator */
150         IE_NA,          /* Restart Indicator */
151         IE_NA,          /* Broadband Locking Shift */
152         IE_NA,          /* Broadband Non-locking Shift */
153         IE_NA,          /* Broadband Sending Complete */
154         IE_NA,          /* Transit Net */
155         IE_OPT,         /* Endpoint Reference */
156         IE_NA           /* Endpoint State */
157 };
158
159 static u_char uni_cack_ie_tbl[] = {
160         IE_NA,          /* ATM AAL Parameters */
161         IE_NA,          /* ATM User Cell Rate */
162         IE_NA,          /* Broadband Bearer Capability */
163         IE_NA,          /* Broadband High Layer Information */
164         IE_NA,          /* Broadband Low Layer Information */
165         IE_NA,          /* Call State */
166         IE_NA,          /* Called Party Number */
167         IE_NA,          /* Called Party Subaddress */
168         IE_NA,          /* Calling Party Number */
169         IE_NA,          /* Calling Party Subaddress */
170         IE_NA,          /* Cause */
171         IE_NA,          /* Connection Identifier */
172         IE_NA,          /* Quality of Service Parameters */
173         IE_NA,          /* Broadband Repeat Indicator */
174         IE_NA,          /* Restart Indicator */
175         IE_NA,          /* Broadband Locking Shift */
176         IE_NA,          /* Broadband Non-locking Shift */
177         IE_NA,          /* Broadband Sending Complete */
178         IE_NA,          /* Transit Net */
179         IE_NA,          /* Endpoint Reference */
180         IE_NA           /* Endpoint State */
181 };
182
183 static u_char uni_setu_ie_tbl[] = {
184         IE_MAND,        /* ATM AAL Parameters (not required by
185                            UNI 3.0) */
186         IE_MAND,        /* ATM User Cell Rate */
187         IE_MAND,        /* Broadband Bearer Capability */
188         IE_OPT,         /* Broadband High Layer Information */
189         IE_MAND,        /* Broadband Low Layer Information (not required                                   by UNI 3.0 */
190         IE_NA,          /* Call State */
191         IE_MAND,        /* Called Party Number */
192         IE_OPT,         /* Called Party Subaddress */
193         IE_OPT,         /* Calling Party Number */
194         IE_OPT,         /* Calling Party Subaddress */
195         IE_NA,          /* Cause */
196         IE_MAND,        /* Connection Identifier */
197         IE_MAND,        /* Quality of Service Parameters */
198         IE_OPT,         /* Broadband Repeat Indicator */
199         IE_NA,          /* Restart Indicator */
200         IE_NA,          /* Broadband Locking Shift */
201         IE_NA,          /* Broadband Non-locking Shift */
202         IE_OPT,         /* Broadband Sending Complete */
203         IE_NA,          /* Transit Net */
204         IE_OPT,         /* Endpoint Reference */
205         IE_NA           /* Endpoint State */
206 };
207
208 static u_char uni_rlse_ie_tbl[] = {
209         IE_NA,          /* ATM AAL Parameters */
210         IE_NA,          /* ATM User Cell Rate */
211         IE_NA,          /* Broadband Bearer Capability */
212         IE_NA,          /* Broadband High Layer Information */
213         IE_NA,          /* Broadband Low Layer Information */
214         IE_NA,          /* Call State */
215         IE_NA,          /* Called Party Number */
216         IE_NA,          /* Called Party Subaddress */
217         IE_NA,          /* Calling Party Number */
218         IE_NA,          /* Calling Party Subaddress */
219         IE_MAND,        /* Cause */
220         IE_NA,          /* Connection Identifier */
221         IE_NA,          /* Quality of Service Parameters */
222         IE_NA,          /* Broadband Repeat Indicator */
223         IE_NA,          /* Restart Indicator */
224         IE_NA,          /* Broadband Locking Shift */
225         IE_NA,          /* Broadband Non-locking Shift */
226         IE_NA,          /* Broadband Sending Complete */
227         IE_NA,          /* Transit Net */
228         IE_NA,          /* Endpoint Reference */
229         IE_NA           /* Endpoint State */
230 };
231
232 static u_char uni_rlsc_ie_tbl[] = {
233         IE_NA,          /* ATM AAL Parameters */
234         IE_NA,          /* ATM User Cell Rate */
235         IE_NA,          /* Broadband Bearer Capability */
236         IE_NA,          /* Broadband High Layer Information */
237         IE_NA,          /* Broadband Low Layer Information */
238         IE_NA,          /* Call State */
239         IE_NA,          /* Called Party Number */
240         IE_NA,          /* Called Party Subaddress */
241         IE_NA,          /* Calling Party Number */
242         IE_NA,          /* Calling Party Subaddress */
243         IE_MAND,        /* Cause */
244         IE_NA,          /* Connection Identifier */
245         IE_NA,          /* Quality of Service Parameters */
246         IE_NA,          /* Broadband Repeat Indicator */
247         IE_NA,          /* Restart Indicator */
248         IE_NA,          /* Broadband Locking Shift */
249         IE_NA,          /* Broadband Non-locking Shift */
250         IE_NA,          /* Broadband Sending Complete */
251         IE_NA,          /* Transit Net */
252         IE_NA,          /* Endpoint Reference */
253         IE_NA           /* Endpoint State */
254 };
255
256 static u_char uni_rstr_ie_tbl[] = {
257         IE_NA,          /* ATM AAL Parameters */
258         IE_NA,          /* ATM User Cell Rate */
259         IE_NA,          /* Broadband Bearer Capability */
260         IE_NA,          /* Broadband High Layer Information */
261         IE_NA,          /* Broadband Low Layer Information */
262         IE_NA,          /* Call State */
263         IE_NA,          /* Called Party Number */
264         IE_NA,          /* Called Party Subaddress */
265         IE_NA,          /* Calling Party Number */
266         IE_NA,          /* Calling Party Subaddress */
267         IE_NA,          /* Cause */
268         IE_OPT,         /* Connection Identifier */
269         IE_NA,          /* Quality of Service Parameters */
270         IE_NA,          /* Broadband Repeat Indicator */
271         IE_MAND,        /* Restart Indicator */
272         IE_NA,          /* Broadband Locking Shift */
273         IE_NA,          /* Broadband Non-locking Shift */
274         IE_NA,          /* Broadband Sending Complete */
275         IE_NA,          /* Transit Net */
276         IE_NA,          /* Endpoint Reference */
277         IE_NA           /* Endpoint State */
278 };
279
280 static u_char uni_rsta_ie_tbl[] = {
281         IE_NA,          /* ATM AAL Parameters */
282         IE_NA,          /* ATM User Cell Rate */
283         IE_NA,          /* Broadband Bearer Capability */
284         IE_NA,          /* Broadband High Layer Information */
285         IE_NA,          /* Broadband Low Layer Information */
286         IE_NA,          /* Call State */
287         IE_NA,          /* Called Party Number */
288         IE_NA,          /* Called Party Subaddress */
289         IE_NA,          /* Calling Party Number */
290         IE_NA,          /* Calling Party Subaddress */
291         IE_NA,          /* Cause */
292         IE_OPT,         /* Connection Identifier */
293         IE_NA,          /* Quality of Service Parameters */
294         IE_NA,          /* Broadband Repeat Indicator */
295         IE_MAND,        /* Restart Indicator */
296         IE_NA,          /* Broadband Locking Shift */
297         IE_NA,          /* Broadband Non-locking Shift */
298         IE_NA,          /* Broadband Sending Complete */
299         IE_NA,          /* Transit Net */
300         IE_NA,          /* Endpoint Reference */
301         IE_NA           /* Endpoint State */
302 };
303
304 static u_char uni_stat_ie_tbl[] = {
305         IE_NA,          /* ATM AAL Parameters */
306         IE_NA,          /* ATM User Cell Rate */
307         IE_NA,          /* Broadband Bearer Capability */
308         IE_NA,          /* Broadband High Layer Information */
309         IE_NA,          /* Broadband Low Layer Information */
310         IE_MAND,        /* Call State */
311         IE_NA,          /* Called Party Number */
312         IE_NA,          /* Called Party Subaddress */
313         IE_NA,          /* Calling Party Number */
314         IE_NA,          /* Calling Party Subaddress */
315         IE_MAND,        /* Cause */
316         IE_NA,          /* Connection Identifier */
317         IE_NA,          /* Quality of Service Parameters */
318         IE_NA,          /* Broadband Repeat Indicator */
319         IE_NA,          /* Restart Indicator */
320         IE_NA,          /* Broadband Locking Shift */
321         IE_NA,          /* Broadband Non-locking Shift */
322         IE_NA,          /* Broadband Sending Complete */
323         IE_NA,          /* Transit Net */
324         IE_OPT,         /* Endpoint Reference */
325         IE_OPT          /* Endpoint State */
326 };
327
328 static u_char uni_senq_ie_tbl[] = {
329         IE_NA,          /* ATM AAL Parameters */
330         IE_NA,          /* ATM User Cell Rate */
331         IE_NA,          /* Broadband Bearer Capability */
332         IE_NA,          /* Broadband High Layer Information */
333         IE_NA,          /* Broadband Low Layer Information */
334         IE_NA,          /* Call State */
335         IE_NA,          /* Called Party Number */
336         IE_NA,          /* Called Party Subaddress */
337         IE_NA,          /* Calling Party Number */
338         IE_NA,          /* Calling Party Subaddress */
339         IE_NA,          /* Cause */
340         IE_NA,          /* Connection Identifier */
341         IE_NA,          /* Quality of Service Parameters */
342         IE_NA,          /* Broadband Repeat Indicator */
343         IE_NA,          /* Restart Indicator */
344         IE_NA,          /* Broadband Locking Shift */
345         IE_NA,          /* Broadband Non-locking Shift */
346         IE_NA,          /* Broadband Sending Complete */
347         IE_NA,          /* Transit Net */
348         IE_OPT,         /* Endpoint Reference */
349         IE_NA           /* Endpoint State */
350 };
351
352 static u_char uni_addp_ie_tbl[] = {
353         IE_OPT,         /* ATM AAL Parameters */
354         IE_NA,          /* ATM User Cell Rate */
355         IE_NA,          /* Broadband Bearer Capability */
356         IE_OPT,         /* Broadband High Layer Information */
357         IE_OPT,         /* Broadband Low Layer Information */
358         IE_NA,          /* Call State */
359         IE_MAND,        /* Called Party Number */
360         IE_OPT,         /* Called Party Subaddress */
361         IE_OPT,         /* Calling Party Number */
362         IE_OPT,         /* Calling Party Subaddress */
363         IE_NA,          /* Cause */
364         IE_NA,          /* Connection Identifier */
365         IE_NA,          /* Quality of Service Parameters */
366         IE_NA,          /* Broadband Repeat Indicator */
367         IE_NA,          /* Restart Indicator */
368         IE_NA,          /* Broadband Locking Shift */
369         IE_NA,          /* Broadband Non-locking Shift */
370         IE_OPT,         /* Broadband Sending Complete */
371         IE_NA,          /* Transit Net */
372         IE_MAND,        /* Endpoint Reference */
373         IE_NA           /* Endpoint State */
374 };
375
376 static u_char uni_adpa_ie_tbl[] = {
377         IE_NA,          /* ATM AAL Parameters */
378         IE_NA,          /* ATM User Cell Rate */
379         IE_NA,          /* Broadband Bearer Capability */
380         IE_NA,          /* Broadband High Layer Information */
381         IE_NA,          /* Broadband Low Layer Information */
382         IE_NA,          /* Call State */
383         IE_NA,          /* Called Party Number */
384         IE_NA,          /* Called Party Subaddress */
385         IE_NA,          /* Calling Party Number */
386         IE_NA,          /* Calling Party Subaddress */
387         IE_NA,          /* Cause */
388         IE_NA,          /* Connection Identifier */
389         IE_NA,          /* Quality of Service Parameters */
390         IE_NA,          /* Broadband Repeat Indicator */
391         IE_NA,          /* Restart Indicator */
392         IE_NA,          /* Broadband Locking Shift */
393         IE_NA,          /* Broadband Non-locking Shift */
394         IE_NA,          /* Broadband Sending Complete */
395         IE_NA,          /* Transit Net */
396         IE_MAND,        /* Endpoint Reference */
397         IE_NA           /* Endpoint State */
398 };
399
400 static u_char uni_adpr_ie_tbl[] = {
401         IE_NA,          /* ATM AAL Parameters */
402         IE_NA,          /* ATM User Cell Rate */
403         IE_NA,          /* Broadband Bearer Capability */
404         IE_NA,          /* Broadband High Layer Information */
405         IE_NA,          /* Broadband Low Layer Information */
406         IE_NA,          /* Call State */
407         IE_NA,          /* Called Party Number */
408         IE_NA,          /* Called Party Subaddress */
409         IE_NA,          /* Calling Party Number */
410         IE_NA,          /* Calling Party Subaddress */
411         IE_MAND,        /* Cause */
412         IE_NA,          /* Connection Identifier */
413         IE_NA,          /* Quality of Service Parameters */
414         IE_NA,          /* Broadband Repeat Indicator */
415         IE_NA,          /* Restart Indicator */
416         IE_NA,          /* Broadband Locking Shift */
417         IE_NA,          /* Broadband Non-locking Shift */
418         IE_NA,          /* Broadband Sending Complete */
419         IE_NA,          /* Transit Net */
420         IE_MAND,        /* Endpoint Reference */
421         IE_NA           /* Endpoint State */
422 };
423
424 static u_char uni_drpp_ie_tbl[] = {
425         IE_NA,          /* ATM AAL Parameters */
426         IE_NA,          /* ATM User Cell Rate */
427         IE_NA,          /* Broadband Bearer Capability */
428         IE_NA,          /* Broadband High Layer Information */
429         IE_NA,          /* Broadband Low Layer Information */
430         IE_NA,          /* Call State */
431         IE_NA,          /* Called Party Number */
432         IE_NA,          /* Called Party Subaddress */
433         IE_NA,          /* Calling Party Number */
434         IE_NA,          /* Calling Party Subaddress */
435         IE_MAND,        /* Cause */
436         IE_NA,          /* Connection Identifier */
437         IE_NA,          /* Quality of Service Parameters */
438         IE_NA,          /* Broadband Repeat Indicator */
439         IE_NA,          /* Restart Indicator */
440         IE_NA,          /* Broadband Locking Shift */
441         IE_NA,          /* Broadband Non-locking Shift */
442         IE_NA,          /* Broadband Sending Complete */
443         IE_NA,          /* Transit Net */
444         IE_MAND,        /* Endpoint Reference */
445         IE_NA           /* Endpoint State */
446 };
447
448 static u_char uni_drpa_ie_tbl[] = {
449         IE_NA,          /* ATM AAL Parameters */
450         IE_NA,          /* ATM User Cell Rate */
451         IE_NA,          /* Broadband Bearer Capability */
452         IE_NA,          /* Broadband High Layer Information */
453         IE_NA,          /* Broadband Low Layer Information */
454         IE_NA,          /* Call State */
455         IE_NA,          /* Called Party Number */
456         IE_NA,          /* Called Party Subaddress */
457         IE_NA,          /* Calling Party Number */
458         IE_NA,          /* Calling Party Subaddress */
459         IE_OPT,         /* Cause */
460         IE_NA,          /* Connection Identifier */
461         IE_NA,          /* Quality of Service Parameters */
462         IE_NA,          /* Broadband Repeat Indicator */
463         IE_NA,          /* Restart Indicator */
464         IE_NA,          /* Broadband Locking Shift */
465         IE_NA,          /* Broadband Non-locking Shift */
466         IE_NA,          /* Broadband Sending Complete */
467         IE_NA,          /* Transit Net */
468         IE_MAND,        /* Endpoint Reference */
469         IE_NA           /* Endpoint State */
470 };
471
472 /*
473  * Table of Q.2931 message types
474  */
475 static struct {
476         u_char  msg_type;
477         u_char  *msg_ie_tbl;
478 } uni_msg_types[] = {
479         { UNI_MSG_CALP, uni_calp_ie_tbl },
480         { UNI_MSG_CONN, uni_conn_ie_tbl },
481         { UNI_MSG_CACK, uni_cack_ie_tbl },
482         { UNI_MSG_SETU, uni_setu_ie_tbl },
483         { UNI_MSG_RLSE, uni_rlse_ie_tbl },
484         { UNI_MSG_RLSC, uni_rlsc_ie_tbl },
485         { UNI_MSG_RSTR, uni_rstr_ie_tbl },
486         { UNI_MSG_RSTA, uni_rsta_ie_tbl },
487         { UNI_MSG_STAT, uni_stat_ie_tbl },
488         { UNI_MSG_SENQ, uni_senq_ie_tbl },
489         { UNI_MSG_ADDP, uni_addp_ie_tbl },
490         { UNI_MSG_ADPA, uni_adpa_ie_tbl },
491         { UNI_MSG_ADPR, uni_adpr_ie_tbl },
492         { UNI_MSG_DRPP, uni_drpp_ie_tbl },
493         { UNI_MSG_DRPA, uni_drpa_ie_tbl },
494 };
495
496
497 /*
498  * Table of information elements
499  */
500 static struct ie_ent    ie_table[] = {
501         { UNI_IE_AALP, 5, 16, UNI_MSG_IE_AALP, usf_dec_ie_aalp },
502         { UNI_IE_CLRT, 0, 26, UNI_MSG_IE_CLRT, usf_dec_ie_clrt },
503         { UNI_IE_BBCP, 2,  3, UNI_MSG_IE_BBCP, usf_dec_ie_bbcp },
504         { UNI_IE_BHLI, 1,  9, UNI_MSG_IE_BHLI, usf_dec_ie_bhli },
505         { UNI_IE_BLLI, 0, 13, UNI_MSG_IE_BLLI, usf_dec_ie_blli },
506         { UNI_IE_CLST, 1,  1, UNI_MSG_IE_CLST, usf_dec_ie_clst },
507         { UNI_IE_CDAD, 1, 21, UNI_MSG_IE_CDAD, usf_dec_ie_cdad },
508         { UNI_IE_CDSA, 1, 21, UNI_MSG_IE_CDSA, usf_dec_ie_cdsa },
509         { UNI_IE_CGAD, 1, 22, UNI_MSG_IE_CGAD, usf_dec_ie_cgad },
510         { UNI_IE_CGSA, 1, 21, UNI_MSG_IE_CGSA, usf_dec_ie_cgsa },
511         { UNI_IE_CAUS, 2, 30, UNI_MSG_IE_CAUS, usf_dec_ie_caus },
512         { UNI_IE_CNID, 5,  5, UNI_MSG_IE_CNID, usf_dec_ie_cnid },
513         { UNI_IE_QOSP, 2,  2, UNI_MSG_IE_QOSP, usf_dec_ie_qosp },
514         { UNI_IE_BRPI, 1,  1, UNI_MSG_IE_BRPI, usf_dec_ie_brpi },
515         { UNI_IE_RSTI, 1,  1, UNI_MSG_IE_RSTI, usf_dec_ie_rsti },
516         { UNI_IE_BLSH, 1,  1, UNI_MSG_IE_ERR,  usf_dec_ie_uimp },
517         { UNI_IE_BNSH, 1,  1, UNI_MSG_IE_ERR,  usf_dec_ie_uimp },
518         { UNI_IE_BSDC, 1,  1, UNI_MSG_IE_BSDC, usf_dec_ie_bsdc },
519         { UNI_IE_TRNT, 1,  5, UNI_MSG_IE_TRNT, usf_dec_ie_trnt },
520         { UNI_IE_EPRF, 3,  3, UNI_MSG_IE_ERR,  usf_dec_ie_uimp },
521         { UNI_IE_EPST, 1,  1, UNI_MSG_IE_ERR,  usf_dec_ie_uimp },
522         { 0,           0,  0, 0,               0 }
523 };
524
525 /*
526  * Decoding table for AAL 1
527  */
528 struct ie_decode_tbl    ie_aal1_tbl[] = {
529         { 133, 1, IE_OFF_SIZE(ie_aalp_1_subtype) },
530         { 134, 1, IE_OFF_SIZE(ie_aalp_1_cbr_rate) },
531         { 135, 2, IE_OFF_SIZE(ie_aalp_1_multiplier) },
532         { 136, 1, IE_OFF_SIZE(ie_aalp_1_clock_recovery) },
533         { 137, 1, IE_OFF_SIZE(ie_aalp_1_error_correction) },
534         { 138, 1, IE_OFF_SIZE(ie_aalp_1_struct_data_tran) },
535         { 139, 1, IE_OFF_SIZE(ie_aalp_1_partial_cells) },
536         {   0, 0, 0, 0 }
537 };
538
539 /*
540  * Decoding table for AAL 3/4
541  */
542 struct ie_decode_tbl    ie_aal4_tbl_30[] = {
543         { 140, 2, IE_OFF_SIZE(ie_aalp_4_fwd_max_sdu) },
544         { 129, 2, IE_OFF_SIZE(ie_aalp_4_bkwd_max_sdu) },
545         { 130, 2, IE_OFF_SIZE(ie_aalp_4_mid_range) },
546         { 131, 1, IE_OFF_SIZE(ie_aalp_4_mode) },
547         { 132, 1, IE_OFF_SIZE(ie_aalp_4_sscs_type) },
548         {   0, 0, 0, 0 }
549 };
550 struct ie_decode_tbl    ie_aal4_tbl_31[] = {
551         { 140, 2, IE_OFF_SIZE(ie_aalp_4_fwd_max_sdu) },
552         { 129, 2, IE_OFF_SIZE(ie_aalp_4_bkwd_max_sdu) },
553         { 130, 4, IE_OFF_SIZE(ie_aalp_4_mid_range) },
554         { 132, 1, IE_OFF_SIZE(ie_aalp_4_sscs_type) },
555         {   0, 0, 0, 0 }
556 };
557
558 /*
559  * Decoding table for AAL 5
560  */
561 struct ie_decode_tbl    ie_aal5_tbl_30[] = {
562         { 140, 2, IE_OFF_SIZE(ie_aalp_5_fwd_max_sdu) },
563         { 129, 2, IE_OFF_SIZE(ie_aalp_5_bkwd_max_sdu) },
564         { 131, 1, IE_OFF_SIZE(ie_aalp_5_mode) },
565         { 132, 1, IE_OFF_SIZE(ie_aalp_5_sscs_type) },
566         {   0, 0, 0, 0 }
567 };
568 struct ie_decode_tbl    ie_aal5_tbl_31[] = {
569         { 140, 2, IE_OFF_SIZE(ie_aalp_5_fwd_max_sdu) },
570         { 129, 2, IE_OFF_SIZE(ie_aalp_5_bkwd_max_sdu) },
571         { 132, 1, IE_OFF_SIZE(ie_aalp_5_sscs_type) },
572         {   0, 0, 0, 0 }
573 };
574
575 /*
576  * Decoding table for ATM user cell rate
577  */
578 struct ie_decode_tbl    ie_clrt_tbl[] = {
579     {UNI_IE_CLRT_FWD_PEAK_ID,      3, IE_OFF_SIZE(ie_clrt_fwd_peak)},
580     {UNI_IE_CLRT_BKWD_PEAK_ID,     3, IE_OFF_SIZE(ie_clrt_bkwd_peak)},
581     {UNI_IE_CLRT_FWD_PEAK_01_ID,   3, IE_OFF_SIZE(ie_clrt_fwd_peak_01)},
582     {UNI_IE_CLRT_BKWD_PEAK_01_ID,  3, IE_OFF_SIZE(ie_clrt_bkwd_peak_01)},
583     {UNI_IE_CLRT_FWD_SUST_ID,      3, IE_OFF_SIZE(ie_clrt_fwd_sust)},
584     {UNI_IE_CLRT_BKWD_SUST_ID,     3, IE_OFF_SIZE(ie_clrt_bkwd_sust)},
585     {UNI_IE_CLRT_FWD_SUST_01_ID,   3, IE_OFF_SIZE(ie_clrt_fwd_sust_01)},
586     {UNI_IE_CLRT_BKWD_SUST_01_ID,  3, IE_OFF_SIZE(ie_clrt_bkwd_sust_01)},
587     {UNI_IE_CLRT_FWD_BURST_ID,     3, IE_OFF_SIZE(ie_clrt_fwd_burst)},
588     {UNI_IE_CLRT_BKWD_BURST_ID,    3, IE_OFF_SIZE(ie_clrt_bkwd_burst)},
589     {UNI_IE_CLRT_FWD_BURST_01_ID,  3, IE_OFF_SIZE(ie_clrt_fwd_burst_01)},
590     {UNI_IE_CLRT_BKWD_BURST_01_ID, 3, IE_OFF_SIZE(ie_clrt_bkwd_burst_01)},
591     {UNI_IE_CLRT_BEST_EFFORT_ID,   0, IE_OFF_SIZE(ie_clrt_best_effort)},
592     {UNI_IE_CLRT_TM_OPTIONS_ID,    1, IE_OFF_SIZE(ie_clrt_tm_options)},
593     {0,                            0, 0, 0 }
594 };
595
596 /*
597  * IEs initialized to empty values
598  */
599 struct ie_aalp  ie_aalp_absent = {
600         T_ATM_ABSENT
601 };
602
603 struct ie_clrt  ie_clrt_absent = {
604         T_ATM_ABSENT,
605         T_ATM_ABSENT,
606         T_ATM_ABSENT,
607         T_ATM_ABSENT,
608         T_ATM_ABSENT,
609         T_ATM_ABSENT,
610         T_ATM_ABSENT,
611         T_ATM_ABSENT,
612         T_ATM_ABSENT,
613         T_ATM_ABSENT,
614         T_ATM_ABSENT,
615         T_ATM_ABSENT,
616         T_ATM_ABSENT,
617         T_ATM_ABSENT
618 };
619
620 struct ie_bbcp  ie_bbcp_absent = {
621         T_ATM_ABSENT,
622         T_ATM_ABSENT,
623         T_ATM_ABSENT,
624         T_ATM_ABSENT,
625         T_ATM_ABSENT
626 };
627
628 struct ie_bhli  ie_bhli_absent = {
629         T_ATM_ABSENT,
630         { 0, 0, 0, 0, 0, 0, 0, 0 }
631 };
632
633 struct ie_blli  ie_blli_absent = {
634         T_ATM_ABSENT,
635         T_ATM_ABSENT,
636         T_ATM_ABSENT,
637         T_ATM_ABSENT,
638         T_ATM_ABSENT,
639         T_ATM_ABSENT,
640         T_ATM_ABSENT,
641         T_ATM_ABSENT,
642         T_ATM_ABSENT,
643         T_ATM_ABSENT,
644         T_ATM_ABSENT,
645         T_ATM_ABSENT,
646         T_ATM_ABSENT,
647         { 0, 0, 0 },
648         { 0, 0 }
649 };
650
651 struct ie_clst  ie_clst_absent = {
652         T_ATM_ABSENT
653 };
654
655 struct ie_cdad  ie_cdad_absent = {
656         T_ATM_ABSENT,
657         T_ATM_ABSENT,
658         { T_ATM_ABSENT, 0 }
659 };
660
661 struct ie_cdsa  ie_cdsa_absent = {
662         { T_ATM_ABSENT, 0 }
663 };
664
665 struct ie_cgad  ie_cgad_absent = {
666         T_ATM_ABSENT,
667         T_ATM_ABSENT,
668         T_ATM_ABSENT,
669         T_ATM_ABSENT,
670         { T_ATM_ABSENT, 0 }
671 };
672
673 struct ie_cgsa  ie_cgsa_absent = {
674         { T_ATM_ABSENT, 0 }
675 };
676
677 struct ie_caus  ie_caus_absent = {
678         T_ATM_ABSENT,
679         T_ATM_ABSENT,
680         0
681 };
682
683 struct ie_cnid  ie_cnid_absent = {
684         T_ATM_ABSENT,
685         T_ATM_ABSENT,
686         T_ATM_ABSENT,
687         T_ATM_ABSENT
688 };
689
690 struct ie_qosp  ie_qosp_absent = {
691         T_ATM_ABSENT,
692         T_ATM_ABSENT
693 };
694
695 struct ie_brpi  ie_brpi_absent = {
696         T_ATM_ABSENT
697 };
698
699 struct ie_rsti  ie_rsti_absent = {
700         T_ATM_ABSENT
701 };
702
703 struct ie_blsh  ie_blsh_absent = {
704         T_ATM_ABSENT
705 };
706
707 struct ie_bnsh  ie_bnsh_absent = {
708         T_ATM_ABSENT
709 };
710
711 struct ie_bsdc  ie_bsdc_absent = {
712         T_ATM_ABSENT
713 };
714
715 struct ie_trnt  ie_trnt_absent = {
716         T_ATM_ABSENT,
717         T_ATM_ABSENT,
718         0
719 };
720
721 struct ie_eprf  ie_eprf_absent = {
722         T_ATM_ABSENT,
723         T_ATM_ABSENT
724 };
725
726 struct ie_epst  ie_epst_absent = {
727         T_ATM_ABSENT
728 };
729
730
731 /*
732  * Decode a UNI signalling message
733  *
734  * Arguments:
735  *      usf     pointer to a unisig formatting structure
736  *      msg     pointer to a signalling message structure
737  *
738  * Returns:
739  *      0       success
740  *      errno   error encountered
741  *
742  */
743 int
744 usf_dec_msg(struct usfmt *usf, struct unisig_msg *msg)
745 {
746         int                     i, len, rc;
747         short                   s;
748         u_char                  c, *ie_tbl;
749         struct ie_generic       *ie;
750
751         ATM_DEBUG2("usf_dec_msg: usf=%p, msg=%p\n", usf, msg);
752
753         /*
754          * Check the total message length
755          */
756         if (usf_count(usf) < UNI_MSG_MIN_LEN) {
757                 return(EIO);
758         }
759
760         /*
761          * Get and check the protocol discriminator
762          */
763         rc = usf_byte(usf, &c);
764         if (rc)
765                 return(rc);
766         if (c != UNI_MSG_DISC_Q93B)
767                 return(EIO);
768
769         /*
770          * Get and check the call reference length
771          */
772         rc = usf_byte(usf, &c);
773         if (rc)
774                 return(rc);
775         if (c != 3)
776                 return(EIO);
777
778         /*
779          * Get the call reference
780          */
781         rc = usf_int3(usf, &msg->msg_call_ref);
782         if (rc)
783                 return(rc);
784
785         /*
786          * Get the message type
787          */
788         rc = usf_byte(usf, &msg->msg_type);
789         if (rc)
790                 return(rc);
791
792         /*
793          * Get the message type extension
794          */
795         rc = usf_byte(usf, &c);
796         if (rc)
797                 return(rc);
798         msg->msg_type_flag = (c >> UNI_MSG_TYPE_FLAG_SHIFT) &
799                         UNI_MSG_TYPE_FLAG_MASK;
800         msg->msg_type_action = c & UNI_MSG_TYPE_ACT_MASK;
801
802         /*
803          * Get the message length and make sure we actually have
804          * enough data for the whole message
805          */
806         rc = usf_short(usf, &s);
807         if (rc)
808                 return(rc);
809         msg->msg_length = s;
810         if (usf_count(usf) != msg->msg_length) {
811                 return(EMSGSIZE);
812         }
813
814         /*
815          * Process information elements
816          */
817         len = msg->msg_length;
818         while (len) {
819                 ALLOC_IE(ie);
820                 rc = usf_dec_ie(usf, msg, ie);
821                 if (rc) {
822                         atm_free(ie);
823                         return(rc);
824                 }
825                 len -= (ie->ie_length + UNI_IE_HDR_LEN);
826         }
827
828         /*
829          * Make sure that mandatory IEs are included and
830          * unwanted ones aren't
831          */
832         for (i=0; msg->msg_type!=uni_msg_types[i].msg_type &&
833                         uni_msg_types[i].msg_type!=0; i++) {
834         }
835         if (!uni_msg_types[i].msg_ie_tbl)
836                 goto done;
837
838         /*
839          * If the message type is in the table, check the IEs.
840          * If it isn't, the receive routine will catch the error.
841          */
842         ie_tbl = uni_msg_types[i].msg_ie_tbl;
843         for (i=0; i<UNI_MSG_IE_CNT-1; i++) {
844                 switch(ie_tbl[i]) {
845                 case IE_MAND:
846                         if (!msg->msg_ie_vec[i]) {
847                                 /*
848                                  * Mandatory IE missing
849                                  */
850                                 ALLOC_IE(ie);
851                                 ie->ie_ident = unisig_ie_ident_vec[i];
852                                 ie->ie_err_cause = UNI_IE_CAUS_MISSING;
853                                 MSG_IE_ADD(msg, ie, UNI_MSG_IE_ERR);
854                         }
855                         break;
856                 case IE_NA:
857                         if (msg->msg_ie_vec[i]) {
858                                 /*
859                                  * Disallowed IE present
860                                  */
861                                 ie = msg->msg_ie_vec[i];
862                                 msg->msg_ie_vec[i] =
863                                                 (struct ie_generic *) 0;
864                                 MSG_IE_ADD(msg, ie, UNI_MSG_IE_ERR);
865                                 while (ie) {
866                                         ie->ie_err_cause =
867                                                 UNI_IE_CAUS_IEEXIST;
868                                         ie = ie->ie_next;
869                                 }
870                         }
871                         break;
872                 case IE_OPT:
873                         break;
874                 }
875         }
876
877 done:
878         return(0);
879 }
880
881
882 /*
883  * Decode an information element
884  *
885  * This routine will be called repeatedly as long as there are
886  * information elements left to be decoded.  It will decode the
887  * first part of the IE, look its type up in a table, and call
888  * the appropriate routine to decode the rest.  After an IE is
889  * successfully decoded, it is linked into the UNI signalling
890  * message structure.  If an error is discovered, the IE is linked
891  * into the IE error chain and an error cause is set in the header.
892  *
893  * Arguments:
894  *      usf     pointer to a UNISIG formatting structure
895  *      msg     pointer to a UNISIG message structure
896  *      ie      pointer to a generic IE structure
897  *
898  * Returns:
899  *      0       success
900  *      errno   error encountered
901  *
902  */
903 static int
904 usf_dec_ie(struct usfmt *usf, struct unisig_msg *msg, struct ie_generic *ie)
905 {
906         int                     i, ie_index, rc;
907
908         /*
909          * Decode the IE header (identifier, instruction field,
910          * and length)
911          */
912         rc = usf_dec_ie_hdr(usf, ie);
913         if (rc)
914                 return(rc);
915         /*
916          * Ignore the IE if it is of zero length.
917          */
918         if (!ie->ie_length) {
919                 atm_free(ie);
920                 return(0);
921         }
922
923         /*
924          * Look up the information element in the table
925          */
926         for (i=0; (ie->ie_ident != ie_table[i].ident) &&
927                         (ie_table[i].decode != NULL); i++) {
928         }
929         if (ie_table[i].decode == NULL) {
930                 /*
931                  * Unrecognized IE
932                  */
933                 ie_index = UNI_MSG_IE_ERR;
934         } else {
935                 ie_index = ie_table[i].p_idx;
936         }
937
938         /*
939          * Check for unimplemented or unrecognized IEs
940          */
941         if (ie_index == UNI_MSG_IE_ERR) {
942                 ie->ie_err_cause = UNI_IE_CAUS_IEEXIST;
943
944                 /*
945                  * Skip over the invalid IE
946                  */
947                 rc = usf_dec_ie_uimp(usf, ie);
948                 if (rc)
949                         return(rc);
950                 goto done;
951         }
952
953         /*
954          * Check the length against the IE table
955          */
956         if (ie->ie_length < ie_table[i].min_len ||
957                         ie->ie_length > ie_table[i].max_len) {
958                 ie_index = UNI_MSG_IE_ERR;
959                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
960
961                 /*
962                  * Skip over the invalid IE
963                  */
964                 rc = usf_dec_ie_uimp(usf, ie);
965                 if (rc)
966                         return(rc);
967                 goto done;
968         }
969
970         /*
971          * Process the IE by calling the function indicated
972          * in the IE table
973          */
974         rc = ie_table[i].decode(usf, ie);
975         if (rc)
976                 return(rc);
977
978         /*
979          * Link the IE into the signalling message
980          */
981 done:
982         if (ie->ie_err_cause) {
983                 ie_index = UNI_MSG_IE_ERR;
984         }
985         MSG_IE_ADD(msg, ie, ie_index);
986
987         return(0);
988 }
989
990
991 /*
992  * Decode an information element header
993  *
994  * Arguments:
995  *      usf     pointer to a UNISIG formatting structure
996  *      ie      pointer to a generic IE structure
997  *
998  * Returns:
999  *      0       success
1000  *      errno   error encountered
1001  *
1002  */
1003 static int
1004 usf_dec_ie_hdr(struct usfmt *usf, struct ie_generic *ie)
1005 {
1006         u_char                  c;
1007         short                   s;
1008         int                     rc;
1009
1010         /*
1011          * Get the IE identifier
1012          */
1013         rc = usf_byte(usf, &ie->ie_ident);
1014         if (rc)
1015                 return(rc);
1016
1017         /*
1018          * Get the extended type
1019          */
1020         rc = usf_byte(usf, &c);
1021         if (rc)
1022                 return(rc);
1023         ie->ie_coding = (c >> UNI_IE_CODE_SHIFT) & UNI_IE_CODE_MASK;
1024         ie->ie_flag = (c >> UNI_IE_FLAG_SHIFT) & UNI_IE_FLAG_MASK;
1025         ie->ie_action = c & UNI_IE_ACT_MASK;
1026
1027         /*
1028          * Get the length.
1029          */
1030         rc = usf_short(usf, &s);
1031         if (rc)
1032                 return(rc);
1033         ie->ie_length = s;
1034
1035         return(0);
1036 }
1037
1038
1039 /*
1040  * Decode an AAL parameters information element
1041  *
1042  * Arguments:
1043  *      usf     pointer to a unisig formatting structure
1044  *      ie      pointer to an AAL parms IE structure
1045  *
1046  * Returns:
1047  *      0       success
1048  *      errno   error encountered
1049  *
1050  */
1051 static int
1052 usf_dec_ie_aalp(struct usfmt *usf, struct ie_generic *ie)
1053 {
1054         int             i, rc = 0;
1055
1056         /*
1057          * Clear the IE
1058          */
1059         KM_COPY(&ie_aalp_absent, &ie->ie_u.ie_aalp,
1060                         sizeof(ie_aalp_absent));
1061
1062         /*
1063          * Get the AAL type
1064          */
1065         rc = usf_byte(usf, &ie->ie_aalp_aal_type);
1066         if (rc)
1067                 return(rc);
1068
1069         /*
1070          * Subtract the length of the AAL type from the total.
1071          * It will be readjusted after usf_dec_ie_ident is finished.
1072          */
1073         ie->ie_length--;
1074
1075         /*
1076          * Process based on AAL type
1077          */
1078         switch (ie->ie_aalp_aal_type) {
1079         case UNI_IE_AALP_AT_AAL1:
1080                 /*
1081                  * Clear the AAL 1 subparameters
1082                  */
1083                 ie->ie_aalp_1_subtype = T_ATM_ABSENT;
1084                 ie->ie_aalp_1_cbr_rate = T_ATM_ABSENT;
1085                 ie->ie_aalp_1_multiplier = T_ATM_ABSENT;
1086                 ie->ie_aalp_1_clock_recovery = T_ATM_ABSENT;
1087                 ie->ie_aalp_1_error_correction = T_ATM_ABSENT;
1088                 ie->ie_aalp_1_struct_data_tran = T_ATM_ABSENT;
1089                 ie->ie_aalp_1_partial_cells = T_ATM_ABSENT;
1090
1091                 /*
1092                  * Parse the AAL fields based on their IDs
1093                  */
1094                 rc = usf_dec_ie_ident(usf, ie, ie_aal1_tbl);
1095                 break;
1096         case UNI_IE_AALP_AT_AAL3:
1097                 /*
1098                  * Clear the AAL 3/4 subparameters
1099                  */
1100                 ie->ie_aalp_4_fwd_max_sdu = T_ATM_ABSENT;
1101                 ie->ie_aalp_4_bkwd_max_sdu = T_ATM_ABSENT;
1102                 ie->ie_aalp_4_mid_range = T_ATM_ABSENT;
1103                 ie->ie_aalp_4_mode = T_ATM_ABSENT;
1104                 ie->ie_aalp_4_sscs_type = T_ATM_ABSENT;
1105
1106                 /*
1107                  * Parse the AAL fields based on their IDs
1108                  */
1109                 if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
1110                         rc = usf_dec_ie_ident(usf, ie, ie_aal4_tbl_30);
1111                 else
1112                         rc = usf_dec_ie_ident(usf, ie, ie_aal4_tbl_31);
1113
1114                 /*
1115                  * If either forward or backward maximum SDU
1116                  * size is specified, the other must also be
1117                  * specified.
1118                  */
1119                 if ((ie->ie_aalp_4_fwd_max_sdu != T_ATM_ABSENT &&
1120                                 ie->ie_aalp_4_bkwd_max_sdu == T_ATM_ABSENT) ||
1121                     (ie->ie_aalp_4_fwd_max_sdu == T_ATM_ABSENT &&
1122                                 ie->ie_aalp_4_bkwd_max_sdu != T_ATM_ABSENT)) {
1123                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1124                 }
1125                 break;
1126         case UNI_IE_AALP_AT_AAL5:
1127                 /*
1128                  * Clear the AAL 5 subparameters
1129                  */
1130                 ie->ie_aalp_5_fwd_max_sdu = T_ATM_ABSENT;
1131                 ie->ie_aalp_5_bkwd_max_sdu = T_ATM_ABSENT;
1132                 ie->ie_aalp_5_mode = T_ATM_ABSENT;
1133                 ie->ie_aalp_5_sscs_type = T_ATM_ABSENT;
1134
1135                 /*
1136                  * Parse the AAL fields based on their IDs
1137                  */
1138                 if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
1139                         rc = usf_dec_ie_ident(usf, ie, ie_aal5_tbl_30);
1140                 else
1141                         rc = usf_dec_ie_ident(usf, ie, ie_aal5_tbl_31);
1142
1143                 /*
1144                  * If either forward or backward maximum SDU
1145                  * size is specified, the other must also be
1146                  * specified.
1147                  */
1148                 if ((ie->ie_aalp_5_fwd_max_sdu != T_ATM_ABSENT &&
1149                                 ie->ie_aalp_5_bkwd_max_sdu == T_ATM_ABSENT) ||
1150                     (ie->ie_aalp_5_fwd_max_sdu == T_ATM_ABSENT &&
1151                                 ie->ie_aalp_5_bkwd_max_sdu != T_ATM_ABSENT)) {
1152                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1153                 }
1154                 break;
1155         case UNI_IE_AALP_AT_AALU:
1156                 /*
1157                  * Check user parameter length
1158                  */
1159                 if (ie->ie_length >
1160                                 sizeof(ie->ie_aalp_user_info) +
1161                                 1) {
1162                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1163                 }
1164
1165                 /*
1166                  * Get the user data
1167                  */
1168                 i = 0;
1169                 while (i < ie->ie_length - 2) {
1170                         rc = usf_byte(usf, &ie->ie_aalp_user_info[i]);
1171                         if (rc)
1172                                 break;
1173                         i++;
1174                 }
1175                 break;
1176         default:
1177                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1178         }
1179         ie->ie_length++;
1180
1181         return(rc);
1182 }
1183
1184
1185 /*
1186  * Decode a user cell rate information element
1187  *
1188  * Arguments:
1189  *      usf     pointer to a unisig formatting structure
1190  *      ie      pointer to a cell rate IE structure
1191  *
1192  * Returns:
1193  *      0       success
1194  *      errno   error encountered
1195  *
1196  */
1197 static int
1198 usf_dec_ie_clrt(struct usfmt *usf, struct ie_generic *ie)
1199 {
1200         int     rc;
1201
1202         /*
1203          * Clear the IE
1204          */
1205         KM_COPY(&ie_clrt_absent, &ie->ie_u.ie_clrt,
1206                         sizeof(ie_clrt_absent));
1207
1208         /*
1209          * Parse the IE using field identifiers
1210          */
1211         rc = usf_dec_ie_ident(usf, ie, ie_clrt_tbl);
1212         return(rc);
1213 }
1214
1215
1216 /*
1217  * Decode a broadband bearer capability information element
1218  *
1219  * Arguments:
1220  *      usf     pointer to a unisig formatting structure
1221  *      ie      pointer to a cell rate IE structure
1222  *
1223  * Returns:
1224  *      0       success
1225  *      errno   error encountered
1226  *
1227  */
1228 static int
1229 usf_dec_ie_bbcp(struct usfmt *usf, struct ie_generic *ie)
1230 {
1231         int     rc;
1232         u_char  c;
1233
1234         /*
1235          * Clear the IE
1236          */
1237         KM_COPY(&ie_bbcp_absent, &ie->ie_u.ie_bbcp,
1238                         sizeof(ie_bbcp_absent));
1239
1240         /*
1241          * Get the broadband bearer class
1242          */
1243         rc = usf_byte(usf, &c);
1244         if (rc)
1245                 return(rc);
1246         ie->ie_bbcp_bearer_class = c & UNI_IE_BBCP_BC_MASK;
1247
1248         /*
1249          * If the broadband bearer class was X, the next
1250          * byte has the traffic type and timing requirements
1251          */
1252         if (ie->ie_bbcp_bearer_class == UNI_IE_BBCP_BC_BCOB_X &&
1253                         !(c & UNI_IE_EXT_BIT)) {
1254                 rc = usf_byte(usf, &c);
1255                 if (rc)
1256                         return(rc);
1257                 ie->ie_bbcp_traffic_type = (c >> UNI_IE_BBCP_TT_SHIFT) &
1258                                 UNI_IE_BBCP_TT_MASK;
1259                 ie->ie_bbcp_timing_req = c & UNI_IE_BBCP_TR_MASK;
1260         }
1261
1262         /*
1263          * Get the clipping and user plane connection configuration
1264          */
1265         if (c & UNI_IE_EXT_BIT) {
1266                 rc = usf_byte(usf, &c);
1267                 if (rc)
1268                         return(rc);
1269                 ie->ie_bbcp_clipping = (c >> UNI_IE_BBCP_SC_SHIFT) &
1270                                 UNI_IE_BBCP_SC_MASK;
1271                 ie->ie_bbcp_conn_config = c & UNI_IE_BBCP_CC_MASK;
1272         }
1273
1274         return(0);
1275 }
1276
1277
1278 /*
1279  * Decode a broadband high layer information element
1280  *
1281  * Arguments:
1282  *      usf     pointer to a unisig formatting structure
1283  *      ie      pointer to a cell rate IE structure
1284  *
1285  * Returns:
1286  *      0       success
1287  *      errno   error encountered
1288  *
1289  */
1290 static int
1291 usf_dec_ie_bhli(struct usfmt *usf, struct ie_generic *ie)
1292 {
1293         int     i, rc;
1294         u_char  c;
1295
1296         /*
1297          * Clear the IE
1298          */
1299         KM_COPY(&ie_bhli_absent, &ie->ie_u.ie_bhli,
1300                         sizeof(ie_bhli_absent));
1301
1302         /*
1303          * Get the high layer information type
1304          */
1305         rc = usf_ext(usf, &i);
1306         ie->ie_bhli_type = i & UNI_IE_EXT_MASK;
1307         if (rc)
1308                 return(rc);
1309
1310         /*
1311          * What comes next depends on the type
1312          */
1313         switch (ie->ie_bhli_type) {
1314         case UNI_IE_BHLI_TYPE_ISO:
1315         case UNI_IE_BHLI_TYPE_USER:
1316                 /*
1317                  * ISO or user-specified parameters -- take the
1318                  * length of information from the IE length
1319                  */
1320                 for (i=0; i<ie->ie_length-1; i++) {
1321                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
1322                         if (rc)
1323                                 return(rc);
1324                 }
1325                 break;
1326         case UNI_IE_BHLI_TYPE_HLP:
1327                 /*
1328                  * Make sure the IE is long enough for the high
1329                  * layer profile information, then get it
1330                  */
1331                 if (usf->usf_sig->us_proto != ATM_SIG_UNI30)
1332                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1333                 if (ie->ie_length < UNI_IE_BHLI_HLP_LEN+1)
1334                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1335                 for (i=0; i<ie->ie_length &&
1336                                 i<UNI_IE_BHLI_HLP_LEN; i++) {
1337                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
1338                         if (rc)
1339                                 return(rc);
1340                 }
1341                 break;
1342         case UNI_IE_BHLI_TYPE_VSA:
1343                 /*
1344                  * Make sure the IE is long enough for the vendor-
1345                  * specific application information, then get it
1346                  */
1347                 if (ie->ie_length < UNI_IE_BHLI_VSA_LEN+1)
1348                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1349                 for (i=0; i<ie->ie_length &&
1350                                 i<UNI_IE_BHLI_VSA_LEN; i++) {
1351                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
1352                         if (rc)
1353                                 return(rc);
1354                 }
1355                 break;
1356         default:
1357                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1358                 for (i=0; i<ie->ie_length; i++) {
1359                         rc = usf_byte(usf, &c);
1360                         if (rc)
1361                                 return(rc);
1362                 }
1363         }
1364
1365         return(0);
1366 }
1367
1368
1369 /*
1370  * Decode a broadband low layer information element
1371  *
1372  * Arguments:
1373  *      usf     pointer to a unisig formatting structure
1374  *      ie      pointer to a cell rate IE structure
1375  *
1376  * Returns:
1377  *      0       success
1378  *      errno   error encountered
1379  *
1380  */
1381 static int
1382 usf_dec_ie_blli(struct usfmt *usf, struct ie_generic *ie)
1383 {
1384         u_char          c, id;
1385         int             bc, i, rc;
1386         u_int           ipi;
1387
1388         /*
1389          * Clear the IE
1390          */
1391         KM_COPY(&ie_blli_absent, &ie->ie_u.ie_blli,
1392                         sizeof(ie_blli_absent));
1393
1394         /*
1395          * Get paramteters for the protocol layers as long as
1396          * there is still information left in the IE
1397          */
1398         bc = ie->ie_length;
1399         while (bc) {
1400                 /*
1401                  * Get the type and process based on what it is
1402                  */
1403                 rc = usf_byte(usf, &id);
1404                 if (rc)
1405                         return(rc);
1406                 switch (((id & UNI_IE_EXT_MASK) >>
1407                                 UNI_IE_BLLI_LID_SHIFT) &
1408                                 UNI_IE_BLLI_LID_MASK) {
1409                 case UNI_IE_BLLI_L1_ID:
1410                         /*
1411                          * Layer 1 info
1412                          */
1413                         ie->ie_blli_l1_id = id & UNI_IE_BLLI_LP_MASK;
1414                         bc--;
1415                         break;
1416                 case UNI_IE_BLLI_L2_ID:
1417                         /*
1418                          * Layer 2 info--contents vary based on type
1419                          */
1420                         ie->ie_blli_l2_id = id & UNI_IE_BLLI_LP_MASK;
1421                         bc--;
1422                         if (id & UNI_IE_EXT_BIT)
1423                                 break;
1424                         switch (ie->ie_blli_l2_id) {
1425                         case UNI_IE_BLLI_L2P_X25L:
1426                         case UNI_IE_BLLI_L2P_X25M:
1427                         case UNI_IE_BLLI_L2P_HDLC1:
1428                         case UNI_IE_BLLI_L2P_HDLC2:
1429                         case UNI_IE_BLLI_L2P_HDLC3:
1430                         case UNI_IE_BLLI_L2P_Q922:
1431                         case UNI_IE_BLLI_L2P_ISO7776:
1432                                 rc = usf_byte(usf, &c);
1433                                 if (rc)
1434                                         return(rc);
1435                                 bc--;
1436                                 ie->ie_blli_l2_mode = (c >>
1437                                         UNI_IE_BLLI_L2MODE_SHIFT) &
1438                                         UNI_IE_BLLI_L2MODE_MASK;
1439                                 if (!(c & UNI_IE_EXT_BIT))
1440                                         break;
1441                                 rc = usf_byte(usf, &c);
1442                                 if (rc)
1443                                         return(rc);
1444                                 bc--;
1445                                 ie->ie_blli_l2_window =
1446                                                 c & UNI_IE_EXT_MASK;
1447                                 break;
1448                         case UNI_IE_BLLI_L2P_USER:
1449                                 rc = usf_byte(usf, &c);
1450                                 if (rc)
1451                                         return(rc);
1452                                 bc--;
1453                                 ie->ie_blli_l2_user_proto =
1454                                                 c & UNI_IE_EXT_MASK;
1455                                 break;
1456                         }
1457                         break;
1458                 case UNI_IE_BLLI_L3_ID:
1459                         /*
1460                          * Layer 3 info--contents vary based on type
1461                          */
1462                         ie->ie_blli_l3_id = id & UNI_IE_BLLI_LP_MASK;
1463                         bc--;
1464                         switch (ie->ie_blli_l3_id) {
1465                         case UNI_IE_BLLI_L3P_X25:
1466                         case UNI_IE_BLLI_L3P_ISO8208:
1467                         case UNI_IE_BLLI_L3P_ISO8878:
1468                                 rc = usf_byte(usf, &c);
1469                                 if (rc)
1470                                         return(rc);
1471                                 bc--;
1472                                 ie->ie_blli_l3_mode = (c >>
1473                                         UNI_IE_BLLI_L3MODE_SHIFT) &
1474                                         UNI_IE_BLLI_L3MODE_MASK;
1475                                 if (!(c & UNI_IE_EXT_BIT))
1476                                         break;
1477                                 rc = usf_byte(usf, &c);
1478                                 if (rc)
1479                                         return(rc);
1480                                 bc--;
1481                                 ie->ie_blli_l3_packet_size =
1482                                         c & UNI_IE_BLLI_L3PS_MASK;
1483                                 if (!(c & UNI_IE_EXT_BIT))
1484                                         break;
1485                                 rc = usf_byte(usf, &c);
1486                                 if (rc)
1487                                         return(rc);
1488                                 bc--;
1489                                 ie->ie_blli_l3_window =
1490                                                 c & UNI_IE_EXT_MASK;
1491                                 break;
1492                         case UNI_IE_BLLI_L3P_USER:
1493                                 rc = usf_byte(usf, &c);
1494                                 if (rc)
1495                                         return(rc);
1496                                 bc--;
1497                                 ie->ie_blli_l3_mode =
1498                                                 c & UNI_IE_EXT_MASK;
1499                                 break;
1500                         case UNI_IE_BLLI_L3P_ISO9577:
1501                                 rc = usf_ext(usf, &ipi);
1502                                 if (rc)
1503                                         return(rc);
1504                                 bc -= 2;
1505                                 ie->ie_blli_l3_ipi = ipi >>
1506                                                 UNI_IE_BLLI_L3IPI_SHIFT;
1507                                 if (ie->ie_blli_l3_ipi !=
1508                                                 UNI_IE_BLLI_L3IPI_SNAP)
1509                                         break;
1510
1511                                 rc = usf_byte(usf, &c);
1512                                 ie->ie_blli_l3_snap_id = c & UNI_IE_EXT_MASK;
1513                                 if (rc)
1514                                         return(rc);
1515                                 bc --;
1516
1517                                 rc = usf_byte(usf,
1518                                                 &ie->ie_blli_l3_oui[0]);
1519                                 if (rc)
1520                                         return(rc);
1521                                 rc = usf_byte(usf,
1522                                                 &ie->ie_blli_l3_oui[1]);
1523                                 if (rc)
1524                                         return(rc);
1525                                 rc = usf_byte(usf,
1526                                                 &ie->ie_blli_l3_oui[2]);
1527                                 if (rc)
1528                                         return(rc);
1529                                 rc = usf_byte(usf,
1530                                                 &ie->ie_blli_l3_pid[0]);
1531                                 if (rc)
1532                                         return(rc);
1533                                 rc = usf_byte(usf,
1534                                                 &ie->ie_blli_l3_pid[1]);
1535                                 if (rc)
1536                                         return(rc);
1537                                 bc -= 5;
1538                                 break;
1539                         }
1540                         break;
1541                 default:
1542                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1543                         for (i=0; i<ie->ie_length; i++) {
1544                                 rc = usf_byte(usf, &c);
1545                                 if (rc)
1546                                         return(rc);
1547                         }
1548                 }
1549         }
1550
1551         return(0);
1552 }
1553
1554
1555 /*
1556  * Decode a call state information element
1557  *
1558  * Arguments:
1559  *      usf     pointer to a unisig formatting structure
1560  *      ie      pointer to a cell rate IE structure
1561  *
1562  * Returns:
1563  *      0       success
1564  *      errno   error encountered
1565  *
1566  */
1567 static int
1568 usf_dec_ie_clst(struct usfmt *usf, struct ie_generic *ie)
1569 {
1570         int     rc;
1571         u_char  c;
1572
1573         /*
1574          * Clear the IE
1575          */
1576         KM_COPY(&ie_clst_absent, &ie->ie_u.ie_clst,
1577                         sizeof(ie_clst_absent));
1578
1579         rc = usf_byte(usf, &c);
1580         if (rc)
1581                 return(rc);
1582         ie->ie_clst_state = c & UNI_IE_CLST_STATE_MASK;
1583
1584         return(0);
1585 }
1586
1587
1588 /*
1589  * Decode a called party number information element
1590  *
1591  * Arguments:
1592  *      usf     pointer to a unisig formatting structure
1593  *      ie      pointer to a cell rate IE structure
1594  *
1595  * Returns:
1596  *      0       success
1597  *      errno   error encountered
1598  *
1599  */
1600 static int
1601 usf_dec_ie_cdad(struct usfmt *usf, struct ie_generic *ie)
1602 {
1603         int             len, rc;
1604         u_char          c;
1605
1606         /*
1607          * Clear the IE
1608          */
1609         KM_COPY(&ie_cdad_absent, &ie->ie_u.ie_cdad,
1610                         sizeof(ie_cdad_absent));
1611
1612         /*
1613          * Get and check the numbering plan
1614          */
1615         rc = usf_byte(usf, &c);
1616         if (rc)
1617                 return(rc);
1618         ie->ie_cdad_plan = c & UNI_IE_CDAD_PLAN_MASK;
1619         len = ie->ie_length - 1;
1620         switch (ie->ie_cdad_plan) {
1621         case UNI_IE_CDAD_PLAN_E164:
1622                 ie->ie_cdad_addr.address_format = T_ATM_E164_ADDR;
1623                 break;
1624         case UNI_IE_CDAD_PLAN_NSAP:
1625                 ie->ie_cdad_addr.address_format = T_ATM_ENDSYS_ADDR;
1626                 break;
1627         default:
1628                 /*
1629                  * Invalid numbering plan
1630                  */
1631                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1632                 while (len) {
1633                         rc = usf_byte(usf, &c);
1634                         if (rc)
1635                                 return(rc);
1636                         len--;
1637                 }
1638
1639                 return(0);
1640         }
1641
1642         /*
1643          * Get the ATM address
1644          */
1645         rc = usf_dec_atm_addr(usf, &ie->ie_cdad_addr, len);
1646         if (rc == EINVAL) {
1647                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1648                 rc = 0;
1649         }
1650
1651         return(rc);
1652 }
1653
1654
1655 /*
1656  * Decode a called party subaddress information element
1657  *
1658  * Arguments:
1659  *      usf     pointer to a unisig formatting structure
1660  *      ie      pointer to a cell rate IE structure
1661  *
1662  * Returns:
1663  *      0       success
1664  *      errno   error encountered
1665  *
1666  */
1667 static int
1668 usf_dec_ie_cdsa(struct usfmt *usf, struct ie_generic *ie)
1669 {
1670         int             len, rc;
1671         u_char          c;
1672
1673         /*
1674          * Clear the IE
1675          */
1676         KM_COPY(&ie_cdsa_absent, &ie->ie_u.ie_cdsa,
1677                         sizeof(ie_cdsa_absent));
1678
1679         /*
1680          * Get and check the subaddress type
1681          */
1682         rc = usf_byte(usf, &c);
1683         if (rc)
1684                 return(rc);
1685         len = ie->ie_length - 1;
1686         if (((c >> UNI_IE_CDSA_TYPE_SHIFT) & UNI_IE_CDSA_TYPE_MASK) != 
1687                         UNI_IE_CDSA_TYPE_AESA) {
1688                 /*
1689                  * Invalid subaddress type
1690                  */
1691                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1692                 while (len) {
1693                         rc = usf_byte(usf, &c);
1694                         if (rc)
1695                                 return(rc);
1696                         len--;
1697                 }
1698
1699                 return(0);
1700         }
1701
1702         /*
1703          * Get the ATM address
1704          */
1705         ie->ie_cdsa_addr.address_format = T_ATM_ENDSYS_ADDR;
1706         rc = usf_dec_atm_addr(usf, &ie->ie_cdsa_addr, len);
1707         if (rc == EINVAL) {
1708                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1709                 rc = 0;
1710         }
1711
1712         return(rc);
1713 }
1714
1715
1716 /*
1717  * Decode a calling party number information element
1718  *
1719  * Arguments:
1720  *      usf     pointer to a unisig formatting structure
1721  *      ie      pointer to a cell rate IE structure
1722  *
1723  * Returns:
1724  *      0       success
1725  *      errno   error encountered
1726  *
1727  */
1728 static int
1729 usf_dec_ie_cgad(struct usfmt *usf, struct ie_generic *ie)
1730 {
1731         int             len, rc;
1732         u_char          c;
1733
1734         /*
1735          * Clear the IE
1736          */
1737         KM_COPY(&ie_cgad_absent, &ie->ie_u.ie_cgad,
1738                         sizeof(ie_cgad_absent));
1739
1740         /*
1741          * Get and check the numbering plan
1742          */
1743         len = ie->ie_length;
1744         rc = usf_byte(usf, &c);
1745         if (rc)
1746                 return(rc);
1747         ie->ie_cgad_type = (c >> UNI_IE_CGAD_TYPE_SHIFT) &
1748                         UNI_IE_CGAD_TYPE_MASK;
1749         ie->ie_cgad_plan = c & UNI_IE_CGAD_PLAN_MASK;
1750         len--;
1751         switch (ie->ie_cgad_plan) {
1752         case UNI_IE_CGAD_PLAN_E164:
1753                 ie->ie_cgad_addr.address_format = T_ATM_E164_ADDR;
1754                 break;
1755         case UNI_IE_CGAD_PLAN_NSAP:
1756                 ie->ie_cgad_addr.address_format = T_ATM_ENDSYS_ADDR;
1757                 break;
1758         default:
1759                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1760                 while (len) {
1761                         rc = usf_byte(usf, &c);
1762                         if (rc)
1763                                 return(rc);
1764                         len--;
1765                 }
1766
1767                 return(0);
1768         }
1769
1770         /*
1771          * Get the presentation and screening indicators, if present
1772          */
1773         if (!(c & UNI_IE_EXT_BIT)) {
1774                 rc = usf_byte(usf, &c);
1775                 if (rc)
1776                         return(rc);
1777                 len--;
1778                 ie->ie_cgad_pres_ind = (c >> UNI_IE_CGAD_PRES_SHIFT) &
1779                                 UNI_IE_CGAD_PRES_MASK;
1780                 ie->ie_cgad_screen_ind = c & UNI_IE_CGAD_SCR_MASK;
1781         } else {
1782                 ie->ie_cgad_pres_ind = 0;
1783                 ie->ie_cgad_screen_ind =0;
1784         }
1785
1786         /*
1787          * Get the ATM address
1788          */
1789         rc = usf_dec_atm_addr(usf, &ie->ie_cgad_addr, len);
1790         if (rc == EINVAL) {
1791                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1792                 rc = 0;
1793         }
1794
1795         return(rc);
1796 }
1797
1798
1799 /*
1800  * Decode a calling party subaddress information element
1801  *
1802  * Arguments:
1803  *      usf     pointer to a unisig formatting structure
1804  *      ie      pointer to a cell rate IE structure
1805  *
1806  * Returns:
1807  *      0       success
1808  *      errno   error encountered
1809  *
1810  */
1811 static int
1812 usf_dec_ie_cgsa(struct usfmt *usf, struct ie_generic *ie)
1813 {
1814         int             len, rc;
1815         u_char          c;
1816
1817         /*
1818          * Clear the IE
1819          */
1820         KM_COPY(&ie_cgsa_absent, &ie->ie_u.ie_cgsa,
1821                         sizeof(ie_cgsa_absent));
1822
1823         /*
1824          * Get and check the subaddress type
1825          */
1826         rc = usf_byte(usf, &c);
1827         if (rc)
1828                 return(rc);
1829         len = ie->ie_length - 1;
1830         if (((c >> UNI_IE_CGSA_TYPE_SHIFT) & UNI_IE_CGSA_TYPE_MASK) != 
1831                         UNI_IE_CGSA_TYPE_AESA) {
1832                 /*
1833                  * Invalid subaddress type
1834                  */
1835                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1836                 while (len) {
1837                         rc = usf_byte(usf, &c);
1838                         if (rc)
1839                                 return(rc);
1840                         len--;
1841                 }
1842
1843                 return(0);
1844         }
1845
1846         /*
1847          * Get the ATM address
1848          */
1849         ie->ie_cgsa_addr.address_format = T_ATM_ENDSYS_ADDR;
1850         rc = usf_dec_atm_addr(usf, &ie->ie_cgsa_addr, len);
1851         if (rc == EINVAL) {
1852                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1853                 rc = 0;
1854         }
1855
1856         return(rc);
1857 }
1858
1859
1860 /*
1861  * Decode a cause information element
1862  *
1863  * Arguments:
1864  *      usf     pointer to a unisig formatting structure
1865  *      ie      pointer to a cell rate IE structure
1866  *
1867  * Returns:
1868  *      0       success
1869  *      errno   error encountered
1870  *
1871  */
1872 static int
1873 usf_dec_ie_caus(struct usfmt *usf, struct ie_generic *ie)
1874 {
1875         int     i, len, rc;
1876         u_char  c;
1877
1878         /*
1879          * Clear the IE
1880          */
1881         KM_COPY(&ie_caus_absent, &ie->ie_u.ie_caus,
1882                         sizeof(ie_caus_absent));
1883
1884         /*
1885          * Get the cause location
1886          */
1887         rc = usf_byte(usf, &c);
1888         if (rc)
1889                 return(rc);
1890         ie->ie_caus_loc = c & UNI_IE_CAUS_LOC_MASK;
1891
1892         /*
1893          * Get the cause value
1894          */
1895         rc = usf_byte(usf, &c);
1896         if (rc)
1897                 return(rc);
1898         ie->ie_caus_cause = c & UNI_IE_EXT_MASK;
1899
1900         /*
1901          * Get any included diagnostics
1902          */
1903         len = ie->ie_length - 2;
1904         for (i = 0, ie->ie_caus_diag_len = 0;
1905                         len && i < sizeof(ie->ie_caus_diagnostic);
1906                         len--, i++, ie->ie_caus_diag_len++) {
1907                 rc = usf_byte(usf, &ie->ie_caus_diagnostic[i]);
1908                 if (rc)
1909                         return(rc);
1910         }
1911
1912         return(0);
1913 }
1914
1915
1916 /*
1917  * Decode a conection identifier information element
1918  *
1919  * Arguments:
1920  *      usf     pointer to a unisig formatting structure
1921  *      ie      pointer to a cell rate IE structure
1922  *
1923  * Returns:
1924  *      0       success
1925  *      errno   error encountered
1926  *
1927  */
1928 static int
1929 usf_dec_ie_cnid(struct usfmt *usf, struct ie_generic *ie)
1930 {
1931         int     i, rc;
1932
1933         /*
1934          * Clear the IE
1935          */
1936         KM_COPY(&ie_cnid_absent, &ie->ie_u.ie_cnid,
1937                         sizeof(ie_cnid_absent));
1938
1939         rc = usf_ext(usf, &i);
1940         if (rc)
1941                 return(rc);
1942         ie->ie_cnid_vp_sig = (i >> UNI_IE_CNID_VPSIG_SHIFT) &
1943                         UNI_IE_CNID_VPSIG_MASK;
1944         ie->ie_cnid_pref_excl = i & UNI_IE_CNID_PREX_MASK;
1945
1946         rc = usf_short(usf, &ie->ie_cnid_vpci);
1947         if (rc)
1948                 return(rc);
1949         rc = usf_short(usf, &ie->ie_cnid_vci);
1950         return(rc);
1951 }
1952
1953
1954 /*
1955  * Decode a quality of service parameters information element
1956  *
1957  * Arguments:
1958  *      usf     pointer to a unisig formatting structure
1959  *      ie      pointer to a cell rate IE structure
1960  *
1961  * Returns:
1962  *      0       success
1963  *      errno   error encountered
1964  *
1965  */
1966 static int
1967 usf_dec_ie_qosp(struct usfmt *usf, struct ie_generic *ie)
1968 {
1969         int             rc;
1970
1971         /*
1972          * Clear the IE
1973          */
1974         KM_COPY(&ie_qosp_absent, &ie->ie_u.ie_qosp,
1975                         sizeof(ie_qosp_absent));
1976
1977         /*
1978          * Get forward QoS class
1979          */
1980         rc = usf_byte(usf, &ie->ie_qosp_fwd_class);
1981         if (rc)
1982                 return(rc);
1983
1984         /*
1985          * Get backward QoS class
1986          */
1987         rc = usf_byte(usf, &ie->ie_qosp_bkwd_class);
1988
1989         return(rc);
1990 }
1991
1992
1993 /*
1994  * Decode a broadband repeat indicator information element
1995  *
1996  * Arguments:
1997  *      usf     pointer to a unisig formatting structure
1998  *      ie      pointer to a cell rate IE structure
1999  *
2000  * Returns:
2001  *      0       success
2002  *      errno   error encountered
2003  *
2004  */
2005 static int
2006 usf_dec_ie_brpi(struct usfmt *usf, struct ie_generic *ie)
2007 {
2008         int     rc;
2009         u_char  c;
2010
2011         /*
2012          * Clear the IE
2013          */
2014         KM_COPY(&ie_brpi_absent, &ie->ie_u.ie_brpi,
2015                         sizeof(ie_brpi_absent));
2016
2017         /*
2018          * Get the repeat indicator
2019          */
2020         rc = usf_byte(usf, &c);
2021         if (rc)
2022                 return(rc);
2023
2024         ie->ie_brpi_ind = c & UNI_IE_BRPI_IND_MASK;
2025
2026         return(0);
2027 }
2028
2029
2030 /*
2031  * Decode a restart indicator information element
2032  *
2033  * Arguments:
2034  *      usf     pointer to a unisig formatting structure
2035  *      ie      pointer to a cell rate IE structure
2036  *
2037  * Returns:
2038  *      0       success
2039  *      errno   error encountered
2040  *
2041  */
2042 static int
2043 usf_dec_ie_rsti(struct usfmt *usf, struct ie_generic *ie)
2044 {
2045         int             rc;
2046         u_char          c;
2047
2048         /*
2049          * Clear the IE
2050          */
2051         KM_COPY(&ie_rsti_absent, &ie->ie_u.ie_rsti,
2052                         sizeof(ie_rsti_absent));
2053
2054         /*
2055          * Get the restart class
2056          */
2057         rc = usf_byte(usf, &c);
2058         if (rc)
2059                 return(rc);
2060
2061         ie->ie_rsti_class = c & UNI_IE_RSTI_CLASS_MASK;
2062
2063         return(0);
2064 }
2065
2066
2067 /*
2068  * Decode a broadband sending complete information element
2069  *
2070  * Arguments:
2071  *      usf     pointer to a unisig formatting structure
2072  *      ie      pointer to a broadband sending complete IE structure
2073  *
2074  * Returns:
2075  *      0       success
2076  *      errno   error encountered
2077  *
2078  */
2079 static int
2080 usf_dec_ie_bsdc(struct usfmt *usf, struct ie_generic *ie)
2081 {
2082         int     rc;
2083         u_char  c;
2084
2085         /*
2086          * Clear the IE
2087          */
2088         KM_COPY(&ie_bsdc_absent, &ie->ie_u.ie_bsdc,
2089                         sizeof(ie_bsdc_absent));
2090
2091         /*
2092          * Get the sending complete indicator
2093          */
2094         rc = usf_byte(usf, &c);
2095         if (rc)
2096                 return(rc);
2097
2098         /*
2099          * Validate the indicator
2100          */
2101         c &= UNI_IE_EXT_MASK;
2102         if (c != UNI_IE_BSDC_IND)
2103                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
2104         ie->ie_bsdc_ind = c;
2105
2106         return(0);
2107 }
2108
2109
2110 /*
2111  * Decode a transit network selection information element
2112  *
2113  * Arguments:
2114  *      usf     pointer to a unisig formatting structure
2115  *      ie      pointer to a transit network selection IE structure
2116  *
2117  * Returns:
2118  *      0       success
2119  *      errno   error encountered
2120  *
2121  */
2122 static int
2123 usf_dec_ie_trnt(struct usfmt *usf, struct ie_generic *ie)
2124 {
2125         int     i, len, rc;
2126         u_char  c;
2127
2128         /*
2129          * Clear the IE
2130          */
2131         KM_COPY(&ie_trnt_absent, &ie->ie_u.ie_trnt,
2132                         sizeof(ie_trnt_absent));
2133
2134         /*
2135          * Get the network ID type and plan
2136          */
2137         rc = usf_byte(usf, &c);
2138         if (rc)
2139                 return(rc);
2140         ie->ie_trnt_id_type = (c >> UNI_IE_TRNT_IDT_SHIFT) &
2141                         UNI_IE_TRNT_IDT_MASK;
2142         ie->ie_trnt_id_plan = c & UNI_IE_TRNT_IDP_MASK;
2143
2144         /*
2145          * Get the length of the network ID
2146          */
2147         len = ie->ie_length - 1;
2148         ie->ie_trnt_id_len = MIN(len, sizeof(ie->ie_trnt_id));
2149
2150         /*
2151          * Get the network ID
2152          */
2153         for (i=0; i<len; i++) {
2154                 if (i<sizeof(ie->ie_trnt_id))
2155                         rc = usf_byte(usf, &ie->ie_trnt_id[i]);
2156                 else
2157                         rc = usf_byte(usf, &c);
2158                 if (rc)
2159                         return(rc);
2160         }
2161
2162         return(0);
2163 }
2164
2165
2166 /*
2167  * Decode an unimplemented information element
2168  *
2169  * Arguments:
2170  *      usf     pointer to a unisig formatting structure
2171  *      ie      pointer to a cell rate IE structure
2172  *
2173  * Returns:
2174  *      0       success
2175  *      errno   error encountered
2176  *
2177  */
2178 static int
2179 usf_dec_ie_uimp(struct usfmt *usf, struct ie_generic *ie)
2180 {
2181         int     i, rc;
2182         u_char  c;
2183
2184         /*
2185          * Skip over the IE contents
2186          */
2187         for (i=0; i<ie->ie_length; i++) {
2188                 rc = usf_byte(usf, &c);
2189                 if (rc)
2190                         return(rc);
2191         }
2192
2193         return(0);
2194 }
2195
2196
2197 /*
2198  * Decode an information element using field identifiers
2199  *
2200  * The AAL parameters and ATM user cell rate IEs are formatted
2201  * with a one-byte identifier preceeding each field.  The routine
2202  * parses these IEs by using a table which relates the field
2203  * identifiers with the fields in the appropriate IE structure.
2204  * Field order in the received message is immaterial.
2205  *
2206  * Arguments:
2207  *      usf     pointer to a unisig formatting structure
2208  *      ie      pointer to a cell rate IE structure
2209  *      tbl     pointer to an IE decoding table
2210  *
2211  * Returns:
2212  *      0       success
2213  *      errno   error encountered
2214  *
2215  */
2216 static int
2217 usf_dec_ie_ident(struct usfmt *usf, struct ie_generic *ie,
2218                  struct ie_decode_tbl *tbl)
2219 {
2220         int     i, len, rc;
2221         u_char  c;
2222         u_int8_t        cv;
2223         u_int16_t       sv;
2224         u_int32_t       iv;
2225         void            *dest;
2226
2227         /*
2228          * Scan through the IE
2229          */
2230         len = ie->ie_length;
2231         while (len) {
2232                 /*
2233                  * Get the field identifier
2234                  */
2235                 rc = usf_byte(usf, &c);
2236                 if (rc)
2237                         return(rc);
2238                 len--;
2239
2240                 /*
2241                  * Look up the field in the table
2242                  */
2243                 for (i=0; (tbl[i].ident != c) && tbl[i].len; i++) {
2244                 }
2245                 if (tbl[i].ident == 0) {
2246                         /*
2247                          * Bad subfield identifier -- flag an
2248                          * error and skip over the rest of the IE
2249                          */
2250                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
2251                         while (len) {
2252                                 rc = usf_byte(usf, &c);
2253                                 if (rc)
2254                                         return(rc);
2255                         }
2256                         return(0);
2257                 }
2258
2259                 /*
2260                  * Save final destination address
2261                  */
2262                 dest = (void *)((int)ie + tbl[i].f_offs);
2263
2264                 /*
2265                  * Get the field value
2266                  */
2267                 switch (tbl[i].len) {
2268                         case 0:
2269                                 cv = 1;
2270                                 goto savec;
2271
2272                         case 1:
2273                                 rc = usf_byte(usf, &cv);
2274                                 if (rc)
2275                                         break;
2276 savec:
2277                                 /*
2278                                  * Save field value
2279                                  */
2280                                 switch (tbl[i].f_size) {
2281                                 case 1:
2282                                         *(u_int8_t *)dest = cv;
2283                                         break;
2284                                 case 2:
2285                                         *(u_int16_t *)dest = cv;
2286                                         break;
2287                                 case 4:
2288                                         *(u_int32_t *)dest = cv;
2289                                         break;
2290                                 default:
2291                                         goto badtbl;
2292                                 }
2293                                 break;
2294
2295                         case 2:
2296                                 rc = usf_short(usf, &sv);
2297                                 if (rc)
2298                                         break;
2299
2300                                 /*
2301                                  * Save field value
2302                                  */
2303                                 switch (tbl[i].f_size) {
2304                                 case 2:
2305                                         *(u_int16_t *)dest = sv;
2306                                         break;
2307                                 case 4:
2308                                         *(u_int32_t *)dest = sv;
2309                                         break;
2310                                 default:
2311                                         goto badtbl;
2312                                 }
2313                                 break;
2314
2315                         case 3:
2316                                 rc = usf_int3(usf, &iv);
2317                                 goto savei;
2318
2319                         case 4:
2320                                 rc = usf_int(usf, &iv);
2321 savei:
2322                                 /*
2323                                  * Save field value
2324                                  */
2325                                 if (rc)
2326                                         break;
2327                                 switch (tbl[i].f_size) {
2328                                 case 4:
2329                                         *(u_int32_t *)dest = iv;
2330                                         break;
2331                                 default:
2332                                         goto badtbl;
2333                                 }
2334                                 break;
2335
2336                         default:
2337 badtbl:
2338                                 log(LOG_ERR,
2339                                     "uni decode: id=%d,len=%d,off=%d,size=%d\n",
2340                                         tbl[i].ident, tbl[i].len,
2341                                         tbl[i].f_offs, tbl[i].f_size);
2342                                 rc = EFAULT;
2343                                 break;
2344                 }
2345
2346                 if (rc)
2347                         return(rc);
2348
2349                 len -= tbl[i].len;
2350
2351         }
2352
2353         return(0);
2354 }
2355
2356
2357 /*
2358  * Decode an ATM address
2359  *
2360  * Arguments:
2361  *      usf     pointer to a unisig formatting structure
2362  *      addr    pointer to an ATM address structure
2363  *      len     length of data remainig in the IE
2364  *
2365  * Returns:
2366  *      0       success
2367  *      errno   error encountered
2368  *
2369  */
2370 static int
2371 usf_dec_atm_addr(struct usfmt *usf, Atm_addr *addr, int len)
2372 {
2373         int             rc;
2374         u_char          c, *cp;
2375
2376         /*
2377          * Check the address type
2378          */
2379         addr->address_length = len;
2380         switch (addr->address_format) {
2381         case T_ATM_E164_ADDR:
2382                 if (len > sizeof(Atm_addr_e164)) {
2383                         goto flush;
2384                 }
2385                 cp = (u_char *) addr->address;
2386                 break;
2387         case T_ATM_ENDSYS_ADDR:
2388                 if (len != sizeof(Atm_addr_nsap)) {
2389                         goto flush;
2390                 }
2391                 cp = (u_char *) addr->address;
2392                 break;
2393         default:
2394                 /* Silence the compiler */
2395                 cp = NULL;
2396         }
2397
2398         /*
2399          * Get the ATM address
2400          */
2401         while (len) {
2402                 rc = usf_byte(usf, cp);
2403                 if (rc)
2404                         return(rc);
2405                 len--;
2406                 cp++;
2407         }
2408
2409         return(0);
2410
2411 flush:
2412         while (len) {
2413                 rc = usf_byte(usf, &c);
2414                 if (rc)
2415                         return(rc);
2416                 len--;
2417         }
2418
2419         return(EINVAL);
2420 }