140b0b3f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ca9b0147SVarsha Rao /*
305ba4c89SYonatan Goldschmidt  * BER and PER decoding library for H.323 conntrack/NAT module.
4f587de0eSPatrick McHardy  *
5f587de0eSPatrick McHardy  * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
6f587de0eSPatrick McHardy  *
705ba4c89SYonatan Goldschmidt  * See nf_conntrack_helper_h323_asn1.h for details.
8ca9b0147SVarsha Rao  */
9f587de0eSPatrick McHardy 
10f587de0eSPatrick McHardy #ifdef __KERNEL__
11f587de0eSPatrick McHardy #include <linux/kernel.h>
12f587de0eSPatrick McHardy #else
13f587de0eSPatrick McHardy #include <stdio.h>
14f587de0eSPatrick McHardy #endif
15f587de0eSPatrick McHardy #include <linux/netfilter/nf_conntrack_h323_asn1.h>
16f587de0eSPatrick McHardy 
17f587de0eSPatrick McHardy /* Trace Flag */
18f587de0eSPatrick McHardy #ifndef H323_TRACE
19f587de0eSPatrick McHardy #define H323_TRACE 0
20f587de0eSPatrick McHardy #endif
21f587de0eSPatrick McHardy 
22f587de0eSPatrick McHardy #if H323_TRACE
23f587de0eSPatrick McHardy #define TAB_SIZE 4
24f587de0eSPatrick McHardy #define IFTHEN(cond, act) if(cond){act;}
25f587de0eSPatrick McHardy #ifdef __KERNEL__
26f587de0eSPatrick McHardy #define PRINT printk
27f587de0eSPatrick McHardy #else
28f587de0eSPatrick McHardy #define PRINT printf
29f587de0eSPatrick McHardy #endif
30f587de0eSPatrick McHardy #define FNAME(name) name,
31f587de0eSPatrick McHardy #else
32f587de0eSPatrick McHardy #define IFTHEN(cond, act)
33f587de0eSPatrick McHardy #define PRINT(fmt, args...)
34f587de0eSPatrick McHardy #define FNAME(name)
35f587de0eSPatrick McHardy #endif
36f587de0eSPatrick McHardy 
37f587de0eSPatrick McHardy /* ASN.1 Types */
38f587de0eSPatrick McHardy #define NUL 0
39f587de0eSPatrick McHardy #define BOOL 1
40f587de0eSPatrick McHardy #define OID 2
41f587de0eSPatrick McHardy #define INT 3
42f587de0eSPatrick McHardy #define ENUM 4
43f587de0eSPatrick McHardy #define BITSTR 5
44f587de0eSPatrick McHardy #define NUMSTR 6
45f587de0eSPatrick McHardy #define NUMDGT 6
46f587de0eSPatrick McHardy #define TBCDSTR 6
47f587de0eSPatrick McHardy #define OCTSTR 7
48f587de0eSPatrick McHardy #define PRTSTR 7
49f587de0eSPatrick McHardy #define IA5STR 7
50f587de0eSPatrick McHardy #define GENSTR 7
51f587de0eSPatrick McHardy #define BMPSTR 8
52f587de0eSPatrick McHardy #define SEQ 9
53f587de0eSPatrick McHardy #define SET 9
54f587de0eSPatrick McHardy #define SEQOF 10
55f587de0eSPatrick McHardy #define SETOF 10
56f587de0eSPatrick McHardy #define CHOICE 11
57f587de0eSPatrick McHardy 
58f587de0eSPatrick McHardy /* Constraint Types */
59f587de0eSPatrick McHardy #define FIXD 0
60f587de0eSPatrick McHardy /* #define BITS 1-8 */
61f587de0eSPatrick McHardy #define BYTE 9
62f587de0eSPatrick McHardy #define WORD 10
63f587de0eSPatrick McHardy #define CONS 11
64f587de0eSPatrick McHardy #define SEMI 12
65f587de0eSPatrick McHardy #define UNCO 13
66f587de0eSPatrick McHardy 
67f587de0eSPatrick McHardy /* ASN.1 Type Attributes */
68f587de0eSPatrick McHardy #define SKIP 0
69f587de0eSPatrick McHardy #define STOP 1
70f587de0eSPatrick McHardy #define DECODE 2
71f587de0eSPatrick McHardy #define EXT 4
72f587de0eSPatrick McHardy #define OPEN 8
73f587de0eSPatrick McHardy #define OPT 16
74f587de0eSPatrick McHardy 
75f587de0eSPatrick McHardy 
76f587de0eSPatrick McHardy /* ASN.1 Field Structure */
77f587de0eSPatrick McHardy typedef struct field_t {
78f587de0eSPatrick McHardy #if H323_TRACE
79f587de0eSPatrick McHardy 	char *name;
80f587de0eSPatrick McHardy #endif
81f587de0eSPatrick McHardy 	unsigned char type;
82f587de0eSPatrick McHardy 	unsigned char sz;
83f587de0eSPatrick McHardy 	unsigned char lb;
84f587de0eSPatrick McHardy 	unsigned char ub;
85f587de0eSPatrick McHardy 	unsigned short attr;
86f587de0eSPatrick McHardy 	unsigned short offset;
87905e3e8eSJan Engelhardt 	const struct field_t *fields;
88f587de0eSPatrick McHardy } field_t;
89f587de0eSPatrick McHardy 
90f587de0eSPatrick McHardy /* Bit Stream */
9167704c2aSHarsha Sharma struct bitstr {
92f587de0eSPatrick McHardy 	unsigned char *buf;
93f587de0eSPatrick McHardy 	unsigned char *beg;
94f587de0eSPatrick McHardy 	unsigned char *end;
95f587de0eSPatrick McHardy 	unsigned char *cur;
961f807d6eSJan Engelhardt 	unsigned int bit;
9767704c2aSHarsha Sharma };
98f587de0eSPatrick McHardy 
99f587de0eSPatrick McHardy /* Tool Functions */
100e79ec50bSJan Engelhardt #define INC_BIT(bs) if((++(bs)->bit)>7){(bs)->cur++;(bs)->bit=0;}
101e79ec50bSJan Engelhardt #define INC_BITS(bs,b) if(((bs)->bit+=(b))>7){(bs)->cur+=(bs)->bit>>3;(bs)->bit&=7;}
102e79ec50bSJan Engelhardt #define BYTE_ALIGN(bs) if((bs)->bit){(bs)->cur++;(bs)->bit=0;}
10367704c2aSHarsha Sharma static unsigned int get_len(struct bitstr *bs);
10467704c2aSHarsha Sharma static unsigned int get_bit(struct bitstr *bs);
10567704c2aSHarsha Sharma static unsigned int get_bits(struct bitstr *bs, unsigned int b);
10667704c2aSHarsha Sharma static unsigned int get_bitmap(struct bitstr *bs, unsigned int b);
10767704c2aSHarsha Sharma static unsigned int get_uint(struct bitstr *bs, int b);
108f587de0eSPatrick McHardy 
109f587de0eSPatrick McHardy /* Decoder Functions */
11067704c2aSHarsha Sharma static int decode_nul(struct bitstr *bs, const struct field_t *f, char *base, int level);
11167704c2aSHarsha Sharma static int decode_bool(struct bitstr *bs, const struct field_t *f, char *base, int level);
11267704c2aSHarsha Sharma static int decode_oid(struct bitstr *bs, const struct field_t *f, char *base, int level);
11367704c2aSHarsha Sharma static int decode_int(struct bitstr *bs, const struct field_t *f, char *base, int level);
11467704c2aSHarsha Sharma static int decode_enum(struct bitstr *bs, const struct field_t *f, char *base, int level);
11567704c2aSHarsha Sharma static int decode_bitstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
11667704c2aSHarsha Sharma static int decode_numstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
11767704c2aSHarsha Sharma static int decode_octstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
11867704c2aSHarsha Sharma static int decode_bmpstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
11967704c2aSHarsha Sharma static int decode_seq(struct bitstr *bs, const struct field_t *f, char *base, int level);
12067704c2aSHarsha Sharma static int decode_seqof(struct bitstr *bs, const struct field_t *f, char *base, int level);
12167704c2aSHarsha Sharma static int decode_choice(struct bitstr *bs, const struct field_t *f, char *base, int level);
122f587de0eSPatrick McHardy 
123f587de0eSPatrick McHardy /* Decoder Functions Vector */
12467704c2aSHarsha Sharma typedef int (*decoder_t)(struct bitstr *, const struct field_t *, char *, int);
125dc64d02bSStephen Hemminger static const decoder_t Decoders[] = {
126f587de0eSPatrick McHardy 	decode_nul,
127f587de0eSPatrick McHardy 	decode_bool,
128f587de0eSPatrick McHardy 	decode_oid,
129f587de0eSPatrick McHardy 	decode_int,
130f587de0eSPatrick McHardy 	decode_enum,
131f587de0eSPatrick McHardy 	decode_bitstr,
132f587de0eSPatrick McHardy 	decode_numstr,
133f587de0eSPatrick McHardy 	decode_octstr,
134f587de0eSPatrick McHardy 	decode_bmpstr,
135f587de0eSPatrick McHardy 	decode_seq,
136f587de0eSPatrick McHardy 	decode_seqof,
137f587de0eSPatrick McHardy 	decode_choice,
138f587de0eSPatrick McHardy };
139f587de0eSPatrick McHardy 
140ca9b0147SVarsha Rao /*
141f587de0eSPatrick McHardy  * H.323 Types
142ca9b0147SVarsha Rao  */
143f587de0eSPatrick McHardy #include "nf_conntrack_h323_types.c"
144f587de0eSPatrick McHardy 
145ca9b0147SVarsha Rao /*
146f587de0eSPatrick McHardy  * Functions
147ca9b0147SVarsha Rao  */
148ca9b0147SVarsha Rao 
149f587de0eSPatrick McHardy /* Assume bs is aligned && v < 16384 */
get_len(struct bitstr * bs)15067704c2aSHarsha Sharma static unsigned int get_len(struct bitstr *bs)
151f587de0eSPatrick McHardy {
1521f807d6eSJan Engelhardt 	unsigned int v;
153f587de0eSPatrick McHardy 
154f587de0eSPatrick McHardy 	v = *bs->cur++;
155f587de0eSPatrick McHardy 
156f587de0eSPatrick McHardy 	if (v & 0x80) {
157f587de0eSPatrick McHardy 		v &= 0x3f;
158f587de0eSPatrick McHardy 		v <<= 8;
159f587de0eSPatrick McHardy 		v += *bs->cur++;
160f587de0eSPatrick McHardy 	}
161f587de0eSPatrick McHardy 
162f587de0eSPatrick McHardy 	return v;
163f587de0eSPatrick McHardy }
164f587de0eSPatrick McHardy 
nf_h323_error_boundary(struct bitstr * bs,size_t bytes,size_t bits)165ec8a8f3cSEric Sesterhenn static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits)
166bc7d811aSEric Sesterhenn {
167ec8a8f3cSEric Sesterhenn 	bits += bs->bit;
168ec8a8f3cSEric Sesterhenn 	bytes += bits / BITS_PER_BYTE;
169ec8a8f3cSEric Sesterhenn 	if (bits % BITS_PER_BYTE > 0)
170ec8a8f3cSEric Sesterhenn 		bytes++;
171ec8a8f3cSEric Sesterhenn 
172f5e85ce8SJakub Jankowski 	if (bs->cur + bytes > bs->end)
173bc7d811aSEric Sesterhenn 		return 1;
174bc7d811aSEric Sesterhenn 
175bc7d811aSEric Sesterhenn 	return 0;
176bc7d811aSEric Sesterhenn }
177bc7d811aSEric Sesterhenn 
get_bit(struct bitstr * bs)17867704c2aSHarsha Sharma static unsigned int get_bit(struct bitstr *bs)
179f587de0eSPatrick McHardy {
1801f807d6eSJan Engelhardt 	unsigned int b = (*bs->cur) & (0x80 >> bs->bit);
181f587de0eSPatrick McHardy 
182f587de0eSPatrick McHardy 	INC_BIT(bs);
183f587de0eSPatrick McHardy 
184f587de0eSPatrick McHardy 	return b;
185f587de0eSPatrick McHardy }
186f587de0eSPatrick McHardy 
187f587de0eSPatrick McHardy /* Assume b <= 8 */
get_bits(struct bitstr * bs,unsigned int b)18867704c2aSHarsha Sharma static unsigned int get_bits(struct bitstr *bs, unsigned int b)
189f587de0eSPatrick McHardy {
1901f807d6eSJan Engelhardt 	unsigned int v, l;
191f587de0eSPatrick McHardy 
192f587de0eSPatrick McHardy 	v = (*bs->cur) & (0xffU >> bs->bit);
193f587de0eSPatrick McHardy 	l = b + bs->bit;
194f587de0eSPatrick McHardy 
195f587de0eSPatrick McHardy 	if (l < 8) {
196f587de0eSPatrick McHardy 		v >>= 8 - l;
197f587de0eSPatrick McHardy 		bs->bit = l;
198f587de0eSPatrick McHardy 	} else if (l == 8) {
199f587de0eSPatrick McHardy 		bs->cur++;
200f587de0eSPatrick McHardy 		bs->bit = 0;
201f587de0eSPatrick McHardy 	} else {		/* l > 8 */
202f587de0eSPatrick McHardy 
203f587de0eSPatrick McHardy 		v <<= 8;
204f587de0eSPatrick McHardy 		v += *(++bs->cur);
205f587de0eSPatrick McHardy 		v >>= 16 - l;
206f587de0eSPatrick McHardy 		bs->bit = l - 8;
207f587de0eSPatrick McHardy 	}
208f587de0eSPatrick McHardy 
209f587de0eSPatrick McHardy 	return v;
210f587de0eSPatrick McHardy }
211f587de0eSPatrick McHardy 
212f587de0eSPatrick McHardy /* Assume b <= 32 */
get_bitmap(struct bitstr * bs,unsigned int b)21367704c2aSHarsha Sharma static unsigned int get_bitmap(struct bitstr *bs, unsigned int b)
214f587de0eSPatrick McHardy {
2151f807d6eSJan Engelhardt 	unsigned int v, l, shift, bytes;
216f587de0eSPatrick McHardy 
217f587de0eSPatrick McHardy 	if (!b)
218f587de0eSPatrick McHardy 		return 0;
219f587de0eSPatrick McHardy 
220f587de0eSPatrick McHardy 	l = bs->bit + b;
221f587de0eSPatrick McHardy 
222f587de0eSPatrick McHardy 	if (l < 8) {
2231f807d6eSJan Engelhardt 		v = (unsigned int)(*bs->cur) << (bs->bit + 24);
224f587de0eSPatrick McHardy 		bs->bit = l;
225f587de0eSPatrick McHardy 	} else if (l == 8) {
2261f807d6eSJan Engelhardt 		v = (unsigned int)(*bs->cur++) << (bs->bit + 24);
227f587de0eSPatrick McHardy 		bs->bit = 0;
228f587de0eSPatrick McHardy 	} else {
229f587de0eSPatrick McHardy 		for (bytes = l >> 3, shift = 24, v = 0; bytes;
230f587de0eSPatrick McHardy 		     bytes--, shift -= 8)
2311f807d6eSJan Engelhardt 			v |= (unsigned int)(*bs->cur++) << shift;
232f587de0eSPatrick McHardy 
233f587de0eSPatrick McHardy 		if (l < 32) {
2341f807d6eSJan Engelhardt 			v |= (unsigned int)(*bs->cur) << shift;
235f587de0eSPatrick McHardy 			v <<= bs->bit;
236f587de0eSPatrick McHardy 		} else if (l > 32) {
237f587de0eSPatrick McHardy 			v <<= bs->bit;
238f587de0eSPatrick McHardy 			v |= (*bs->cur) >> (8 - bs->bit);
239f587de0eSPatrick McHardy 		}
240f587de0eSPatrick McHardy 
241f587de0eSPatrick McHardy 		bs->bit = l & 0x7;
242f587de0eSPatrick McHardy 	}
243f587de0eSPatrick McHardy 
244f587de0eSPatrick McHardy 	v &= 0xffffffff << (32 - b);
245f587de0eSPatrick McHardy 
246f587de0eSPatrick McHardy 	return v;
247f587de0eSPatrick McHardy }
248f587de0eSPatrick McHardy 
249ca9b0147SVarsha Rao /*
250f587de0eSPatrick McHardy  * Assume bs is aligned and sizeof(unsigned int) == 4
251ca9b0147SVarsha Rao  */
get_uint(struct bitstr * bs,int b)25267704c2aSHarsha Sharma static unsigned int get_uint(struct bitstr *bs, int b)
253f587de0eSPatrick McHardy {
2541f807d6eSJan Engelhardt 	unsigned int v = 0;
255f587de0eSPatrick McHardy 
256f587de0eSPatrick McHardy 	switch (b) {
257f587de0eSPatrick McHardy 	case 4:
258f587de0eSPatrick McHardy 		v |= *bs->cur++;
259f587de0eSPatrick McHardy 		v <<= 8;
260954d8297SGustavo A. R. Silva 		fallthrough;
261f587de0eSPatrick McHardy 	case 3:
262f587de0eSPatrick McHardy 		v |= *bs->cur++;
263f587de0eSPatrick McHardy 		v <<= 8;
264954d8297SGustavo A. R. Silva 		fallthrough;
265f587de0eSPatrick McHardy 	case 2:
266f587de0eSPatrick McHardy 		v |= *bs->cur++;
267f587de0eSPatrick McHardy 		v <<= 8;
268954d8297SGustavo A. R. Silva 		fallthrough;
269f587de0eSPatrick McHardy 	case 1:
270f587de0eSPatrick McHardy 		v |= *bs->cur++;
271f587de0eSPatrick McHardy 		break;
272f587de0eSPatrick McHardy 	}
273f587de0eSPatrick McHardy 	return v;
274f587de0eSPatrick McHardy }
275f587de0eSPatrick McHardy 
decode_nul(struct bitstr * bs,const struct field_t * f,char * base,int level)27667704c2aSHarsha Sharma static int decode_nul(struct bitstr *bs, const struct field_t *f,
277905e3e8eSJan Engelhardt                       char *base, int level)
278f587de0eSPatrick McHardy {
279f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
280f587de0eSPatrick McHardy 
281f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
282f587de0eSPatrick McHardy }
283f587de0eSPatrick McHardy 
decode_bool(struct bitstr * bs,const struct field_t * f,char * base,int level)28467704c2aSHarsha Sharma static int decode_bool(struct bitstr *bs, const struct field_t *f,
285905e3e8eSJan Engelhardt                        char *base, int level)
286f587de0eSPatrick McHardy {
287f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
288f587de0eSPatrick McHardy 
289f587de0eSPatrick McHardy 	INC_BIT(bs);
290ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
291bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
292f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
293f587de0eSPatrick McHardy }
294f587de0eSPatrick McHardy 
decode_oid(struct bitstr * bs,const struct field_t * f,char * base,int level)29567704c2aSHarsha Sharma static int decode_oid(struct bitstr *bs, const struct field_t *f,
296905e3e8eSJan Engelhardt                       char *base, int level)
297f587de0eSPatrick McHardy {
298f587de0eSPatrick McHardy 	int len;
299f587de0eSPatrick McHardy 
300f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
301f587de0eSPatrick McHardy 
302f587de0eSPatrick McHardy 	BYTE_ALIGN(bs);
303ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 1, 0))
304bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
305bc7d811aSEric Sesterhenn 
306f587de0eSPatrick McHardy 	len = *bs->cur++;
307f587de0eSPatrick McHardy 	bs->cur += len;
308ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
309bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
310f587de0eSPatrick McHardy 
311f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
312f587de0eSPatrick McHardy }
313f587de0eSPatrick McHardy 
decode_int(struct bitstr * bs,const struct field_t * f,char * base,int level)31467704c2aSHarsha Sharma static int decode_int(struct bitstr *bs, const struct field_t *f,
315905e3e8eSJan Engelhardt                       char *base, int level)
316f587de0eSPatrick McHardy {
3171f807d6eSJan Engelhardt 	unsigned int len;
318f587de0eSPatrick McHardy 
319f587de0eSPatrick McHardy 	PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
320f587de0eSPatrick McHardy 
321f587de0eSPatrick McHardy 	switch (f->sz) {
322f587de0eSPatrick McHardy 	case BYTE:		/* Range == 256 */
323f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
324f587de0eSPatrick McHardy 		bs->cur++;
325f587de0eSPatrick McHardy 		break;
326f587de0eSPatrick McHardy 	case WORD:		/* 257 <= Range <= 64K */
327f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
328f587de0eSPatrick McHardy 		bs->cur += 2;
329f587de0eSPatrick McHardy 		break;
330f587de0eSPatrick McHardy 	case CONS:		/* 64K < Range < 4G */
331ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 0, 2))
332ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
333f587de0eSPatrick McHardy 		len = get_bits(bs, 2) + 1;
334f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
335f587de0eSPatrick McHardy 		if (base && (f->attr & DECODE)) {	/* timeToLive */
3361f807d6eSJan Engelhardt 			unsigned int v = get_uint(bs, len) + f->lb;
337f587de0eSPatrick McHardy 			PRINT(" = %u", v);
3381f807d6eSJan Engelhardt 			*((unsigned int *)(base + f->offset)) = v;
339f587de0eSPatrick McHardy 		}
340f587de0eSPatrick McHardy 		bs->cur += len;
341f587de0eSPatrick McHardy 		break;
342f587de0eSPatrick McHardy 	case UNCO:
343f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
344ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
345bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
346f587de0eSPatrick McHardy 		len = get_len(bs);
347f587de0eSPatrick McHardy 		bs->cur += len;
348f587de0eSPatrick McHardy 		break;
349f587de0eSPatrick McHardy 	default:		/* 2 <= Range <= 255 */
350f587de0eSPatrick McHardy 		INC_BITS(bs, f->sz);
351f587de0eSPatrick McHardy 		break;
352f587de0eSPatrick McHardy 	}
353f587de0eSPatrick McHardy 
354f587de0eSPatrick McHardy 	PRINT("\n");
355f587de0eSPatrick McHardy 
356ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
357bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
358f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
359f587de0eSPatrick McHardy }
360f587de0eSPatrick McHardy 
decode_enum(struct bitstr * bs,const struct field_t * f,char * base,int level)36167704c2aSHarsha Sharma static int decode_enum(struct bitstr *bs, const struct field_t *f,
362905e3e8eSJan Engelhardt                        char *base, int level)
363f587de0eSPatrick McHardy {
364f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
365f587de0eSPatrick McHardy 
366f587de0eSPatrick McHardy 	if ((f->attr & EXT) && get_bit(bs)) {
367f587de0eSPatrick McHardy 		INC_BITS(bs, 7);
368f587de0eSPatrick McHardy 	} else {
369f587de0eSPatrick McHardy 		INC_BITS(bs, f->sz);
370f587de0eSPatrick McHardy 	}
371f587de0eSPatrick McHardy 
372ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
373bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
374f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
375f587de0eSPatrick McHardy }
376f587de0eSPatrick McHardy 
decode_bitstr(struct bitstr * bs,const struct field_t * f,char * base,int level)37767704c2aSHarsha Sharma static int decode_bitstr(struct bitstr *bs, const struct field_t *f,
378905e3e8eSJan Engelhardt                          char *base, int level)
379f587de0eSPatrick McHardy {
3801f807d6eSJan Engelhardt 	unsigned int len;
381f587de0eSPatrick McHardy 
382f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
383f587de0eSPatrick McHardy 
384f587de0eSPatrick McHardy 	BYTE_ALIGN(bs);
385f587de0eSPatrick McHardy 	switch (f->sz) {
386f587de0eSPatrick McHardy 	case FIXD:		/* fixed length > 16 */
387f587de0eSPatrick McHardy 		len = f->lb;
388f587de0eSPatrick McHardy 		break;
389f587de0eSPatrick McHardy 	case WORD:		/* 2-byte length */
390ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
391bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
392f587de0eSPatrick McHardy 		len = (*bs->cur++) << 8;
393f587de0eSPatrick McHardy 		len += (*bs->cur++) + f->lb;
394f587de0eSPatrick McHardy 		break;
395f587de0eSPatrick McHardy 	case SEMI:
396ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
397bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
398f587de0eSPatrick McHardy 		len = get_len(bs);
399f587de0eSPatrick McHardy 		break;
400f587de0eSPatrick McHardy 	default:
401f587de0eSPatrick McHardy 		len = 0;
402f587de0eSPatrick McHardy 		break;
403f587de0eSPatrick McHardy 	}
404f587de0eSPatrick McHardy 
405f587de0eSPatrick McHardy 	bs->cur += len >> 3;
406f587de0eSPatrick McHardy 	bs->bit = len & 7;
407f587de0eSPatrick McHardy 
408ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
409bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
410f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
411f587de0eSPatrick McHardy }
412f587de0eSPatrick McHardy 
decode_numstr(struct bitstr * bs,const struct field_t * f,char * base,int level)41367704c2aSHarsha Sharma static int decode_numstr(struct bitstr *bs, const struct field_t *f,
414905e3e8eSJan Engelhardt                          char *base, int level)
415f587de0eSPatrick McHardy {
4161f807d6eSJan Engelhardt 	unsigned int len;
417f587de0eSPatrick McHardy 
418f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
419f587de0eSPatrick McHardy 
420f587de0eSPatrick McHardy 	/* 2 <= Range <= 255 */
421ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, f->sz))
422ec8a8f3cSEric Sesterhenn 		return H323_ERROR_BOUND;
423f587de0eSPatrick McHardy 	len = get_bits(bs, f->sz) + f->lb;
424f587de0eSPatrick McHardy 
425f587de0eSPatrick McHardy 	BYTE_ALIGN(bs);
426f587de0eSPatrick McHardy 	INC_BITS(bs, (len << 2));
427f587de0eSPatrick McHardy 
428ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
429bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
430f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
431f587de0eSPatrick McHardy }
432f587de0eSPatrick McHardy 
decode_octstr(struct bitstr * bs,const struct field_t * f,char * base,int level)43367704c2aSHarsha Sharma static int decode_octstr(struct bitstr *bs, const struct field_t *f,
434905e3e8eSJan Engelhardt                          char *base, int level)
435f587de0eSPatrick McHardy {
4361f807d6eSJan Engelhardt 	unsigned int len;
437f587de0eSPatrick McHardy 
438f587de0eSPatrick McHardy 	PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
439f587de0eSPatrick McHardy 
440f587de0eSPatrick McHardy 	switch (f->sz) {
441f587de0eSPatrick McHardy 	case FIXD:		/* Range == 1 */
442f587de0eSPatrick McHardy 		if (f->lb > 2) {
443f587de0eSPatrick McHardy 			BYTE_ALIGN(bs);
444f587de0eSPatrick McHardy 			if (base && (f->attr & DECODE)) {
445f587de0eSPatrick McHardy 				/* The IP Address */
446f587de0eSPatrick McHardy 				IFTHEN(f->lb == 4,
447f587de0eSPatrick McHardy 				       PRINT(" = %d.%d.%d.%d:%d",
448f587de0eSPatrick McHardy 					     bs->cur[0], bs->cur[1],
449f587de0eSPatrick McHardy 					     bs->cur[2], bs->cur[3],
450f587de0eSPatrick McHardy 					     bs->cur[4] * 256 + bs->cur[5]));
4511f807d6eSJan Engelhardt 				*((unsigned int *)(base + f->offset)) =
452f587de0eSPatrick McHardy 				    bs->cur - bs->buf;
453f587de0eSPatrick McHardy 			}
454f587de0eSPatrick McHardy 		}
455f587de0eSPatrick McHardy 		len = f->lb;
456f587de0eSPatrick McHardy 		break;
457f587de0eSPatrick McHardy 	case BYTE:		/* Range == 256 */
458f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
459ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 1, 0))
460bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
461f587de0eSPatrick McHardy 		len = (*bs->cur++) + f->lb;
462f587de0eSPatrick McHardy 		break;
463f587de0eSPatrick McHardy 	case SEMI:
464f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
465ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
466bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
467f587de0eSPatrick McHardy 		len = get_len(bs) + f->lb;
468f587de0eSPatrick McHardy 		break;
469f587de0eSPatrick McHardy 	default:		/* 2 <= Range <= 255 */
470ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 0, f->sz))
471ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
472f587de0eSPatrick McHardy 		len = get_bits(bs, f->sz) + f->lb;
473f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
474f587de0eSPatrick McHardy 		break;
475f587de0eSPatrick McHardy 	}
476f587de0eSPatrick McHardy 
477f587de0eSPatrick McHardy 	bs->cur += len;
478f587de0eSPatrick McHardy 
479f587de0eSPatrick McHardy 	PRINT("\n");
480f587de0eSPatrick McHardy 
481ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
482bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
483f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
484f587de0eSPatrick McHardy }
485f587de0eSPatrick McHardy 
decode_bmpstr(struct bitstr * bs,const struct field_t * f,char * base,int level)48667704c2aSHarsha Sharma static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,
487905e3e8eSJan Engelhardt                          char *base, int level)
488f587de0eSPatrick McHardy {
4891f807d6eSJan Engelhardt 	unsigned int len;
490f587de0eSPatrick McHardy 
491f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
492f587de0eSPatrick McHardy 
493f587de0eSPatrick McHardy 	switch (f->sz) {
494f587de0eSPatrick McHardy 	case BYTE:		/* Range == 256 */
495f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
496ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 1, 0))
497bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
498f587de0eSPatrick McHardy 		len = (*bs->cur++) + f->lb;
499f587de0eSPatrick McHardy 		break;
500f587de0eSPatrick McHardy 	default:		/* 2 <= Range <= 255 */
501ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 0, f->sz))
502ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
503f587de0eSPatrick McHardy 		len = get_bits(bs, f->sz) + f->lb;
504f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
505f587de0eSPatrick McHardy 		break;
506f587de0eSPatrick McHardy 	}
507f587de0eSPatrick McHardy 
508f587de0eSPatrick McHardy 	bs->cur += len << 1;
509f587de0eSPatrick McHardy 
510ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 0))
511bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
512f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
513f587de0eSPatrick McHardy }
514f587de0eSPatrick McHardy 
decode_seq(struct bitstr * bs,const struct field_t * f,char * base,int level)51567704c2aSHarsha Sharma static int decode_seq(struct bitstr *bs, const struct field_t *f,
516905e3e8eSJan Engelhardt                       char *base, int level)
517f587de0eSPatrick McHardy {
5181f807d6eSJan Engelhardt 	unsigned int ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
519f587de0eSPatrick McHardy 	int err;
520905e3e8eSJan Engelhardt 	const struct field_t *son;
521f587de0eSPatrick McHardy 	unsigned char *beg = NULL;
522f587de0eSPatrick McHardy 
523f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
524f587de0eSPatrick McHardy 
525f587de0eSPatrick McHardy 	/* Decode? */
526f587de0eSPatrick McHardy 	base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
527f587de0eSPatrick McHardy 
528f587de0eSPatrick McHardy 	/* Extensible? */
529ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 1))
530ec8a8f3cSEric Sesterhenn 		return H323_ERROR_BOUND;
531f587de0eSPatrick McHardy 	ext = (f->attr & EXT) ? get_bit(bs) : 0;
532f587de0eSPatrick McHardy 
533f587de0eSPatrick McHardy 	/* Get fields bitmap */
534ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, f->sz))
535ec8a8f3cSEric Sesterhenn 		return H323_ERROR_BOUND;
536*014a807fSLena Wang 	if (f->sz > 32)
537*014a807fSLena Wang 		return H323_ERROR_RANGE;
538f587de0eSPatrick McHardy 	bmp = get_bitmap(bs, f->sz);
539f587de0eSPatrick McHardy 	if (base)
5401f807d6eSJan Engelhardt 		*(unsigned int *)base = bmp;
541f587de0eSPatrick McHardy 
542f587de0eSPatrick McHardy 	/* Decode the root components */
543f587de0eSPatrick McHardy 	for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
544f587de0eSPatrick McHardy 		if (son->attr & STOP) {
545f587de0eSPatrick McHardy 			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
546f587de0eSPatrick McHardy 			      son->name);
547f587de0eSPatrick McHardy 			return H323_ERROR_STOP;
548f587de0eSPatrick McHardy 		}
549f587de0eSPatrick McHardy 
550f587de0eSPatrick McHardy 		if (son->attr & OPT) {	/* Optional component */
551f587de0eSPatrick McHardy 			if (!((0x80000000U >> (opt++)) & bmp))	/* Not exist */
552f587de0eSPatrick McHardy 				continue;
553f587de0eSPatrick McHardy 		}
554f587de0eSPatrick McHardy 
555f587de0eSPatrick McHardy 		/* Decode */
556f587de0eSPatrick McHardy 		if (son->attr & OPEN) {	/* Open field */
557ec8a8f3cSEric Sesterhenn 			if (nf_h323_error_boundary(bs, 2, 0))
558bc7d811aSEric Sesterhenn 				return H323_ERROR_BOUND;
559f587de0eSPatrick McHardy 			len = get_len(bs);
560ec8a8f3cSEric Sesterhenn 			if (nf_h323_error_boundary(bs, len, 0))
561bc7d811aSEric Sesterhenn 				return H323_ERROR_BOUND;
56225845b51SJing Min Zhao 			if (!base || !(son->attr & DECODE)) {
563f587de0eSPatrick McHardy 				PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
564f587de0eSPatrick McHardy 				      " ", son->name);
565f587de0eSPatrick McHardy 				bs->cur += len;
566f587de0eSPatrick McHardy 				continue;
567f587de0eSPatrick McHardy 			}
568f587de0eSPatrick McHardy 			beg = bs->cur;
569f587de0eSPatrick McHardy 
570f587de0eSPatrick McHardy 			/* Decode */
571f587de0eSPatrick McHardy 			if ((err = (Decoders[son->type]) (bs, son, base,
572f587de0eSPatrick McHardy 							  level + 1)) <
573f587de0eSPatrick McHardy 			    H323_ERROR_NONE)
574f587de0eSPatrick McHardy 				return err;
575f587de0eSPatrick McHardy 
576f587de0eSPatrick McHardy 			bs->cur = beg + len;
577f587de0eSPatrick McHardy 			bs->bit = 0;
578f587de0eSPatrick McHardy 		} else if ((err = (Decoders[son->type]) (bs, son, base,
579f587de0eSPatrick McHardy 							 level + 1)) <
580f587de0eSPatrick McHardy 			   H323_ERROR_NONE)
581f587de0eSPatrick McHardy 			return err;
582f587de0eSPatrick McHardy 	}
583f587de0eSPatrick McHardy 
584f587de0eSPatrick McHardy 	/* No extension? */
585f587de0eSPatrick McHardy 	if (!ext)
586f587de0eSPatrick McHardy 		return H323_ERROR_NONE;
587f587de0eSPatrick McHardy 
588f587de0eSPatrick McHardy 	/* Get the extension bitmap */
589ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 7))
590ec8a8f3cSEric Sesterhenn 		return H323_ERROR_BOUND;
591f587de0eSPatrick McHardy 	bmp2_len = get_bits(bs, 7) + 1;
592ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, bmp2_len))
593bc7d811aSEric Sesterhenn 		return H323_ERROR_BOUND;
594*014a807fSLena Wang 	if (bmp2_len > 32)
595*014a807fSLena Wang 		return H323_ERROR_RANGE;
596f587de0eSPatrick McHardy 	bmp2 = get_bitmap(bs, bmp2_len);
597f587de0eSPatrick McHardy 	bmp |= bmp2 >> f->sz;
598f587de0eSPatrick McHardy 	if (base)
5991f807d6eSJan Engelhardt 		*(unsigned int *)base = bmp;
600f587de0eSPatrick McHardy 	BYTE_ALIGN(bs);
601f587de0eSPatrick McHardy 
602f587de0eSPatrick McHardy 	/* Decode the extension components */
603f587de0eSPatrick McHardy 	for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
604f587de0eSPatrick McHardy 		/* Check Range */
605f587de0eSPatrick McHardy 		if (i >= f->ub) {	/* Newer Version? */
606ec8a8f3cSEric Sesterhenn 			if (nf_h323_error_boundary(bs, 2, 0))
607bc7d811aSEric Sesterhenn 				return H323_ERROR_BOUND;
608f587de0eSPatrick McHardy 			len = get_len(bs);
609ec8a8f3cSEric Sesterhenn 			if (nf_h323_error_boundary(bs, len, 0))
610bc7d811aSEric Sesterhenn 				return H323_ERROR_BOUND;
611f587de0eSPatrick McHardy 			bs->cur += len;
612f587de0eSPatrick McHardy 			continue;
613f587de0eSPatrick McHardy 		}
614f587de0eSPatrick McHardy 
615558585aaSJing Min Zhao 		if (son->attr & STOP) {
616558585aaSJing Min Zhao 			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
617558585aaSJing Min Zhao 			      son->name);
618558585aaSJing Min Zhao 			return H323_ERROR_STOP;
619558585aaSJing Min Zhao 		}
620558585aaSJing Min Zhao 
621558585aaSJing Min Zhao 		if (!((0x80000000 >> opt) & bmp2))	/* Not present */
622558585aaSJing Min Zhao 			continue;
623558585aaSJing Min Zhao 
624ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
625bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
626f587de0eSPatrick McHardy 		len = get_len(bs);
627ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, len, 0))
628bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
629f587de0eSPatrick McHardy 		if (!base || !(son->attr & DECODE)) {
630f587de0eSPatrick McHardy 			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
631f587de0eSPatrick McHardy 			      son->name);
632f587de0eSPatrick McHardy 			bs->cur += len;
633f587de0eSPatrick McHardy 			continue;
634f587de0eSPatrick McHardy 		}
635f587de0eSPatrick McHardy 		beg = bs->cur;
636f587de0eSPatrick McHardy 
637f587de0eSPatrick McHardy 		if ((err = (Decoders[son->type]) (bs, son, base,
638f587de0eSPatrick McHardy 						  level + 1)) <
639f587de0eSPatrick McHardy 		    H323_ERROR_NONE)
640f587de0eSPatrick McHardy 			return err;
641f587de0eSPatrick McHardy 
642f587de0eSPatrick McHardy 		bs->cur = beg + len;
643f587de0eSPatrick McHardy 		bs->bit = 0;
644f587de0eSPatrick McHardy 	}
645f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
646f587de0eSPatrick McHardy }
647f587de0eSPatrick McHardy 
decode_seqof(struct bitstr * bs,const struct field_t * f,char * base,int level)64867704c2aSHarsha Sharma static int decode_seqof(struct bitstr *bs, const struct field_t *f,
649905e3e8eSJan Engelhardt                         char *base, int level)
650f587de0eSPatrick McHardy {
6511f807d6eSJan Engelhardt 	unsigned int count, effective_count = 0, i, len = 0;
652f587de0eSPatrick McHardy 	int err;
653905e3e8eSJan Engelhardt 	const struct field_t *son;
654f587de0eSPatrick McHardy 	unsigned char *beg = NULL;
655f587de0eSPatrick McHardy 
656f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
657f587de0eSPatrick McHardy 
658f587de0eSPatrick McHardy 	/* Decode? */
659f587de0eSPatrick McHardy 	base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
660f587de0eSPatrick McHardy 
661f587de0eSPatrick McHardy 	/* Decode item count */
662f587de0eSPatrick McHardy 	switch (f->sz) {
663f587de0eSPatrick McHardy 	case BYTE:
664f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
665ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 1, 0))
666bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
667f587de0eSPatrick McHardy 		count = *bs->cur++;
668f587de0eSPatrick McHardy 		break;
669f587de0eSPatrick McHardy 	case WORD:
670f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
671ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
672bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
673f587de0eSPatrick McHardy 		count = *bs->cur++;
674f587de0eSPatrick McHardy 		count <<= 8;
675b4232a22SDavid Sterba 		count += *bs->cur++;
676f587de0eSPatrick McHardy 		break;
677f587de0eSPatrick McHardy 	case SEMI:
678f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
679ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
680bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
681f587de0eSPatrick McHardy 		count = get_len(bs);
682f587de0eSPatrick McHardy 		break;
683f587de0eSPatrick McHardy 	default:
684ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 0, f->sz))
685ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
686f587de0eSPatrick McHardy 		count = get_bits(bs, f->sz);
687f587de0eSPatrick McHardy 		break;
688f587de0eSPatrick McHardy 	}
689f587de0eSPatrick McHardy 	count += f->lb;
690f587de0eSPatrick McHardy 
691f587de0eSPatrick McHardy 	/* Write Count */
692f587de0eSPatrick McHardy 	if (base) {
693f587de0eSPatrick McHardy 		effective_count = count > f->ub ? f->ub : count;
6941f807d6eSJan Engelhardt 		*(unsigned int *)base = effective_count;
6951f807d6eSJan Engelhardt 		base += sizeof(unsigned int);
696f587de0eSPatrick McHardy 	}
697f587de0eSPatrick McHardy 
698f587de0eSPatrick McHardy 	/* Decode nested field */
699f587de0eSPatrick McHardy 	son = f->fields;
700f587de0eSPatrick McHardy 	if (base)
701f587de0eSPatrick McHardy 		base -= son->offset;
702f587de0eSPatrick McHardy 	for (i = 0; i < count; i++) {
703f587de0eSPatrick McHardy 		if (son->attr & OPEN) {
704f587de0eSPatrick McHardy 			BYTE_ALIGN(bs);
705ec8a8f3cSEric Sesterhenn 			if (nf_h323_error_boundary(bs, 2, 0))
706ec8a8f3cSEric Sesterhenn 				return H323_ERROR_BOUND;
707f587de0eSPatrick McHardy 			len = get_len(bs);
708ec8a8f3cSEric Sesterhenn 			if (nf_h323_error_boundary(bs, len, 0))
709bc7d811aSEric Sesterhenn 				return H323_ERROR_BOUND;
710f587de0eSPatrick McHardy 			if (!base || !(son->attr & DECODE)) {
711f587de0eSPatrick McHardy 				PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
712f587de0eSPatrick McHardy 				      " ", son->name);
713f587de0eSPatrick McHardy 				bs->cur += len;
714f587de0eSPatrick McHardy 				continue;
715f587de0eSPatrick McHardy 			}
716f587de0eSPatrick McHardy 			beg = bs->cur;
717f587de0eSPatrick McHardy 
718f587de0eSPatrick McHardy 			if ((err = (Decoders[son->type]) (bs, son,
719f587de0eSPatrick McHardy 							  i <
720f587de0eSPatrick McHardy 							  effective_count ?
721f587de0eSPatrick McHardy 							  base : NULL,
722f587de0eSPatrick McHardy 							  level + 1)) <
723f587de0eSPatrick McHardy 			    H323_ERROR_NONE)
724f587de0eSPatrick McHardy 				return err;
725f587de0eSPatrick McHardy 
726f587de0eSPatrick McHardy 			bs->cur = beg + len;
727f587de0eSPatrick McHardy 			bs->bit = 0;
728f587de0eSPatrick McHardy 		} else
729f587de0eSPatrick McHardy 			if ((err = (Decoders[son->type]) (bs, son,
730f587de0eSPatrick McHardy 							  i <
731f587de0eSPatrick McHardy 							  effective_count ?
732f587de0eSPatrick McHardy 							  base : NULL,
733f587de0eSPatrick McHardy 							  level + 1)) <
734f587de0eSPatrick McHardy 			    H323_ERROR_NONE)
735f587de0eSPatrick McHardy 				return err;
736f587de0eSPatrick McHardy 
737f587de0eSPatrick McHardy 		if (base)
738f587de0eSPatrick McHardy 			base += son->offset;
739f587de0eSPatrick McHardy 	}
740f587de0eSPatrick McHardy 
741f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
742f587de0eSPatrick McHardy }
743f587de0eSPatrick McHardy 
decode_choice(struct bitstr * bs,const struct field_t * f,char * base,int level)74467704c2aSHarsha Sharma static int decode_choice(struct bitstr *bs, const struct field_t *f,
745905e3e8eSJan Engelhardt                          char *base, int level)
746f587de0eSPatrick McHardy {
7471f807d6eSJan Engelhardt 	unsigned int type, ext, len = 0;
748f587de0eSPatrick McHardy 	int err;
749905e3e8eSJan Engelhardt 	const struct field_t *son;
750f587de0eSPatrick McHardy 	unsigned char *beg = NULL;
751f587de0eSPatrick McHardy 
752f587de0eSPatrick McHardy 	PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
753f587de0eSPatrick McHardy 
754f587de0eSPatrick McHardy 	/* Decode? */
755f587de0eSPatrick McHardy 	base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
756f587de0eSPatrick McHardy 
757f587de0eSPatrick McHardy 	/* Decode the choice index number */
758ec8a8f3cSEric Sesterhenn 	if (nf_h323_error_boundary(bs, 0, 1))
759ec8a8f3cSEric Sesterhenn 		return H323_ERROR_BOUND;
760f587de0eSPatrick McHardy 	if ((f->attr & EXT) && get_bit(bs)) {
761f587de0eSPatrick McHardy 		ext = 1;
762ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 0, 7))
763ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
764f587de0eSPatrick McHardy 		type = get_bits(bs, 7) + f->lb;
765f587de0eSPatrick McHardy 	} else {
766f587de0eSPatrick McHardy 		ext = 0;
767ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 0, f->sz))
768ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
769f587de0eSPatrick McHardy 		type = get_bits(bs, f->sz);
77025845b51SJing Min Zhao 		if (type >= f->lb)
77125845b51SJing Min Zhao 			return H323_ERROR_RANGE;
772f587de0eSPatrick McHardy 	}
773f587de0eSPatrick McHardy 
774f587de0eSPatrick McHardy 	/* Write Type */
775f587de0eSPatrick McHardy 	if (base)
7761f807d6eSJan Engelhardt 		*(unsigned int *)base = type;
777f587de0eSPatrick McHardy 
778f587de0eSPatrick McHardy 	/* Check Range */
779f587de0eSPatrick McHardy 	if (type >= f->ub) {	/* Newer version? */
780f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
781ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, 2, 0))
782ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
783f587de0eSPatrick McHardy 		len = get_len(bs);
784ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, len, 0))
785bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
786f587de0eSPatrick McHardy 		bs->cur += len;
787f587de0eSPatrick McHardy 		return H323_ERROR_NONE;
788f587de0eSPatrick McHardy 	}
789f587de0eSPatrick McHardy 
790f587de0eSPatrick McHardy 	/* Transfer to son level */
791f587de0eSPatrick McHardy 	son = &f->fields[type];
792f587de0eSPatrick McHardy 	if (son->attr & STOP) {
793f587de0eSPatrick McHardy 		PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
794f587de0eSPatrick McHardy 		return H323_ERROR_STOP;
795f587de0eSPatrick McHardy 	}
796f587de0eSPatrick McHardy 
797f587de0eSPatrick McHardy 	if (ext || (son->attr & OPEN)) {
798f587de0eSPatrick McHardy 		BYTE_ALIGN(bs);
799ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, len, 0))
800ec8a8f3cSEric Sesterhenn 			return H323_ERROR_BOUND;
801f587de0eSPatrick McHardy 		len = get_len(bs);
802ec8a8f3cSEric Sesterhenn 		if (nf_h323_error_boundary(bs, len, 0))
803bc7d811aSEric Sesterhenn 			return H323_ERROR_BOUND;
804f587de0eSPatrick McHardy 		if (!base || !(son->attr & DECODE)) {
805f587de0eSPatrick McHardy 			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
806f587de0eSPatrick McHardy 			      son->name);
807f587de0eSPatrick McHardy 			bs->cur += len;
808f587de0eSPatrick McHardy 			return H323_ERROR_NONE;
809f587de0eSPatrick McHardy 		}
810f587de0eSPatrick McHardy 		beg = bs->cur;
811f587de0eSPatrick McHardy 
812f587de0eSPatrick McHardy 		if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
813f587de0eSPatrick McHardy 		    H323_ERROR_NONE)
814f587de0eSPatrick McHardy 			return err;
815f587de0eSPatrick McHardy 
816f587de0eSPatrick McHardy 		bs->cur = beg + len;
817f587de0eSPatrick McHardy 		bs->bit = 0;
818f587de0eSPatrick McHardy 	} else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
819f587de0eSPatrick McHardy 		   H323_ERROR_NONE)
820f587de0eSPatrick McHardy 		return err;
821f587de0eSPatrick McHardy 
822f587de0eSPatrick McHardy 	return H323_ERROR_NONE;
823f587de0eSPatrick McHardy }
824f587de0eSPatrick McHardy 
DecodeRasMessage(unsigned char * buf,size_t sz,RasMessage * ras)825f587de0eSPatrick McHardy int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage *ras)
826f587de0eSPatrick McHardy {
827905e3e8eSJan Engelhardt 	static const struct field_t ras_message = {
828f587de0eSPatrick McHardy 		FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
829f587de0eSPatrick McHardy 		0, _RasMessage
830f587de0eSPatrick McHardy 	};
83167704c2aSHarsha Sharma 	struct bitstr bs;
832f587de0eSPatrick McHardy 
833f587de0eSPatrick McHardy 	bs.buf = bs.beg = bs.cur = buf;
834f587de0eSPatrick McHardy 	bs.end = buf + sz;
835f587de0eSPatrick McHardy 	bs.bit = 0;
836f587de0eSPatrick McHardy 
837f587de0eSPatrick McHardy 	return decode_choice(&bs, &ras_message, (char *) ras, 0);
838f587de0eSPatrick McHardy }
839f587de0eSPatrick McHardy 
DecodeH323_UserInformation(unsigned char * buf,unsigned char * beg,size_t sz,H323_UserInformation * uuie)840f587de0eSPatrick McHardy static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
841f587de0eSPatrick McHardy 				      size_t sz, H323_UserInformation *uuie)
842f587de0eSPatrick McHardy {
843905e3e8eSJan Engelhardt 	static const struct field_t h323_userinformation = {
844f587de0eSPatrick McHardy 		FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
845f587de0eSPatrick McHardy 		0, _H323_UserInformation
846f587de0eSPatrick McHardy 	};
84767704c2aSHarsha Sharma 	struct bitstr bs;
848f587de0eSPatrick McHardy 
849f587de0eSPatrick McHardy 	bs.buf = buf;
850f587de0eSPatrick McHardy 	bs.beg = bs.cur = beg;
851f587de0eSPatrick McHardy 	bs.end = beg + sz;
852f587de0eSPatrick McHardy 	bs.bit = 0;
853f587de0eSPatrick McHardy 
854f587de0eSPatrick McHardy 	return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
855f587de0eSPatrick McHardy }
856f587de0eSPatrick McHardy 
DecodeMultimediaSystemControlMessage(unsigned char * buf,size_t sz,MultimediaSystemControlMessage * mscm)857f587de0eSPatrick McHardy int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
858f587de0eSPatrick McHardy 					 MultimediaSystemControlMessage *
859f587de0eSPatrick McHardy 					 mscm)
860f587de0eSPatrick McHardy {
861905e3e8eSJan Engelhardt 	static const struct field_t multimediasystemcontrolmessage = {
862f587de0eSPatrick McHardy 		FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
863f587de0eSPatrick McHardy 		DECODE | EXT, 0, _MultimediaSystemControlMessage
864f587de0eSPatrick McHardy 	};
86567704c2aSHarsha Sharma 	struct bitstr bs;
866f587de0eSPatrick McHardy 
867f587de0eSPatrick McHardy 	bs.buf = bs.beg = bs.cur = buf;
868f587de0eSPatrick McHardy 	bs.end = buf + sz;
869f587de0eSPatrick McHardy 	bs.bit = 0;
870f587de0eSPatrick McHardy 
871f587de0eSPatrick McHardy 	return decode_choice(&bs, &multimediasystemcontrolmessage,
872f587de0eSPatrick McHardy 			     (char *) mscm, 0);
873f587de0eSPatrick McHardy }
874f587de0eSPatrick McHardy 
DecodeQ931(unsigned char * buf,size_t sz,Q931 * q931)875f587de0eSPatrick McHardy int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931)
876f587de0eSPatrick McHardy {
877f587de0eSPatrick McHardy 	unsigned char *p = buf;
878f587de0eSPatrick McHardy 	int len;
879f587de0eSPatrick McHardy 
880f587de0eSPatrick McHardy 	if (!p || sz < 1)
881f587de0eSPatrick McHardy 		return H323_ERROR_BOUND;
882f587de0eSPatrick McHardy 
883f587de0eSPatrick McHardy 	/* Protocol Discriminator */
884f587de0eSPatrick McHardy 	if (*p != 0x08) {
885f587de0eSPatrick McHardy 		PRINT("Unknown Protocol Discriminator\n");
886f587de0eSPatrick McHardy 		return H323_ERROR_RANGE;
887f587de0eSPatrick McHardy 	}
888f587de0eSPatrick McHardy 	p++;
889f587de0eSPatrick McHardy 	sz--;
890f587de0eSPatrick McHardy 
891f587de0eSPatrick McHardy 	/* CallReferenceValue */
892f587de0eSPatrick McHardy 	if (sz < 1)
893f587de0eSPatrick McHardy 		return H323_ERROR_BOUND;
894f587de0eSPatrick McHardy 	len = *p++;
895f587de0eSPatrick McHardy 	sz--;
896f587de0eSPatrick McHardy 	if (sz < len)
897f587de0eSPatrick McHardy 		return H323_ERROR_BOUND;
898f587de0eSPatrick McHardy 	p += len;
899f587de0eSPatrick McHardy 	sz -= len;
900f587de0eSPatrick McHardy 
901f587de0eSPatrick McHardy 	/* Message Type */
902c2b9b4feSToby DiPasquale 	if (sz < 2)
903f587de0eSPatrick McHardy 		return H323_ERROR_BOUND;
904f587de0eSPatrick McHardy 	q931->MessageType = *p++;
905c2b9b4feSToby DiPasquale 	sz--;
906f587de0eSPatrick McHardy 	PRINT("MessageType = %02X\n", q931->MessageType);
907f587de0eSPatrick McHardy 	if (*p & 0x80) {
908f587de0eSPatrick McHardy 		p++;
909f587de0eSPatrick McHardy 		sz--;
910f587de0eSPatrick McHardy 	}
911f587de0eSPatrick McHardy 
912f587de0eSPatrick McHardy 	/* Decode Information Elements */
913f587de0eSPatrick McHardy 	while (sz > 0) {
914f587de0eSPatrick McHardy 		if (*p == 0x7e) {	/* UserUserIE */
915f587de0eSPatrick McHardy 			if (sz < 3)
916f587de0eSPatrick McHardy 				break;
917f587de0eSPatrick McHardy 			p++;
918f587de0eSPatrick McHardy 			len = *p++ << 8;
919f587de0eSPatrick McHardy 			len |= *p++;
920f587de0eSPatrick McHardy 			sz -= 3;
921f587de0eSPatrick McHardy 			if (sz < len)
922f587de0eSPatrick McHardy 				break;
923f587de0eSPatrick McHardy 			p++;
924f587de0eSPatrick McHardy 			len--;
925f587de0eSPatrick McHardy 			return DecodeH323_UserInformation(buf, p, len,
926f587de0eSPatrick McHardy 							  &q931->UUIE);
927f587de0eSPatrick McHardy 		}
928f587de0eSPatrick McHardy 		p++;
929f587de0eSPatrick McHardy 		sz--;
930f587de0eSPatrick McHardy 		if (sz < 1)
931f587de0eSPatrick McHardy 			break;
932f587de0eSPatrick McHardy 		len = *p++;
933e8daf27cSEric Sesterhenn 		sz--;
934f587de0eSPatrick McHardy 		if (sz < len)
935f587de0eSPatrick McHardy 			break;
936f587de0eSPatrick McHardy 		p += len;
937f587de0eSPatrick McHardy 		sz -= len;
938f587de0eSPatrick McHardy 	}
939f587de0eSPatrick McHardy 
940f587de0eSPatrick McHardy 	PRINT("Q.931 UUIE not found\n");
941f587de0eSPatrick McHardy 
942f587de0eSPatrick McHardy 	return H323_ERROR_BOUND;
943f587de0eSPatrick McHardy }
944