Release 4.11 net/netfilter/nf_conntrack_h323_asn1.c
/****************************************************************************
* 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>
*
* This source code is licensed under General Public License version 2.
*
* 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 */
typedef struct {
unsigned char *buf;
unsigned char *beg;
unsigned char *end;
unsigned char *cur;
unsigned int bit;
}
bitstr_t;
/* 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;}
#define CHECK_BOUND(bs,n) if((bs)->cur+(n)>(bs)->end)return(H323_ERROR_BOUND)
static unsigned int get_len(bitstr_t *bs);
static unsigned int get_bit(bitstr_t *bs);
static unsigned int get_bits(bitstr_t *bs, unsigned int b);
static unsigned int get_bitmap(bitstr_t *bs, unsigned int b);
static unsigned int get_uint(bitstr_t *bs, int b);
/* Decoder Functions */
static int decode_nul(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_bool(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_oid(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_int(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_enum(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_bitstr(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_numstr(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_octstr(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_bmpstr(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_seq(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_seqof(bitstr_t *bs, const struct field_t *f, char *base, int level);
static int decode_choice(bitstr_t *bs, const struct field_t *f, char *base, int level);
/* Decoder Functions Vector */
typedef int (*decoder_t)(bitstr_t *, 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(bitstr_t *bs)
{
unsigned int v;
v = *bs->cur++;
if (v & 0x80) {
v &= 0x3f;
v <<= 8;
v += *bs->cur++;
}
return v;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 47 | 94.00% | 1 | 33.33% |
Jan Engelhardt | 2 | 4.00% | 1 | 33.33% |
Stephen Hemminger | 1 | 2.00% | 1 | 33.33% |
Total | 50 | 100.00% | 3 | 100.00% |
/****************************************************************************/
static unsigned int get_bit(bitstr_t *bs)
{
unsigned int b = (*bs->cur) & (0x80 >> bs->bit);
INC_BIT(bs);
return b;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 35 | 92.11% | 1 | 33.33% |
Jan Engelhardt | 2 | 5.26% | 1 | 33.33% |
Stephen Hemminger | 1 | 2.63% | 1 | 33.33% |
Total | 38 | 100.00% | 3 | 100.00% |
/****************************************************************************/
/* Assume b <= 8 */
static unsigned int get_bits(bitstr_t *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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 117 | 96.69% | 1 | 33.33% |
Jan Engelhardt | 3 | 2.48% | 1 | 33.33% |
Stephen Hemminger | 1 | 0.83% | 1 | 33.33% |
Total | 121 | 100.00% | 3 | 100.00% |
/****************************************************************************/
/* Assume b <= 32 */
static unsigned int get_bitmap(bitstr_t *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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 231 | 96.65% | 1 | 33.33% |
Jan Engelhardt | 7 | 2.93% | 1 | 33.33% |
Stephen Hemminger | 1 | 0.42% | 1 | 33.33% |
Total | 239 | 100.00% | 3 | 100.00% |
/****************************************************************************
* Assume bs is aligned and sizeof(unsigned int) == 4
****************************************************************************/
static unsigned int get_uint(bitstr_t *bs, int b)
{
unsigned int v = 0;
switch (b) {
case 4:
v |= *bs->cur++;
v <<= 8;
case 3:
v |= *bs->cur++;
v <<= 8;
case 2:
v |= *bs->cur++;
v <<= 8;
case 1:
v |= *bs->cur++;
break;
}
return v;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 83 | 96.51% | 1 | 33.33% |
Jan Engelhardt | 2 | 2.33% | 1 | 33.33% |
Stephen Hemminger | 1 | 1.16% | 1 | 33.33% |
Total | 86 | 100.00% | 3 | 100.00% |
/****************************************************************************/
static int decode_nul(bitstr_t *bs, const struct field_t *f,
char *base, int level)
{
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 38 | 92.68% | 1 | 33.33% |
Jan Engelhardt | 2 | 4.88% | 1 | 33.33% |
Stephen Hemminger | 1 | 2.44% | 1 | 33.33% |
Total | 41 | 100.00% | 3 | 100.00% |
/****************************************************************************/
static int decode_bool(bitstr_t *bs, const struct field_t *f,
char *base, int level)
{
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
INC_BIT(bs);
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 50 | 94.34% | 1 | 33.33% |
Jan Engelhardt | 2 | 3.77% | 1 | 33.33% |
Stephen Hemminger | 1 | 1.89% | 1 | 33.33% |
Total | 53 | 100.00% | 3 | 100.00% |
/****************************************************************************/
static int decode_oid(bitstr_t *bs, const struct field_t *f,
char *base, int level)
{
int len;
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
BYTE_ALIGN(bs);
CHECK_BOUND(bs, 1);
len = *bs->cur++;
bs->cur += len;
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 74 | 96.10% | 1 | 33.33% |
Jan Engelhardt | 2 | 2.60% | 1 | 33.33% |
Stephen Hemminger | 1 | 1.30% | 1 | 33.33% |
Total | 77 | 100.00% | 3 | 100.00% |
/****************************************************************************/
static int decode_int(bitstr_t *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 */
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);
CHECK_BOUND(bs, 2);
len = get_len(bs);
bs->cur += len;
break;
default: /* 2 <= Range <= 255 */
INC_BITS(bs, f->sz);
break;
}
PRINT("\n");
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 213 | 97.26% | 1 | 25.00% |
Jan Engelhardt | 5 | 2.28% | 2 | 50.00% |
Stephen Hemminger | 1 | 0.46% | 1 | 25.00% |
Total | 219 | 100.00% | 4 | 100.00% |
/****************************************************************************/
static int decode_enum(bitstr_t *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);
}
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 81 | 96.43% | 1 | 33.33% |
Jan Engelhardt | 2 | 2.38% | 1 | 33.33% |
Stephen Hemminger | 1 | 1.19% | 1 | 33.33% |
Total | 84 | 100.00% | 3 | 100.00% |
/****************************************************************************/
static int decode_bitstr(bitstr_t *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 */
CHECK_BOUND(bs, 2);
len = (*bs->cur++) << 8;
len += (*bs->cur++) + f->lb;
break;
case SEMI:
CHECK_BOUND(bs, 2);
len = get_len(bs);
break;
default:
len = 0;
break;
}
bs->cur += len >> 3;
bs->bit = len & 7;
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 150 | 97.40% | 1 | 25.00% |
Jan Engelhardt | 3 | 1.95% | 2 | 50.00% |
Stephen Hemminger | 1 | 0.65% | 1 | 25.00% |
Total | 154 | 100.00% | 4 | 100.00% |
/****************************************************************************/
static int decode_numstr(bitstr_t *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 */
len = get_bits(bs, f->sz) + f->lb;
BYTE_ALIGN(bs);
INC_BITS(bs, (len << 2));
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 80 | 95.24% | 1 | 25.00% |
Jan Engelhardt | 3 | 3.57% | 2 | 50.00% |
Stephen Hemminger | 1 | 1.19% | 1 | 25.00% |
Total | 84 | 100.00% | 4 | 100.00% |
/****************************************************************************/
static int decode_octstr(bitstr_t *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);
CHECK_BOUND(bs, 1);
len = (*bs->cur++) + f->lb;
break;
case SEMI:
BYTE_ALIGN(bs);
CHECK_BOUND(bs, 2);
len = get_len(bs) + f->lb;
break;
default: /* 2 <= Range <= 255 */
len = get_bits(bs, f->sz) + f->lb;
BYTE_ALIGN(bs);
break;
}
bs->cur += len;
PRINT("\n");
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 270 | 98.18% | 1 | 25.00% |
Jan Engelhardt | 4 | 1.45% | 2 | 50.00% |
Stephen Hemminger | 1 | 0.36% | 1 | 25.00% |
Total | 275 | 100.00% | 4 | 100.00% |
/****************************************************************************/
static int decode_bmpstr(bitstr_t *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);
CHECK_BOUND(bs, 1);
len = (*bs->cur++) + f->lb;
break;
default: /* 2 <= Range <= 255 */
len = get_bits(bs, f->sz) + f->lb;
BYTE_ALIGN(bs);
break;
}
bs->cur += len << 1;
CHECK_BOUND(bs, 0);
return H323_ERROR_NONE;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jing Min Zhao | 118 | 96.72% | 1 | 25.00% |
Jan Engelhardt | 3 | 2.46% | 2 | 50.00% |
Stephen Hemminger | 1 | 0.82% | 1 | 25.00% |
Total | 122 | 100.00% | 4 | 100.00% |
/****************************************************************************/
static int decode_seq(bitstr_t *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? */
ext = (f->attr & EXT) ? get_bit(bs) : 0;
/* Get fields bitmap */
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 */
CHECK_BOUND(bs, 2);
len = get_len(bs);
CHECK_BOUND(bs, len);
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 */
bmp2_len = get_bits(bs, 7) + 1;
CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
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? */
CHECK_BOUND(bs, 2);
len = get_len(bs);
CHECK_BOUND(bs, len);
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;
CHECK_BOUND(bs, 2);
len = get_len(bs);
CHECK_BOUND(bs, len);
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])