mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
![Yonatan Goldschmidt](/assets/img/avatar_default.png)
In 9fb9cbb108
("[NETFILTER]: Add nf_conntrack subsystem.") the new
generic nf_conntrack was introduced, and it came to supersede the old
ip_conntrack.
This change updates (some) of the obsolete comments referring to old
file/function names of the ip_conntrack mechanism, as well as removes a
few self-referencing comments that we shouldn't maintain anymore.
I did not update any comments referring to historical actions (e.g,
comments like "this file was derived from ..." were left untouched, even
if the referenced file is no longer here).
Signed-off-by: Yonatan Goldschmidt <yon.goldschmidt@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
939 lines
20 KiB
C
939 lines
20 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* BER and PER decoding library for H.323 conntrack/NAT module.
|
|
*
|
|
* Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
|
|
*
|
|
* See nf_conntrack_helper_h323_asn1.h for details.
|
|
*/
|
|
|
|
#ifdef __KERNEL__
|
|
#include <linux/kernel.h>
|
|
#else
|
|
#include <stdio.h>
|
|
#endif
|
|
#include <linux/netfilter/nf_conntrack_h323_asn1.h>
|
|
|
|
/* Trace Flag */
|
|
#ifndef H323_TRACE
|
|
#define H323_TRACE 0
|
|
#endif
|
|
|
|
#if H323_TRACE
|
|
#define TAB_SIZE 4
|
|
#define IFTHEN(cond, act) if(cond){act;}
|
|
#ifdef __KERNEL__
|
|
#define PRINT printk
|
|
#else
|
|
#define PRINT printf
|
|
#endif
|
|
#define FNAME(name) name,
|
|
#else
|
|
#define IFTHEN(cond, act)
|
|
#define PRINT(fmt, args...)
|
|
#define FNAME(name)
|
|
#endif
|
|
|
|
/* ASN.1 Types */
|
|
#define NUL 0
|
|
#define BOOL 1
|
|
#define OID 2
|
|
#define INT 3
|
|
#define ENUM 4
|
|
#define BITSTR 5
|
|
#define NUMSTR 6
|
|
#define NUMDGT 6
|
|
#define TBCDSTR 6
|
|
#define OCTSTR 7
|
|
#define PRTSTR 7
|
|
#define IA5STR 7
|
|
#define GENSTR 7
|
|
#define BMPSTR 8
|
|
#define SEQ 9
|
|
#define SET 9
|
|
#define SEQOF 10
|
|
#define SETOF 10
|
|
#define CHOICE 11
|
|
|
|
/* Constraint Types */
|
|
#define FIXD 0
|
|
/* #define BITS 1-8 */
|
|
#define BYTE 9
|
|
#define WORD 10
|
|
#define CONS 11
|
|
#define SEMI 12
|
|
#define UNCO 13
|
|
|
|
/* ASN.1 Type Attributes */
|
|
#define SKIP 0
|
|
#define STOP 1
|
|
#define DECODE 2
|
|
#define EXT 4
|
|
#define OPEN 8
|
|
#define OPT 16
|
|
|
|
|
|
/* ASN.1 Field Structure */
|
|
typedef struct field_t {
|
|
#if H323_TRACE
|
|
char *name;
|
|
#endif
|
|
unsigned char type;
|
|
unsigned char sz;
|
|
unsigned char lb;
|
|
unsigned char ub;
|
|
unsigned short attr;
|
|
unsigned short offset;
|
|
const struct field_t *fields;
|
|
} field_t;
|
|
|
|
/* Bit Stream */
|
|
struct bitstr {
|
|
unsigned char *buf;
|
|
unsigned char *beg;
|
|
unsigned char *end;
|
|
unsigned char *cur;
|
|
unsigned int bit;
|
|
};
|
|
|
|
/* Tool Functions */
|
|
#define INC_BIT(bs) if((++(bs)->bit)>7){(bs)->cur++;(bs)->bit=0;}
|
|
#define INC_BITS(bs,b) if(((bs)->bit+=(b))>7){(bs)->cur+=(bs)->bit>>3;(bs)->bit&=7;}
|
|
#define BYTE_ALIGN(bs) if((bs)->bit){(bs)->cur++;(bs)->bit=0;}
|
|
static unsigned int get_len(struct bitstr *bs);
|
|
static unsigned int get_bit(struct bitstr *bs);
|
|
static unsigned int get_bits(struct bitstr *bs, unsigned int b);
|
|
static unsigned int get_bitmap(struct bitstr *bs, unsigned int b);
|
|
static unsigned int get_uint(struct bitstr *bs, int b);
|
|
|
|
/* Decoder Functions */
|
|
static int decode_nul(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_bool(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_oid(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_int(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_enum(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_bitstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_numstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_octstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_bmpstr(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_seq(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_seqof(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
static int decode_choice(struct bitstr *bs, const struct field_t *f, char *base, int level);
|
|
|
|
/* Decoder Functions Vector */
|
|
typedef int (*decoder_t)(struct bitstr *, const struct field_t *, char *, int);
|
|
static const decoder_t Decoders[] = {
|
|
decode_nul,
|
|
decode_bool,
|
|
decode_oid,
|
|
decode_int,
|
|
decode_enum,
|
|
decode_bitstr,
|
|
decode_numstr,
|
|
decode_octstr,
|
|
decode_bmpstr,
|
|
decode_seq,
|
|
decode_seqof,
|
|
decode_choice,
|
|
};
|
|
|
|
/*
|
|
* H.323 Types
|
|
*/
|
|
#include "nf_conntrack_h323_types.c"
|
|
|
|
/*
|
|
* Functions
|
|
*/
|
|
|
|
/* Assume bs is aligned && v < 16384 */
|
|
static unsigned int get_len(struct bitstr *bs)
|
|
{
|
|
unsigned int v;
|
|
|
|
v = *bs->cur++;
|
|
|
|
if (v & 0x80) {
|
|
v &= 0x3f;
|
|
v <<= 8;
|
|
v += *bs->cur++;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
static int nf_h323_error_boundary(struct bitstr *bs, size_t bytes, size_t bits)
|
|
{
|
|
bits += bs->bit;
|
|
bytes += bits / BITS_PER_BYTE;
|
|
if (bits % BITS_PER_BYTE > 0)
|
|
bytes++;
|
|
|
|
if (bs->cur + bytes > bs->end)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int get_bit(struct bitstr *bs)
|
|
{
|
|
unsigned int b = (*bs->cur) & (0x80 >> bs->bit);
|
|
|
|
INC_BIT(bs);
|
|
|
|
return b;
|
|
}
|
|
|
|
/* Assume b <= 8 */
|
|
static unsigned int get_bits(struct bitstr *bs, unsigned int b)
|
|
{
|
|
unsigned int v, l;
|
|
|
|
v = (*bs->cur) & (0xffU >> bs->bit);
|
|
l = b + bs->bit;
|
|
|
|
if (l < 8) {
|
|
v >>= 8 - l;
|
|
bs->bit = l;
|
|
} else if (l == 8) {
|
|
bs->cur++;
|
|
bs->bit = 0;
|
|
} else { /* l > 8 */
|
|
|
|
v <<= 8;
|
|
v += *(++bs->cur);
|
|
v >>= 16 - l;
|
|
bs->bit = l - 8;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
/* Assume b <= 32 */
|
|
static unsigned int get_bitmap(struct bitstr *bs, unsigned int b)
|
|
{
|
|
unsigned int v, l, shift, bytes;
|
|
|
|
if (!b)
|
|
return 0;
|
|
|
|
l = bs->bit + b;
|
|
|
|
if (l < 8) {
|
|
v = (unsigned int)(*bs->cur) << (bs->bit + 24);
|
|
bs->bit = l;
|
|
} else if (l == 8) {
|
|
v = (unsigned int)(*bs->cur++) << (bs->bit + 24);
|
|
bs->bit = 0;
|
|
} else {
|
|
for (bytes = l >> 3, shift = 24, v = 0; bytes;
|
|
bytes--, shift -= 8)
|
|
v |= (unsigned int)(*bs->cur++) << shift;
|
|
|
|
if (l < 32) {
|
|
v |= (unsigned int)(*bs->cur) << shift;
|
|
v <<= bs->bit;
|
|
} else if (l > 32) {
|
|
v <<= bs->bit;
|
|
v |= (*bs->cur) >> (8 - bs->bit);
|
|
}
|
|
|
|
bs->bit = l & 0x7;
|
|
}
|
|
|
|
v &= 0xffffffff << (32 - b);
|
|
|
|
return v;
|
|
}
|
|
|
|
/*
|
|
* Assume bs is aligned and sizeof(unsigned int) == 4
|
|
*/
|
|
static unsigned int get_uint(struct bitstr *bs, int b)
|
|
{
|
|
unsigned int v = 0;
|
|
|
|
switch (b) {
|
|
case 4:
|
|
v |= *bs->cur++;
|
|
v <<= 8;
|
|
/* fall through */
|
|
case 3:
|
|
v |= *bs->cur++;
|
|
v <<= 8;
|
|
/* fall through */
|
|
case 2:
|
|
v |= *bs->cur++;
|
|
v <<= 8;
|
|
/* fall through */
|
|
case 1:
|
|
v |= *bs->cur++;
|
|
break;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
static int decode_nul(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_bool(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
INC_BIT(bs);
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_oid(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
int len;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 1, 0))
|
|
return H323_ERROR_BOUND;
|
|
|
|
len = *bs->cur++;
|
|
bs->cur += len;
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_int(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int len;
|
|
|
|
PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
|
|
|
|
switch (f->sz) {
|
|
case BYTE: /* Range == 256 */
|
|
BYTE_ALIGN(bs);
|
|
bs->cur++;
|
|
break;
|
|
case WORD: /* 257 <= Range <= 64K */
|
|
BYTE_ALIGN(bs);
|
|
bs->cur += 2;
|
|
break;
|
|
case CONS: /* 64K < Range < 4G */
|
|
if (nf_h323_error_boundary(bs, 0, 2))
|
|
return H323_ERROR_BOUND;
|
|
len = get_bits(bs, 2) + 1;
|
|
BYTE_ALIGN(bs);
|
|
if (base && (f->attr & DECODE)) { /* timeToLive */
|
|
unsigned int v = get_uint(bs, len) + f->lb;
|
|
PRINT(" = %u", v);
|
|
*((unsigned int *)(base + f->offset)) = v;
|
|
}
|
|
bs->cur += len;
|
|
break;
|
|
case UNCO:
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
bs->cur += len;
|
|
break;
|
|
default: /* 2 <= Range <= 255 */
|
|
INC_BITS(bs, f->sz);
|
|
break;
|
|
}
|
|
|
|
PRINT("\n");
|
|
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_enum(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
if ((f->attr & EXT) && get_bit(bs)) {
|
|
INC_BITS(bs, 7);
|
|
} else {
|
|
INC_BITS(bs, f->sz);
|
|
}
|
|
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_bitstr(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int len;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
BYTE_ALIGN(bs);
|
|
switch (f->sz) {
|
|
case FIXD: /* fixed length > 16 */
|
|
len = f->lb;
|
|
break;
|
|
case WORD: /* 2-byte length */
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = (*bs->cur++) << 8;
|
|
len += (*bs->cur++) + f->lb;
|
|
break;
|
|
case SEMI:
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
break;
|
|
default:
|
|
len = 0;
|
|
break;
|
|
}
|
|
|
|
bs->cur += len >> 3;
|
|
bs->bit = len & 7;
|
|
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_numstr(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int len;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
/* 2 <= Range <= 255 */
|
|
if (nf_h323_error_boundary(bs, 0, f->sz))
|
|
return H323_ERROR_BOUND;
|
|
len = get_bits(bs, f->sz) + f->lb;
|
|
|
|
BYTE_ALIGN(bs);
|
|
INC_BITS(bs, (len << 2));
|
|
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_octstr(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int len;
|
|
|
|
PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
|
|
|
|
switch (f->sz) {
|
|
case FIXD: /* Range == 1 */
|
|
if (f->lb > 2) {
|
|
BYTE_ALIGN(bs);
|
|
if (base && (f->attr & DECODE)) {
|
|
/* The IP Address */
|
|
IFTHEN(f->lb == 4,
|
|
PRINT(" = %d.%d.%d.%d:%d",
|
|
bs->cur[0], bs->cur[1],
|
|
bs->cur[2], bs->cur[3],
|
|
bs->cur[4] * 256 + bs->cur[5]));
|
|
*((unsigned int *)(base + f->offset)) =
|
|
bs->cur - bs->buf;
|
|
}
|
|
}
|
|
len = f->lb;
|
|
break;
|
|
case BYTE: /* Range == 256 */
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 1, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = (*bs->cur++) + f->lb;
|
|
break;
|
|
case SEMI:
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs) + f->lb;
|
|
break;
|
|
default: /* 2 <= Range <= 255 */
|
|
if (nf_h323_error_boundary(bs, 0, f->sz))
|
|
return H323_ERROR_BOUND;
|
|
len = get_bits(bs, f->sz) + f->lb;
|
|
BYTE_ALIGN(bs);
|
|
break;
|
|
}
|
|
|
|
bs->cur += len;
|
|
|
|
PRINT("\n");
|
|
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_bmpstr(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int len;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
switch (f->sz) {
|
|
case BYTE: /* Range == 256 */
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 1, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = (*bs->cur++) + f->lb;
|
|
break;
|
|
default: /* 2 <= Range <= 255 */
|
|
if (nf_h323_error_boundary(bs, 0, f->sz))
|
|
return H323_ERROR_BOUND;
|
|
len = get_bits(bs, f->sz) + f->lb;
|
|
BYTE_ALIGN(bs);
|
|
break;
|
|
}
|
|
|
|
bs->cur += len << 1;
|
|
|
|
if (nf_h323_error_boundary(bs, 0, 0))
|
|
return H323_ERROR_BOUND;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_seq(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
|
|
int err;
|
|
const struct field_t *son;
|
|
unsigned char *beg = NULL;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
/* Decode? */
|
|
base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
|
|
|
|
/* Extensible? */
|
|
if (nf_h323_error_boundary(bs, 0, 1))
|
|
return H323_ERROR_BOUND;
|
|
ext = (f->attr & EXT) ? get_bit(bs) : 0;
|
|
|
|
/* Get fields bitmap */
|
|
if (nf_h323_error_boundary(bs, 0, f->sz))
|
|
return H323_ERROR_BOUND;
|
|
bmp = get_bitmap(bs, f->sz);
|
|
if (base)
|
|
*(unsigned int *)base = bmp;
|
|
|
|
/* Decode the root components */
|
|
for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
|
|
if (son->attr & STOP) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
|
|
son->name);
|
|
return H323_ERROR_STOP;
|
|
}
|
|
|
|
if (son->attr & OPT) { /* Optional component */
|
|
if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */
|
|
continue;
|
|
}
|
|
|
|
/* Decode */
|
|
if (son->attr & OPEN) { /* Open field */
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
if (!base || !(son->attr & DECODE)) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
|
|
" ", son->name);
|
|
bs->cur += len;
|
|
continue;
|
|
}
|
|
beg = bs->cur;
|
|
|
|
/* Decode */
|
|
if ((err = (Decoders[son->type]) (bs, son, base,
|
|
level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
|
|
bs->cur = beg + len;
|
|
bs->bit = 0;
|
|
} else if ((err = (Decoders[son->type]) (bs, son, base,
|
|
level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
}
|
|
|
|
/* No extension? */
|
|
if (!ext)
|
|
return H323_ERROR_NONE;
|
|
|
|
/* Get the extension bitmap */
|
|
if (nf_h323_error_boundary(bs, 0, 7))
|
|
return H323_ERROR_BOUND;
|
|
bmp2_len = get_bits(bs, 7) + 1;
|
|
if (nf_h323_error_boundary(bs, 0, bmp2_len))
|
|
return H323_ERROR_BOUND;
|
|
bmp2 = get_bitmap(bs, bmp2_len);
|
|
bmp |= bmp2 >> f->sz;
|
|
if (base)
|
|
*(unsigned int *)base = bmp;
|
|
BYTE_ALIGN(bs);
|
|
|
|
/* Decode the extension components */
|
|
for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
|
|
/* Check Range */
|
|
if (i >= f->ub) { /* Newer Version? */
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
bs->cur += len;
|
|
continue;
|
|
}
|
|
|
|
if (son->attr & STOP) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
|
|
son->name);
|
|
return H323_ERROR_STOP;
|
|
}
|
|
|
|
if (!((0x80000000 >> opt) & bmp2)) /* Not present */
|
|
continue;
|
|
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
if (!base || !(son->attr & DECODE)) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
|
|
son->name);
|
|
bs->cur += len;
|
|
continue;
|
|
}
|
|
beg = bs->cur;
|
|
|
|
if ((err = (Decoders[son->type]) (bs, son, base,
|
|
level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
|
|
bs->cur = beg + len;
|
|
bs->bit = 0;
|
|
}
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_seqof(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int count, effective_count = 0, i, len = 0;
|
|
int err;
|
|
const struct field_t *son;
|
|
unsigned char *beg = NULL;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
/* Decode? */
|
|
base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
|
|
|
|
/* Decode item count */
|
|
switch (f->sz) {
|
|
case BYTE:
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 1, 0))
|
|
return H323_ERROR_BOUND;
|
|
count = *bs->cur++;
|
|
break;
|
|
case WORD:
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
count = *bs->cur++;
|
|
count <<= 8;
|
|
count += *bs->cur++;
|
|
break;
|
|
case SEMI:
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
count = get_len(bs);
|
|
break;
|
|
default:
|
|
if (nf_h323_error_boundary(bs, 0, f->sz))
|
|
return H323_ERROR_BOUND;
|
|
count = get_bits(bs, f->sz);
|
|
break;
|
|
}
|
|
count += f->lb;
|
|
|
|
/* Write Count */
|
|
if (base) {
|
|
effective_count = count > f->ub ? f->ub : count;
|
|
*(unsigned int *)base = effective_count;
|
|
base += sizeof(unsigned int);
|
|
}
|
|
|
|
/* Decode nested field */
|
|
son = f->fields;
|
|
if (base)
|
|
base -= son->offset;
|
|
for (i = 0; i < count; i++) {
|
|
if (son->attr & OPEN) {
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
if (!base || !(son->attr & DECODE)) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
|
|
" ", son->name);
|
|
bs->cur += len;
|
|
continue;
|
|
}
|
|
beg = bs->cur;
|
|
|
|
if ((err = (Decoders[son->type]) (bs, son,
|
|
i <
|
|
effective_count ?
|
|
base : NULL,
|
|
level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
|
|
bs->cur = beg + len;
|
|
bs->bit = 0;
|
|
} else
|
|
if ((err = (Decoders[son->type]) (bs, son,
|
|
i <
|
|
effective_count ?
|
|
base : NULL,
|
|
level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
|
|
if (base)
|
|
base += son->offset;
|
|
}
|
|
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
static int decode_choice(struct bitstr *bs, const struct field_t *f,
|
|
char *base, int level)
|
|
{
|
|
unsigned int type, ext, len = 0;
|
|
int err;
|
|
const struct field_t *son;
|
|
unsigned char *beg = NULL;
|
|
|
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
|
|
|
/* Decode? */
|
|
base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
|
|
|
|
/* Decode the choice index number */
|
|
if (nf_h323_error_boundary(bs, 0, 1))
|
|
return H323_ERROR_BOUND;
|
|
if ((f->attr & EXT) && get_bit(bs)) {
|
|
ext = 1;
|
|
if (nf_h323_error_boundary(bs, 0, 7))
|
|
return H323_ERROR_BOUND;
|
|
type = get_bits(bs, 7) + f->lb;
|
|
} else {
|
|
ext = 0;
|
|
if (nf_h323_error_boundary(bs, 0, f->sz))
|
|
return H323_ERROR_BOUND;
|
|
type = get_bits(bs, f->sz);
|
|
if (type >= f->lb)
|
|
return H323_ERROR_RANGE;
|
|
}
|
|
|
|
/* Write Type */
|
|
if (base)
|
|
*(unsigned int *)base = type;
|
|
|
|
/* Check Range */
|
|
if (type >= f->ub) { /* Newer version? */
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, 2, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
bs->cur += len;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
/* Transfer to son level */
|
|
son = &f->fields[type];
|
|
if (son->attr & STOP) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
|
|
return H323_ERROR_STOP;
|
|
}
|
|
|
|
if (ext || (son->attr & OPEN)) {
|
|
BYTE_ALIGN(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
len = get_len(bs);
|
|
if (nf_h323_error_boundary(bs, len, 0))
|
|
return H323_ERROR_BOUND;
|
|
if (!base || !(son->attr & DECODE)) {
|
|
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
|
|
son->name);
|
|
bs->cur += len;
|
|
return H323_ERROR_NONE;
|
|
}
|
|
beg = bs->cur;
|
|
|
|
if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
|
|
bs->cur = beg + len;
|
|
bs->bit = 0;
|
|
} else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
|
|
H323_ERROR_NONE)
|
|
return err;
|
|
|
|
return H323_ERROR_NONE;
|
|
}
|
|
|
|
int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage *ras)
|
|
{
|
|
static const struct field_t ras_message = {
|
|
FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
|
|
0, _RasMessage
|
|
};
|
|
struct bitstr bs;
|
|
|
|
bs.buf = bs.beg = bs.cur = buf;
|
|
bs.end = buf + sz;
|
|
bs.bit = 0;
|
|
|
|
return decode_choice(&bs, &ras_message, (char *) ras, 0);
|
|
}
|
|
|
|
static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
|
|
size_t sz, H323_UserInformation *uuie)
|
|
{
|
|
static const struct field_t h323_userinformation = {
|
|
FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
|
|
0, _H323_UserInformation
|
|
};
|
|
struct bitstr bs;
|
|
|
|
bs.buf = buf;
|
|
bs.beg = bs.cur = beg;
|
|
bs.end = beg + sz;
|
|
bs.bit = 0;
|
|
|
|
return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
|
|
}
|
|
|
|
int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
|
|
MultimediaSystemControlMessage *
|
|
mscm)
|
|
{
|
|
static const struct field_t multimediasystemcontrolmessage = {
|
|
FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
|
|
DECODE | EXT, 0, _MultimediaSystemControlMessage
|
|
};
|
|
struct bitstr bs;
|
|
|
|
bs.buf = bs.beg = bs.cur = buf;
|
|
bs.end = buf + sz;
|
|
bs.bit = 0;
|
|
|
|
return decode_choice(&bs, &multimediasystemcontrolmessage,
|
|
(char *) mscm, 0);
|
|
}
|
|
|
|
int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931)
|
|
{
|
|
unsigned char *p = buf;
|
|
int len;
|
|
|
|
if (!p || sz < 1)
|
|
return H323_ERROR_BOUND;
|
|
|
|
/* Protocol Discriminator */
|
|
if (*p != 0x08) {
|
|
PRINT("Unknown Protocol Discriminator\n");
|
|
return H323_ERROR_RANGE;
|
|
}
|
|
p++;
|
|
sz--;
|
|
|
|
/* CallReferenceValue */
|
|
if (sz < 1)
|
|
return H323_ERROR_BOUND;
|
|
len = *p++;
|
|
sz--;
|
|
if (sz < len)
|
|
return H323_ERROR_BOUND;
|
|
p += len;
|
|
sz -= len;
|
|
|
|
/* Message Type */
|
|
if (sz < 2)
|
|
return H323_ERROR_BOUND;
|
|
q931->MessageType = *p++;
|
|
sz--;
|
|
PRINT("MessageType = %02X\n", q931->MessageType);
|
|
if (*p & 0x80) {
|
|
p++;
|
|
sz--;
|
|
}
|
|
|
|
/* Decode Information Elements */
|
|
while (sz > 0) {
|
|
if (*p == 0x7e) { /* UserUserIE */
|
|
if (sz < 3)
|
|
break;
|
|
p++;
|
|
len = *p++ << 8;
|
|
len |= *p++;
|
|
sz -= 3;
|
|
if (sz < len)
|
|
break;
|
|
p++;
|
|
len--;
|
|
return DecodeH323_UserInformation(buf, p, len,
|
|
&q931->UUIE);
|
|
}
|
|
p++;
|
|
sz--;
|
|
if (sz < 1)
|
|
break;
|
|
len = *p++;
|
|
sz--;
|
|
if (sz < len)
|
|
break;
|
|
p += len;
|
|
sz -= len;
|
|
}
|
|
|
|
PRINT("Q.931 UUIE not found\n");
|
|
|
|
return H323_ERROR_BOUND;
|
|
}
|