Commit 5e35941d authored by Jing Min Zhao's avatar Jing Min Zhao Committed by David S. Miller

[NETFILTER]: Add H.323 conntrack/NAT helper

Signed-off-by: default avatarJing Min Zhao <zhaojignmin@hotmail.com>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 30ca3e37
......@@ -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;
......
#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
......
/*
* H.323 connection tracking helper
*
* 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 connection tracking module by
* Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* For more information, please see http://nath323.sourceforge.net/
*
* 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. Avoid excessive stack usage (based on Patrick McHardy's patch)
* 3. Added support for non-linear skb (based on Patrick McHardy's patch)
* 4. Fixed missing H.245 module owner (Patrick McHardy)
* 5. Avoid long RAS expectation chains (Patrick McHardy)
* 6. Fixed incorrect __exit attribute (Patrick McHardy)
* 7. Eliminated unnecessary return code
* 8. Fixed incorrect use of NAT data from conntrack code (suggested by
* Patrick McHardy)
* 9. Fixed TTL calculation error in RCF
* 10. Added TTL support in RRQ
* 11. Better support for separate TPKT header and data
*
* 2006-03-15 - version 0.4
* 1. Added support for T.120 channels
* 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
* 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
* 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
* Patrick McHardy)
* 5. Reset next TPKT data length in get_tpkt_data()
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
#include <linux/moduleparam.h>
#include "ip_conntrack_helper_h323_asn1.h"
#if 0
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif
/* Parameters */
static int gkrouted_only = 1;
module_param(gkrouted_only, int, 0600);
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
/* Hooks for NAT */
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);
int (*set_h225_addr_hook) (struct sk_buff ** pskb,
unsigned char **data, int dataoff,
TransportAddress * addr,
u_int32_t ip, u_int16_t port);
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);
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);
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);
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);
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);
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 DEFINE_SPINLOCK(ip_h323_lock);
static char *h323_buffer;
/****************************************************************************/
static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int *datalen, int *dataoff)
{
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int dir = CTINFO2DIR(ctinfo);
struct tcphdr _tcph, *th;
int tcpdatalen;
int tcpdataoff;
unsigned char *tpkt;
int tpktlen;
int tpktoff;
/* Get TCP header */
th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
sizeof(_tcph), &_tcph);
if (th == NULL)
return 0;
/* Get TCP data offset */
tcpdataoff = (*pskb)->nh.iph->ihl * 4 + th->doff * 4;
/* Get TCP data length */
tcpdatalen = (*pskb)->len - tcpdataoff;
if (tcpdatalen <= 0) /* No TCP data */
goto clear_out;
if (*data == NULL) { /* first TPKT */
/* Get first TPKT pointer */
tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
h323_buffer);
BUG_ON(tpkt == NULL);
/* Validate TPKT identifier */
if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
/* Netmeeting sends TPKT header and data separately */
if (info->tpkt_len[dir] > 0) {
DEBUGP("ip_ct_h323: previous packet "
"indicated separate TPKT data of %hu "
"bytes\n", info->tpkt_len[dir]);
if (info->tpkt_len[dir] <= tcpdatalen) {
/* Yes, there was a TPKT header
* received */
*data = tpkt;
*datalen = info->tpkt_len[dir];
*dataoff = 0;
goto out;
}
/* Fragmented TPKT */
if (net_ratelimit())
printk("ip_ct_h323: "
"fragmented TPKT\n");
goto clear_out;
}
/* It is not even a TPKT */
return 0;
}
tpktoff = 0;
} else { /* Next TPKT */
tpktoff = *dataoff + *datalen;
tcpdatalen -= tpktoff;
if (tcpdatalen <= 4) /* No more TPKT */
goto clear_out;
tpkt = *data + *datalen;
/* Validate TPKT identifier */
if (tpkt[0] != 0x03 || tpkt[1] != 0)
goto clear_out;
}
/* Validate TPKT length */
tpktlen = tpkt[2] * 256 + tpkt[3];
if (tpktlen > tcpdatalen) {
if (tcpdatalen == 4) { /* Separate TPKT header */
/* Netmeeting sends TPKT header and data separately */
DEBUGP("ip_ct_h323: separate TPKT header indicates "
"there will be TPKT data of %hu bytes\n",
tpktlen - 4);
info->tpkt_len[dir] = tpktlen - 4;
return 0;
}
if (net_ratelimit())
printk("ip_ct_h323: incomplete TPKT (fragmented?)\n");
goto clear_out;
}
/* This is the encapsulated data */
*data = tpkt + 4;
*datalen = tpktlen - 4;
*dataoff = tpktoff + 4;
out:
/* Clear TPKT length */
info->tpkt_len[dir] = 0;
return 1;
clear_out:
info->tpkt_len[dir] = 0;
return 0;
}
/****************************************************************************/
int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
u_int32_t * ip, u_int16_t * port)
{
unsigned char *p;
if (addr->choice != eH245_TransportAddress_unicastAddress ||
addr->unicastAddress.choice != eUnicastAddress_iPAddress)
return 0;
p = data + addr->unicastAddress.iPAddress.network;
*ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
*port = (p[4] << 8) | (p[5]);
return 1;
}
/****************************************************************************/
static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress * addr)
{
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
u_int32_t ip;
u_int16_t port;
u_int16_t rtp_port;
struct ip_conntrack_expect *rtp_exp;
struct ip_conntrack_expect *rtcp_exp;
/* Read RTP or RTCP address */
if (!get_h245_addr(*data, addr, &ip, &port) ||
ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
return 0;
/* RTP port is even */
rtp_port = port & (~1);
/* Create expect for RTP */
if ((rtp_exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
rtp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
rtp_exp->tuple.src.u.udp.port = 0;
rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);
rtp_exp->tuple.dst.protonum = IPPROTO_UDP;
rtp_exp->mask.src.ip = 0xFFFFFFFF;
rtp_exp->mask.src.u.udp.port = 0;
rtp_exp->mask.dst.ip = 0xFFFFFFFF;
rtp_exp->mask.dst.u.udp.port = 0xFFFF;
rtp_exp->mask.dst.protonum = 0xFF;
rtp_exp->flags = 0;
/* Create expect for RTCP */
if ((rtcp_exp = ip_conntrack_expect_alloc(ct)) == NULL) {
ip_conntrack_expect_put(rtp_exp);
return -1;
}
rtcp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
rtcp_exp->tuple.src.u.udp.port = 0;
rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);
rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;
rtcp_exp->mask.src.ip = 0xFFFFFFFF;
rtcp_exp->mask.src.u.udp.port = 0;
rtcp_exp->mask.dst.ip = 0xFFFFFFFF;
rtcp_exp->mask.dst.u.udp.port = 0xFFFF;
rtcp_exp->mask.dst.protonum = 0xFF;
rtcp_exp->flags = 0;
if (ct->tuplehash[dir].tuple.src.ip !=
ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {
/* NAT needed */
ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,
addr, port, rtp_port, rtp_exp,
rtcp_exp);
} else { /* Conntrack only */
rtp_exp->expectfn = NULL;
rtcp_exp->expectfn = NULL;
if (ip_conntrack_expect_related(rtp_exp) == 0) {
if (ip_conntrack_expect_related(rtcp_exp) == 0) {
DEBUGP("ip_ct_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_ct_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));
} else {
ip_conntrack_unexpect_related(rtp_exp);
ret = -1;
}
} else
ret = -1;
}
ip_conntrack_expect_put(rtp_exp);
ip_conntrack_expect_put(rtcp_exp);
return ret;
}
/****************************************************************************/
static int expect_t120(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H245_TransportAddress * addr)
{
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
u_int32_t ip;
u_int16_t port;
struct ip_conntrack_expect *exp = NULL;
/* Read T.120 address */
if (!get_h245_addr(*data, addr, &ip, &port) ||
ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
return 0;
/* Create expect for T.120 connections */
if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
exp->tuple.dst.u.tcp.port = htons(port);
exp->tuple.dst.protonum = IPPROTO_TCP;
exp->mask.src.ip = 0xFFFFFFFF;
exp->mask.src.u.tcp.port = 0;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.tcp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */
if (ct->tuplehash[dir].tuple.src.ip !=
ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {
/* NAT needed */
ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,
port, exp);
} else { /* Conntrack only */
exp->expectfn = NULL;
if (ip_conntrack_expect_related(exp) == 0) {
DEBUGP("ip_ct_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));
} else
ret = -1;
}
ip_conntrack_expect_put(exp);
return ret;
}
/****************************************************************************/
static int process_h245_channel(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
H2250LogicalChannelParameters * channel)
{
int ret;
if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
/* RTP */
ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
&channel->mediaChannel);
if (ret < 0)
return -1;
}
if (channel->
options & eH2250LogicalChannelParameters_mediaControlChannel) {
/* RTCP */
ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
&channel->mediaControlChannel);
if (ret < 0)
return -1;
}
return 0;
}
/****************************************************************************/
static int process_olc(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
OpenLogicalChannel * olc)
{
int ret;
DEBUGP("ip_ct_h323: OpenLogicalChannel\n");
if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
{
ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
&olc->
forwardLogicalChannelParameters.
multiplexParameters.
h2250LogicalChannelParameters);
if (ret < 0)
return -1;
}
if ((olc->options &
eOpenLogicalChannel_reverseLogicalChannelParameters) &&
(olc->reverseLogicalChannelParameters.options &
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
&& (olc->reverseLogicalChannelParameters.multiplexParameters.
choice ==
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
{
ret =
process_h245_channel(pskb, ct, ctinfo, data, dataoff,
&olc->
reverseLogicalChannelParameters.
multiplexParameters.
h2250LogicalChannelParameters);
if (ret < 0)
return -1;
}
if ((olc->options & eOpenLogicalChannel_separateStack) &&
olc->forwardLogicalChannelParameters.dataType.choice ==
eDataType_data &&
olc->forwardLogicalChannelParameters.dataType.data.application.
choice == eDataApplicationCapability_application_t120 &&
olc->forwardLogicalChannelParameters.dataType.data.application.
t120.choice == eDataProtocolCapability_separateLANStack &&
olc->separateStack.networkAddress.choice ==
eNetworkAccessParameters_networkAddress_localAreaAddress) {
ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
&olc->separateStack.networkAddress.
localAreaAddress);
if (ret < 0)
return -1;
}
return 0;
}
/****************************************************************************/
static int process_olca(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
OpenLogicalChannelAck * olca)
{
H2250LogicalChannelAckParameters *ack;
int ret;
DEBUGP("ip_ct_h323: OpenLogicalChannelAck\n");
if ((olca->options &
eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
(olca->reverseLogicalChannelParameters.options &
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
&& (olca->reverseLogicalChannelParameters.multiplexParameters.
choice ==
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
{
ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
&olca->
reverseLogicalChannelParameters.
multiplexParameters.
h2250LogicalChannelParameters);
if (ret < 0)
return -1;
}
if ((olca->options &
eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
(olca->forwardMultiplexAckParameters.choice ==
eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
{
ack = &olca->forwardMultiplexAckParameters.
h2250LogicalChannelAckParameters;
if (ack->options &
eH2250LogicalChannelAckParameters_mediaChannel) {
/* RTP */
ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
&ack->mediaChannel);
if (ret < 0)
return -1;
}
if (ack->options &
eH2250LogicalChannelAckParameters_mediaControlChannel) {
/* RTCP */
ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
&ack->mediaControlChannel);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
MultimediaSystemControlMessage * mscm)
{
switch (mscm->choice) {
case eMultimediaSystemControlMessage_request:
if (mscm->request.choice ==
eRequestMessage_openLogicalChannel) {
return process_olc(pskb, ct, ctinfo, data, dataoff,
&mscm->request.openLogicalChannel);
}
DEBUGP("ip_ct_h323: H.245 Request %d\n",
mscm->request.choice);
break;
case eMultimediaSystemControlMessage_response:
if (mscm->response.choice ==
eResponseMessage_openLogicalChannelAck) {
return process_olca(pskb, ct, ctinfo, data, dataoff,
&mscm->response.
openLogicalChannelAck);
}
DEBUGP("ip_ct_h323: H.245 Response %d\n",
mscm->response.choice);
break;
default:
DEBUGP("ip_ct_h323: H.245 signal %d\n", mscm->choice);
break;
}
return 0;
}
/****************************************************************************/
static int h245_help(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
static MultimediaSystemControlMessage mscm;
unsigned char *data = NULL;
int datalen;
int dataoff;
int ret;
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
&& ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
return NF_ACCEPT;
}
DEBUGP("ip_ct_h245: skblen = %u\n", (*pskb)->len);
spin_lock_bh(&ip_h323_lock);
/* Process each TPKT */
while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
DEBUGP("ip_ct_h245: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
NIPQUAD((*pskb)->nh.iph->saddr),
NIPQUAD((*pskb)->nh.iph->daddr), datalen);
/* Decode H.245 signal */
ret = DecodeMultimediaSystemControlMessage(data, datalen,
&mscm);
if (ret < 0) {
if (net_ratelimit())
printk("ip_ct_h245: decoding error: %s\n",
ret == H323_ERROR_BOUND ?
"out of bound" : "out of range");
/* We don't drop when decoding error */
break;
}
/* Process H.245 signal */
if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
goto drop;
}
spin_unlock_bh(&ip_h323_lock);
return NF_ACCEPT;
drop:
spin_unlock_bh(&ip_h323_lock);
if (net_ratelimit())
printk("ip_ct_h245: packet dropped\n");
return NF_DROP;
}
/****************************************************************************/
static struct ip_conntrack_helper ip_conntrack_helper_h245 = {
.name = "H.245",
.me = THIS_MODULE,
.max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */ ,
.timeout = 240,
.tuple = {.dst = {.protonum = IPPROTO_TCP}},
.mask = {.src = {.u = {0xFFFF}},
.dst = {.protonum = 0xFF}},
.help = h245_help
};
/****************************************************************************/
void ip_conntrack_h245_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this)
{
write_lock_bh(&ip_conntrack_lock);
new->helper = &ip_conntrack_helper_h245;
write_unlock_bh(&ip_conntrack_lock);
}
/****************************************************************************/
static int get_h225_addr(unsigned char *data, TransportAddress * addr,
u_int32_t * ip, u_int16_t * port)
{
unsigned char *p;
if (addr->choice != eTransportAddress_ipAddress)
return 0;
p = data + addr->ipAddress.ip;
*ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
*port = (p[4] << 8) | (p[5]);
return 1;
}
/****************************************************************************/
static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
TransportAddress * addr)
{
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
u_int32_t ip;
u_int16_t port;
struct ip_conntrack_expect *exp = NULL;
/* Read h245Address */
if (!get_h225_addr(*data, addr, &ip, &port) ||
ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
return 0;
/* Create expect for h245 connection */
if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
exp->tuple.dst.u.tcp.port = htons(port);
exp->tuple.dst.protonum = IPPROTO_TCP;
exp->mask.src.ip = 0xFFFFFFFF;
exp->mask.src.u.tcp.port = 0;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.tcp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->flags = 0;
if (ct->tuplehash[dir].tuple.src.ip !=
ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) {
/* NAT needed */
ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr,
port, exp);
} else { /* Conntrack only */
exp->expectfn = ip_conntrack_h245_expect;
if (ip_conntrack_expect_related(exp) == 0) {
DEBUGP("ip_ct_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));
} else
ret = -1;
}
ip_conntrack_expect_put(exp);
return ret;
}
/****************************************************************************/
static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Setup_UUIE * setup)
{
int dir = CTINFO2DIR(ctinfo);
int ret;
int i;
u_int32_t ip;
u_int16_t port;
DEBUGP("ip_ct_q931: Setup\n");
if (setup->options & eSetup_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
&setup->h245Address);
if (ret < 0)
return -1;
}
if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
(set_h225_addr_hook) &&
get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
ip != ct->tuplehash[!dir].tuple.src.ip) {
DEBUGP("ip_ct_q931: set destCallSignalAddress "
"%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
NIPQUAD(ip), port,
NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
ret = set_h225_addr_hook(pskb, data, dataoff,
&setup->destCallSignalAddress,
ct->tuplehash[!dir].tuple.src.ip,
ntohs(ct->tuplehash[!dir].tuple.src.
u.tcp.port));
if (ret < 0)
return -1;
}
if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
(set_h225_addr_hook) &&
get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
&& ip != ct->tuplehash[!dir].tuple.dst.ip) {
DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
"%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.tcp.port));
ret = set_h225_addr_hook(pskb, data, dataoff,
&setup->sourceCallSignalAddress,
ct->tuplehash[!dir].tuple.dst.ip,
ntohs(ct->tuplehash[!dir].tuple.dst.
u.tcp.port));
if (ret < 0)
return -1;
}
if (setup->options & eSetup_UUIE_fastStart) {
for (i = 0; i < setup->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&setup->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_callproceeding(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
CallProceeding_UUIE * callproc)
{
int ret;
int i;
DEBUGP("ip_ct_q931: CallProceeding\n");
if (callproc->options & eCallProceeding_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
&callproc->h245Address);
if (ret < 0)
return -1;
}
if (callproc->options & eCallProceeding_UUIE_fastStart) {
for (i = 0; i < callproc->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&callproc->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_connect(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Connect_UUIE * connect)
{
int ret;
int i;
DEBUGP("ip_ct_q931: Connect\n");
if (connect->options & eConnect_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
&connect->h245Address);
if (ret < 0)
return -1;
}
if (connect->options & eConnect_UUIE_fastStart) {
for (i = 0; i < connect->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&connect->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_alerting(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Alerting_UUIE * alert)
{
int ret;
int i;
DEBUGP("ip_ct_q931: Alerting\n");
if (alert->options & eAlerting_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
&alert->h245Address);
if (ret < 0)
return -1;
}
if (alert->options & eAlerting_UUIE_fastStart) {
for (i = 0; i < alert->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&alert->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_information(struct sk_buff **pskb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Information_UUIE * info)
{
int ret;
int i;
DEBUGP("ip_ct_q931: Information\n");
if (info->options & eInformation_UUIE_fastStart) {
for (i = 0; i < info->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&info->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Facility_UUIE * facility)
{
int ret;
int i;
DEBUGP("ip_ct_q931: Facility\n");
if (facility->options & eFacility_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
&facility->h245Address);
if (ret < 0)
return -1;
}
if (facility->options & eFacility_UUIE_fastStart) {
for (i = 0; i < facility->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&facility->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_progress(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff,
Progress_UUIE * progress)
{
int ret;
int i;
DEBUGP("ip_ct_q931: Progress\n");
if (progress->options & eProgress_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
&progress->h245Address);
if (ret < 0)
return -1;
}
if (progress->options & eProgress_UUIE_fastStart) {
for (i = 0; i < progress->fastStart.count; i++) {
ret = process_olc(pskb, ct, ctinfo, data, dataoff,
&progress->fastStart.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int process_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, int dataoff, Q931 * q931)
{
H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
int i;
int ret = 0;
switch (pdu->h323_message_body.choice) {
case eH323_UU_PDU_h323_message_body_setup:
ret = process_setup(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.setup);
break;
case eH323_UU_PDU_h323_message_body_callProceeding:
ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.
callProceeding);
break;
case eH323_UU_PDU_h323_message_body_connect:
ret = process_connect(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.connect);
break;
case eH323_UU_PDU_h323_message_body_alerting:
ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.alerting);
break;
case eH323_UU_PDU_h323_message_body_information:
ret = process_information(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.
information);
break;
case eH323_UU_PDU_h323_message_body_facility:
ret = process_facility(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.facility);
break;
case eH323_UU_PDU_h323_message_body_progress:
ret = process_progress(pskb, ct, ctinfo, data, dataoff,
&pdu->h323_message_body.progress);
break;
default:
DEBUGP("ip_ct_q931: Q.931 signal %d\n",
pdu->h323_message_body.choice);
break;
}
if (ret < 0)
return -1;
if (pdu->options & eH323_UU_PDU_h245Control) {
for (i = 0; i < pdu->h245Control.count; i++) {
ret = process_h245(pskb, ct, ctinfo, data, dataoff,
&pdu->h245Control.item[i]);
if (ret < 0)
return -1;
}
}
return 0;
}
/****************************************************************************/
static int q931_help(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
static Q931 q931;
unsigned char *data = NULL;
int datalen;
int dataoff;
int ret;
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
&& ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
return NF_ACCEPT;
}
DEBUGP("ip_ct_q931: skblen = %u\n", (*pskb)->len);
spin_lock_bh(&ip_h323_lock);
/* Process each TPKT */
while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
DEBUGP("ip_ct_q931: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
NIPQUAD((*pskb)->nh.iph->saddr),
NIPQUAD((*pskb)->nh.iph->daddr), datalen);
/* Decode Q.931 signal */
ret = DecodeQ931(data, datalen, &q931);
if (ret < 0) {
if (net_ratelimit())
printk("ip_ct_q931: decoding error: %s\n",
ret == H323_ERROR_BOUND ?
"out of bound" : "out of range");
/* We don't drop when decoding error */
break;
}
/* Process Q.931 signal */
if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
goto drop;
}
spin_unlock_bh(&ip_h323_lock);
return NF_ACCEPT;
drop:
spin_unlock_bh(&ip_h323_lock);
if (net_ratelimit())
printk("ip_ct_q931: packet dropped\n");
return NF_DROP;
}
/****************************************************************************/
static struct ip_conntrack_helper ip_conntrack_helper_q931 = {
.name = "Q.931",
.me = THIS_MODULE,
.max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ ,
.timeout = 240,
.tuple = {.src = {.u = {__constant_htons(Q931_PORT)}},
.dst = {.protonum = IPPROTO_TCP}},
.mask = {.src = {.u = {0xFFFF}},
.dst = {.protonum = 0xFF}},
.help = q931_help
};
/****************************************************************************/
void ip_conntrack_q931_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this)
{
write_lock_bh(&ip_conntrack_lock);
new->helper = &ip_conntrack_helper_q931;
write_unlock_bh(&ip_conntrack_lock);
}
/****************************************************************************/
static unsigned char *get_udp_data(struct sk_buff **pskb, int *datalen)
{
struct udphdr _uh, *uh;
int dataoff;
uh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, sizeof(_uh),
&_uh);
if (uh == NULL)
return NULL;
dataoff = (*pskb)->nh.iph->ihl * 4 + sizeof(_uh);
if (dataoff >= (*pskb)->len)
return NULL;
*datalen = (*pskb)->len - dataoff;
return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
}
/****************************************************************************/
static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct,
u_int32_t ip, u_int16_t port)
{
struct ip_conntrack_expect *exp;
struct ip_conntrack_tuple tuple;
tuple.src.ip = 0;
tuple.src.u.tcp.port = 0;
tuple.dst.ip = ip;
tuple.dst.u.tcp.port = htons(port);
tuple.dst.protonum = IPPROTO_TCP;
exp = __ip_conntrack_expect_find(&tuple);
if (exp->master == ct)
return exp;
return NULL;
}
/****************************************************************************/
static int set_expect_timeout(struct ip_conntrack_expect *exp,
unsigned timeout)
{
if (!exp || !del_timer(&exp->timeout))
return 0;
exp->timeout.expires = jiffies + timeout * HZ;
add_timer(&exp->timeout);
return 1;
}
/****************************************************************************/
static int expect_q931(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 ret = 0;
int i;
u_int32_t ip;
u_int16_t port;
struct ip_conntrack_expect *exp;
/* Look for the first related address */
for (i = 0; i < count; i++) {
if (get_h225_addr(*data, &addr[i], &ip, &port) &&
ip == ct->tuplehash[dir].tuple.src.ip && port != 0)
break;
}
if (i >= count) /* Not found */
return 0;
/* Create expect for Q.931 */
if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
exp->tuple.src.ip = gkrouted_only ? /* only accept calls from GK? */
ct->tuplehash[!dir].tuple.src.ip : 0;
exp->tuple.src.u.tcp.port = 0;
exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
exp->tuple.dst.u.tcp.port = htons(port);
exp->tuple.dst.protonum = IPPROTO_TCP;
exp->mask.src.ip = gkrouted_only ? 0xFFFFFFFF : 0;
exp->mask.src.u.tcp.port = 0;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.tcp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */
if (nat_q931_hook) { /* Need NAT */
ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i,
port, exp);
} else { /* Conntrack only */
exp->expectfn = ip_conntrack_q931_expect;
if (ip_conntrack_expect_related(exp) == 0) {
DEBUGP("ip_ct_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));
/* Save port for looking up expect in processing RCF */
info->sig_port[dir] = port;
} else
ret = -1;
}
ip_conntrack_expect_put(exp);
return ret;
}
/****************************************************************************/
static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, GatekeeperRequest * grq)
{
DEBUGP("ip_ct_ras: GRQ\n");
if (set_ras_addr_hook) /* NATed */
return set_ras_addr_hook(pskb, ct, ctinfo, data,
&grq->rasAddress, 1);
return 0;
}
/* Declare before using */
static void ip_conntrack_ras_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this);
/****************************************************************************/
static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, GatekeeperConfirm * gcf)
{
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
u_int32_t ip;
u_int16_t port;
struct ip_conntrack_expect *exp;
DEBUGP("ip_ct_ras: GCF\n");
if (!get_h225_addr(*data, &gcf->rasAddress, &ip, &port))
return 0;
/* Registration port is the same as discovery port */
if (ip == ct->tuplehash[dir].tuple.src.ip &&
port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port))
return 0;
/* Avoid RAS expectation loops. A GCF is never expected. */
if (test_bit(IPS_EXPECTED_BIT, &ct->status))
return 0;
/* Need new expect */
if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
exp->tuple.dst.ip = ip;
exp->tuple.dst.u.tcp.port = htons(port);
exp->tuple.dst.protonum = IPPROTO_UDP;
exp->mask.src.ip = 0xFFFFFFFF;
exp->mask.src.u.tcp.port = 0;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.tcp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->flags = 0;
exp->expectfn = ip_conntrack_ras_expect;
if (ip_conntrack_expect_related(exp) == 0) {
DEBUGP("ip_ct_ras: expect RAS "
"%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));
} else
ret = -1;
ip_conntrack_expect_put(exp);
return ret;
}
/****************************************************************************/
static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, RegistrationRequest * rrq)
{
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int ret;
DEBUGP("ip_ct_ras: RRQ\n");
ret = expect_q931(pskb, ct, ctinfo, data,
rrq->callSignalAddress.item,
rrq->callSignalAddress.count);
if (ret < 0)
return -1;
if (set_ras_addr_hook) {
ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
rrq->rasAddress.item,
rrq->rasAddress.count);
if (ret < 0)
return -1;
}
if (rrq->options & eRegistrationRequest_timeToLive) {
DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
info->timeout = rrq->timeToLive;
} else
info->timeout = 0;
return 0;
}
/****************************************************************************/
static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, RegistrationConfirm * rcf)
{
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int dir = CTINFO2DIR(ctinfo);
int ret;
struct ip_conntrack_expect *exp;
DEBUGP("ip_ct_ras: RCF\n");
if (set_sig_addr_hook) {
ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
rcf->callSignalAddress.item,
rcf->callSignalAddress.count);
if (ret < 0)
return -1;
}
if (rcf->options & eRegistrationConfirm_timeToLive) {
DEBUGP("ip_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
info->timeout = rcf->timeToLive;
}
if (info->timeout > 0) {
DEBUGP
("ip_ct_ras: set RAS connection timeout to %u seconds\n",
info->timeout);
ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ);
/* Set expect timeout */
read_lock_bh(&ip_conntrack_lock);
exp = find_expect(ct, ct->tuplehash[dir].tuple.dst.ip,
info->sig_port[!dir]);
if (exp) {
DEBUGP("ip_ct_ras: set Q.931 expect "
"(%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu) "
"timeout to %u seconds\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),
info->timeout);
set_expect_timeout(exp, info->timeout);
}
read_unlock_bh(&ip_conntrack_lock);
}
return 0;
}
/****************************************************************************/
static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, UnregistrationRequest * urq)
{
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int dir = CTINFO2DIR(ctinfo);
int ret;
DEBUGP("ip_ct_ras: URQ\n");
if (set_sig_addr_hook) {
ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
urq->callSignalAddress.item,
urq->callSignalAddress.count);
if (ret < 0)
return -1;
}
/* Clear old expect */
ip_ct_remove_expectations(ct);
info->sig_port[dir] = 0;
info->sig_port[!dir] = 0;
/* Give it 30 seconds for UCF or URJ */
ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ);
return 0;
}
/****************************************************************************/
static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, AdmissionRequest * arq)
{
struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
int dir = CTINFO2DIR(ctinfo);
u_int32_t ip;
u_int16_t port;
DEBUGP("ip_ct_ras: ARQ\n");
if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
ip == ct->tuplehash[dir].tuple.src.ip &&
port == info->sig_port[dir] && set_h225_addr_hook) {
/* Answering ARQ */
return set_h225_addr_hook(pskb, data, 0,
&arq->destCallSignalAddress,
ct->tuplehash[!dir].tuple.dst.ip,
info->sig_port[!dir]);
}
if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) {
/* Calling ARQ */
return set_h225_addr_hook(pskb, data, 0,
&arq->srcCallSignalAddress,
ct->tuplehash[!dir].tuple.dst.ip,
port);
}
return 0;
}
/****************************************************************************/
static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, AdmissionConfirm * acf)
{
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
u_int32_t ip;
u_int16_t port;
struct ip_conntrack_expect *exp;
DEBUGP("ip_ct_ras: ACF\n");
if (!get_h225_addr(*data, &acf->destCallSignalAddress, &ip, &port))
return 0;
if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */
if (set_sig_addr_hook)
return set_sig_addr_hook(pskb, ct, ctinfo, data,
&acf->destCallSignalAddress,
1);
return 0;
}
/* Need new expect */
if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
exp->tuple.dst.ip = ip;
exp->tuple.dst.u.tcp.port = htons(port);
exp->tuple.dst.protonum = IPPROTO_TCP;
exp->mask.src.ip = 0xFFFFFFFF;
exp->mask.src.u.tcp.port = 0;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.tcp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->flags = IP_CT_EXPECT_PERMANENT;
exp->expectfn = ip_conntrack_q931_expect;
if (ip_conntrack_expect_related(exp) == 0) {
DEBUGP("ip_ct_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));
} else
ret = -1;
ip_conntrack_expect_put(exp);
return ret;
}
/****************************************************************************/
static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, LocationRequest * lrq)
{
DEBUGP("ip_ct_ras: LRQ\n");
if (set_ras_addr_hook)
return set_ras_addr_hook(pskb, ct, ctinfo, data,
&lrq->replyAddress, 1);
return 0;
}
/****************************************************************************/
static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, LocationConfirm * lcf)
{
int dir = CTINFO2DIR(ctinfo);
int ret = 0;
u_int32_t ip;
u_int16_t port;
struct ip_conntrack_expect *exp = NULL;
DEBUGP("ip_ct_ras: LCF\n");
if (!get_h225_addr(*data, &lcf->callSignalAddress, &ip, &port))
return 0;
/* Need new expect for call signal */
if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
return -1;
exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
exp->tuple.src.u.tcp.port = 0;
exp->tuple.dst.ip = ip;
exp->tuple.dst.u.tcp.port = htons(port);
exp->tuple.dst.protonum = IPPROTO_TCP;
exp->mask.src.ip = 0xFFFFFFFF;
exp->mask.src.u.tcp.port = 0;
exp->mask.dst.ip = 0xFFFFFFFF;
exp->mask.dst.u.tcp.port = 0xFFFF;
exp->mask.dst.protonum = 0xFF;
exp->flags = IP_CT_EXPECT_PERMANENT;
exp->expectfn = ip_conntrack_q931_expect;
if (ip_conntrack_expect_related(exp) == 0) {
DEBUGP("ip_ct_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));
} else
ret = -1;
ip_conntrack_expect_put(exp);
/* Ignore rasAddress */
return ret;
}
/****************************************************************************/
static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, InfoRequestResponse * irr)
{
int ret;
DEBUGP("ip_ct_ras: IRR\n");
if (set_ras_addr_hook) {
ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
&irr->rasAddress, 1);
if (ret < 0)
return -1;
}
if (set_sig_addr_hook) {
ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
irr->callSignalAddress.item,
irr->callSignalAddress.count);
if (ret < 0)
return -1;
}
return 0;
}
/****************************************************************************/
static int process_ras(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned char **data, RasMessage * ras)
{
switch (ras->choice) {
case eRasMessage_gatekeeperRequest:
return process_grq(pskb, ct, ctinfo, data,
&ras->gatekeeperRequest);
case eRasMessage_gatekeeperConfirm:
return process_gcf(pskb, ct, ctinfo, data,
&ras->gatekeeperConfirm);
case eRasMessage_registrationRequest:
return process_rrq(pskb, ct, ctinfo, data,
&ras->registrationRequest);
case eRasMessage_registrationConfirm:
return process_rcf(pskb, ct, ctinfo, data,
&ras->registrationConfirm);
case eRasMessage_unregistrationRequest:
return process_urq(pskb, ct, ctinfo, data,
&ras->unregistrationRequest);
case eRasMessage_admissionRequest:
return process_arq(pskb, ct, ctinfo, data,
&ras->admissionRequest);
case eRasMessage_admissionConfirm:
return process_acf(pskb, ct, ctinfo, data,
&ras->admissionConfirm);
case eRasMessage_locationRequest:
return process_lrq(pskb, ct, ctinfo, data,
&ras->locationRequest);
case eRasMessage_locationConfirm:
return process_lcf(pskb, ct, ctinfo, data,
&ras->locationConfirm);
case eRasMessage_infoRequestResponse:
return process_irr(pskb, ct, ctinfo, data,
&ras->infoRequestResponse);
default:
DEBUGP("ip_ct_ras: RAS message %d\n", ras->choice);
break;
}
return 0;
}
/****************************************************************************/
static int ras_help(struct sk_buff **pskb, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo)
{
static RasMessage ras;
unsigned char *data;
int datalen = 0;
int ret;
DEBUGP("ip_ct_ras: skblen = %u\n", (*pskb)->len);
spin_lock_bh(&ip_h323_lock);
/* Get UDP data */
data = get_udp_data(pskb, &datalen);
if (data == NULL)
goto accept;
DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
NIPQUAD((*pskb)->nh.iph->saddr),
NIPQUAD((*pskb)->nh.iph->daddr), datalen);
/* Decode RAS message */
ret = DecodeRasMessage(data, datalen, &ras);
if (ret < 0) {
if (net_ratelimit())
printk("ip_ct_ras: decoding error: %s\n",
ret == H323_ERROR_BOUND ?
"out of bound" : "out of range");
goto accept;
}
/* Process RAS message */
if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
goto drop;
accept:
spin_unlock_bh(&ip_h323_lock);
return NF_ACCEPT;
drop:
spin_unlock_bh(&ip_h323_lock);
if (net_ratelimit())
printk("ip_ct_ras: packet dropped\n");
return NF_DROP;
}
/****************************************************************************/
static struct ip_conntrack_helper ip_conntrack_helper_ras = {
.name = "RAS",
.me = THIS_MODULE,
.max_expected = 32,
.timeout = 240,
.tuple = {.src = {.u = {__constant_htons(RAS_PORT)}},
.dst = {.protonum = IPPROTO_UDP}},
.mask = {.src = {.u = {0xFFFE}},
.dst = {.protonum = 0xFF}},
.help = ras_help,
};
/****************************************************************************/
static void ip_conntrack_ras_expect(struct ip_conntrack *new,
struct ip_conntrack_expect *this)
{
write_lock_bh(&ip_conntrack_lock);
new->helper = &ip_conntrack_helper_ras;
write_unlock_bh(&ip_conntrack_lock);
}
/****************************************************************************/
/* Not __exit - called from init() */
static void fini(void)
{
ip_conntrack_helper_unregister(&ip_conntrack_helper_ras);
ip_conntrack_helper_unregister(&ip_conntrack_helper_q931);
kfree(h323_buffer);
DEBUGP("ip_ct_h323: fini\n");
}
/****************************************************************************/
static int __init init(void)
{
int ret;
h323_buffer = kmalloc(65536, GFP_KERNEL);
if (!h323_buffer)
return -ENOMEM;
if ((ret = ip_conntrack_helper_register(&ip_conntrack_helper_q931)) ||
(ret = ip_conntrack_helper_register(&ip_conntrack_helper_ras))) {
fini();
return ret;
}
DEBUGP("ip_ct_h323: init success\n");
return 0;
}
/****************************************************************************/
module_init(init);
module_exit(fini);
EXPORT_SYMBOL(get_h245_addr);
EXPORT_SYMBOL(get_h225_addr);
EXPORT_SYMBOL(ip_conntrack_h245_expect);
EXPORT_SYMBOL(ip_conntrack_q931_expect);
EXPORT_SYMBOL(set_h245_addr_hook);
EXPORT_SYMBOL(set_h225_addr_hook);
EXPORT_SYMBOL(set_sig_addr_hook);
EXPORT_SYMBOL(set_ras_addr_hook);
EXPORT_SYMBOL(nat_rtp_rtcp_hook);
EXPORT_SYMBOL(nat_t120_hook);
EXPORT_SYMBOL(nat_h245_hook);
EXPORT_SYMBOL(nat_q931_hook);
MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
MODULE_DESCRIPTION("H.323 connection tracking helper");
MODULE_LICENSE("GPL");
/****************************************************************************
* 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;
}
/****************************************************************************
* 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
/* 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.
*/
static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */
{FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE,
offsetof(TransportAddress_ipAddress, ip), NULL},
{FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */
{FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
};
static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */
{FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */
{FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
{FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
{FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
_TransportAddress_ipSourceRoute_route},
{FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0,
_TransportAddress_ipSourceRoute_routing},
};
static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */
{FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
{FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
{FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
};
static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */
{FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _H221NonStandard[] = { /* SEQUENCE */
{FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _NonStandardIdentifier[] = { /* CHOICE */
{FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0,
_H221NonStandard},
};
static field_t _NonStandardParameter[] = { /* SEQUENCE */
{FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0,
_NonStandardIdentifier},
{FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _TransportAddress[] = { /* CHOICE */
{FNAME("ipAddress") SEQ, 0, 2, 2, DECODE,
offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress},
{FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0,
_TransportAddress_ipSourceRoute},
{FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
_TransportAddress_ipxAddress},
{FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
_TransportAddress_ip6Address},
{FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
{FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
_NonStandardParameter},
};
static field_t _AliasAddress[] = { /* CHOICE */
{FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
{FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL},
{FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL},
{FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL},
};
static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _VendorIdentifier[] = { /* SEQUENCE */
{FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard},
{FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
};
static field_t _GatekeeperInfo[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
};
static field_t _H310Caps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H320Caps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H321Caps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H322Caps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H323Caps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H324Caps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _VoiceCaps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _T120OnlyCaps[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _SupportedProtocols[] = { /* CHOICE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0,
_NonStandardParameter},
{FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps},
{FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps},
{FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps},
{FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps},
{FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps},
{FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps},
{FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps},
{FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps},
{FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL},
{FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL},
};
static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols},
};
static field_t _GatewayInfo[] = { /* SEQUENCE */
{FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_GatewayInfo_protocol},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
};
static field_t _McuInfo[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
};
static field_t _TerminalInfo[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
};
static field_t _EndpointType[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0,
_VendorIdentifier},
{FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0,
_GatekeeperInfo},
{FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo},
{FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo},
{FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo},
{FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT,
0, NULL},
};
static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */
{FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */
{FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP,
0, NULL},
};
static field_t _Q954Details[] = { /* SEQUENCE */
{FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _QseriesOptions[] = { /* SEQUENCE */
{FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details},
};
static field_t _CallType[] = { /* CHOICE */
{FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */
{FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */
{FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0,
_H245_NonStandardIdentifier_h221NonStandard},
};
static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */
{FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0,
_H245_NonStandardIdentifier},
{FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H261VideoCapability[] = { /* SEQUENCE */
{FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
NULL},
{FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _H262VideoCapability[] = { /* SEQUENCE */
{FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0,
NULL},
{FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _H263VideoCapability[] = { /* SEQUENCE */
{FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL},
{FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
NULL},
{FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0,
NULL},
{FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL},
};
static field_t _IS11172VideoCapability[] = { /* SEQUENCE */
{FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _VideoCapability[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0,
_H261VideoCapability},
{FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0,
_H262VideoCapability},
{FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0,
_H263VideoCapability},
{FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0,
_IS11172VideoCapability},
{FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
};
static field_t _AudioCapability_g7231[] = { /* SEQUENCE */
{FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _IS11172AudioCapability[] = { /* SEQUENCE */
{FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
};
static field_t _IS13818AudioCapability[] = { /* SEQUENCE */
{FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
};
static field_t _AudioCapability[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231},
{FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0,
_IS11172AudioCapability},
{FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0,
_IS13818AudioCapability},
{FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
{FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL},
{FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
{FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
{FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
{FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
{FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL},
};
static field_t _DataProtocolCapability[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL},
{FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */
{FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _T84Profile[] = { /* CHOICE */
{FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0,
_T84Profile_t84Restricted},
};
static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */
{FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile},
};
static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */
{FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _DataApplicationCapability_application[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT,
offsetof(DataApplicationCapability_application, t120),
_DataProtocolCapability},
{FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("t84") SEQ, 0, 2, 2, SKIP, 0,
_DataApplicationCapability_application_t84},
{FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0,
_DataApplicationCapability_application_nlpid},
{FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0,
_DataProtocolCapability},
{FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
{FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
{FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL},
{FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
};
static field_t _DataApplicationCapability[] = { /* SEQUENCE */
{FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT,
offsetof(DataApplicationCapability, application),
_DataApplicationCapability_application},
{FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL},
};
static field_t _EncryptionMode[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _DataType[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability},
{FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0,
_AudioCapability},
{FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data),
_DataApplicationCapability},
{FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0,
_EncryptionMode},
{FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL},
{FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
{FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
};
static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL},
{FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL},
{FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
};
static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */
{FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL},
{FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL},
};
static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
_H245_NonStandardParameter},
{FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("al3") SEQ, 0, 2, 2, SKIP, 0,
_H223LogicalChannelParameters_adaptationLayerType_al3},
{FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL},
{FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
{FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL},
};
static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0,
_H223LogicalChannelParameters_adaptationLayerType},
{FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _CRCLength[] = { /* CHOICE */
{FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _V76HDLCParameters[] = { /* SEQUENCE */
{FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength},
{FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */
{FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */
{FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */
{FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL},
{FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0,
_V76LogicalChannelParameters_mode_eRM_recovery},
};
static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */
{FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0,
_V76LogicalChannelParameters_mode_eRM},
{FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _V75Parameters[] = { /* SEQUENCE */
{FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0,
_V76HDLCParameters},
{FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0,
_V76LogicalChannelParameters_suspendResume},
{FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0,
_V76LogicalChannelParameters_mode},
{FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters},
};
static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
};
static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */
{FNAME("network") OCTSTR, FIXD, 4, 0, DECODE,
offsetof(UnicastAddress_iPAddress, network), NULL},
{FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */
{FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
{FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
{FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
};
static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */
{FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */
{FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */
{FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
};
static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */
{FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0,
_UnicastAddress_iPSourceRouteAddress_routing},
{FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
{FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
{FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
_UnicastAddress_iPSourceRouteAddress_route},
};
static field_t _UnicastAddress[] = { /* CHOICE */
{FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT,
offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress},
{FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0,
_UnicastAddress_iPXAddress},
{FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
_UnicastAddress_iP6Address},
{FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0,
_UnicastAddress_iPSourceRouteAddress},
{FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
{FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
};
static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */
{FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
{FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */
{FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _MulticastAddress[] = { /* CHOICE */
{FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0,
_MulticastAddress_iPAddress},
{FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
_MulticastAddress_iP6Address},
{FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
{FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
};
static field_t _H245_TransportAddress[] = { /* CHOICE */
{FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT,
offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress},
{FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0,
_MulticastAddress},
};
static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_H2250LogicalChannelParameters_nonStandard},
{FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
offsetof(H2250LogicalChannelParameters, mediaChannel),
_H245_TransportAddress},
{FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0,
NULL},
{FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
offsetof(H2250LogicalChannelParameters, mediaControlChannel),
_H245_TransportAddress},
{FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT,
0, NULL},
{FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL},
{FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0,
NULL},
{FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0,
NULL},
{FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL},
};
static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
{FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
_H222LogicalChannelParameters},
{FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
_H223LogicalChannelParameters},
{FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
_V76LogicalChannelParameters},
{FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
offsetof
(OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters,
h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
{FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT,
offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
dataType), _DataType},
{FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT,
offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
multiplexParameters),
_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters},
{FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
0, NULL},
{FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
};
static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
{FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
_H223LogicalChannelParameters},
{FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
_V76LogicalChannelParameters},
{FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
offsetof
(OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters,
h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
};
static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType},
{FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT,
offsetof(OpenLogicalChannel_reverseLogicalChannelParameters,
multiplexParameters),
_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters},
{FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
0, NULL},
{FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
};
static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */
{FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _Q2931Address_address[] = { /* CHOICE */
{FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL},
{FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
};
static field_t _Q2931Address[] = { /* SEQUENCE */
{FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0,
_Q2931Address_address},
{FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL},
};
static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */
{FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address},
{FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
{FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT,
offsetof(NetworkAccessParameters_networkAddress, localAreaAddress),
_H245_TransportAddress},
};
static field_t _NetworkAccessParameters[] = { /* SEQUENCE */
{FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0,
_NetworkAccessParameters_distribution},
{FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT,
offsetof(NetworkAccessParameters, networkAddress),
_NetworkAccessParameters_networkAddress},
{FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
NULL},
};
static field_t _OpenLogicalChannel[] = { /* SEQUENCE */
{FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT,
offsetof(OpenLogicalChannel, forwardLogicalChannelParameters),
_OpenLogicalChannel_forwardLogicalChannelParameters},
{FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4,
DECODE | EXT | OPT, offsetof(OpenLogicalChannel,
reverseLogicalChannelParameters),
_OpenLogicalChannel_reverseLogicalChannelParameters},
{FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT,
offsetof(OpenLogicalChannel, separateStack),
_NetworkAccessParameters},
{FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
};
static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _Setup_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Setup_UUIE, h245Address), _TransportAddress},
{FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Setup_UUIE_sourceAddress},
{FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
{FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Setup_UUIE_destinationAddress},
{FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress},
{FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Setup_UUIE_destExtraCallInfo},
{FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Setup_UUIE_destExtraCRV},
{FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0,
_Setup_UUIE_conferenceGoal},
{FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0,
_QseriesOptions},
{FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
{FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress},
{FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
NULL},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart},
{FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0,
NULL},
{FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
NULL},
{FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0,
NULL},
{FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
{FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
NULL},
};
static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
_EndpointType},
{FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(CallProceeding_UUIE, h245Address), _TransportAddress},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(CallProceeding_UUIE, fastStart),
_CallProceeding_UUIE_fastStart},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
};
static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _Connect_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Connect_UUIE, h245Address), _TransportAddress},
{FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
_EndpointType},
{FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
NULL},
{FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
NULL},
{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
};
static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _Alerting_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
_EndpointType},
{FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Alerting_UUIE, h245Address), _TransportAddress},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
NULL},
{FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
NULL},
{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
};
static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _Information_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart},
{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
};
static field_t _ReleaseCompleteReason[] = { /* CHOICE */
{FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL},
{FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0,
NULL},
{FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0,
_ReleaseCompleteReason},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
NULL},
{FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
NULL},
{FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
};
static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _FacilityReason[] = { /* CHOICE */
{FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _Facility_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0,
_TransportAddress},
{FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Facility_UUIE_alternativeAliasAddress},
{FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
{FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT,
offsetof(Facility_UUIE, reason), _FacilityReason},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
{FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Facility_UUIE, h245Address), _TransportAddress},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
{FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL},
{FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
NULL},
};
static field_t _CallIdentifier[] = { /* SEQUENCE */
{FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
};
static field_t _SecurityServiceMode[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
{FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _SecurityCapabilities[] = { /* SEQUENCE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0,
_SecurityServiceMode},
{FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0,
_SecurityServiceMode},
{FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0,
_SecurityServiceMode},
};
static field_t _H245Security[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
{FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
{FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
};
static field_t _DHset[] = { /* SEQUENCE */
{FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
{FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
{FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
};
static field_t _TypedCertificate[] = { /* SEQUENCE */
{FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */
{FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _ClearToken[] = { /* SEQUENCE */
{FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset},
{FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL},
{FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0,
_TypedCertificate},
{FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
_H235_NonStandardParameter},
{FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL},
{FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
};
static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
};
static field_t _Params[] = { /* SEQUENCE */
{FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL},
{FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
};
static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */
{FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
{FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
{FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
_CryptoH323Token_cryptoEPPwdHash_token},
};
static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */
{FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
{FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
{FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
_CryptoH323Token_cryptoGKPwdHash_token},
};
static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */
{FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */
{FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */
{FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */
{FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
_CryptoToken_cryptoEncryptedToken_token},
};
static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */
{FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */
{FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("token") SEQ, 0, 4, 4, SKIP, 0,
_CryptoToken_cryptoSignedToken_token},
};
static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */
{FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
{FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
_CryptoToken_cryptoHashedToken_token},
};
static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */
{FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
{FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
};
static field_t _CryptoToken[] = { /* CHOICE */
{FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0,
_CryptoToken_cryptoEncryptedToken},
{FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0,
_CryptoToken_cryptoSignedToken},
{FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0,
_CryptoToken_cryptoHashedToken},
{FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
_CryptoToken_cryptoPwdEncr},
};
static field_t _CryptoH323Token[] = { /* CHOICE */
{FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0,
_CryptoH323Token_cryptoEPPwdHash},
{FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0,
_CryptoH323Token_cryptoGKPwdHash},
{FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
_CryptoH323Token_cryptoEPPwdEncr},
{FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
_CryptoH323Token_cryptoGKPwdEncr},
{FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0,
_CryptoH323Token_cryptoEPCert},
{FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0,
_CryptoH323Token_cryptoGKCert},
{FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0,
_CryptoH323Token_cryptoFastStart},
{FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0,
_CryptoToken},
};
static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token},
};
static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
sizeof(OpenLogicalChannel), _OpenLogicalChannel}
,
};
static field_t _Progress_UUIE[] = { /* SEQUENCE */
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
_EndpointType},
{FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(Progress_UUIE, h245Address), _TransportAddress},
{FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0,
_CallIdentifier},
{FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
_H245Security},
{FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Progress_UUIE_tokens},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_Progress_UUIE_cryptoTokens},
{FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
};
static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */
{FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE},
{FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, callProceeding),
_CallProceeding_UUIE},
{FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE},
{FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE},
{FNAME("information") SEQ, 0, 1, 7, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, information),
_Information_UUIE},
{FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0,
_ReleaseComplete_UUIE},
{FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE},
{FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT,
offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE},
{FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
{FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
{FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
{FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
};
static field_t _RequestMessage[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL},
{FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT,
offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel},
{FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL},
{FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL},
{FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL},
{FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
{FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
{FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0,
NULL},
};
static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
{FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
_H222LogicalChannelParameters},
{FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
offsetof
(OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters,
h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
};
static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */
{FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT,
offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters,
multiplexParameters),
_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters},
{FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
};
static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */
{FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
};
static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */
{FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_H2250LogicalChannelAckParameters_nonStandard},
{FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
offsetof(H2250LogicalChannelAckParameters, mediaChannel),
_H245_TransportAddress},
{FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
offsetof(H2250LogicalChannelAckParameters, mediaControlChannel),
_H245_TransportAddress},
{FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL},
{FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
};
static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */
{FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT,
offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters,
h2250LogicalChannelAckParameters),
_H2250LogicalChannelAckParameters},
};
static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */
{FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4,
DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
reverseLogicalChannelParameters),
_OpenLogicalChannelAck_reverseLogicalChannelParameters},
{FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL},
{FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1,
DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
forwardMultiplexAckParameters),
_OpenLogicalChannelAck_forwardMultiplexAckParameters},
{FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
};
static field_t _ResponseMessage[] = { /* CHOICE */
{FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0,
NULL},
{FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0,
NULL},
{FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0,
NULL},
{FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT,
offsetof(ResponseMessage, openLogicalChannelAck),
_OpenLogicalChannelAck},
{FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0,
NULL},
{FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0,
NULL},
{FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
{FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0,
NULL},
{FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
{FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
{FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0,
NULL},
{FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL},
};
static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */
{FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT,
offsetof(MultimediaSystemControlMessage, request), _RequestMessage},
{FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT,
offsetof(MultimediaSystemControlMessage, response),
_ResponseMessage},
{FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL},
{FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL},
};
static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT,
sizeof(MultimediaSystemControlMessage),
_MultimediaSystemControlMessage}
,
};
static field_t _H323_UU_PDU[] = { /* SEQUENCE */
{FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT,
offsetof(H323_UU_PDU, h323_message_body),
_H323_UU_PDU_h323_message_body},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
NULL},
{FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT,
offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control},
{FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT,
0, NULL},
{FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT,
0, NULL},
{FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _H323_UserInformation[] = { /* SEQUENCE */
{FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT,
offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU},
{FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
};
static field_t _GatekeeperRequest[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(GatekeeperRequest, rasAddress), _TransportAddress},
{FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
{FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _GatekeeperConfirm[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(GatekeeperConfirm, rasAddress), _TransportAddress},
{FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0,
NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
sizeof(TransportAddress), _TransportAddress}
,
};
static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
sizeof(TransportAddress), _TransportAddress}
,
};
static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _RegistrationRequest[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
offsetof(RegistrationRequest, callSignalAddress),
_RegistrationRequest_callSignalAddress},
{FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE,
offsetof(RegistrationRequest, rasAddress),
_RegistrationRequest_rasAddress},
{FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
{FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_RegistrationRequest_terminalAlias},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0,
_VendorIdentifier},
{FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
offsetof(RegistrationRequest, timeToLive), NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
0, NULL},
{FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0,
NULL},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0,
NULL},
{FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT,
0, NULL},
{FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
sizeof(TransportAddress), _TransportAddress}
,
};
static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _RegistrationConfirm[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
offsetof(RegistrationConfirm, callSignalAddress),
_RegistrationConfirm_callSignalAddress},
{FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_RegistrationConfirm_terminalAlias},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
{FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
{FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
offsetof(RegistrationConfirm, timeToLive), NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL},
{FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0,
NULL},
{FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0,
NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
sizeof(TransportAddress), _TransportAddress}
,
};
static field_t _UnregistrationRequest[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
offsetof(UnregistrationRequest, callSignalAddress),
_UnregistrationRequest_callSignalAddress},
{FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL},
{FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _CallModel[] = { /* CHOICE */
{FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL},
{FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
};
static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _AdmissionRequest[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
{FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
{FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_AdmissionRequest_destinationInfo},
{FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(AdmissionRequest, destCallSignalAddress),
_TransportAddress},
{FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
_AdmissionRequest_destExtraCallInfo},
{FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
_AdmissionRequest_srcInfo},
{FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress},
{FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL},
{FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
{FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL},
{FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
{FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _AdmissionConfirm[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL},
{FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel},
{FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(AdmissionConfirm, destCallSignalAddress),
_TransportAddress},
{FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL},
{FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
{FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL},
{FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
0, NULL},
{FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0,
NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
};
static field_t _LocationRequest[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
{FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
_LocationRequest_destinationInfo},
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(LocationRequest, replyAddress), _TransportAddress},
{FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
};
static field_t _LocationConfirm[] = { /* SEQUENCE */
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(LocationConfirm, callSignalAddress), _TransportAddress},
{FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(LocationConfirm, rasAddress), _TransportAddress},
{FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
{FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
NULL},
{FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
0, NULL},
{FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
{FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
{FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */
{FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
sizeof(TransportAddress), _TransportAddress}
,
};
static field_t _InfoRequestResponse[] = { /* SEQUENCE */
{FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
_NonStandardParameter},
{FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
{FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
{FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
{FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
offsetof(InfoRequestResponse, rasAddress), _TransportAddress},
{FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
offsetof(InfoRequestResponse, callSignalAddress),
_InfoRequestResponse_callSignalAddress},
{FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
{FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
{FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
{FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
{FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL},
{FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
};
static field_t _RasMessage[] = { /* CHOICE */
{FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT,
offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest},
{FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT,
offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm},
{FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
{FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT,
offsetof(RasMessage, registrationRequest), _RegistrationRequest},
{FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT,
offsetof(RasMessage, registrationConfirm), _RegistrationConfirm},
{FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
{FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT,
offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest},
{FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL},
{FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
{FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT,
offsetof(RasMessage, admissionRequest), _AdmissionRequest},
{FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT,
offsetof(RasMessage, admissionConfirm), _AdmissionConfirm},
{FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL},
{FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL},
{FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
{FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL},
{FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL},
{FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL},
{FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
{FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT,
offsetof(RasMessage, locationRequest), _LocationRequest},
{FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT,
offsetof(RasMessage, locationConfirm), _LocationConfirm},
{FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL},
{FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL},
{FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT,
offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse},
{FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL},
{FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL},
{FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL},
{FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0,
NULL},
{FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0,
NULL},
{FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL},
{FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL},
{FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0,
NULL},
{FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL},
};
/* 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;
/*
* 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");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment