Generally use NULL instead of explicitly casting 0 to some pointer type (part2).
[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] = NULL;
863                                 MSG_IE_ADD(msg, ie, UNI_MSG_IE_ERR);
864                                 while (ie) {
865                                         ie->ie_err_cause =
866                                                 UNI_IE_CAUS_IEEXIST;
867                                         ie = ie->ie_next;
868                                 }
869                         }
870                         break;
871                 case IE_OPT:
872                         break;
873                 }
874         }
875
876 done:
877         return(0);
878 }
879
880
881 /*
882  * Decode an information element
883  *
884  * This routine will be called repeatedly as long as there are
885  * information elements left to be decoded.  It will decode the
886  * first part of the IE, look its type up in a table, and call
887  * the appropriate routine to decode the rest.  After an IE is
888  * successfully decoded, it is linked into the UNI signalling
889  * message structure.  If an error is discovered, the IE is linked
890  * into the IE error chain and an error cause is set in the header.
891  *
892  * Arguments:
893  *      usf     pointer to a UNISIG formatting structure
894  *      msg     pointer to a UNISIG message structure
895  *      ie      pointer to a generic IE structure
896  *
897  * Returns:
898  *      0       success
899  *      errno   error encountered
900  *
901  */
902 static int
903 usf_dec_ie(struct usfmt *usf, struct unisig_msg *msg, struct ie_generic *ie)
904 {
905         int                     i, ie_index, rc;
906
907         /*
908          * Decode the IE header (identifier, instruction field,
909          * and length)
910          */
911         rc = usf_dec_ie_hdr(usf, ie);
912         if (rc)
913                 return(rc);
914         /*
915          * Ignore the IE if it is of zero length.
916          */
917         if (!ie->ie_length) {
918                 atm_free(ie);
919                 return(0);
920         }
921
922         /*
923          * Look up the information element in the table
924          */
925         for (i=0; (ie->ie_ident != ie_table[i].ident) &&
926                         (ie_table[i].decode != NULL); i++) {
927         }
928         if (ie_table[i].decode == NULL) {
929                 /*
930                  * Unrecognized IE
931                  */
932                 ie_index = UNI_MSG_IE_ERR;
933         } else {
934                 ie_index = ie_table[i].p_idx;
935         }
936
937         /*
938          * Check for unimplemented or unrecognized IEs
939          */
940         if (ie_index == UNI_MSG_IE_ERR) {
941                 ie->ie_err_cause = UNI_IE_CAUS_IEEXIST;
942
943                 /*
944                  * Skip over the invalid IE
945                  */
946                 rc = usf_dec_ie_uimp(usf, ie);
947                 if (rc)
948                         return(rc);
949                 goto done;
950         }
951
952         /*
953          * Check the length against the IE table
954          */
955         if (ie->ie_length < ie_table[i].min_len ||
956                         ie->ie_length > ie_table[i].max_len) {
957                 ie_index = UNI_MSG_IE_ERR;
958                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
959
960                 /*
961                  * Skip over the invalid IE
962                  */
963                 rc = usf_dec_ie_uimp(usf, ie);
964                 if (rc)
965                         return(rc);
966                 goto done;
967         }
968
969         /*
970          * Process the IE by calling the function indicated
971          * in the IE table
972          */
973         rc = ie_table[i].decode(usf, ie);
974         if (rc)
975                 return(rc);
976
977         /*
978          * Link the IE into the signalling message
979          */
980 done:
981         if (ie->ie_err_cause) {
982                 ie_index = UNI_MSG_IE_ERR;
983         }
984         MSG_IE_ADD(msg, ie, ie_index);
985
986         return(0);
987 }
988
989
990 /*
991  * Decode an information element header
992  *
993  * Arguments:
994  *      usf     pointer to a UNISIG formatting structure
995  *      ie      pointer to a generic IE structure
996  *
997  * Returns:
998  *      0       success
999  *      errno   error encountered
1000  *
1001  */
1002 static int
1003 usf_dec_ie_hdr(struct usfmt *usf, struct ie_generic *ie)
1004 {
1005         u_char                  c;
1006         short                   s;
1007         int                     rc;
1008
1009         /*
1010          * Get the IE identifier
1011          */
1012         rc = usf_byte(usf, &ie->ie_ident);
1013         if (rc)
1014                 return(rc);
1015
1016         /*
1017          * Get the extended type
1018          */
1019         rc = usf_byte(usf, &c);
1020         if (rc)
1021                 return(rc);
1022         ie->ie_coding = (c >> UNI_IE_CODE_SHIFT) & UNI_IE_CODE_MASK;
1023         ie->ie_flag = (c >> UNI_IE_FLAG_SHIFT) & UNI_IE_FLAG_MASK;
1024         ie->ie_action = c & UNI_IE_ACT_MASK;
1025
1026         /*
1027          * Get the length.
1028          */
1029         rc = usf_short(usf, &s);
1030         if (rc)
1031                 return(rc);
1032         ie->ie_length = s;
1033
1034         return(0);
1035 }
1036
1037
1038 /*
1039  * Decode an AAL parameters information element
1040  *
1041  * Arguments:
1042  *      usf     pointer to a unisig formatting structure
1043  *      ie      pointer to an AAL parms IE structure
1044  *
1045  * Returns:
1046  *      0       success
1047  *      errno   error encountered
1048  *
1049  */
1050 static int
1051 usf_dec_ie_aalp(struct usfmt *usf, struct ie_generic *ie)
1052 {
1053         int             i, rc = 0;
1054
1055         /*
1056          * Clear the IE
1057          */
1058         KM_COPY(&ie_aalp_absent, &ie->ie_u.ie_aalp,
1059                         sizeof(ie_aalp_absent));
1060
1061         /*
1062          * Get the AAL type
1063          */
1064         rc = usf_byte(usf, &ie->ie_aalp_aal_type);
1065         if (rc)
1066                 return(rc);
1067
1068         /*
1069          * Subtract the length of the AAL type from the total.
1070          * It will be readjusted after usf_dec_ie_ident is finished.
1071          */
1072         ie->ie_length--;
1073
1074         /*
1075          * Process based on AAL type
1076          */
1077         switch (ie->ie_aalp_aal_type) {
1078         case UNI_IE_AALP_AT_AAL1:
1079                 /*
1080                  * Clear the AAL 1 subparameters
1081                  */
1082                 ie->ie_aalp_1_subtype = T_ATM_ABSENT;
1083                 ie->ie_aalp_1_cbr_rate = T_ATM_ABSENT;
1084                 ie->ie_aalp_1_multiplier = T_ATM_ABSENT;
1085                 ie->ie_aalp_1_clock_recovery = T_ATM_ABSENT;
1086                 ie->ie_aalp_1_error_correction = T_ATM_ABSENT;
1087                 ie->ie_aalp_1_struct_data_tran = T_ATM_ABSENT;
1088                 ie->ie_aalp_1_partial_cells = T_ATM_ABSENT;
1089
1090                 /*
1091                  * Parse the AAL fields based on their IDs
1092                  */
1093                 rc = usf_dec_ie_ident(usf, ie, ie_aal1_tbl);
1094                 break;
1095         case UNI_IE_AALP_AT_AAL3:
1096                 /*
1097                  * Clear the AAL 3/4 subparameters
1098                  */
1099                 ie->ie_aalp_4_fwd_max_sdu = T_ATM_ABSENT;
1100                 ie->ie_aalp_4_bkwd_max_sdu = T_ATM_ABSENT;
1101                 ie->ie_aalp_4_mid_range = T_ATM_ABSENT;
1102                 ie->ie_aalp_4_mode = T_ATM_ABSENT;
1103                 ie->ie_aalp_4_sscs_type = T_ATM_ABSENT;
1104
1105                 /*
1106                  * Parse the AAL fields based on their IDs
1107                  */
1108                 if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
1109                         rc = usf_dec_ie_ident(usf, ie, ie_aal4_tbl_30);
1110                 else
1111                         rc = usf_dec_ie_ident(usf, ie, ie_aal4_tbl_31);
1112
1113                 /*
1114                  * If either forward or backward maximum SDU
1115                  * size is specified, the other must also be
1116                  * specified.
1117                  */
1118                 if ((ie->ie_aalp_4_fwd_max_sdu != T_ATM_ABSENT &&
1119                                 ie->ie_aalp_4_bkwd_max_sdu == T_ATM_ABSENT) ||
1120                     (ie->ie_aalp_4_fwd_max_sdu == T_ATM_ABSENT &&
1121                                 ie->ie_aalp_4_bkwd_max_sdu != T_ATM_ABSENT)) {
1122                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1123                 }
1124                 break;
1125         case UNI_IE_AALP_AT_AAL5:
1126                 /*
1127                  * Clear the AAL 5 subparameters
1128                  */
1129                 ie->ie_aalp_5_fwd_max_sdu = T_ATM_ABSENT;
1130                 ie->ie_aalp_5_bkwd_max_sdu = T_ATM_ABSENT;
1131                 ie->ie_aalp_5_mode = T_ATM_ABSENT;
1132                 ie->ie_aalp_5_sscs_type = T_ATM_ABSENT;
1133
1134                 /*
1135                  * Parse the AAL fields based on their IDs
1136                  */
1137                 if (usf->usf_sig->us_proto == ATM_SIG_UNI30)
1138                         rc = usf_dec_ie_ident(usf, ie, ie_aal5_tbl_30);
1139                 else
1140                         rc = usf_dec_ie_ident(usf, ie, ie_aal5_tbl_31);
1141
1142                 /*
1143                  * If either forward or backward maximum SDU
1144                  * size is specified, the other must also be
1145                  * specified.
1146                  */
1147                 if ((ie->ie_aalp_5_fwd_max_sdu != T_ATM_ABSENT &&
1148                                 ie->ie_aalp_5_bkwd_max_sdu == T_ATM_ABSENT) ||
1149                     (ie->ie_aalp_5_fwd_max_sdu == T_ATM_ABSENT &&
1150                                 ie->ie_aalp_5_bkwd_max_sdu != T_ATM_ABSENT)) {
1151                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1152                 }
1153                 break;
1154         case UNI_IE_AALP_AT_AALU:
1155                 /*
1156                  * Check user parameter length
1157                  */
1158                 if (ie->ie_length >
1159                                 sizeof(ie->ie_aalp_user_info) +
1160                                 1) {
1161                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1162                 }
1163
1164                 /*
1165                  * Get the user data
1166                  */
1167                 i = 0;
1168                 while (i < ie->ie_length - 2) {
1169                         rc = usf_byte(usf, &ie->ie_aalp_user_info[i]);
1170                         if (rc)
1171                                 break;
1172                         i++;
1173                 }
1174                 break;
1175         default:
1176                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1177         }
1178         ie->ie_length++;
1179
1180         return(rc);
1181 }
1182
1183
1184 /*
1185  * Decode a user cell rate information element
1186  *
1187  * Arguments:
1188  *      usf     pointer to a unisig formatting structure
1189  *      ie      pointer to a cell rate IE structure
1190  *
1191  * Returns:
1192  *      0       success
1193  *      errno   error encountered
1194  *
1195  */
1196 static int
1197 usf_dec_ie_clrt(struct usfmt *usf, struct ie_generic *ie)
1198 {
1199         int     rc;
1200
1201         /*
1202          * Clear the IE
1203          */
1204         KM_COPY(&ie_clrt_absent, &ie->ie_u.ie_clrt,
1205                         sizeof(ie_clrt_absent));
1206
1207         /*
1208          * Parse the IE using field identifiers
1209          */
1210         rc = usf_dec_ie_ident(usf, ie, ie_clrt_tbl);
1211         return(rc);
1212 }
1213
1214
1215 /*
1216  * Decode a broadband bearer capability information element
1217  *
1218  * Arguments:
1219  *      usf     pointer to a unisig formatting structure
1220  *      ie      pointer to a cell rate IE structure
1221  *
1222  * Returns:
1223  *      0       success
1224  *      errno   error encountered
1225  *
1226  */
1227 static int
1228 usf_dec_ie_bbcp(struct usfmt *usf, struct ie_generic *ie)
1229 {
1230         int     rc;
1231         u_char  c;
1232
1233         /*
1234          * Clear the IE
1235          */
1236         KM_COPY(&ie_bbcp_absent, &ie->ie_u.ie_bbcp,
1237                         sizeof(ie_bbcp_absent));
1238
1239         /*
1240          * Get the broadband bearer class
1241          */
1242         rc = usf_byte(usf, &c);
1243         if (rc)
1244                 return(rc);
1245         ie->ie_bbcp_bearer_class = c & UNI_IE_BBCP_BC_MASK;
1246
1247         /*
1248          * If the broadband bearer class was X, the next
1249          * byte has the traffic type and timing requirements
1250          */
1251         if (ie->ie_bbcp_bearer_class == UNI_IE_BBCP_BC_BCOB_X &&
1252                         !(c & UNI_IE_EXT_BIT)) {
1253                 rc = usf_byte(usf, &c);
1254                 if (rc)
1255                         return(rc);
1256                 ie->ie_bbcp_traffic_type = (c >> UNI_IE_BBCP_TT_SHIFT) &
1257                                 UNI_IE_BBCP_TT_MASK;
1258                 ie->ie_bbcp_timing_req = c & UNI_IE_BBCP_TR_MASK;
1259         }
1260
1261         /*
1262          * Get the clipping and user plane connection configuration
1263          */
1264         if (c & UNI_IE_EXT_BIT) {
1265                 rc = usf_byte(usf, &c);
1266                 if (rc)
1267                         return(rc);
1268                 ie->ie_bbcp_clipping = (c >> UNI_IE_BBCP_SC_SHIFT) &
1269                                 UNI_IE_BBCP_SC_MASK;
1270                 ie->ie_bbcp_conn_config = c & UNI_IE_BBCP_CC_MASK;
1271         }
1272
1273         return(0);
1274 }
1275
1276
1277 /*
1278  * Decode a broadband high layer information element
1279  *
1280  * Arguments:
1281  *      usf     pointer to a unisig formatting structure
1282  *      ie      pointer to a cell rate IE structure
1283  *
1284  * Returns:
1285  *      0       success
1286  *      errno   error encountered
1287  *
1288  */
1289 static int
1290 usf_dec_ie_bhli(struct usfmt *usf, struct ie_generic *ie)
1291 {
1292         int     i, rc;
1293         u_char  c;
1294
1295         /*
1296          * Clear the IE
1297          */
1298         KM_COPY(&ie_bhli_absent, &ie->ie_u.ie_bhli,
1299                         sizeof(ie_bhli_absent));
1300
1301         /*
1302          * Get the high layer information type
1303          */
1304         rc = usf_ext(usf, &i);
1305         ie->ie_bhli_type = i & UNI_IE_EXT_MASK;
1306         if (rc)
1307                 return(rc);
1308
1309         /*
1310          * What comes next depends on the type
1311          */
1312         switch (ie->ie_bhli_type) {
1313         case UNI_IE_BHLI_TYPE_ISO:
1314         case UNI_IE_BHLI_TYPE_USER:
1315                 /*
1316                  * ISO or user-specified parameters -- take the
1317                  * length of information from the IE length
1318                  */
1319                 for (i=0; i<ie->ie_length-1; i++) {
1320                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
1321                         if (rc)
1322                                 return(rc);
1323                 }
1324                 break;
1325         case UNI_IE_BHLI_TYPE_HLP:
1326                 /*
1327                  * Make sure the IE is long enough for the high
1328                  * layer profile information, then get it
1329                  */
1330                 if (usf->usf_sig->us_proto != ATM_SIG_UNI30)
1331                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1332                 if (ie->ie_length < UNI_IE_BHLI_HLP_LEN+1)
1333                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1334                 for (i=0; i<ie->ie_length &&
1335                                 i<UNI_IE_BHLI_HLP_LEN; i++) {
1336                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
1337                         if (rc)
1338                                 return(rc);
1339                 }
1340                 break;
1341         case UNI_IE_BHLI_TYPE_VSA:
1342                 /*
1343                  * Make sure the IE is long enough for the vendor-
1344                  * specific application information, then get it
1345                  */
1346                 if (ie->ie_length < UNI_IE_BHLI_VSA_LEN+1)
1347                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1348                 for (i=0; i<ie->ie_length &&
1349                                 i<UNI_IE_BHLI_VSA_LEN; i++) {
1350                         rc = usf_byte(usf, &ie->ie_bhli_info[i]);
1351                         if (rc)
1352                                 return(rc);
1353                 }
1354                 break;
1355         default:
1356                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1357                 for (i=0; i<ie->ie_length; i++) {
1358                         rc = usf_byte(usf, &c);
1359                         if (rc)
1360                                 return(rc);
1361                 }
1362         }
1363
1364         return(0);
1365 }
1366
1367
1368 /*
1369  * Decode a broadband low layer information element
1370  *
1371  * Arguments:
1372  *      usf     pointer to a unisig formatting structure
1373  *      ie      pointer to a cell rate IE structure
1374  *
1375  * Returns:
1376  *      0       success
1377  *      errno   error encountered
1378  *
1379  */
1380 static int
1381 usf_dec_ie_blli(struct usfmt *usf, struct ie_generic *ie)
1382 {
1383         u_char          c, id;
1384         int             bc, i, rc;
1385         u_int           ipi;
1386
1387         /*
1388          * Clear the IE
1389          */
1390         KM_COPY(&ie_blli_absent, &ie->ie_u.ie_blli,
1391                         sizeof(ie_blli_absent));
1392
1393         /*
1394          * Get paramteters for the protocol layers as long as
1395          * there is still information left in the IE
1396          */
1397         bc = ie->ie_length;
1398         while (bc) {
1399                 /*
1400                  * Get the type and process based on what it is
1401                  */
1402                 rc = usf_byte(usf, &id);
1403                 if (rc)
1404                         return(rc);
1405                 switch (((id & UNI_IE_EXT_MASK) >>
1406                                 UNI_IE_BLLI_LID_SHIFT) &
1407                                 UNI_IE_BLLI_LID_MASK) {
1408                 case UNI_IE_BLLI_L1_ID:
1409                         /*
1410                          * Layer 1 info
1411                          */
1412                         ie->ie_blli_l1_id = id & UNI_IE_BLLI_LP_MASK;
1413                         bc--;
1414                         break;
1415                 case UNI_IE_BLLI_L2_ID:
1416                         /*
1417                          * Layer 2 info--contents vary based on type
1418                          */
1419                         ie->ie_blli_l2_id = id & UNI_IE_BLLI_LP_MASK;
1420                         bc--;
1421                         if (id & UNI_IE_EXT_BIT)
1422                                 break;
1423                         switch (ie->ie_blli_l2_id) {
1424                         case UNI_IE_BLLI_L2P_X25L:
1425                         case UNI_IE_BLLI_L2P_X25M:
1426                         case UNI_IE_BLLI_L2P_HDLC1:
1427                         case UNI_IE_BLLI_L2P_HDLC2:
1428                         case UNI_IE_BLLI_L2P_HDLC3:
1429                         case UNI_IE_BLLI_L2P_Q922:
1430                         case UNI_IE_BLLI_L2P_ISO7776:
1431                                 rc = usf_byte(usf, &c);
1432                                 if (rc)
1433                                         return(rc);
1434                                 bc--;
1435                                 ie->ie_blli_l2_mode = (c >>
1436                                         UNI_IE_BLLI_L2MODE_SHIFT) &
1437                                         UNI_IE_BLLI_L2MODE_MASK;
1438                                 if (!(c & UNI_IE_EXT_BIT))
1439                                         break;
1440                                 rc = usf_byte(usf, &c);
1441                                 if (rc)
1442                                         return(rc);
1443                                 bc--;
1444                                 ie->ie_blli_l2_window =
1445                                                 c & UNI_IE_EXT_MASK;
1446                                 break;
1447                         case UNI_IE_BLLI_L2P_USER:
1448                                 rc = usf_byte(usf, &c);
1449                                 if (rc)
1450                                         return(rc);
1451                                 bc--;
1452                                 ie->ie_blli_l2_user_proto =
1453                                                 c & UNI_IE_EXT_MASK;
1454                                 break;
1455                         }
1456                         break;
1457                 case UNI_IE_BLLI_L3_ID:
1458                         /*
1459                          * Layer 3 info--contents vary based on type
1460                          */
1461                         ie->ie_blli_l3_id = id & UNI_IE_BLLI_LP_MASK;
1462                         bc--;
1463                         switch (ie->ie_blli_l3_id) {
1464                         case UNI_IE_BLLI_L3P_X25:
1465                         case UNI_IE_BLLI_L3P_ISO8208:
1466                         case UNI_IE_BLLI_L3P_ISO8878:
1467                                 rc = usf_byte(usf, &c);
1468                                 if (rc)
1469                                         return(rc);
1470                                 bc--;
1471                                 ie->ie_blli_l3_mode = (c >>
1472                                         UNI_IE_BLLI_L3MODE_SHIFT) &
1473                                         UNI_IE_BLLI_L3MODE_MASK;
1474                                 if (!(c & UNI_IE_EXT_BIT))
1475                                         break;
1476                                 rc = usf_byte(usf, &c);
1477                                 if (rc)
1478                                         return(rc);
1479                                 bc--;
1480                                 ie->ie_blli_l3_packet_size =
1481                                         c & UNI_IE_BLLI_L3PS_MASK;
1482                                 if (!(c & UNI_IE_EXT_BIT))
1483                                         break;
1484                                 rc = usf_byte(usf, &c);
1485                                 if (rc)
1486                                         return(rc);
1487                                 bc--;
1488                                 ie->ie_blli_l3_window =
1489                                                 c & UNI_IE_EXT_MASK;
1490                                 break;
1491                         case UNI_IE_BLLI_L3P_USER:
1492                                 rc = usf_byte(usf, &c);
1493                                 if (rc)
1494                                         return(rc);
1495                                 bc--;
1496                                 ie->ie_blli_l3_mode =
1497                                                 c & UNI_IE_EXT_MASK;
1498                                 break;
1499                         case UNI_IE_BLLI_L3P_ISO9577:
1500                                 rc = usf_ext(usf, &ipi);
1501                                 if (rc)
1502                                         return(rc);
1503                                 bc -= 2;
1504                                 ie->ie_blli_l3_ipi = ipi >>
1505                                                 UNI_IE_BLLI_L3IPI_SHIFT;
1506                                 if (ie->ie_blli_l3_ipi !=
1507                                                 UNI_IE_BLLI_L3IPI_SNAP)
1508                                         break;
1509
1510                                 rc = usf_byte(usf, &c);
1511                                 ie->ie_blli_l3_snap_id = c & UNI_IE_EXT_MASK;
1512                                 if (rc)
1513                                         return(rc);
1514                                 bc --;
1515
1516                                 rc = usf_byte(usf,
1517                                                 &ie->ie_blli_l3_oui[0]);
1518                                 if (rc)
1519                                         return(rc);
1520                                 rc = usf_byte(usf,
1521                                                 &ie->ie_blli_l3_oui[1]);
1522                                 if (rc)
1523                                         return(rc);
1524                                 rc = usf_byte(usf,
1525                                                 &ie->ie_blli_l3_oui[2]);
1526                                 if (rc)
1527                                         return(rc);
1528                                 rc = usf_byte(usf,
1529                                                 &ie->ie_blli_l3_pid[0]);
1530                                 if (rc)
1531                                         return(rc);
1532                                 rc = usf_byte(usf,
1533                                                 &ie->ie_blli_l3_pid[1]);
1534                                 if (rc)
1535                                         return(rc);
1536                                 bc -= 5;
1537                                 break;
1538                         }
1539                         break;
1540                 default:
1541                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1542                         for (i=0; i<ie->ie_length; i++) {
1543                                 rc = usf_byte(usf, &c);
1544                                 if (rc)
1545                                         return(rc);
1546                         }
1547                 }
1548         }
1549
1550         return(0);
1551 }
1552
1553
1554 /*
1555  * Decode a call state information element
1556  *
1557  * Arguments:
1558  *      usf     pointer to a unisig formatting structure
1559  *      ie      pointer to a cell rate IE structure
1560  *
1561  * Returns:
1562  *      0       success
1563  *      errno   error encountered
1564  *
1565  */
1566 static int
1567 usf_dec_ie_clst(struct usfmt *usf, struct ie_generic *ie)
1568 {
1569         int     rc;
1570         u_char  c;
1571
1572         /*
1573          * Clear the IE
1574          */
1575         KM_COPY(&ie_clst_absent, &ie->ie_u.ie_clst,
1576                         sizeof(ie_clst_absent));
1577
1578         rc = usf_byte(usf, &c);
1579         if (rc)
1580                 return(rc);
1581         ie->ie_clst_state = c & UNI_IE_CLST_STATE_MASK;
1582
1583         return(0);
1584 }
1585
1586
1587 /*
1588  * Decode a called party number information element
1589  *
1590  * Arguments:
1591  *      usf     pointer to a unisig formatting structure
1592  *      ie      pointer to a cell rate IE structure
1593  *
1594  * Returns:
1595  *      0       success
1596  *      errno   error encountered
1597  *
1598  */
1599 static int
1600 usf_dec_ie_cdad(struct usfmt *usf, struct ie_generic *ie)
1601 {
1602         int             len, rc;
1603         u_char          c;
1604
1605         /*
1606          * Clear the IE
1607          */
1608         KM_COPY(&ie_cdad_absent, &ie->ie_u.ie_cdad,
1609                         sizeof(ie_cdad_absent));
1610
1611         /*
1612          * Get and check the numbering plan
1613          */
1614         rc = usf_byte(usf, &c);
1615         if (rc)
1616                 return(rc);
1617         ie->ie_cdad_plan = c & UNI_IE_CDAD_PLAN_MASK;
1618         len = ie->ie_length - 1;
1619         switch (ie->ie_cdad_plan) {
1620         case UNI_IE_CDAD_PLAN_E164:
1621                 ie->ie_cdad_addr.address_format = T_ATM_E164_ADDR;
1622                 break;
1623         case UNI_IE_CDAD_PLAN_NSAP:
1624                 ie->ie_cdad_addr.address_format = T_ATM_ENDSYS_ADDR;
1625                 break;
1626         default:
1627                 /*
1628                  * Invalid numbering plan
1629                  */
1630                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1631                 while (len) {
1632                         rc = usf_byte(usf, &c);
1633                         if (rc)
1634                                 return(rc);
1635                         len--;
1636                 }
1637
1638                 return(0);
1639         }
1640
1641         /*
1642          * Get the ATM address
1643          */
1644         rc = usf_dec_atm_addr(usf, &ie->ie_cdad_addr, len);
1645         if (rc == EINVAL) {
1646                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1647                 rc = 0;
1648         }
1649
1650         return(rc);
1651 }
1652
1653
1654 /*
1655  * Decode a called party subaddress information element
1656  *
1657  * Arguments:
1658  *      usf     pointer to a unisig formatting structure
1659  *      ie      pointer to a cell rate IE structure
1660  *
1661  * Returns:
1662  *      0       success
1663  *      errno   error encountered
1664  *
1665  */
1666 static int
1667 usf_dec_ie_cdsa(struct usfmt *usf, struct ie_generic *ie)
1668 {
1669         int             len, rc;
1670         u_char          c;
1671
1672         /*
1673          * Clear the IE
1674          */
1675         KM_COPY(&ie_cdsa_absent, &ie->ie_u.ie_cdsa,
1676                         sizeof(ie_cdsa_absent));
1677
1678         /*
1679          * Get and check the subaddress type
1680          */
1681         rc = usf_byte(usf, &c);
1682         if (rc)
1683                 return(rc);
1684         len = ie->ie_length - 1;
1685         if (((c >> UNI_IE_CDSA_TYPE_SHIFT) & UNI_IE_CDSA_TYPE_MASK) != 
1686                         UNI_IE_CDSA_TYPE_AESA) {
1687                 /*
1688                  * Invalid subaddress type
1689                  */
1690                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1691                 while (len) {
1692                         rc = usf_byte(usf, &c);
1693                         if (rc)
1694                                 return(rc);
1695                         len--;
1696                 }
1697
1698                 return(0);
1699         }
1700
1701         /*
1702          * Get the ATM address
1703          */
1704         ie->ie_cdsa_addr.address_format = T_ATM_ENDSYS_ADDR;
1705         rc = usf_dec_atm_addr(usf, &ie->ie_cdsa_addr, len);
1706         if (rc == EINVAL) {
1707                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1708                 rc = 0;
1709         }
1710
1711         return(rc);
1712 }
1713
1714
1715 /*
1716  * Decode a calling party number information element
1717  *
1718  * Arguments:
1719  *      usf     pointer to a unisig formatting structure
1720  *      ie      pointer to a cell rate IE structure
1721  *
1722  * Returns:
1723  *      0       success
1724  *      errno   error encountered
1725  *
1726  */
1727 static int
1728 usf_dec_ie_cgad(struct usfmt *usf, struct ie_generic *ie)
1729 {
1730         int             len, rc;
1731         u_char          c;
1732
1733         /*
1734          * Clear the IE
1735          */
1736         KM_COPY(&ie_cgad_absent, &ie->ie_u.ie_cgad,
1737                         sizeof(ie_cgad_absent));
1738
1739         /*
1740          * Get and check the numbering plan
1741          */
1742         len = ie->ie_length;
1743         rc = usf_byte(usf, &c);
1744         if (rc)
1745                 return(rc);
1746         ie->ie_cgad_type = (c >> UNI_IE_CGAD_TYPE_SHIFT) &
1747                         UNI_IE_CGAD_TYPE_MASK;
1748         ie->ie_cgad_plan = c & UNI_IE_CGAD_PLAN_MASK;
1749         len--;
1750         switch (ie->ie_cgad_plan) {
1751         case UNI_IE_CGAD_PLAN_E164:
1752                 ie->ie_cgad_addr.address_format = T_ATM_E164_ADDR;
1753                 break;
1754         case UNI_IE_CGAD_PLAN_NSAP:
1755                 ie->ie_cgad_addr.address_format = T_ATM_ENDSYS_ADDR;
1756                 break;
1757         default:
1758                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1759                 while (len) {
1760                         rc = usf_byte(usf, &c);
1761                         if (rc)
1762                                 return(rc);
1763                         len--;
1764                 }
1765
1766                 return(0);
1767         }
1768
1769         /*
1770          * Get the presentation and screening indicators, if present
1771          */
1772         if (!(c & UNI_IE_EXT_BIT)) {
1773                 rc = usf_byte(usf, &c);
1774                 if (rc)
1775                         return(rc);
1776                 len--;
1777                 ie->ie_cgad_pres_ind = (c >> UNI_IE_CGAD_PRES_SHIFT) &
1778                                 UNI_IE_CGAD_PRES_MASK;
1779                 ie->ie_cgad_screen_ind = c & UNI_IE_CGAD_SCR_MASK;
1780         } else {
1781                 ie->ie_cgad_pres_ind = 0;
1782                 ie->ie_cgad_screen_ind =0;
1783         }
1784
1785         /*
1786          * Get the ATM address
1787          */
1788         rc = usf_dec_atm_addr(usf, &ie->ie_cgad_addr, len);
1789         if (rc == EINVAL) {
1790                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1791                 rc = 0;
1792         }
1793
1794         return(rc);
1795 }
1796
1797
1798 /*
1799  * Decode a calling party subaddress information element
1800  *
1801  * Arguments:
1802  *      usf     pointer to a unisig formatting structure
1803  *      ie      pointer to a cell rate IE structure
1804  *
1805  * Returns:
1806  *      0       success
1807  *      errno   error encountered
1808  *
1809  */
1810 static int
1811 usf_dec_ie_cgsa(struct usfmt *usf, struct ie_generic *ie)
1812 {
1813         int             len, rc;
1814         u_char          c;
1815
1816         /*
1817          * Clear the IE
1818          */
1819         KM_COPY(&ie_cgsa_absent, &ie->ie_u.ie_cgsa,
1820                         sizeof(ie_cgsa_absent));
1821
1822         /*
1823          * Get and check the subaddress type
1824          */
1825         rc = usf_byte(usf, &c);
1826         if (rc)
1827                 return(rc);
1828         len = ie->ie_length - 1;
1829         if (((c >> UNI_IE_CGSA_TYPE_SHIFT) & UNI_IE_CGSA_TYPE_MASK) != 
1830                         UNI_IE_CGSA_TYPE_AESA) {
1831                 /*
1832                  * Invalid subaddress type
1833                  */
1834                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1835                 while (len) {
1836                         rc = usf_byte(usf, &c);
1837                         if (rc)
1838                                 return(rc);
1839                         len--;
1840                 }
1841
1842                 return(0);
1843         }
1844
1845         /*
1846          * Get the ATM address
1847          */
1848         ie->ie_cgsa_addr.address_format = T_ATM_ENDSYS_ADDR;
1849         rc = usf_dec_atm_addr(usf, &ie->ie_cgsa_addr, len);
1850         if (rc == EINVAL) {
1851                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
1852                 rc = 0;
1853         }
1854
1855         return(rc);
1856 }
1857
1858
1859 /*
1860  * Decode a cause information element
1861  *
1862  * Arguments:
1863  *      usf     pointer to a unisig formatting structure
1864  *      ie      pointer to a cell rate IE structure
1865  *
1866  * Returns:
1867  *      0       success
1868  *      errno   error encountered
1869  *
1870  */
1871 static int
1872 usf_dec_ie_caus(struct usfmt *usf, struct ie_generic *ie)
1873 {
1874         int     i, len, rc;
1875         u_char  c;
1876
1877         /*
1878          * Clear the IE
1879          */
1880         KM_COPY(&ie_caus_absent, &ie->ie_u.ie_caus,
1881                         sizeof(ie_caus_absent));
1882
1883         /*
1884          * Get the cause location
1885          */
1886         rc = usf_byte(usf, &c);
1887         if (rc)
1888                 return(rc);
1889         ie->ie_caus_loc = c & UNI_IE_CAUS_LOC_MASK;
1890
1891         /*
1892          * Get the cause value
1893          */
1894         rc = usf_byte(usf, &c);
1895         if (rc)
1896                 return(rc);
1897         ie->ie_caus_cause = c & UNI_IE_EXT_MASK;
1898
1899         /*
1900          * Get any included diagnostics
1901          */
1902         len = ie->ie_length - 2;
1903         for (i = 0, ie->ie_caus_diag_len = 0;
1904                         len && i < sizeof(ie->ie_caus_diagnostic);
1905                         len--, i++, ie->ie_caus_diag_len++) {
1906                 rc = usf_byte(usf, &ie->ie_caus_diagnostic[i]);
1907                 if (rc)
1908                         return(rc);
1909         }
1910
1911         return(0);
1912 }
1913
1914
1915 /*
1916  * Decode a conection identifier information element
1917  *
1918  * Arguments:
1919  *      usf     pointer to a unisig formatting structure
1920  *      ie      pointer to a cell rate IE structure
1921  *
1922  * Returns:
1923  *      0       success
1924  *      errno   error encountered
1925  *
1926  */
1927 static int
1928 usf_dec_ie_cnid(struct usfmt *usf, struct ie_generic *ie)
1929 {
1930         int     i, rc;
1931
1932         /*
1933          * Clear the IE
1934          */
1935         KM_COPY(&ie_cnid_absent, &ie->ie_u.ie_cnid,
1936                         sizeof(ie_cnid_absent));
1937
1938         rc = usf_ext(usf, &i);
1939         if (rc)
1940                 return(rc);
1941         ie->ie_cnid_vp_sig = (i >> UNI_IE_CNID_VPSIG_SHIFT) &
1942                         UNI_IE_CNID_VPSIG_MASK;
1943         ie->ie_cnid_pref_excl = i & UNI_IE_CNID_PREX_MASK;
1944
1945         rc = usf_short(usf, &ie->ie_cnid_vpci);
1946         if (rc)
1947                 return(rc);
1948         rc = usf_short(usf, &ie->ie_cnid_vci);
1949         return(rc);
1950 }
1951
1952
1953 /*
1954  * Decode a quality of service parameters information element
1955  *
1956  * Arguments:
1957  *      usf     pointer to a unisig formatting structure
1958  *      ie      pointer to a cell rate IE structure
1959  *
1960  * Returns:
1961  *      0       success
1962  *      errno   error encountered
1963  *
1964  */
1965 static int
1966 usf_dec_ie_qosp(struct usfmt *usf, struct ie_generic *ie)
1967 {
1968         int             rc;
1969
1970         /*
1971          * Clear the IE
1972          */
1973         KM_COPY(&ie_qosp_absent, &ie->ie_u.ie_qosp,
1974                         sizeof(ie_qosp_absent));
1975
1976         /*
1977          * Get forward QoS class
1978          */
1979         rc = usf_byte(usf, &ie->ie_qosp_fwd_class);
1980         if (rc)
1981                 return(rc);
1982
1983         /*
1984          * Get backward QoS class
1985          */
1986         rc = usf_byte(usf, &ie->ie_qosp_bkwd_class);
1987
1988         return(rc);
1989 }
1990
1991
1992 /*
1993  * Decode a broadband repeat indicator information element
1994  *
1995  * Arguments:
1996  *      usf     pointer to a unisig formatting structure
1997  *      ie      pointer to a cell rate IE structure
1998  *
1999  * Returns:
2000  *      0       success
2001  *      errno   error encountered
2002  *
2003  */
2004 static int
2005 usf_dec_ie_brpi(struct usfmt *usf, struct ie_generic *ie)
2006 {
2007         int     rc;
2008         u_char  c;
2009
2010         /*
2011          * Clear the IE
2012          */
2013         KM_COPY(&ie_brpi_absent, &ie->ie_u.ie_brpi,
2014                         sizeof(ie_brpi_absent));
2015
2016         /*
2017          * Get the repeat indicator
2018          */
2019         rc = usf_byte(usf, &c);
2020         if (rc)
2021                 return(rc);
2022
2023         ie->ie_brpi_ind = c & UNI_IE_BRPI_IND_MASK;
2024
2025         return(0);
2026 }
2027
2028
2029 /*
2030  * Decode a restart indicator information element
2031  *
2032  * Arguments:
2033  *      usf     pointer to a unisig formatting structure
2034  *      ie      pointer to a cell rate IE structure
2035  *
2036  * Returns:
2037  *      0       success
2038  *      errno   error encountered
2039  *
2040  */
2041 static int
2042 usf_dec_ie_rsti(struct usfmt *usf, struct ie_generic *ie)
2043 {
2044         int             rc;
2045         u_char          c;
2046
2047         /*
2048          * Clear the IE
2049          */
2050         KM_COPY(&ie_rsti_absent, &ie->ie_u.ie_rsti,
2051                         sizeof(ie_rsti_absent));
2052
2053         /*
2054          * Get the restart class
2055          */
2056         rc = usf_byte(usf, &c);
2057         if (rc)
2058                 return(rc);
2059
2060         ie->ie_rsti_class = c & UNI_IE_RSTI_CLASS_MASK;
2061
2062         return(0);
2063 }
2064
2065
2066 /*
2067  * Decode a broadband sending complete information element
2068  *
2069  * Arguments:
2070  *      usf     pointer to a unisig formatting structure
2071  *      ie      pointer to a broadband sending complete IE structure
2072  *
2073  * Returns:
2074  *      0       success
2075  *      errno   error encountered
2076  *
2077  */
2078 static int
2079 usf_dec_ie_bsdc(struct usfmt *usf, struct ie_generic *ie)
2080 {
2081         int     rc;
2082         u_char  c;
2083
2084         /*
2085          * Clear the IE
2086          */
2087         KM_COPY(&ie_bsdc_absent, &ie->ie_u.ie_bsdc,
2088                         sizeof(ie_bsdc_absent));
2089
2090         /*
2091          * Get the sending complete indicator
2092          */
2093         rc = usf_byte(usf, &c);
2094         if (rc)
2095                 return(rc);
2096
2097         /*
2098          * Validate the indicator
2099          */
2100         c &= UNI_IE_EXT_MASK;
2101         if (c != UNI_IE_BSDC_IND)
2102                 ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
2103         ie->ie_bsdc_ind = c;
2104
2105         return(0);
2106 }
2107
2108
2109 /*
2110  * Decode a transit network selection information element
2111  *
2112  * Arguments:
2113  *      usf     pointer to a unisig formatting structure
2114  *      ie      pointer to a transit network selection IE structure
2115  *
2116  * Returns:
2117  *      0       success
2118  *      errno   error encountered
2119  *
2120  */
2121 static int
2122 usf_dec_ie_trnt(struct usfmt *usf, struct ie_generic *ie)
2123 {
2124         int     i, len, rc;
2125         u_char  c;
2126
2127         /*
2128          * Clear the IE
2129          */
2130         KM_COPY(&ie_trnt_absent, &ie->ie_u.ie_trnt,
2131                         sizeof(ie_trnt_absent));
2132
2133         /*
2134          * Get the network ID type and plan
2135          */
2136         rc = usf_byte(usf, &c);
2137         if (rc)
2138                 return(rc);
2139         ie->ie_trnt_id_type = (c >> UNI_IE_TRNT_IDT_SHIFT) &
2140                         UNI_IE_TRNT_IDT_MASK;
2141         ie->ie_trnt_id_plan = c & UNI_IE_TRNT_IDP_MASK;
2142
2143         /*
2144          * Get the length of the network ID
2145          */
2146         len = ie->ie_length - 1;
2147         ie->ie_trnt_id_len = MIN(len, sizeof(ie->ie_trnt_id));
2148
2149         /*
2150          * Get the network ID
2151          */
2152         for (i=0; i<len; i++) {
2153                 if (i<sizeof(ie->ie_trnt_id))
2154                         rc = usf_byte(usf, &ie->ie_trnt_id[i]);
2155                 else
2156                         rc = usf_byte(usf, &c);
2157                 if (rc)
2158                         return(rc);
2159         }
2160
2161         return(0);
2162 }
2163
2164
2165 /*
2166  * Decode an unimplemented information element
2167  *
2168  * Arguments:
2169  *      usf     pointer to a unisig formatting structure
2170  *      ie      pointer to a cell rate IE structure
2171  *
2172  * Returns:
2173  *      0       success
2174  *      errno   error encountered
2175  *
2176  */
2177 static int
2178 usf_dec_ie_uimp(struct usfmt *usf, struct ie_generic *ie)
2179 {
2180         int     i, rc;
2181         u_char  c;
2182
2183         /*
2184          * Skip over the IE contents
2185          */
2186         for (i=0; i<ie->ie_length; i++) {
2187                 rc = usf_byte(usf, &c);
2188                 if (rc)
2189                         return(rc);
2190         }
2191
2192         return(0);
2193 }
2194
2195
2196 /*
2197  * Decode an information element using field identifiers
2198  *
2199  * The AAL parameters and ATM user cell rate IEs are formatted
2200  * with a one-byte identifier preceeding each field.  The routine
2201  * parses these IEs by using a table which relates the field
2202  * identifiers with the fields in the appropriate IE structure.
2203  * Field order in the received message is immaterial.
2204  *
2205  * Arguments:
2206  *      usf     pointer to a unisig formatting structure
2207  *      ie      pointer to a cell rate IE structure
2208  *      tbl     pointer to an IE decoding table
2209  *
2210  * Returns:
2211  *      0       success
2212  *      errno   error encountered
2213  *
2214  */
2215 static int
2216 usf_dec_ie_ident(struct usfmt *usf, struct ie_generic *ie,
2217                  struct ie_decode_tbl *tbl)
2218 {
2219         int     i, len, rc;
2220         u_char  c;
2221         u_int8_t        cv;
2222         u_int16_t       sv;
2223         u_int32_t       iv;
2224         void            *dest;
2225
2226         /*
2227          * Scan through the IE
2228          */
2229         len = ie->ie_length;
2230         while (len) {
2231                 /*
2232                  * Get the field identifier
2233                  */
2234                 rc = usf_byte(usf, &c);
2235                 if (rc)
2236                         return(rc);
2237                 len--;
2238
2239                 /*
2240                  * Look up the field in the table
2241                  */
2242                 for (i=0; (tbl[i].ident != c) && tbl[i].len; i++) {
2243                 }
2244                 if (tbl[i].ident == 0) {
2245                         /*
2246                          * Bad subfield identifier -- flag an
2247                          * error and skip over the rest of the IE
2248                          */
2249                         ie->ie_err_cause = UNI_IE_CAUS_IECONTENT;
2250                         while (len) {
2251                                 rc = usf_byte(usf, &c);
2252                                 if (rc)
2253                                         return(rc);
2254                         }
2255                         return(0);
2256                 }
2257
2258                 /*
2259                  * Save final destination address
2260                  */
2261                 dest = (void *)((int)ie + tbl[i].f_offs);
2262
2263                 /*
2264                  * Get the field value
2265                  */
2266                 switch (tbl[i].len) {
2267                         case 0:
2268                                 cv = 1;
2269                                 goto savec;
2270
2271                         case 1:
2272                                 rc = usf_byte(usf, &cv);
2273                                 if (rc)
2274                                         break;
2275 savec:
2276                                 /*
2277                                  * Save field value
2278                                  */
2279                                 switch (tbl[i].f_size) {
2280                                 case 1:
2281                                         *(u_int8_t *)dest = cv;
2282                                         break;
2283                                 case 2:
2284                                         *(u_int16_t *)dest = cv;
2285                                         break;
2286                                 case 4:
2287                                         *(u_int32_t *)dest = cv;
2288                                         break;
2289                                 default:
2290                                         goto badtbl;
2291                                 }
2292                                 break;
2293
2294                         case 2:
2295                                 rc = usf_short(usf, &sv);
2296                                 if (rc)
2297                                         break;
2298
2299                                 /*
2300                                  * Save field value
2301                                  */
2302                                 switch (tbl[i].f_size) {
2303                                 case 2:
2304                                         *(u_int16_t *)dest = sv;
2305                                         break;
2306                                 case 4:
2307                                         *(u_int32_t *)dest = sv;
2308                                         break;
2309                                 default:
2310                                         goto badtbl;
2311                                 }
2312                                 break;
2313
2314                         case 3:
2315                                 rc = usf_int3(usf, &iv);
2316                                 goto savei;
2317
2318                         case 4:
2319                                 rc = usf_int(usf, &iv);
2320 savei:
2321                                 /*
2322                                  * Save field value
2323                                  */
2324                                 if (rc)
2325                                         break;
2326                                 switch (tbl[i].f_size) {
2327                                 case 4:
2328                                         *(u_int32_t *)dest = iv;
2329                                         break;
2330                                 default:
2331                                         goto badtbl;
2332                                 }
2333                                 break;
2334
2335                         default:
2336 badtbl:
2337                                 log(LOG_ERR,
2338                                     "uni decode: id=%d,len=%d,off=%d,size=%d\n",
2339                                         tbl[i].ident, tbl[i].len,
2340                                         tbl[i].f_offs, tbl[i].f_size);
2341                                 rc = EFAULT;
2342                                 break;
2343                 }
2344
2345                 if (rc)
2346                         return(rc);
2347
2348                 len -= tbl[i].len;
2349
2350         }
2351
2352         return(0);
2353 }
2354
2355
2356 /*
2357  * Decode an ATM address
2358  *
2359  * Arguments:
2360  *      usf     pointer to a unisig formatting structure
2361  *      addr    pointer to an ATM address structure
2362  *      len     length of data remainig in the IE
2363  *
2364  * Returns:
2365  *      0       success
2366  *      errno   error encountered
2367  *
2368  */
2369 static int
2370 usf_dec_atm_addr(struct usfmt *usf, Atm_addr *addr, int len)
2371 {
2372         int             rc;
2373         u_char          c, *cp;
2374
2375         /*
2376          * Check the address type
2377          */
2378         addr->address_length = len;
2379         switch (addr->address_format) {
2380         case T_ATM_E164_ADDR:
2381                 if (len > sizeof(Atm_addr_e164)) {
2382                         goto flush;
2383                 }
2384                 cp = (u_char *) addr->address;
2385                 break;
2386         case T_ATM_ENDSYS_ADDR:
2387                 if (len != sizeof(Atm_addr_nsap)) {
2388                         goto flush;
2389                 }
2390                 cp = (u_char *) addr->address;
2391                 break;
2392         default:
2393                 /* Silence the compiler */
2394                 cp = NULL;
2395         }
2396
2397         /*
2398          * Get the ATM address
2399          */
2400         while (len) {
2401                 rc = usf_byte(usf, cp);
2402                 if (rc)
2403                         return(rc);
2404                 len--;
2405                 cp++;
2406         }
2407
2408         return(0);
2409
2410 flush:
2411         while (len) {
2412                 rc = usf_byte(usf, &c);
2413                 if (rc)
2414                         return(rc);
2415                 len--;
2416         }
2417
2418         return(EINVAL);
2419 }