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