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