[NETFILTER]: Add H.323 conntrack/NAT helper
Signed-off-by: Jing Min Zhao <zhaojignmin@hotmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
30ca3e376e
commit
5e35941d99
|
@ -29,6 +29,7 @@ union ip_conntrack_expect_proto {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Add protocol helper include file here */
|
/* Add protocol helper include file here */
|
||||||
|
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
||||||
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
|
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
|
||||||
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
|
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
|
||||||
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
|
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
|
||||||
|
@ -37,6 +38,7 @@ union ip_conntrack_expect_proto {
|
||||||
/* per conntrack: application helper private data */
|
/* per conntrack: application helper private data */
|
||||||
union ip_conntrack_help {
|
union ip_conntrack_help {
|
||||||
/* insert conntrack helper private data (master) here */
|
/* insert conntrack helper private data (master) here */
|
||||||
|
struct ip_ct_h323_master ct_h323_info;
|
||||||
struct ip_ct_pptp_master ct_pptp_info;
|
struct ip_ct_pptp_master ct_pptp_info;
|
||||||
struct ip_ct_ftp_master ct_ftp_info;
|
struct ip_ct_ftp_master ct_ftp_info;
|
||||||
struct ip_ct_irc_master ct_irc_info;
|
struct ip_ct_irc_master ct_irc_info;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef _IP_CONNTRACK_H323_H
|
||||||
|
#define _IP_CONNTRACK_H323_H
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#define RAS_PORT 1719
|
||||||
|
#define Q931_PORT 1720
|
||||||
|
#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
|
||||||
|
|
||||||
|
/* This structure exists only once per master */
|
||||||
|
struct ip_ct_h323_master {
|
||||||
|
|
||||||
|
/* Original and NATed Q.931 or H.245 signal ports */
|
||||||
|
u_int16_t sig_port[IP_CT_DIR_MAX];
|
||||||
|
|
||||||
|
/* Original and NATed RTP ports */
|
||||||
|
u_int16_t rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX];
|
||||||
|
|
||||||
|
union {
|
||||||
|
/* RAS connection timeout */
|
||||||
|
u_int32_t timeout;
|
||||||
|
|
||||||
|
/* Next TPKT length (for separate TPKT header and data) */
|
||||||
|
u_int16_t tpkt_len[IP_CT_DIR_MAX];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -168,6 +168,26 @@ config IP_NF_PPTP
|
||||||
If you want to compile it as a module, say M here and read
|
If you want to compile it as a module, say M here and read
|
||||||
Documentation/modules.txt. If unsure, say `N'.
|
Documentation/modules.txt. If unsure, say `N'.
|
||||||
|
|
||||||
|
config IP_NF_H323
|
||||||
|
tristate 'H.323 protocol support'
|
||||||
|
depends on IP_NF_CONNTRACK
|
||||||
|
help
|
||||||
|
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
|
||||||
|
important VoIP protocols, it is widely used by voice hardware and
|
||||||
|
software including voice gateways, IP phones, Netmeeting, OpenPhone,
|
||||||
|
Gnomemeeting, etc.
|
||||||
|
|
||||||
|
With this module you can support H.323 on a connection tracking/NAT
|
||||||
|
firewall.
|
||||||
|
|
||||||
|
This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
|
||||||
|
and T.120 based data and applications including audio, video, FAX,
|
||||||
|
chat, whiteboard, file transfer, etc. For more information, please
|
||||||
|
see http://nath323.sourceforge.net/.
|
||||||
|
|
||||||
|
If you want to compile it as a module, say 'M' here and read
|
||||||
|
Documentation/modules.txt. If unsure, say 'N'.
|
||||||
|
|
||||||
config IP_NF_QUEUE
|
config IP_NF_QUEUE
|
||||||
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
|
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
|
||||||
help
|
help
|
||||||
|
@ -484,6 +504,12 @@ config IP_NF_NAT_PPTP
|
||||||
default IP_NF_NAT if IP_NF_PPTP=y
|
default IP_NF_NAT if IP_NF_PPTP=y
|
||||||
default m if IP_NF_PPTP=m
|
default m if IP_NF_PPTP=m
|
||||||
|
|
||||||
|
config IP_NF_NAT_H323
|
||||||
|
tristate
|
||||||
|
depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
|
||||||
|
default IP_NF_NAT if IP_NF_H323=y
|
||||||
|
default m if IP_NF_H323=m
|
||||||
|
|
||||||
# mangle + specific targets
|
# mangle + specific targets
|
||||||
config IP_NF_MANGLE
|
config IP_NF_MANGLE
|
||||||
tristate "Packet mangling"
|
tristate "Packet mangling"
|
||||||
|
|
|
@ -10,6 +10,9 @@ iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
|
||||||
ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
|
ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
|
||||||
ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
|
ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
|
||||||
|
|
||||||
|
ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o
|
||||||
|
ip_nat_h323-objs := ip_nat_helper_h323.o
|
||||||
|
|
||||||
# connection tracking
|
# connection tracking
|
||||||
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
|
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
|
||||||
obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
|
obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
|
||||||
|
@ -22,6 +25,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
|
||||||
obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
|
obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
|
||||||
|
|
||||||
# connection tracking helpers
|
# connection tracking helpers
|
||||||
|
obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
|
||||||
obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
|
obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
|
||||||
obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
|
obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
|
||||||
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
|
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
|
||||||
|
@ -30,6 +34,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
|
||||||
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
|
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
|
||||||
|
|
||||||
# NAT helpers
|
# NAT helpers
|
||||||
|
obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
|
||||||
obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
|
obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
|
||||||
obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
|
obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
|
||||||
obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
|
obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,870 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* 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@hotmail.com>
|
||||||
|
*
|
||||||
|
* 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 "ip_conntrack_helper_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;
|
||||||
|
struct field_t *fields;
|
||||||
|
} field_t;
|
||||||
|
|
||||||
|
/* Bit Stream */
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *buf;
|
||||||
|
unsigned char *beg;
|
||||||
|
unsigned char *end;
|
||||||
|
unsigned char *cur;
|
||||||
|
unsigned 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 get_len(bitstr_t * bs);
|
||||||
|
static unsigned get_bit(bitstr_t * bs);
|
||||||
|
static unsigned get_bits(bitstr_t * bs, unsigned b);
|
||||||
|
static unsigned get_bitmap(bitstr_t * bs, unsigned b);
|
||||||
|
static unsigned get_uint(bitstr_t * bs, int b);
|
||||||
|
|
||||||
|
/* Decoder Functions */
|
||||||
|
static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_int(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level);
|
||||||
|
|
||||||
|
/* Decoder Functions Vector */
|
||||||
|
typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int);
|
||||||
|
static 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 "ip_conntrack_helper_h323_types.c"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Functions
|
||||||
|
****************************************************************************/
|
||||||
|
/* Assume bs is aligned && v < 16384 */
|
||||||
|
unsigned get_len(bitstr_t * bs)
|
||||||
|
{
|
||||||
|
unsigned v;
|
||||||
|
|
||||||
|
v = *bs->cur++;
|
||||||
|
|
||||||
|
if (v & 0x80) {
|
||||||
|
v &= 0x3f;
|
||||||
|
v <<= 8;
|
||||||
|
v += *bs->cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
unsigned get_bit(bitstr_t * bs)
|
||||||
|
{
|
||||||
|
unsigned b = (*bs->cur) & (0x80 >> bs->bit);
|
||||||
|
|
||||||
|
INC_BIT(bs);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Assume b <= 8 */
|
||||||
|
unsigned get_bits(bitstr_t * bs, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned 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 */
|
||||||
|
unsigned get_bitmap(bitstr_t * bs, unsigned b)
|
||||||
|
{
|
||||||
|
unsigned v, l, shift, bytes;
|
||||||
|
|
||||||
|
if (!b)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
l = bs->bit + b;
|
||||||
|
|
||||||
|
if (l < 8) {
|
||||||
|
v = (unsigned) (*bs->cur) << (bs->bit + 24);
|
||||||
|
bs->bit = l;
|
||||||
|
} else if (l == 8) {
|
||||||
|
v = (unsigned) (*bs->cur++) << (bs->bit + 24);
|
||||||
|
bs->bit = 0;
|
||||||
|
} else {
|
||||||
|
for (bytes = l >> 3, shift = 24, v = 0; bytes;
|
||||||
|
bytes--, shift -= 8)
|
||||||
|
v |= (unsigned) (*bs->cur++) << shift;
|
||||||
|
|
||||||
|
if (l < 32) {
|
||||||
|
v |= (unsigned) (*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
|
||||||
|
****************************************************************************/
|
||||||
|
unsigned get_uint(bitstr_t * bs, int b)
|
||||||
|
{
|
||||||
|
unsigned 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_nul(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
|
||||||
|
|
||||||
|
return H323_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_bool(bitstr_t * bs, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_oid(bitstr_t * bs, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_int(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned 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 v = get_uint(bs, len) + f->lb;
|
||||||
|
PRINT(" = %u", v);
|
||||||
|
*((unsigned *) (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_enum(bitstr_t * bs, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned 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 *) (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
|
||||||
|
int err;
|
||||||
|
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 *) 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) {
|
||||||
|
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_STOP)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
bs->cur = beg + len;
|
||||||
|
bs->bit = 0;
|
||||||
|
} else if ((err = (Decoders[son->type]) (bs, son, base,
|
||||||
|
level + 1)))
|
||||||
|
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 *) base = bmp;
|
||||||
|
BYTE_ALIGN(bs);
|
||||||
|
|
||||||
|
/* Decode the extension components */
|
||||||
|
for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
|
||||||
|
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 Range */
|
||||||
|
if (i >= f->ub) { /* Newer Version? */
|
||||||
|
CHECK_BOUND(bs, 2);
|
||||||
|
len = get_len(bs);
|
||||||
|
CHECK_BOUND(bs, len);
|
||||||
|
bs->cur += len;
|
||||||
|
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]) (bs, son, base,
|
||||||
|
level + 1)) >
|
||||||
|
H323_ERROR_STOP)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
bs->cur = beg + len;
|
||||||
|
bs->bit = 0;
|
||||||
|
}
|
||||||
|
return H323_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned count, effective_count = 0, i, len = 0;
|
||||||
|
int err;
|
||||||
|
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);
|
||||||
|
CHECK_BOUND(bs, 1);
|
||||||
|
count = *bs->cur++;
|
||||||
|
break;
|
||||||
|
case WORD:
|
||||||
|
BYTE_ALIGN(bs);
|
||||||
|
CHECK_BOUND(bs, 2);
|
||||||
|
count = *bs->cur++;
|
||||||
|
count <<= 8;
|
||||||
|
count = *bs->cur++;
|
||||||
|
break;
|
||||||
|
case SEMI:
|
||||||
|
BYTE_ALIGN(bs);
|
||||||
|
CHECK_BOUND(bs, 2);
|
||||||
|
count = get_len(bs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
count = get_bits(bs, f->sz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count += f->lb;
|
||||||
|
|
||||||
|
/* Write Count */
|
||||||
|
if (base) {
|
||||||
|
effective_count = count > f->ub ? f->ub : count;
|
||||||
|
*(unsigned *) base = effective_count;
|
||||||
|
base += sizeof(unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decode nested field */
|
||||||
|
son = f->fields;
|
||||||
|
if (base)
|
||||||
|
base -= son->offset;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (son->attr & OPEN) {
|
||||||
|
BYTE_ALIGN(bs);
|
||||||
|
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]) (bs, son,
|
||||||
|
i <
|
||||||
|
effective_count ?
|
||||||
|
base : NULL,
|
||||||
|
level + 1)) >
|
||||||
|
H323_ERROR_STOP)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
bs->cur = beg + len;
|
||||||
|
bs->bit = 0;
|
||||||
|
} else
|
||||||
|
if ((err = (Decoders[son->type]) (bs, son,
|
||||||
|
i < effective_count ?
|
||||||
|
base : NULL,
|
||||||
|
level + 1)))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (base)
|
||||||
|
base += son->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return H323_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
|
||||||
|
{
|
||||||
|
unsigned type, ext, len = 0;
|
||||||
|
int err;
|
||||||
|
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 ((f->attr & EXT) && get_bit(bs)) {
|
||||||
|
ext = 1;
|
||||||
|
type = get_bits(bs, 7) + f->lb;
|
||||||
|
} else {
|
||||||
|
ext = 0;
|
||||||
|
type = get_bits(bs, f->sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check Range */
|
||||||
|
if (type >= f->ub) { /* Newer version? */
|
||||||
|
BYTE_ALIGN(bs);
|
||||||
|
len = get_len(bs);
|
||||||
|
CHECK_BOUND(bs, len);
|
||||||
|
bs->cur += len;
|
||||||
|
return H323_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write Type */
|
||||||
|
if (base)
|
||||||
|
*(unsigned *) base = type;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
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;
|
||||||
|
return H323_ERROR_NONE;
|
||||||
|
}
|
||||||
|
beg = bs->cur;
|
||||||
|
|
||||||
|
if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) >
|
||||||
|
H323_ERROR_STOP)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
bs->cur = beg + len;
|
||||||
|
bs->bit = 0;
|
||||||
|
} else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return H323_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras)
|
||||||
|
{
|
||||||
|
static field_t ras_message = {
|
||||||
|
FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
|
||||||
|
0, _RasMessage
|
||||||
|
};
|
||||||
|
bitstr_t 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 field_t h323_userinformation = {
|
||||||
|
FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
|
||||||
|
0, _H323_UserInformation
|
||||||
|
};
|
||||||
|
bitstr_t 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 field_t multimediasystemcontrolmessage = {
|
||||||
|
FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
|
||||||
|
DECODE | EXT, 0, _MultimediaSystemControlMessage
|
||||||
|
};
|
||||||
|
bitstr_t 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 < 1)
|
||||||
|
return H323_ERROR_BOUND;
|
||||||
|
q931->MessageType = *p++;
|
||||||
|
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++;
|
||||||
|
if (sz < len)
|
||||||
|
break;
|
||||||
|
p += len;
|
||||||
|
sz -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT("Q.931 UUIE not found\n");
|
||||||
|
|
||||||
|
return H323_ERROR_BOUND;
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
|
||||||
|
* conntrack/NAT module.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
|
||||||
|
*
|
||||||
|
* This source code is licensed under General Public License version 2.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This library is based on H.225 version 4, H.235 version 2 and H.245
|
||||||
|
* version 7. It is extremely optimized to decode only the absolutely
|
||||||
|
* necessary objects in a signal for Linux kernel NAT module use, so don't
|
||||||
|
* expect it to be a full ASN.1 library.
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
*
|
||||||
|
* 1. Small. The total size of code plus data is less than 20 KB (IA32).
|
||||||
|
* 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866
|
||||||
|
* takes only 3.9 seconds.
|
||||||
|
* 3. No memory allocation. It uses a static object. No need to initialize or
|
||||||
|
* cleanup.
|
||||||
|
* 4. Thread safe.
|
||||||
|
* 5. Support embedded architectures that has no misaligned memory access
|
||||||
|
* support.
|
||||||
|
*
|
||||||
|
* Limitations:
|
||||||
|
*
|
||||||
|
* 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU.
|
||||||
|
* If a Setup signal contains more than 30 faststart, the packet size will
|
||||||
|
* very likely exceed the MTU size, then the TPKT will be fragmented. I
|
||||||
|
* don't know how to handle this in a Netfilter module. Anybody can help?
|
||||||
|
* Although I think 30 is enough for most of the cases.
|
||||||
|
* 2. IPv4 addresses only.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
|
||||||
|
#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* H.323 Types
|
||||||
|
****************************************************************************/
|
||||||
|
#include "ip_conntrack_helper_h323_types.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
enum {
|
||||||
|
Q931_NationalEscape = 0x00,
|
||||||
|
Q931_Alerting = 0x01,
|
||||||
|
Q931_CallProceeding = 0x02,
|
||||||
|
Q931_Connect = 0x07,
|
||||||
|
Q931_ConnectAck = 0x0F,
|
||||||
|
Q931_Progress = 0x03,
|
||||||
|
Q931_Setup = 0x05,
|
||||||
|
Q931_SetupAck = 0x0D,
|
||||||
|
Q931_Resume = 0x26,
|
||||||
|
Q931_ResumeAck = 0x2E,
|
||||||
|
Q931_ResumeReject = 0x22,
|
||||||
|
Q931_Suspend = 0x25,
|
||||||
|
Q931_SuspendAck = 0x2D,
|
||||||
|
Q931_SuspendReject = 0x21,
|
||||||
|
Q931_UserInformation = 0x20,
|
||||||
|
Q931_Disconnect = 0x45,
|
||||||
|
Q931_Release = 0x4D,
|
||||||
|
Q931_ReleaseComplete = 0x5A,
|
||||||
|
Q931_Restart = 0x46,
|
||||||
|
Q931_RestartAck = 0x4E,
|
||||||
|
Q931_Segment = 0x60,
|
||||||
|
Q931_CongestionCtrl = 0x79,
|
||||||
|
Q931_Information = 0x7B,
|
||||||
|
Q931_Notify = 0x6E,
|
||||||
|
Q931_Status = 0x7D,
|
||||||
|
Q931_StatusEnquiry = 0x75,
|
||||||
|
Q931_Facility = 0x62
|
||||||
|
} MessageType;
|
||||||
|
H323_UserInformation UUIE;
|
||||||
|
} Q931;
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Decode Functions Return Codes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define H323_ERROR_NONE 0 /* Decoded successfully */
|
||||||
|
#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */
|
||||||
|
#define H323_ERROR_BOUND -1
|
||||||
|
#define H323_ERROR_RANGE -2
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Decode Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras);
|
||||||
|
int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931);
|
||||||
|
int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
|
||||||
|
MultimediaSystemControlMessage *
|
||||||
|
mscm);
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,938 @@
|
||||||
|
/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This source code is licensed under General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct TransportAddress_ipAddress { /* SEQUENCE */
|
||||||
|
int options; /* No use */
|
||||||
|
unsigned ip;
|
||||||
|
} TransportAddress_ipAddress;
|
||||||
|
|
||||||
|
typedef struct TransportAddress { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eTransportAddress_ipAddress,
|
||||||
|
eTransportAddress_ipSourceRoute,
|
||||||
|
eTransportAddress_ipxAddress,
|
||||||
|
eTransportAddress_ip6Address,
|
||||||
|
eTransportAddress_netBios,
|
||||||
|
eTransportAddress_nsap,
|
||||||
|
eTransportAddress_nonStandardAddress,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
TransportAddress_ipAddress ipAddress;
|
||||||
|
};
|
||||||
|
} TransportAddress;
|
||||||
|
|
||||||
|
typedef struct DataProtocolCapability { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eDataProtocolCapability_nonStandard,
|
||||||
|
eDataProtocolCapability_v14buffered,
|
||||||
|
eDataProtocolCapability_v42lapm,
|
||||||
|
eDataProtocolCapability_hdlcFrameTunnelling,
|
||||||
|
eDataProtocolCapability_h310SeparateVCStack,
|
||||||
|
eDataProtocolCapability_h310SingleVCStack,
|
||||||
|
eDataProtocolCapability_transparent,
|
||||||
|
eDataProtocolCapability_segmentationAndReassembly,
|
||||||
|
eDataProtocolCapability_hdlcFrameTunnelingwSAR,
|
||||||
|
eDataProtocolCapability_v120,
|
||||||
|
eDataProtocolCapability_separateLANStack,
|
||||||
|
eDataProtocolCapability_v76wCompression,
|
||||||
|
eDataProtocolCapability_tcp,
|
||||||
|
eDataProtocolCapability_udp,
|
||||||
|
} choice;
|
||||||
|
} DataProtocolCapability;
|
||||||
|
|
||||||
|
typedef struct DataApplicationCapability_application { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eDataApplicationCapability_application_nonStandard,
|
||||||
|
eDataApplicationCapability_application_t120,
|
||||||
|
eDataApplicationCapability_application_dsm_cc,
|
||||||
|
eDataApplicationCapability_application_userData,
|
||||||
|
eDataApplicationCapability_application_t84,
|
||||||
|
eDataApplicationCapability_application_t434,
|
||||||
|
eDataApplicationCapability_application_h224,
|
||||||
|
eDataApplicationCapability_application_nlpid,
|
||||||
|
eDataApplicationCapability_application_dsvdControl,
|
||||||
|
eDataApplicationCapability_application_h222DataPartitioning,
|
||||||
|
eDataApplicationCapability_application_t30fax,
|
||||||
|
eDataApplicationCapability_application_t140,
|
||||||
|
eDataApplicationCapability_application_t38fax,
|
||||||
|
eDataApplicationCapability_application_genericDataCapability,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
DataProtocolCapability t120;
|
||||||
|
};
|
||||||
|
} DataApplicationCapability_application;
|
||||||
|
|
||||||
|
typedef struct DataApplicationCapability { /* SEQUENCE */
|
||||||
|
int options; /* No use */
|
||||||
|
DataApplicationCapability_application application;
|
||||||
|
} DataApplicationCapability;
|
||||||
|
|
||||||
|
typedef struct DataType { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eDataType_nonStandard,
|
||||||
|
eDataType_nullData,
|
||||||
|
eDataType_videoData,
|
||||||
|
eDataType_audioData,
|
||||||
|
eDataType_data,
|
||||||
|
eDataType_encryptionData,
|
||||||
|
eDataType_h235Control,
|
||||||
|
eDataType_h235Media,
|
||||||
|
eDataType_multiplexedStream,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
DataApplicationCapability data;
|
||||||
|
};
|
||||||
|
} DataType;
|
||||||
|
|
||||||
|
typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
|
||||||
|
int options; /* No use */
|
||||||
|
unsigned network;
|
||||||
|
} UnicastAddress_iPAddress;
|
||||||
|
|
||||||
|
typedef struct UnicastAddress { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eUnicastAddress_iPAddress,
|
||||||
|
eUnicastAddress_iPXAddress,
|
||||||
|
eUnicastAddress_iP6Address,
|
||||||
|
eUnicastAddress_netBios,
|
||||||
|
eUnicastAddress_iPSourceRouteAddress,
|
||||||
|
eUnicastAddress_nsap,
|
||||||
|
eUnicastAddress_nonStandardAddress,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
UnicastAddress_iPAddress iPAddress;
|
||||||
|
};
|
||||||
|
} UnicastAddress;
|
||||||
|
|
||||||
|
typedef struct H245_TransportAddress { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eH245_TransportAddress_unicastAddress,
|
||||||
|
eH245_TransportAddress_multicastAddress,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
UnicastAddress unicastAddress;
|
||||||
|
};
|
||||||
|
} H245_TransportAddress;
|
||||||
|
|
||||||
|
typedef struct H2250LogicalChannelParameters { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eH2250LogicalChannelParameters_nonStandard = (1 << 31),
|
||||||
|
eH2250LogicalChannelParameters_associatedSessionID =
|
||||||
|
(1 << 30),
|
||||||
|
eH2250LogicalChannelParameters_mediaChannel = (1 << 29),
|
||||||
|
eH2250LogicalChannelParameters_mediaGuaranteedDelivery =
|
||||||
|
(1 << 28),
|
||||||
|
eH2250LogicalChannelParameters_mediaControlChannel =
|
||||||
|
(1 << 27),
|
||||||
|
eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery
|
||||||
|
= (1 << 26),
|
||||||
|
eH2250LogicalChannelParameters_silenceSuppression = (1 << 25),
|
||||||
|
eH2250LogicalChannelParameters_destination = (1 << 24),
|
||||||
|
eH2250LogicalChannelParameters_dynamicRTPPayloadType =
|
||||||
|
(1 << 23),
|
||||||
|
eH2250LogicalChannelParameters_mediaPacketization = (1 << 22),
|
||||||
|
eH2250LogicalChannelParameters_transportCapability =
|
||||||
|
(1 << 21),
|
||||||
|
eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20),
|
||||||
|
eH2250LogicalChannelParameters_source = (1 << 19),
|
||||||
|
} options;
|
||||||
|
H245_TransportAddress mediaChannel;
|
||||||
|
H245_TransportAddress mediaControlChannel;
|
||||||
|
} H2250LogicalChannelParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
H2250LogicalChannelParameters h2250LogicalChannelParameters;
|
||||||
|
};
|
||||||
|
} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber
|
||||||
|
= (1 << 31),
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency
|
||||||
|
= (1 << 30),
|
||||||
|
eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor
|
||||||
|
= (1 << 29),
|
||||||
|
} options;
|
||||||
|
DataType dataType;
|
||||||
|
OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
|
||||||
|
multiplexParameters;
|
||||||
|
} OpenLogicalChannel_forwardLogicalChannelParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
H2250LogicalChannelParameters h2250LogicalChannelParameters;
|
||||||
|
};
|
||||||
|
} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
|
||||||
|
= (1 << 31),
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency
|
||||||
|
= (1 << 30),
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor
|
||||||
|
= (1 << 29),
|
||||||
|
} options;
|
||||||
|
OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
|
||||||
|
multiplexParameters;
|
||||||
|
} OpenLogicalChannel_reverseLogicalChannelParameters;
|
||||||
|
|
||||||
|
typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eNetworkAccessParameters_networkAddress_q2931Address,
|
||||||
|
eNetworkAccessParameters_networkAddress_e164Address,
|
||||||
|
eNetworkAccessParameters_networkAddress_localAreaAddress,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
H245_TransportAddress localAreaAddress;
|
||||||
|
};
|
||||||
|
} NetworkAccessParameters_networkAddress;
|
||||||
|
|
||||||
|
typedef struct NetworkAccessParameters { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eNetworkAccessParameters_distribution = (1 << 31),
|
||||||
|
eNetworkAccessParameters_externalReference = (1 << 30),
|
||||||
|
eNetworkAccessParameters_t120SetupProcedure = (1 << 29),
|
||||||
|
} options;
|
||||||
|
NetworkAccessParameters_networkAddress networkAddress;
|
||||||
|
} NetworkAccessParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannel { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannel_reverseLogicalChannelParameters =
|
||||||
|
(1 << 31),
|
||||||
|
eOpenLogicalChannel_separateStack = (1 << 30),
|
||||||
|
eOpenLogicalChannel_encryptionSync = (1 << 29),
|
||||||
|
} options;
|
||||||
|
OpenLogicalChannel_forwardLogicalChannelParameters
|
||||||
|
forwardLogicalChannelParameters;
|
||||||
|
OpenLogicalChannel_reverseLogicalChannelParameters
|
||||||
|
reverseLogicalChannelParameters;
|
||||||
|
NetworkAccessParameters separateStack;
|
||||||
|
} OpenLogicalChannel;
|
||||||
|
|
||||||
|
typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} Setup_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct Setup_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eSetup_UUIE_h245Address = (1 << 31),
|
||||||
|
eSetup_UUIE_sourceAddress = (1 << 30),
|
||||||
|
eSetup_UUIE_destinationAddress = (1 << 29),
|
||||||
|
eSetup_UUIE_destCallSignalAddress = (1 << 28),
|
||||||
|
eSetup_UUIE_destExtraCallInfo = (1 << 27),
|
||||||
|
eSetup_UUIE_destExtraCRV = (1 << 26),
|
||||||
|
eSetup_UUIE_callServices = (1 << 25),
|
||||||
|
eSetup_UUIE_sourceCallSignalAddress = (1 << 24),
|
||||||
|
eSetup_UUIE_remoteExtensionAddress = (1 << 23),
|
||||||
|
eSetup_UUIE_callIdentifier = (1 << 22),
|
||||||
|
eSetup_UUIE_h245SecurityCapability = (1 << 21),
|
||||||
|
eSetup_UUIE_tokens = (1 << 20),
|
||||||
|
eSetup_UUIE_cryptoTokens = (1 << 19),
|
||||||
|
eSetup_UUIE_fastStart = (1 << 18),
|
||||||
|
eSetup_UUIE_mediaWaitForConnect = (1 << 17),
|
||||||
|
eSetup_UUIE_canOverlapSend = (1 << 16),
|
||||||
|
eSetup_UUIE_endpointIdentifier = (1 << 15),
|
||||||
|
eSetup_UUIE_multipleCalls = (1 << 14),
|
||||||
|
eSetup_UUIE_maintainConnection = (1 << 13),
|
||||||
|
eSetup_UUIE_connectionParameters = (1 << 12),
|
||||||
|
eSetup_UUIE_language = (1 << 11),
|
||||||
|
eSetup_UUIE_presentationIndicator = (1 << 10),
|
||||||
|
eSetup_UUIE_screeningIndicator = (1 << 9),
|
||||||
|
eSetup_UUIE_serviceControl = (1 << 8),
|
||||||
|
eSetup_UUIE_symmetricOperationRequired = (1 << 7),
|
||||||
|
eSetup_UUIE_capacity = (1 << 6),
|
||||||
|
eSetup_UUIE_circuitInfo = (1 << 5),
|
||||||
|
eSetup_UUIE_desiredProtocols = (1 << 4),
|
||||||
|
eSetup_UUIE_neededFeatures = (1 << 3),
|
||||||
|
eSetup_UUIE_desiredFeatures = (1 << 2),
|
||||||
|
eSetup_UUIE_supportedFeatures = (1 << 1),
|
||||||
|
eSetup_UUIE_parallelH245Control = (1 << 0),
|
||||||
|
} options;
|
||||||
|
TransportAddress h245Address;
|
||||||
|
TransportAddress destCallSignalAddress;
|
||||||
|
TransportAddress sourceCallSignalAddress;
|
||||||
|
Setup_UUIE_fastStart fastStart;
|
||||||
|
} Setup_UUIE;
|
||||||
|
|
||||||
|
typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} CallProceeding_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct CallProceeding_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eCallProceeding_UUIE_h245Address = (1 << 31),
|
||||||
|
eCallProceeding_UUIE_callIdentifier = (1 << 30),
|
||||||
|
eCallProceeding_UUIE_h245SecurityMode = (1 << 29),
|
||||||
|
eCallProceeding_UUIE_tokens = (1 << 28),
|
||||||
|
eCallProceeding_UUIE_cryptoTokens = (1 << 27),
|
||||||
|
eCallProceeding_UUIE_fastStart = (1 << 26),
|
||||||
|
eCallProceeding_UUIE_multipleCalls = (1 << 25),
|
||||||
|
eCallProceeding_UUIE_maintainConnection = (1 << 24),
|
||||||
|
eCallProceeding_UUIE_fastConnectRefused = (1 << 23),
|
||||||
|
eCallProceeding_UUIE_featureSet = (1 << 22),
|
||||||
|
} options;
|
||||||
|
TransportAddress h245Address;
|
||||||
|
CallProceeding_UUIE_fastStart fastStart;
|
||||||
|
} CallProceeding_UUIE;
|
||||||
|
|
||||||
|
typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} Connect_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct Connect_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eConnect_UUIE_h245Address = (1 << 31),
|
||||||
|
eConnect_UUIE_callIdentifier = (1 << 30),
|
||||||
|
eConnect_UUIE_h245SecurityMode = (1 << 29),
|
||||||
|
eConnect_UUIE_tokens = (1 << 28),
|
||||||
|
eConnect_UUIE_cryptoTokens = (1 << 27),
|
||||||
|
eConnect_UUIE_fastStart = (1 << 26),
|
||||||
|
eConnect_UUIE_multipleCalls = (1 << 25),
|
||||||
|
eConnect_UUIE_maintainConnection = (1 << 24),
|
||||||
|
eConnect_UUIE_language = (1 << 23),
|
||||||
|
eConnect_UUIE_connectedAddress = (1 << 22),
|
||||||
|
eConnect_UUIE_presentationIndicator = (1 << 21),
|
||||||
|
eConnect_UUIE_screeningIndicator = (1 << 20),
|
||||||
|
eConnect_UUIE_fastConnectRefused = (1 << 19),
|
||||||
|
eConnect_UUIE_serviceControl = (1 << 18),
|
||||||
|
eConnect_UUIE_capacity = (1 << 17),
|
||||||
|
eConnect_UUIE_featureSet = (1 << 16),
|
||||||
|
} options;
|
||||||
|
TransportAddress h245Address;
|
||||||
|
Connect_UUIE_fastStart fastStart;
|
||||||
|
} Connect_UUIE;
|
||||||
|
|
||||||
|
typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} Alerting_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct Alerting_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eAlerting_UUIE_h245Address = (1 << 31),
|
||||||
|
eAlerting_UUIE_callIdentifier = (1 << 30),
|
||||||
|
eAlerting_UUIE_h245SecurityMode = (1 << 29),
|
||||||
|
eAlerting_UUIE_tokens = (1 << 28),
|
||||||
|
eAlerting_UUIE_cryptoTokens = (1 << 27),
|
||||||
|
eAlerting_UUIE_fastStart = (1 << 26),
|
||||||
|
eAlerting_UUIE_multipleCalls = (1 << 25),
|
||||||
|
eAlerting_UUIE_maintainConnection = (1 << 24),
|
||||||
|
eAlerting_UUIE_alertingAddress = (1 << 23),
|
||||||
|
eAlerting_UUIE_presentationIndicator = (1 << 22),
|
||||||
|
eAlerting_UUIE_screeningIndicator = (1 << 21),
|
||||||
|
eAlerting_UUIE_fastConnectRefused = (1 << 20),
|
||||||
|
eAlerting_UUIE_serviceControl = (1 << 19),
|
||||||
|
eAlerting_UUIE_capacity = (1 << 18),
|
||||||
|
eAlerting_UUIE_featureSet = (1 << 17),
|
||||||
|
} options;
|
||||||
|
TransportAddress h245Address;
|
||||||
|
Alerting_UUIE_fastStart fastStart;
|
||||||
|
} Alerting_UUIE;
|
||||||
|
|
||||||
|
typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} Information_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct Information_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eInformation_UUIE_callIdentifier = (1 << 31),
|
||||||
|
eInformation_UUIE_tokens = (1 << 30),
|
||||||
|
eInformation_UUIE_cryptoTokens = (1 << 29),
|
||||||
|
eInformation_UUIE_fastStart = (1 << 28),
|
||||||
|
eInformation_UUIE_fastConnectRefused = (1 << 27),
|
||||||
|
eInformation_UUIE_circuitInfo = (1 << 26),
|
||||||
|
} options;
|
||||||
|
Information_UUIE_fastStart fastStart;
|
||||||
|
} Information_UUIE;
|
||||||
|
|
||||||
|
typedef struct FacilityReason { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eFacilityReason_routeCallToGatekeeper,
|
||||||
|
eFacilityReason_callForwarded,
|
||||||
|
eFacilityReason_routeCallToMC,
|
||||||
|
eFacilityReason_undefinedReason,
|
||||||
|
eFacilityReason_conferenceListChoice,
|
||||||
|
eFacilityReason_startH245,
|
||||||
|
eFacilityReason_noH245,
|
||||||
|
eFacilityReason_newTokens,
|
||||||
|
eFacilityReason_featureSetUpdate,
|
||||||
|
eFacilityReason_forwardedElements,
|
||||||
|
eFacilityReason_transportedInformation,
|
||||||
|
} choice;
|
||||||
|
} FacilityReason;
|
||||||
|
|
||||||
|
typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} Facility_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct Facility_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eFacility_UUIE_alternativeAddress = (1 << 31),
|
||||||
|
eFacility_UUIE_alternativeAliasAddress = (1 << 30),
|
||||||
|
eFacility_UUIE_conferenceID = (1 << 29),
|
||||||
|
eFacility_UUIE_callIdentifier = (1 << 28),
|
||||||
|
eFacility_UUIE_destExtraCallInfo = (1 << 27),
|
||||||
|
eFacility_UUIE_remoteExtensionAddress = (1 << 26),
|
||||||
|
eFacility_UUIE_tokens = (1 << 25),
|
||||||
|
eFacility_UUIE_cryptoTokens = (1 << 24),
|
||||||
|
eFacility_UUIE_conferences = (1 << 23),
|
||||||
|
eFacility_UUIE_h245Address = (1 << 22),
|
||||||
|
eFacility_UUIE_fastStart = (1 << 21),
|
||||||
|
eFacility_UUIE_multipleCalls = (1 << 20),
|
||||||
|
eFacility_UUIE_maintainConnection = (1 << 19),
|
||||||
|
eFacility_UUIE_fastConnectRefused = (1 << 18),
|
||||||
|
eFacility_UUIE_serviceControl = (1 << 17),
|
||||||
|
eFacility_UUIE_circuitInfo = (1 << 16),
|
||||||
|
eFacility_UUIE_featureSet = (1 << 15),
|
||||||
|
eFacility_UUIE_destinationInfo = (1 << 14),
|
||||||
|
eFacility_UUIE_h245SecurityMode = (1 << 13),
|
||||||
|
} options;
|
||||||
|
FacilityReason reason;
|
||||||
|
TransportAddress h245Address;
|
||||||
|
Facility_UUIE_fastStart fastStart;
|
||||||
|
} Facility_UUIE;
|
||||||
|
|
||||||
|
typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
OpenLogicalChannel item[30];
|
||||||
|
} Progress_UUIE_fastStart;
|
||||||
|
|
||||||
|
typedef struct Progress_UUIE { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eProgress_UUIE_h245Address = (1 << 31),
|
||||||
|
eProgress_UUIE_h245SecurityMode = (1 << 30),
|
||||||
|
eProgress_UUIE_tokens = (1 << 29),
|
||||||
|
eProgress_UUIE_cryptoTokens = (1 << 28),
|
||||||
|
eProgress_UUIE_fastStart = (1 << 27),
|
||||||
|
eProgress_UUIE_multipleCalls = (1 << 26),
|
||||||
|
eProgress_UUIE_maintainConnection = (1 << 25),
|
||||||
|
eProgress_UUIE_fastConnectRefused = (1 << 24),
|
||||||
|
} options;
|
||||||
|
TransportAddress h245Address;
|
||||||
|
Progress_UUIE_fastStart fastStart;
|
||||||
|
} Progress_UUIE;
|
||||||
|
|
||||||
|
typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eH323_UU_PDU_h323_message_body_setup,
|
||||||
|
eH323_UU_PDU_h323_message_body_callProceeding,
|
||||||
|
eH323_UU_PDU_h323_message_body_connect,
|
||||||
|
eH323_UU_PDU_h323_message_body_alerting,
|
||||||
|
eH323_UU_PDU_h323_message_body_information,
|
||||||
|
eH323_UU_PDU_h323_message_body_releaseComplete,
|
||||||
|
eH323_UU_PDU_h323_message_body_facility,
|
||||||
|
eH323_UU_PDU_h323_message_body_progress,
|
||||||
|
eH323_UU_PDU_h323_message_body_empty,
|
||||||
|
eH323_UU_PDU_h323_message_body_status,
|
||||||
|
eH323_UU_PDU_h323_message_body_statusInquiry,
|
||||||
|
eH323_UU_PDU_h323_message_body_setupAcknowledge,
|
||||||
|
eH323_UU_PDU_h323_message_body_notify,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
Setup_UUIE setup;
|
||||||
|
CallProceeding_UUIE callProceeding;
|
||||||
|
Connect_UUIE connect;
|
||||||
|
Alerting_UUIE alerting;
|
||||||
|
Information_UUIE information;
|
||||||
|
Facility_UUIE facility;
|
||||||
|
Progress_UUIE progress;
|
||||||
|
};
|
||||||
|
} H323_UU_PDU_h323_message_body;
|
||||||
|
|
||||||
|
typedef struct RequestMessage { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eRequestMessage_nonStandard,
|
||||||
|
eRequestMessage_masterSlaveDetermination,
|
||||||
|
eRequestMessage_terminalCapabilitySet,
|
||||||
|
eRequestMessage_openLogicalChannel,
|
||||||
|
eRequestMessage_closeLogicalChannel,
|
||||||
|
eRequestMessage_requestChannelClose,
|
||||||
|
eRequestMessage_multiplexEntrySend,
|
||||||
|
eRequestMessage_requestMultiplexEntry,
|
||||||
|
eRequestMessage_requestMode,
|
||||||
|
eRequestMessage_roundTripDelayRequest,
|
||||||
|
eRequestMessage_maintenanceLoopRequest,
|
||||||
|
eRequestMessage_communicationModeRequest,
|
||||||
|
eRequestMessage_conferenceRequest,
|
||||||
|
eRequestMessage_multilinkRequest,
|
||||||
|
eRequestMessage_logicalChannelRateRequest,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
OpenLogicalChannel openLogicalChannel;
|
||||||
|
};
|
||||||
|
} RequestMessage;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
|
||||||
|
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
H2250LogicalChannelParameters h2250LogicalChannelParameters;
|
||||||
|
};
|
||||||
|
} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber
|
||||||
|
= (1 << 31),
|
||||||
|
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
|
||||||
|
= (1 << 30),
|
||||||
|
eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor
|
||||||
|
= (1 << 29),
|
||||||
|
} options;
|
||||||
|
OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
|
||||||
|
multiplexParameters;
|
||||||
|
} OpenLogicalChannelAck_reverseLogicalChannelParameters;
|
||||||
|
|
||||||
|
typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eH2250LogicalChannelAckParameters_nonStandard = (1 << 31),
|
||||||
|
eH2250LogicalChannelAckParameters_sessionID = (1 << 30),
|
||||||
|
eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29),
|
||||||
|
eH2250LogicalChannelAckParameters_mediaControlChannel =
|
||||||
|
(1 << 28),
|
||||||
|
eH2250LogicalChannelAckParameters_dynamicRTPPayloadType =
|
||||||
|
(1 << 27),
|
||||||
|
eH2250LogicalChannelAckParameters_flowControlToZero =
|
||||||
|
(1 << 26),
|
||||||
|
eH2250LogicalChannelAckParameters_portNumber = (1 << 25),
|
||||||
|
} options;
|
||||||
|
H245_TransportAddress mediaChannel;
|
||||||
|
H245_TransportAddress mediaControlChannel;
|
||||||
|
} H2250LogicalChannelAckParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
H2250LogicalChannelAckParameters
|
||||||
|
h2250LogicalChannelAckParameters;
|
||||||
|
};
|
||||||
|
} OpenLogicalChannelAck_forwardMultiplexAckParameters;
|
||||||
|
|
||||||
|
typedef struct OpenLogicalChannelAck { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eOpenLogicalChannelAck_reverseLogicalChannelParameters =
|
||||||
|
(1 << 31),
|
||||||
|
eOpenLogicalChannelAck_separateStack = (1 << 30),
|
||||||
|
eOpenLogicalChannelAck_forwardMultiplexAckParameters =
|
||||||
|
(1 << 29),
|
||||||
|
eOpenLogicalChannelAck_encryptionSync = (1 << 28),
|
||||||
|
} options;
|
||||||
|
OpenLogicalChannelAck_reverseLogicalChannelParameters
|
||||||
|
reverseLogicalChannelParameters;
|
||||||
|
OpenLogicalChannelAck_forwardMultiplexAckParameters
|
||||||
|
forwardMultiplexAckParameters;
|
||||||
|
} OpenLogicalChannelAck;
|
||||||
|
|
||||||
|
typedef struct ResponseMessage { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eResponseMessage_nonStandard,
|
||||||
|
eResponseMessage_masterSlaveDeterminationAck,
|
||||||
|
eResponseMessage_masterSlaveDeterminationReject,
|
||||||
|
eResponseMessage_terminalCapabilitySetAck,
|
||||||
|
eResponseMessage_terminalCapabilitySetReject,
|
||||||
|
eResponseMessage_openLogicalChannelAck,
|
||||||
|
eResponseMessage_openLogicalChannelReject,
|
||||||
|
eResponseMessage_closeLogicalChannelAck,
|
||||||
|
eResponseMessage_requestChannelCloseAck,
|
||||||
|
eResponseMessage_requestChannelCloseReject,
|
||||||
|
eResponseMessage_multiplexEntrySendAck,
|
||||||
|
eResponseMessage_multiplexEntrySendReject,
|
||||||
|
eResponseMessage_requestMultiplexEntryAck,
|
||||||
|
eResponseMessage_requestMultiplexEntryReject,
|
||||||
|
eResponseMessage_requestModeAck,
|
||||||
|
eResponseMessage_requestModeReject,
|
||||||
|
eResponseMessage_roundTripDelayResponse,
|
||||||
|
eResponseMessage_maintenanceLoopAck,
|
||||||
|
eResponseMessage_maintenanceLoopReject,
|
||||||
|
eResponseMessage_communicationModeResponse,
|
||||||
|
eResponseMessage_conferenceResponse,
|
||||||
|
eResponseMessage_multilinkResponse,
|
||||||
|
eResponseMessage_logicalChannelRateAcknowledge,
|
||||||
|
eResponseMessage_logicalChannelRateReject,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
OpenLogicalChannelAck openLogicalChannelAck;
|
||||||
|
};
|
||||||
|
} ResponseMessage;
|
||||||
|
|
||||||
|
typedef struct MultimediaSystemControlMessage { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eMultimediaSystemControlMessage_request,
|
||||||
|
eMultimediaSystemControlMessage_response,
|
||||||
|
eMultimediaSystemControlMessage_command,
|
||||||
|
eMultimediaSystemControlMessage_indication,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
RequestMessage request;
|
||||||
|
ResponseMessage response;
|
||||||
|
};
|
||||||
|
} MultimediaSystemControlMessage;
|
||||||
|
|
||||||
|
typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
MultimediaSystemControlMessage item[4];
|
||||||
|
} H323_UU_PDU_h245Control;
|
||||||
|
|
||||||
|
typedef struct H323_UU_PDU { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eH323_UU_PDU_nonStandardData = (1 << 31),
|
||||||
|
eH323_UU_PDU_h4501SupplementaryService = (1 << 30),
|
||||||
|
eH323_UU_PDU_h245Tunneling = (1 << 29),
|
||||||
|
eH323_UU_PDU_h245Control = (1 << 28),
|
||||||
|
eH323_UU_PDU_nonStandardControl = (1 << 27),
|
||||||
|
eH323_UU_PDU_callLinkage = (1 << 26),
|
||||||
|
eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25),
|
||||||
|
eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24),
|
||||||
|
eH323_UU_PDU_stimulusControl = (1 << 23),
|
||||||
|
eH323_UU_PDU_genericData = (1 << 22),
|
||||||
|
} options;
|
||||||
|
H323_UU_PDU_h323_message_body h323_message_body;
|
||||||
|
H323_UU_PDU_h245Control h245Control;
|
||||||
|
} H323_UU_PDU;
|
||||||
|
|
||||||
|
typedef struct H323_UserInformation { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eH323_UserInformation_user_data = (1 << 31),
|
||||||
|
} options;
|
||||||
|
H323_UU_PDU h323_uu_pdu;
|
||||||
|
} H323_UserInformation;
|
||||||
|
|
||||||
|
typedef struct GatekeeperRequest { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eGatekeeperRequest_nonStandardData = (1 << 31),
|
||||||
|
eGatekeeperRequest_gatekeeperIdentifier = (1 << 30),
|
||||||
|
eGatekeeperRequest_callServices = (1 << 29),
|
||||||
|
eGatekeeperRequest_endpointAlias = (1 << 28),
|
||||||
|
eGatekeeperRequest_alternateEndpoints = (1 << 27),
|
||||||
|
eGatekeeperRequest_tokens = (1 << 26),
|
||||||
|
eGatekeeperRequest_cryptoTokens = (1 << 25),
|
||||||
|
eGatekeeperRequest_authenticationCapability = (1 << 24),
|
||||||
|
eGatekeeperRequest_algorithmOIDs = (1 << 23),
|
||||||
|
eGatekeeperRequest_integrity = (1 << 22),
|
||||||
|
eGatekeeperRequest_integrityCheckValue = (1 << 21),
|
||||||
|
eGatekeeperRequest_supportsAltGK = (1 << 20),
|
||||||
|
eGatekeeperRequest_featureSet = (1 << 19),
|
||||||
|
eGatekeeperRequest_genericData = (1 << 18),
|
||||||
|
} options;
|
||||||
|
TransportAddress rasAddress;
|
||||||
|
} GatekeeperRequest;
|
||||||
|
|
||||||
|
typedef struct GatekeeperConfirm { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eGatekeeperConfirm_nonStandardData = (1 << 31),
|
||||||
|
eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30),
|
||||||
|
eGatekeeperConfirm_alternateGatekeeper = (1 << 29),
|
||||||
|
eGatekeeperConfirm_authenticationMode = (1 << 28),
|
||||||
|
eGatekeeperConfirm_tokens = (1 << 27),
|
||||||
|
eGatekeeperConfirm_cryptoTokens = (1 << 26),
|
||||||
|
eGatekeeperConfirm_algorithmOID = (1 << 25),
|
||||||
|
eGatekeeperConfirm_integrity = (1 << 24),
|
||||||
|
eGatekeeperConfirm_integrityCheckValue = (1 << 23),
|
||||||
|
eGatekeeperConfirm_featureSet = (1 << 22),
|
||||||
|
eGatekeeperConfirm_genericData = (1 << 21),
|
||||||
|
} options;
|
||||||
|
TransportAddress rasAddress;
|
||||||
|
} GatekeeperConfirm;
|
||||||
|
|
||||||
|
typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
TransportAddress item[10];
|
||||||
|
} RegistrationRequest_callSignalAddress;
|
||||||
|
|
||||||
|
typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
TransportAddress item[10];
|
||||||
|
} RegistrationRequest_rasAddress;
|
||||||
|
|
||||||
|
typedef struct RegistrationRequest { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eRegistrationRequest_nonStandardData = (1 << 31),
|
||||||
|
eRegistrationRequest_terminalAlias = (1 << 30),
|
||||||
|
eRegistrationRequest_gatekeeperIdentifier = (1 << 29),
|
||||||
|
eRegistrationRequest_alternateEndpoints = (1 << 28),
|
||||||
|
eRegistrationRequest_timeToLive = (1 << 27),
|
||||||
|
eRegistrationRequest_tokens = (1 << 26),
|
||||||
|
eRegistrationRequest_cryptoTokens = (1 << 25),
|
||||||
|
eRegistrationRequest_integrityCheckValue = (1 << 24),
|
||||||
|
eRegistrationRequest_keepAlive = (1 << 23),
|
||||||
|
eRegistrationRequest_endpointIdentifier = (1 << 22),
|
||||||
|
eRegistrationRequest_willSupplyUUIEs = (1 << 21),
|
||||||
|
eRegistrationRequest_maintainConnection = (1 << 20),
|
||||||
|
eRegistrationRequest_alternateTransportAddresses = (1 << 19),
|
||||||
|
eRegistrationRequest_additiveRegistration = (1 << 18),
|
||||||
|
eRegistrationRequest_terminalAliasPattern = (1 << 17),
|
||||||
|
eRegistrationRequest_supportsAltGK = (1 << 16),
|
||||||
|
eRegistrationRequest_usageReportingCapability = (1 << 15),
|
||||||
|
eRegistrationRequest_multipleCalls = (1 << 14),
|
||||||
|
eRegistrationRequest_supportedH248Packages = (1 << 13),
|
||||||
|
eRegistrationRequest_callCreditCapability = (1 << 12),
|
||||||
|
eRegistrationRequest_capacityReportingCapability = (1 << 11),
|
||||||
|
eRegistrationRequest_capacity = (1 << 10),
|
||||||
|
eRegistrationRequest_featureSet = (1 << 9),
|
||||||
|
eRegistrationRequest_genericData = (1 << 8),
|
||||||
|
} options;
|
||||||
|
RegistrationRequest_callSignalAddress callSignalAddress;
|
||||||
|
RegistrationRequest_rasAddress rasAddress;
|
||||||
|
unsigned timeToLive;
|
||||||
|
} RegistrationRequest;
|
||||||
|
|
||||||
|
typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
TransportAddress item[10];
|
||||||
|
} RegistrationConfirm_callSignalAddress;
|
||||||
|
|
||||||
|
typedef struct RegistrationConfirm { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eRegistrationConfirm_nonStandardData = (1 << 31),
|
||||||
|
eRegistrationConfirm_terminalAlias = (1 << 30),
|
||||||
|
eRegistrationConfirm_gatekeeperIdentifier = (1 << 29),
|
||||||
|
eRegistrationConfirm_alternateGatekeeper = (1 << 28),
|
||||||
|
eRegistrationConfirm_timeToLive = (1 << 27),
|
||||||
|
eRegistrationConfirm_tokens = (1 << 26),
|
||||||
|
eRegistrationConfirm_cryptoTokens = (1 << 25),
|
||||||
|
eRegistrationConfirm_integrityCheckValue = (1 << 24),
|
||||||
|
eRegistrationConfirm_willRespondToIRR = (1 << 23),
|
||||||
|
eRegistrationConfirm_preGrantedARQ = (1 << 22),
|
||||||
|
eRegistrationConfirm_maintainConnection = (1 << 21),
|
||||||
|
eRegistrationConfirm_serviceControl = (1 << 20),
|
||||||
|
eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19),
|
||||||
|
eRegistrationConfirm_terminalAliasPattern = (1 << 18),
|
||||||
|
eRegistrationConfirm_supportedPrefixes = (1 << 17),
|
||||||
|
eRegistrationConfirm_usageSpec = (1 << 16),
|
||||||
|
eRegistrationConfirm_featureServerAlias = (1 << 15),
|
||||||
|
eRegistrationConfirm_capacityReportingSpec = (1 << 14),
|
||||||
|
eRegistrationConfirm_featureSet = (1 << 13),
|
||||||
|
eRegistrationConfirm_genericData = (1 << 12),
|
||||||
|
} options;
|
||||||
|
RegistrationConfirm_callSignalAddress callSignalAddress;
|
||||||
|
unsigned timeToLive;
|
||||||
|
} RegistrationConfirm;
|
||||||
|
|
||||||
|
typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
TransportAddress item[10];
|
||||||
|
} UnregistrationRequest_callSignalAddress;
|
||||||
|
|
||||||
|
typedef struct UnregistrationRequest { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eUnregistrationRequest_endpointAlias = (1 << 31),
|
||||||
|
eUnregistrationRequest_nonStandardData = (1 << 30),
|
||||||
|
eUnregistrationRequest_endpointIdentifier = (1 << 29),
|
||||||
|
eUnregistrationRequest_alternateEndpoints = (1 << 28),
|
||||||
|
eUnregistrationRequest_gatekeeperIdentifier = (1 << 27),
|
||||||
|
eUnregistrationRequest_tokens = (1 << 26),
|
||||||
|
eUnregistrationRequest_cryptoTokens = (1 << 25),
|
||||||
|
eUnregistrationRequest_integrityCheckValue = (1 << 24),
|
||||||
|
eUnregistrationRequest_reason = (1 << 23),
|
||||||
|
eUnregistrationRequest_endpointAliasPattern = (1 << 22),
|
||||||
|
eUnregistrationRequest_supportedPrefixes = (1 << 21),
|
||||||
|
eUnregistrationRequest_alternateGatekeeper = (1 << 20),
|
||||||
|
eUnregistrationRequest_genericData = (1 << 19),
|
||||||
|
} options;
|
||||||
|
UnregistrationRequest_callSignalAddress callSignalAddress;
|
||||||
|
} UnregistrationRequest;
|
||||||
|
|
||||||
|
typedef struct AdmissionRequest { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eAdmissionRequest_callModel = (1 << 31),
|
||||||
|
eAdmissionRequest_destinationInfo = (1 << 30),
|
||||||
|
eAdmissionRequest_destCallSignalAddress = (1 << 29),
|
||||||
|
eAdmissionRequest_destExtraCallInfo = (1 << 28),
|
||||||
|
eAdmissionRequest_srcCallSignalAddress = (1 << 27),
|
||||||
|
eAdmissionRequest_nonStandardData = (1 << 26),
|
||||||
|
eAdmissionRequest_callServices = (1 << 25),
|
||||||
|
eAdmissionRequest_canMapAlias = (1 << 24),
|
||||||
|
eAdmissionRequest_callIdentifier = (1 << 23),
|
||||||
|
eAdmissionRequest_srcAlternatives = (1 << 22),
|
||||||
|
eAdmissionRequest_destAlternatives = (1 << 21),
|
||||||
|
eAdmissionRequest_gatekeeperIdentifier = (1 << 20),
|
||||||
|
eAdmissionRequest_tokens = (1 << 19),
|
||||||
|
eAdmissionRequest_cryptoTokens = (1 << 18),
|
||||||
|
eAdmissionRequest_integrityCheckValue = (1 << 17),
|
||||||
|
eAdmissionRequest_transportQOS = (1 << 16),
|
||||||
|
eAdmissionRequest_willSupplyUUIEs = (1 << 15),
|
||||||
|
eAdmissionRequest_callLinkage = (1 << 14),
|
||||||
|
eAdmissionRequest_gatewayDataRate = (1 << 13),
|
||||||
|
eAdmissionRequest_capacity = (1 << 12),
|
||||||
|
eAdmissionRequest_circuitInfo = (1 << 11),
|
||||||
|
eAdmissionRequest_desiredProtocols = (1 << 10),
|
||||||
|
eAdmissionRequest_desiredTunnelledProtocol = (1 << 9),
|
||||||
|
eAdmissionRequest_featureSet = (1 << 8),
|
||||||
|
eAdmissionRequest_genericData = (1 << 7),
|
||||||
|
} options;
|
||||||
|
TransportAddress destCallSignalAddress;
|
||||||
|
TransportAddress srcCallSignalAddress;
|
||||||
|
} AdmissionRequest;
|
||||||
|
|
||||||
|
typedef struct AdmissionConfirm { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eAdmissionConfirm_irrFrequency = (1 << 31),
|
||||||
|
eAdmissionConfirm_nonStandardData = (1 << 30),
|
||||||
|
eAdmissionConfirm_destinationInfo = (1 << 29),
|
||||||
|
eAdmissionConfirm_destExtraCallInfo = (1 << 28),
|
||||||
|
eAdmissionConfirm_destinationType = (1 << 27),
|
||||||
|
eAdmissionConfirm_remoteExtensionAddress = (1 << 26),
|
||||||
|
eAdmissionConfirm_alternateEndpoints = (1 << 25),
|
||||||
|
eAdmissionConfirm_tokens = (1 << 24),
|
||||||
|
eAdmissionConfirm_cryptoTokens = (1 << 23),
|
||||||
|
eAdmissionConfirm_integrityCheckValue = (1 << 22),
|
||||||
|
eAdmissionConfirm_transportQOS = (1 << 21),
|
||||||
|
eAdmissionConfirm_willRespondToIRR = (1 << 20),
|
||||||
|
eAdmissionConfirm_uuiesRequested = (1 << 19),
|
||||||
|
eAdmissionConfirm_language = (1 << 18),
|
||||||
|
eAdmissionConfirm_alternateTransportAddresses = (1 << 17),
|
||||||
|
eAdmissionConfirm_useSpecifiedTransport = (1 << 16),
|
||||||
|
eAdmissionConfirm_circuitInfo = (1 << 15),
|
||||||
|
eAdmissionConfirm_usageSpec = (1 << 14),
|
||||||
|
eAdmissionConfirm_supportedProtocols = (1 << 13),
|
||||||
|
eAdmissionConfirm_serviceControl = (1 << 12),
|
||||||
|
eAdmissionConfirm_multipleCalls = (1 << 11),
|
||||||
|
eAdmissionConfirm_featureSet = (1 << 10),
|
||||||
|
eAdmissionConfirm_genericData = (1 << 9),
|
||||||
|
} options;
|
||||||
|
TransportAddress destCallSignalAddress;
|
||||||
|
} AdmissionConfirm;
|
||||||
|
|
||||||
|
typedef struct LocationRequest { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eLocationRequest_endpointIdentifier = (1 << 31),
|
||||||
|
eLocationRequest_nonStandardData = (1 << 30),
|
||||||
|
eLocationRequest_sourceInfo = (1 << 29),
|
||||||
|
eLocationRequest_canMapAlias = (1 << 28),
|
||||||
|
eLocationRequest_gatekeeperIdentifier = (1 << 27),
|
||||||
|
eLocationRequest_tokens = (1 << 26),
|
||||||
|
eLocationRequest_cryptoTokens = (1 << 25),
|
||||||
|
eLocationRequest_integrityCheckValue = (1 << 24),
|
||||||
|
eLocationRequest_desiredProtocols = (1 << 23),
|
||||||
|
eLocationRequest_desiredTunnelledProtocol = (1 << 22),
|
||||||
|
eLocationRequest_featureSet = (1 << 21),
|
||||||
|
eLocationRequest_genericData = (1 << 20),
|
||||||
|
eLocationRequest_hopCount = (1 << 19),
|
||||||
|
eLocationRequest_circuitInfo = (1 << 18),
|
||||||
|
} options;
|
||||||
|
TransportAddress replyAddress;
|
||||||
|
} LocationRequest;
|
||||||
|
|
||||||
|
typedef struct LocationConfirm { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eLocationConfirm_nonStandardData = (1 << 31),
|
||||||
|
eLocationConfirm_destinationInfo = (1 << 30),
|
||||||
|
eLocationConfirm_destExtraCallInfo = (1 << 29),
|
||||||
|
eLocationConfirm_destinationType = (1 << 28),
|
||||||
|
eLocationConfirm_remoteExtensionAddress = (1 << 27),
|
||||||
|
eLocationConfirm_alternateEndpoints = (1 << 26),
|
||||||
|
eLocationConfirm_tokens = (1 << 25),
|
||||||
|
eLocationConfirm_cryptoTokens = (1 << 24),
|
||||||
|
eLocationConfirm_integrityCheckValue = (1 << 23),
|
||||||
|
eLocationConfirm_alternateTransportAddresses = (1 << 22),
|
||||||
|
eLocationConfirm_supportedProtocols = (1 << 21),
|
||||||
|
eLocationConfirm_multipleCalls = (1 << 20),
|
||||||
|
eLocationConfirm_featureSet = (1 << 19),
|
||||||
|
eLocationConfirm_genericData = (1 << 18),
|
||||||
|
eLocationConfirm_circuitInfo = (1 << 17),
|
||||||
|
eLocationConfirm_serviceControl = (1 << 16),
|
||||||
|
} options;
|
||||||
|
TransportAddress callSignalAddress;
|
||||||
|
TransportAddress rasAddress;
|
||||||
|
} LocationConfirm;
|
||||||
|
|
||||||
|
typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */
|
||||||
|
int count;
|
||||||
|
TransportAddress item[10];
|
||||||
|
} InfoRequestResponse_callSignalAddress;
|
||||||
|
|
||||||
|
typedef struct InfoRequestResponse { /* SEQUENCE */
|
||||||
|
enum {
|
||||||
|
eInfoRequestResponse_nonStandardData = (1 << 31),
|
||||||
|
eInfoRequestResponse_endpointAlias = (1 << 30),
|
||||||
|
eInfoRequestResponse_perCallInfo = (1 << 29),
|
||||||
|
eInfoRequestResponse_tokens = (1 << 28),
|
||||||
|
eInfoRequestResponse_cryptoTokens = (1 << 27),
|
||||||
|
eInfoRequestResponse_integrityCheckValue = (1 << 26),
|
||||||
|
eInfoRequestResponse_needResponse = (1 << 25),
|
||||||
|
eInfoRequestResponse_capacity = (1 << 24),
|
||||||
|
eInfoRequestResponse_irrStatus = (1 << 23),
|
||||||
|
eInfoRequestResponse_unsolicited = (1 << 22),
|
||||||
|
eInfoRequestResponse_genericData = (1 << 21),
|
||||||
|
} options;
|
||||||
|
TransportAddress rasAddress;
|
||||||
|
InfoRequestResponse_callSignalAddress callSignalAddress;
|
||||||
|
} InfoRequestResponse;
|
||||||
|
|
||||||
|
typedef struct RasMessage { /* CHOICE */
|
||||||
|
enum {
|
||||||
|
eRasMessage_gatekeeperRequest,
|
||||||
|
eRasMessage_gatekeeperConfirm,
|
||||||
|
eRasMessage_gatekeeperReject,
|
||||||
|
eRasMessage_registrationRequest,
|
||||||
|
eRasMessage_registrationConfirm,
|
||||||
|
eRasMessage_registrationReject,
|
||||||
|
eRasMessage_unregistrationRequest,
|
||||||
|
eRasMessage_unregistrationConfirm,
|
||||||
|
eRasMessage_unregistrationReject,
|
||||||
|
eRasMessage_admissionRequest,
|
||||||
|
eRasMessage_admissionConfirm,
|
||||||
|
eRasMessage_admissionReject,
|
||||||
|
eRasMessage_bandwidthRequest,
|
||||||
|
eRasMessage_bandwidthConfirm,
|
||||||
|
eRasMessage_bandwidthReject,
|
||||||
|
eRasMessage_disengageRequest,
|
||||||
|
eRasMessage_disengageConfirm,
|
||||||
|
eRasMessage_disengageReject,
|
||||||
|
eRasMessage_locationRequest,
|
||||||
|
eRasMessage_locationConfirm,
|
||||||
|
eRasMessage_locationReject,
|
||||||
|
eRasMessage_infoRequest,
|
||||||
|
eRasMessage_infoRequestResponse,
|
||||||
|
eRasMessage_nonStandardMessage,
|
||||||
|
eRasMessage_unknownMessageResponse,
|
||||||
|
eRasMessage_requestInProgress,
|
||||||
|
eRasMessage_resourcesAvailableIndicate,
|
||||||
|
eRasMessage_resourcesAvailableConfirm,
|
||||||
|
eRasMessage_infoRequestAck,
|
||||||
|
eRasMessage_infoRequestNak,
|
||||||
|
eRasMessage_serviceControlIndication,
|
||||||
|
eRasMessage_serviceControlResponse,
|
||||||
|
} choice;
|
||||||
|
union {
|
||||||
|
GatekeeperRequest gatekeeperRequest;
|
||||||
|
GatekeeperConfirm gatekeeperConfirm;
|
||||||
|
RegistrationRequest registrationRequest;
|
||||||
|
RegistrationConfirm registrationConfirm;
|
||||||
|
UnregistrationRequest unregistrationRequest;
|
||||||
|
AdmissionRequest admissionRequest;
|
||||||
|
AdmissionConfirm admissionConfirm;
|
||||||
|
LocationRequest locationRequest;
|
||||||
|
LocationConfirm locationConfirm;
|
||||||
|
InfoRequestResponse infoRequestResponse;
|
||||||
|
};
|
||||||
|
} RasMessage;
|
|
@ -0,0 +1,605 @@
|
||||||
|
/*
|
||||||
|
* H.323 extension for NAT alteration.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This source code is licensed under General Public License version 2.
|
||||||
|
*
|
||||||
|
* Based on the 'brute force' H.323 NAT module by
|
||||||
|
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||||
|
*
|
||||||
|
* Changes:
|
||||||
|
* 2006-02-01 - initial version 0.1
|
||||||
|
*
|
||||||
|
* 2006-02-20 - version 0.2
|
||||||
|
* 1. Changed source format to follow kernel conventions
|
||||||
|
* 2. Deleted some unnecessary structures
|
||||||
|
* 3. Minor fixes
|
||||||
|
*
|
||||||
|
* 2006-03-10 - version 0.3
|
||||||
|
* 1. Added support for multiple TPKTs in one packet (suggested by
|
||||||
|
* Patrick McHardy)
|
||||||
|
* 2. Added support for non-linear skb (based on Patrick McHardy's patch)
|
||||||
|
* 3. Eliminated unnecessary return code
|
||||||
|
*
|
||||||
|
* 2006-03-15 - version 0.4
|
||||||
|
* 1. Added support for T.120 channels
|
||||||
|
* 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/netfilter_ipv4.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/moduleparam.h>
|
||||||
|
#include <net/tcp.h>
|
||||||
|
#include <linux/netfilter_ipv4/ip_nat.h>
|
||||||
|
#include <linux/netfilter_ipv4/ip_nat_helper.h>
|
||||||
|
#include <linux/netfilter_ipv4/ip_nat_rule.h>
|
||||||
|
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
|
||||||
|
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
||||||
|
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
|
||||||
|
|
||||||
|
#include "ip_conntrack_helper_h323_asn1.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define DEBUGP printk
|
||||||
|
#else
|
||||||
|
#define DEBUGP(format, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
|
||||||
|
u_int32_t * ip, u_int16_t * port);
|
||||||
|
extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
|
||||||
|
u_int32_t * ip, u_int16_t * port);
|
||||||
|
extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
|
||||||
|
struct ip_conntrack_expect *this);
|
||||||
|
extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
|
||||||
|
struct ip_conntrack_expect *this);
|
||||||
|
extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
H245_TransportAddress * addr,
|
||||||
|
u_int32_t ip, u_int16_t port);
|
||||||
|
extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
TransportAddress * addr,
|
||||||
|
u_int32_t ip, u_int16_t port);
|
||||||
|
extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
|
||||||
|
struct ip_conntrack * ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data,
|
||||||
|
TransportAddress * addr, int count);
|
||||||
|
extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
|
||||||
|
struct ip_conntrack * ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data,
|
||||||
|
TransportAddress * addr, int count);
|
||||||
|
extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
|
||||||
|
struct ip_conntrack * ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
H245_TransportAddress * addr,
|
||||||
|
u_int16_t port, u_int16_t rtp_port,
|
||||||
|
struct ip_conntrack_expect * rtp_exp,
|
||||||
|
struct ip_conntrack_expect * rtcp_exp);
|
||||||
|
extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
H245_TransportAddress * addr, u_int16_t port,
|
||||||
|
struct ip_conntrack_expect * exp);
|
||||||
|
extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
TransportAddress * addr, u_int16_t port,
|
||||||
|
struct ip_conntrack_expect * exp);
|
||||||
|
extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, TransportAddress * addr,
|
||||||
|
int idx, u_int16_t port,
|
||||||
|
struct ip_conntrack_expect * exp);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int set_addr(struct sk_buff **pskb,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
unsigned int addroff, u_int32_t ip, u_int16_t port)
|
||||||
|
{
|
||||||
|
enum ip_conntrack_info ctinfo;
|
||||||
|
struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
|
||||||
|
struct {
|
||||||
|
u_int32_t ip;
|
||||||
|
u_int16_t port;
|
||||||
|
} __attribute__ ((__packed__)) buf;
|
||||||
|
struct tcphdr _tcph, *th;
|
||||||
|
|
||||||
|
buf.ip = ip;
|
||||||
|
buf.port = htons(port);
|
||||||
|
addroff += dataoff;
|
||||||
|
|
||||||
|
if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
|
||||||
|
if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
|
||||||
|
addroff, sizeof(buf),
|
||||||
|
(char *) &buf, sizeof(buf))) {
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
|
||||||
|
" error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Relocate data pointer */
|
||||||
|
th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
|
||||||
|
sizeof(_tcph), &_tcph);
|
||||||
|
if (th == NULL)
|
||||||
|
return -1;
|
||||||
|
*data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
|
||||||
|
th->doff * 4 + dataoff;
|
||||||
|
} else {
|
||||||
|
if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
|
||||||
|
addroff, sizeof(buf),
|
||||||
|
(char *) &buf, sizeof(buf))) {
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_h323: ip_nat_mangle_udp_packet"
|
||||||
|
" error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
|
||||||
|
* or pull everything in a linear buffer, so we can safely
|
||||||
|
* use the skb pointers now */
|
||||||
|
*data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
|
||||||
|
sizeof(struct udphdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int set_h225_addr(struct sk_buff **pskb,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
TransportAddress * addr,
|
||||||
|
u_int32_t ip, u_int16_t port)
|
||||||
|
{
|
||||||
|
return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int set_h245_addr(struct sk_buff **pskb,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
H245_TransportAddress * addr,
|
||||||
|
u_int32_t ip, u_int16_t port)
|
||||||
|
{
|
||||||
|
return set_addr(pskb, data, dataoff,
|
||||||
|
addr->unicastAddress.iPAddress.network, ip, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data,
|
||||||
|
TransportAddress * addr, int count)
|
||||||
|
{
|
||||||
|
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
|
||||||
|
int dir = CTINFO2DIR(ctinfo);
|
||||||
|
int i;
|
||||||
|
u_int32_t ip;
|
||||||
|
u_int16_t port;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (get_h225_addr(*data, &addr[i], &ip, &port)) {
|
||||||
|
if (ip == ct->tuplehash[dir].tuple.src.ip &&
|
||||||
|
port == info->sig_port[dir]) {
|
||||||
|
/* GW->GK */
|
||||||
|
|
||||||
|
/* Fix for Gnomemeeting */
|
||||||
|
if (i > 0 &&
|
||||||
|
get_h225_addr(*data, &addr[0],
|
||||||
|
&ip, &port) &&
|
||||||
|
(ntohl(ip) & 0xff000000) == 0x7f000000)
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
DEBUGP
|
||||||
|
("ip_nat_ras: set signal address "
|
||||||
|
"%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(ip), port,
|
||||||
|
NIPQUAD(ct->tuplehash[!dir].tuple.dst.
|
||||||
|
ip), info->sig_port[!dir]);
|
||||||
|
return set_h225_addr(pskb, data, 0, &addr[i],
|
||||||
|
ct->tuplehash[!dir].
|
||||||
|
tuple.dst.ip,
|
||||||
|
info->sig_port[!dir]);
|
||||||
|
} else if (ip == ct->tuplehash[dir].tuple.dst.ip &&
|
||||||
|
port == info->sig_port[dir]) {
|
||||||
|
/* GK->GW */
|
||||||
|
DEBUGP
|
||||||
|
("ip_nat_ras: set signal address "
|
||||||
|
"%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(ip), port,
|
||||||
|
NIPQUAD(ct->tuplehash[!dir].tuple.src.
|
||||||
|
ip), info->sig_port[!dir]);
|
||||||
|
return set_h225_addr(pskb, data, 0, &addr[i],
|
||||||
|
ct->tuplehash[!dir].
|
||||||
|
tuple.src.ip,
|
||||||
|
info->sig_port[!dir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data,
|
||||||
|
TransportAddress * addr, int count)
|
||||||
|
{
|
||||||
|
int dir = CTINFO2DIR(ctinfo);
|
||||||
|
int i;
|
||||||
|
u_int32_t ip;
|
||||||
|
u_int16_t port;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (get_h225_addr(*data, &addr[i], &ip, &port) &&
|
||||||
|
ip == ct->tuplehash[dir].tuple.src.ip &&
|
||||||
|
port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) {
|
||||||
|
DEBUGP("ip_nat_ras: set rasAddress "
|
||||||
|
"%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(ip), port,
|
||||||
|
NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
|
||||||
|
ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
|
||||||
|
port));
|
||||||
|
return set_h225_addr(pskb, data, 0, &addr[i],
|
||||||
|
ct->tuplehash[!dir].tuple.dst.ip,
|
||||||
|
ntohs(ct->tuplehash[!dir].tuple.
|
||||||
|
dst.u.udp.port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int nat_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
H245_TransportAddress * addr,
|
||||||
|
u_int16_t port, u_int16_t rtp_port,
|
||||||
|
struct ip_conntrack_expect *rtp_exp,
|
||||||
|
struct ip_conntrack_expect *rtcp_exp)
|
||||||
|
{
|
||||||
|
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
|
||||||
|
int dir = CTINFO2DIR(ctinfo);
|
||||||
|
int i;
|
||||||
|
u_int16_t nated_port;
|
||||||
|
|
||||||
|
/* Set expectations for NAT */
|
||||||
|
rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
|
||||||
|
rtp_exp->expectfn = ip_nat_follow_master;
|
||||||
|
rtp_exp->dir = !dir;
|
||||||
|
rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
|
||||||
|
rtcp_exp->expectfn = ip_nat_follow_master;
|
||||||
|
rtcp_exp->dir = !dir;
|
||||||
|
|
||||||
|
/* Lookup existing expects */
|
||||||
|
for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
|
||||||
|
if (info->rtp_port[i][dir] == rtp_port) {
|
||||||
|
/* Expected */
|
||||||
|
|
||||||
|
/* Use allocated ports first. This will refresh
|
||||||
|
* the expects */
|
||||||
|
rtp_exp->tuple.dst.u.udp.port =
|
||||||
|
htons(info->rtp_port[i][dir]);
|
||||||
|
rtcp_exp->tuple.dst.u.udp.port =
|
||||||
|
htons(info->rtp_port[i][dir] + 1);
|
||||||
|
break;
|
||||||
|
} else if (info->rtp_port[i][dir] == 0) {
|
||||||
|
/* Not expected */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run out of expectations */
|
||||||
|
if (i >= H323_RTP_CHANNEL_MAX) {
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_h323: out of expectations\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get a pair of ports. */
|
||||||
|
for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
|
||||||
|
nated_port != 0; nated_port += 2) {
|
||||||
|
rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
|
||||||
|
if (ip_conntrack_expect_related(rtp_exp) == 0) {
|
||||||
|
rtcp_exp->tuple.dst.u.udp.port =
|
||||||
|
htons(nated_port + 1);
|
||||||
|
if (ip_conntrack_expect_related(rtcp_exp) == 0)
|
||||||
|
break;
|
||||||
|
ip_conntrack_unexpect_related(rtp_exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nated_port == 0) { /* No port available */
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_h323: out of RTP ports\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify signal */
|
||||||
|
if (set_h245_addr(pskb, data, dataoff, addr,
|
||||||
|
ct->tuplehash[!dir].tuple.dst.ip,
|
||||||
|
(port & 1) ? nated_port + 1 : nated_port) == 0) {
|
||||||
|
/* Save ports */
|
||||||
|
info->rtp_port[i][dir] = rtp_port;
|
||||||
|
info->rtp_port[i][!dir] = nated_port;
|
||||||
|
} else {
|
||||||
|
ip_conntrack_unexpect_related(rtp_exp);
|
||||||
|
ip_conntrack_unexpect_related(rtcp_exp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
DEBUGP("ip_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(rtp_exp->tuple.src.ip),
|
||||||
|
ntohs(rtp_exp->tuple.src.u.udp.port),
|
||||||
|
NIPQUAD(rtp_exp->tuple.dst.ip),
|
||||||
|
ntohs(rtp_exp->tuple.dst.u.udp.port));
|
||||||
|
DEBUGP("ip_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(rtcp_exp->tuple.src.ip),
|
||||||
|
ntohs(rtcp_exp->tuple.src.u.udp.port),
|
||||||
|
NIPQUAD(rtcp_exp->tuple.dst.ip),
|
||||||
|
ntohs(rtcp_exp->tuple.dst.u.udp.port));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
H245_TransportAddress * addr, u_int16_t port,
|
||||||
|
struct ip_conntrack_expect *exp)
|
||||||
|
{
|
||||||
|
int dir = CTINFO2DIR(ctinfo);
|
||||||
|
u_int16_t nated_port = port;
|
||||||
|
|
||||||
|
/* Set expectations for NAT */
|
||||||
|
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
|
||||||
|
exp->expectfn = ip_nat_follow_master;
|
||||||
|
exp->dir = !dir;
|
||||||
|
|
||||||
|
/* Try to get same port: if not, try to change it. */
|
||||||
|
for (; nated_port != 0; nated_port++) {
|
||||||
|
exp->tuple.dst.u.tcp.port = htons(nated_port);
|
||||||
|
if (ip_conntrack_expect_related(exp) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nated_port == 0) { /* No port available */
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_h323: out of TCP ports\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify signal */
|
||||||
|
if (set_h245_addr(pskb, data, dataoff, addr,
|
||||||
|
ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) {
|
||||||
|
ip_conntrack_unexpect_related(exp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
|
||||||
|
NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* This conntrack expect function replaces ip_conntrack_h245_expect()
|
||||||
|
* which was set by ip_conntrack_helper_h323.c. It calls both
|
||||||
|
* ip_nat_follow_master() and ip_conntrack_h245_expect()
|
||||||
|
****************************************************************************/
|
||||||
|
static void ip_nat_h245_expect(struct ip_conntrack *new,
|
||||||
|
struct ip_conntrack_expect *this)
|
||||||
|
{
|
||||||
|
ip_nat_follow_master(new, this);
|
||||||
|
ip_conntrack_h245_expect(new, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, int dataoff,
|
||||||
|
TransportAddress * addr, u_int16_t port,
|
||||||
|
struct ip_conntrack_expect *exp)
|
||||||
|
{
|
||||||
|
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
|
||||||
|
int dir = CTINFO2DIR(ctinfo);
|
||||||
|
u_int16_t nated_port = port;
|
||||||
|
|
||||||
|
/* Set expectations for NAT */
|
||||||
|
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
|
||||||
|
exp->expectfn = ip_nat_h245_expect;
|
||||||
|
exp->dir = !dir;
|
||||||
|
|
||||||
|
/* Check existing expects */
|
||||||
|
if (info->sig_port[dir] == port)
|
||||||
|
nated_port = info->sig_port[!dir];
|
||||||
|
|
||||||
|
/* Try to get same port: if not, try to change it. */
|
||||||
|
for (; nated_port != 0; nated_port++) {
|
||||||
|
exp->tuple.dst.u.tcp.port = htons(nated_port);
|
||||||
|
if (ip_conntrack_expect_related(exp) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nated_port == 0) { /* No port available */
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_q931: out of TCP ports\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify signal */
|
||||||
|
if (set_h225_addr(pskb, data, dataoff, addr,
|
||||||
|
ct->tuplehash[!dir].tuple.dst.ip,
|
||||||
|
nated_port) == 0) {
|
||||||
|
/* Save ports */
|
||||||
|
info->sig_port[dir] = port;
|
||||||
|
info->sig_port[!dir] = nated_port;
|
||||||
|
} else {
|
||||||
|
ip_conntrack_unexpect_related(exp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
|
||||||
|
NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* This conntrack expect function replaces ip_conntrack_q931_expect()
|
||||||
|
* which was set by ip_conntrack_helper_h323.c.
|
||||||
|
****************************************************************************/
|
||||||
|
static void ip_nat_q931_expect(struct ip_conntrack *new,
|
||||||
|
struct ip_conntrack_expect *this)
|
||||||
|
{
|
||||||
|
struct ip_nat_range range;
|
||||||
|
|
||||||
|
if (this->tuple.src.ip != 0) { /* Only accept calls from GK */
|
||||||
|
ip_nat_follow_master(new, this);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This must be a fresh one. */
|
||||||
|
BUG_ON(new->status & IPS_NAT_DONE_MASK);
|
||||||
|
|
||||||
|
/* Change src to where master sends to */
|
||||||
|
range.flags = IP_NAT_RANGE_MAP_IPS;
|
||||||
|
range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
|
||||||
|
|
||||||
|
/* hook doesn't matter, but it has to do source manip */
|
||||||
|
ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
|
||||||
|
|
||||||
|
/* For DST manip, map port here to where it's expected. */
|
||||||
|
range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
|
||||||
|
range.min = range.max = this->saved_proto;
|
||||||
|
range.min_ip = range.max_ip =
|
||||||
|
new->master->tuplehash[!this->dir].tuple.src.ip;
|
||||||
|
|
||||||
|
/* hook doesn't matter, but it has to do destination manip */
|
||||||
|
ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
|
||||||
|
|
||||||
|
out:
|
||||||
|
ip_conntrack_q931_expect(new, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
|
||||||
|
enum ip_conntrack_info ctinfo,
|
||||||
|
unsigned char **data, TransportAddress * addr, int idx,
|
||||||
|
u_int16_t port, struct ip_conntrack_expect *exp)
|
||||||
|
{
|
||||||
|
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
|
||||||
|
int dir = CTINFO2DIR(ctinfo);
|
||||||
|
u_int16_t nated_port = port;
|
||||||
|
u_int32_t ip;
|
||||||
|
|
||||||
|
/* Set expectations for NAT */
|
||||||
|
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
|
||||||
|
exp->expectfn = ip_nat_q931_expect;
|
||||||
|
exp->dir = !dir;
|
||||||
|
|
||||||
|
/* Check existing expects */
|
||||||
|
if (info->sig_port[dir] == port)
|
||||||
|
nated_port = info->sig_port[!dir];
|
||||||
|
|
||||||
|
/* Try to get same port: if not, try to change it. */
|
||||||
|
for (; nated_port != 0; nated_port++) {
|
||||||
|
exp->tuple.dst.u.tcp.port = htons(nated_port);
|
||||||
|
if (ip_conntrack_expect_related(exp) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nated_port == 0) { /* No port available */
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("ip_nat_ras: out of TCP ports\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify signal */
|
||||||
|
if (set_h225_addr(pskb, data, 0, &addr[idx],
|
||||||
|
ct->tuplehash[!dir].tuple.dst.ip,
|
||||||
|
nated_port) == 0) {
|
||||||
|
/* Save ports */
|
||||||
|
info->sig_port[dir] = port;
|
||||||
|
info->sig_port[!dir] = nated_port;
|
||||||
|
|
||||||
|
/* Fix for Gnomemeeting */
|
||||||
|
if (idx > 0 &&
|
||||||
|
get_h225_addr(*data, &addr[0], &ip, &port) &&
|
||||||
|
(ntohl(ip) & 0xff000000) == 0x7f000000) {
|
||||||
|
set_h225_addr_hook(pskb, data, 0, &addr[0],
|
||||||
|
ct->tuplehash[!dir].tuple.dst.ip,
|
||||||
|
info->sig_port[!dir]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ip_conntrack_unexpect_related(exp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
|
||||||
|
NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
|
||||||
|
NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static int __init init(void)
|
||||||
|
{
|
||||||
|
BUG_ON(set_h245_addr_hook != NULL);
|
||||||
|
BUG_ON(set_h225_addr_hook != NULL);
|
||||||
|
BUG_ON(set_sig_addr_hook != NULL);
|
||||||
|
BUG_ON(set_ras_addr_hook != NULL);
|
||||||
|
BUG_ON(nat_rtp_rtcp_hook != NULL);
|
||||||
|
BUG_ON(nat_t120_hook != NULL);
|
||||||
|
BUG_ON(nat_h245_hook != NULL);
|
||||||
|
BUG_ON(nat_q931_hook != NULL);
|
||||||
|
|
||||||
|
set_h245_addr_hook = set_h245_addr;
|
||||||
|
set_h225_addr_hook = set_h225_addr;
|
||||||
|
set_sig_addr_hook = set_sig_addr;
|
||||||
|
set_ras_addr_hook = set_ras_addr;
|
||||||
|
nat_rtp_rtcp_hook = nat_rtp_rtcp;
|
||||||
|
nat_t120_hook = nat_t120;
|
||||||
|
nat_h245_hook = nat_h245;
|
||||||
|
nat_q931_hook = nat_q931;
|
||||||
|
|
||||||
|
DEBUGP("ip_nat_h323: init success\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
static void __exit fini(void)
|
||||||
|
{
|
||||||
|
set_h245_addr_hook = NULL;
|
||||||
|
set_h225_addr_hook = NULL;
|
||||||
|
set_sig_addr_hook = NULL;
|
||||||
|
set_ras_addr_hook = NULL;
|
||||||
|
nat_rtp_rtcp_hook = NULL;
|
||||||
|
nat_t120_hook = NULL;
|
||||||
|
nat_h245_hook = NULL;
|
||||||
|
nat_q931_hook = NULL;
|
||||||
|
synchronize_net();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
module_init(init);
|
||||||
|
module_exit(fini);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
|
||||||
|
MODULE_DESCRIPTION("H.323 NAT helper");
|
||||||
|
MODULE_LICENSE("GPL");
|
Loading…
Reference in New Issue