Revision af6af87d7e4ff67324425daa699b9cda32e3161d authored by Linus Torvalds on 20 July 2019, 00:19:24 UTC, committed by Linus Torvalds on 20 July 2019, 00:19:24 UTC
Pull ARM Devicetree updates from Olof Johansson:
 "We continue to see a lot of new material. I've highlighted some of it
  below, but there's been more beyond that as well.

  One of the sweeping changes is that many boards have seen their ARM
  Mali GPU devices added to device trees, since the DRM drivers have now
  been merged.

  So, with the caveat that I have surely missed several great
  contributions, here's a collection of the material this time around:

  New SoCs:

   - Mediatek mt8183 (4x Cortex-A73 + 4x Cortex-A53)

   - TI J721E (2x Cortex-A72 + 3x Cortex-R5F + 3 DSPs + MMA)

   - Amlogic G12B (4x Cortex-A73 + 2x Cortex-A53)

  New Boards / platforms:

   - Aspeed BMC support for a number of new server platforms

   - Kontron SMARC SoM (several i.MX6 versions)

   - Novtech's Meerkat96 (i.MX7)

   - ST Micro Avenger96 board

   - Hardkernel ODROID-N2 (Amlogic G12B)

   - Purism Librem5 devkit (i.MX8MQ)

   - Google Cheza (Qualcomm SDM845)

   - Qualcomm Dragonboard 845c (Qualcomm SDM845)

   - Hugsun X99 TV Box (Rockchip RK3399)

   - Khadas Edge/Edge-V/Captain (Rockchip RK3399)

  Updated / expanded boards and platforms:

   - Renesas r7s9210 has a lot of new peripherals added

   - Fixes and polish for Rockchip-based Chromebooks

   - Amlogic G12A has a lot of peripherals added

   - Nvidia Jetson Nano sees various fixes and improvements, and is now
     at feature parity with TX1"

* tag 'armsoc-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (586 commits)
  ARM: dts: gemini: Set DIR-685 SPI CS as active low
  ARM: dts: exynos: Adjust buck[78] regulators to supported values on Arndale Octa
  ARM: dts: exynos: Adjust buck[78] regulators to supported values on Odroid XU3 family
  ARM: dts: exynos: Move Mali400 GPU node to "/soc"
  ARM: dts: exynos: Fix imprecise abort on Mali GPU probe on Exynos4210
  arm64: dts: qcom: qcs404: Add missing space for cooling-cells property
  arm64: dts: rockchip: Fix USB3 Type-C on rk3399-sapphire
  arm64: dts: rockchip: Update DWC3 modules on RK3399 SoCs
  arm64: dts: rockchip: enable rk3328 watchdog clock
  ARM: dts: rockchip: add display nodes for rk322x
  ARM: dts: rockchip: fix vop iommu-cells on rk322x
  arm64: dts: rockchip: Add support for Hugsun X99 TV Box
  arm64: dts: rockchip: Define values for the IPA governor for rock960
  arm64: dts: rockchip: Fix multiple thermal zones conflict in rk3399.dtsi
  arm64: dts: rockchip: add core dtsi file for RK3399Pro SoCs
  arm64: dts: rockchip: improve rk3328-roc-cc rgmii performance.
  Revert "ARM: dts: rockchip: set PWM delay backlight settings for Minnie"
  ARM: dts: rockchip: Configure BT_DEV_WAKE in on rk3288-veyron
  arm64: dts: qcom: sdm845-cheza: add initial cheza dt
  ARM: dts: msm8974-FP2: Add vibration motor
  ...
2 parent s 8362fd6 + f90b8fd
Raw File
nf_conntrack_h323_asn1.c
// SPDX-License-Identifier: GPL-2.0-only
/*
 * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
 * 			      	     conntrack/NAT module.
 *
 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
 *
 * See ip_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;
}
back to top