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