linux-stable/net/netfilter/nf_conntrack_h323_asn1.c
Lena Wang 014a807f1c netfilter: nf_conntrack_h323: Add protection for bmp length out of range
[ Upstream commit 767146637e ]

UBSAN load reports an exception of BRK#5515 SHIFT_ISSUE:Bitwise shifts
that are out of bounds for their data type.

vmlinux   get_bitmap(b=75) + 712
<net/netfilter/nf_conntrack_h323_asn1.c:0>
vmlinux   decode_seq(bs=0xFFFFFFD008037000, f=0xFFFFFFD008037018, level=134443100) + 1956
<net/netfilter/nf_conntrack_h323_asn1.c:592>
vmlinux   decode_choice(base=0xFFFFFFD0080370F0, level=23843636) + 1216
<net/netfilter/nf_conntrack_h323_asn1.c:814>
vmlinux   decode_seq(f=0xFFFFFFD0080371A8, level=134443500) + 812
<net/netfilter/nf_conntrack_h323_asn1.c:576>
vmlinux   decode_choice(base=0xFFFFFFD008037280, level=0) + 1216
<net/netfilter/nf_conntrack_h323_asn1.c:814>
vmlinux   DecodeRasMessage() + 304
<net/netfilter/nf_conntrack_h323_asn1.c:833>
vmlinux   ras_help() + 684
<net/netfilter/nf_conntrack_h323_main.c:1728>
vmlinux   nf_confirm() + 188
<net/netfilter/nf_conntrack_proto.c:137>

Due to abnormal data in skb->data, the extension bitmap length
exceeds 32 when decoding ras message then uses the length to make
a shift operation. It will change into negative after several loop.
UBSAN load could detect a negative shift as an undefined behaviour
and reports exception.
So we add the protection to avoid the length exceeding 32. Or else
it will return out of range error and stop decoding.

Fixes: 5e35941d99 ("[NETFILTER]: Add H.323 conntrack/NAT helper")
Signed-off-by: Lena Wang <lena.wang@mediatek.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2024-03-15 10:48:19 -04:00

943 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;
fallthrough;
case 3:
v |= *bs->cur++;
v <<= 8;
fallthrough;
case 2:
v |= *bs->cur++;
v <<= 8;
fallthrough;
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;
if (f->sz > 32)
return H323_ERROR_RANGE;
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;
if (bmp2_len > 32)
return H323_ERROR_RANGE;
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;
}