mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
[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 */
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
|
||||
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
|
||||
@ -37,6 +38,7 @@ union ip_conntrack_expect_proto {
|
||||
/* per conntrack: application helper private data */
|
||||
union ip_conntrack_help {
|
||||
/* 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_ftp_master ct_ftp_info;
|
||||
struct ip_ct_irc_master ct_irc_info;
|
||||
|
30
include/linux/netfilter_ipv4/ip_conntrack_h323.h
Normal file
30
include/linux/netfilter_ipv4/ip_conntrack_h323.h
Normal file
@ -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
|
||||
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
|
||||
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
|
||||
help
|
||||
@ -484,6 +504,12 @@ config IP_NF_NAT_PPTP
|
||||
default IP_NF_NAT if IP_NF_PPTP=y
|
||||
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
|
||||
config IP_NF_MANGLE
|
||||
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_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
|
||||
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.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
|
||||
|
||||
# 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_AMANDA) += ip_conntrack_amanda.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
|
||||
|
||||
# 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_AMANDA) += ip_nat_amanda.o
|
||||
obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
|
||||
|
1731
net/ipv4/netfilter/ip_conntrack_helper_h323.c
Normal file
1731
net/ipv4/netfilter/ip_conntrack_helper_h323.c
Normal file
File diff suppressed because it is too large
Load Diff
870
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
Normal file
870
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
Normal file
@ -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;
|
||||
}
|
98
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
Normal file
98
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
Normal file
@ -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
|
1926
net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
Normal file
1926
net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
Normal file
File diff suppressed because it is too large
Load Diff
938
net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
Normal file
938
net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
Normal file
@ -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;
|
605
net/ipv4/netfilter/ip_nat_helper_h323.c
Normal file
605
net/ipv4/netfilter/ip_nat_helper_h323.c
Normal file
@ -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
Block a user