* [NETFILTER 00/09]: Netfilter update
@ 2006-03-21 1:55 Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 01/09]: Fix Kconfig typos Patrick McHardy
` (9 more replies)
0 siblings, 10 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
Hi Dave,
following are my pending netfilter patches for 2.6.17, most notable is
a very nice and clean H.323 connection tracking helper by Jing Min Zhao.
Please apply.
include/linux/netfilter/x_tables.h | 64
include/linux/netfilter_arp/arp_tables.h | 37
include/linux/netfilter_ipv4/ip_conntrack.h | 2
include/linux/netfilter_ipv4/ip_conntrack_h323.h | 30
include/linux/netfilter_ipv4/ip_tables.h | 72
include/linux/netfilter_ipv6/ip6_tables.h | 71
include/net/netfilter/nf_conntrack.h | 4
include/net/tc_act/tc_ipt.h | 4
net/ipv4/netfilter/Kconfig | 26
net/ipv4/netfilter/Makefile | 5
net/ipv4/netfilter/arp_tables.c | 6
net/ipv4/netfilter/ip_conntrack_core.c | 4
net/ipv4/netfilter/ip_conntrack_helper_h323.c | 1731 +++++++++++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 870 +++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h | 98 +
net/ipv4/netfilter/ip_conntrack_helper_h323_types.c | 1926 ++++++++++++++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_types.h | 938 +++++++++
net/ipv4/netfilter/ip_conntrack_netlink.c | 72
net/ipv4/netfilter/ip_nat_helper_h323.c | 605 ++++++
net/ipv4/netfilter/ip_tables.c | 15
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 1
net/ipv6/netfilter/ip6_tables.c | 15
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 1
net/netfilter/Kconfig | 6
net/netfilter/nf_conntrack_core.c | 35
net/netfilter/nf_conntrack_netlink.c | 84
net/netfilter/nf_conntrack_standalone.c | 2
net/netfilter/nfnetlink_queue.c | 19
net/netfilter/x_tables.c | 16
net/netfilter/xt_CLASSIFY.c | 12
net/netfilter/xt_CONNMARK.c | 12
net/netfilter/xt_MARK.c | 21
net/netfilter/xt_NFQUEUE.c | 19
net/netfilter/xt_NOTRACK.c | 12
net/netfilter/xt_comment.c | 12
net/netfilter/xt_connbytes.c | 12
net/netfilter/xt_connmark.c | 29
net/netfilter/xt_conntrack.c | 33
net/netfilter/xt_dccp.c | 12
net/netfilter/xt_helper.c | 29
net/netfilter/xt_length.c | 12
net/netfilter/xt_limit.c | 12
net/netfilter/xt_mac.c | 12
net/netfilter/xt_mark.c | 12
net/netfilter/xt_physdev.c | 12
net/netfilter/xt_pkttype.c | 12
net/netfilter/xt_policy.c | 18
net/netfilter/xt_realm.c | 5
net/netfilter/xt_sctp.c | 12
net/netfilter/xt_state.c | 41
net/netfilter/xt_string.c | 12
net/netfilter/xt_tcpmss.c | 12
net/netfilter/xt_tcpudp.c | 26
scripts/Kbuild.include | 6
54 files changed, 6802 insertions(+), 364 deletions(-)
Dmitry Mishin:
[NETFILTER]: futher {ip,ip6,arp}_tables unification
Jing Min Zhao:
[NETFILTER]: Add H.323 conntrack/NAT helper
Pablo Neira Ayuso:
[NETFILTER]: ctnetlink: Fix expectaction mask dumping
[NETFILTER]: nfnetlink_queue: fix nfnetlink message size
[NETFILTER]: conntrack: cleanup the conntrack ID initialization
[NETFILTER]: x_tables: set the protocol family in x_tables targets/matches
[NETFILTER]: nf_conntrack: support for layer 3 protocol load on demand
Patrick McHardy:
[NETFILTER]: Fix xt_policy address matching
Thomas Voegtle:
[NETFILTER]: Fix Kconfig typos
^ permalink raw reply [flat|nested] 18+ messages in thread
* [NETFILTER 01/09]: Fix Kconfig typos
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 02/09]: ctnetlink: Fix expectaction mask dumping Patrick McHardy
` (8 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1663 bytes --]
[NETFILTER]: Fix Kconfig typos
Signed-off-by: Thomas Vögtle <tv@lio96.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit a1cc87e7efc5abc436e3f2a04931dd40ecdba6d1
tree b2dc3a5e231e09e1b91e049d5056595bbaa9e985
parent b3fad09edaeb07049850ac33d2f51c5bc53e76e1
author Thomas Voegtle <tv@lio96.de> Mon, 20 Mar 2006 14:06:14 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:14 +0100
net/netfilter/Kconfig | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 1e6e311..a7355c5 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -11,7 +11,7 @@ config NETFILTER_NETLINK_QUEUE
tristate "Netfilter NFQUEUE over NFNETLINK interface"
depends on NETFILTER_NETLINK
help
- If this option isenabled, the kernel will include support
+ If this option is enabled, the kernel will include support
for queueing packets via NFNETLINK.
config NETFILTER_NETLINK_LOG
@@ -66,7 +66,7 @@ config NF_CONNTRACK_EVENTS
help
If this option is enabled, the connection tracking code will
provide a notifier chain that can be used by other kernel code
- to get notified aboutchanges in the connection tracking state.
+ to get notified about changes in the connection tracking state.
If unsure, say `N'.
@@ -153,7 +153,7 @@ config NETFILTER_XT_TARGET_NFQUEUE
tristate '"NFQUEUE" target Support'
depends on NETFILTER_XTABLES
help
- This Target replaced the old obsolete QUEUE target.
+ This target replaced the old obsolete QUEUE target.
As opposed to QUEUE, it supports 65535 different queues,
not just one.
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 02/09]: ctnetlink: Fix expectaction mask dumping
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 01/09]: Fix Kconfig typos Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 03/09]: nfnetlink_queue: fix nfnetlink message size Patrick McHardy
` (7 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: ctnetlink: Fix expectaction mask dumping
The expectation mask has some particularities that requires a different
handling. The protocol number fields can be set to non-valid protocols,
ie. l3num is set to 0xFFFF. Since that protocol does not exist, the mask
tuple will not be dumped. Moreover, this results in a kernel panic when
nf_conntrack accesses the array of protocol handlers, that is PF_MAX (0x1F)
long.
This patch introduces the function ctnetlink_exp_dump_mask, that correctly
dumps the expectation mask. Such function uses the l3num value from the
expectation tuple that is a valid layer 3 protocol number. The value of the
l3num mask isn't dumped since it is meaningless from the userspace side.
Thanks to Yasuyuki Kozakai and Patrick McHardy for the feedback.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit daab7149ce33d1782bb37355aea08993219bac99
tree e2357ec08dac6bdd3b79270dd0d00506962822e2
parent a1cc87e7efc5abc436e3f2a04931dd40ecdba6d1
author Pablo Neira Ayuso <pablo@netfilter.org> Mon, 20 Mar 2006 14:06:16 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:16 +0100
net/ipv4/netfilter/ip_conntrack_netlink.c | 72 +++++++++++++++++++------
net/netfilter/nf_conntrack_netlink.c | 84 +++++++++++++++++++++--------
2 files changed, 117 insertions(+), 39 deletions(-)
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 5ce2e3f..730c095 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -4,7 +4,7 @@
* (C) 2001 by Jay Schulist <jschlst@samba.org>
* (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
*
* I've reworked this stuff to use attributes instead of conntrack
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -53,20 +53,18 @@ static char __initdata version[] = "0.90
static inline int
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
- const struct ip_conntrack_tuple *tuple)
+ const struct ip_conntrack_tuple *tuple,
+ struct ip_conntrack_protocol *proto)
{
- struct ip_conntrack_protocol *proto;
int ret = 0;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
- /* If no protocol helper is found, this function will return the
- * generic protocol helper, so proto won't *ever* be NULL */
- proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
if (likely(proto->tuple_to_nfattr))
ret = proto->tuple_to_nfattr(skb, tuple);
- ip_conntrack_proto_put(proto);
+ NFA_NEST_END(skb, nest_parms);
return ret;
@@ -75,28 +73,41 @@ nfattr_failure:
}
static inline int
-ctnetlink_dump_tuples(struct sk_buff *skb,
- const struct ip_conntrack_tuple *tuple)
+ctnetlink_dump_tuples_ip(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple)
{
- struct nfattr *nest_parms;
- int ret;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
- nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
- NFA_NEST_END(skb, nest_parms);
- nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
- ret = ctnetlink_dump_tuples_proto(skb, tuple);
NFA_NEST_END(skb, nest_parms);
- return ret;
+ return 0;
nfattr_failure:
return -1;
}
static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple)
+{
+ int ret;
+ struct ip_conntrack_protocol *proto;
+
+ ret = ctnetlink_dump_tuples_ip(skb, tuple);
+ if (unlikely(ret < 0))
+ return ret;
+
+ proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
+ ip_conntrack_proto_put(proto);
+
+ return ret;
+}
+
+static inline int
ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
{
u_int32_t status = htonl((u_int32_t) ct->status);
@@ -1135,6 +1146,33 @@ nfattr_failure:
}
static inline int
+ctnetlink_exp_dump_mask(struct sk_buff *skb,
+ const struct ip_conntrack_tuple *tuple,
+ const struct ip_conntrack_tuple *mask)
+{
+ int ret;
+ struct ip_conntrack_protocol *proto;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+
+ ret = ctnetlink_dump_tuples_ip(skb, mask);
+ if (unlikely(ret < 0))
+ goto nfattr_failure;
+
+ proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
+ ip_conntrack_proto_put(proto);
+ if (unlikely(ret < 0))
+ goto nfattr_failure;
+
+ NFA_NEST_END(skb, nest_parms);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
ctnetlink_exp_dump_expect(struct sk_buff *skb,
const struct ip_conntrack_expect *exp)
{
@@ -1144,7 +1182,7 @@ ctnetlink_exp_dump_expect(struct sk_buff
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
goto nfattr_failure;
- if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
+ if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
goto nfattr_failure;
if (ctnetlink_exp_dump_tuple(skb,
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 20db402..abf5695 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -4,7 +4,7 @@
* (C) 2001 by Jay Schulist <jschlst@samba.org>
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
*
* I've reworked this stuff to use attributes instead of conntrack
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -55,20 +55,18 @@ static char __initdata version[] = "0.93
static inline int
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
- const struct nf_conntrack_tuple *tuple)
+ const struct nf_conntrack_tuple *tuple,
+ struct nf_conntrack_protocol *proto)
{
- struct nf_conntrack_protocol *proto;
int ret = 0;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
- /* If no protocol helper is found, this function will return the
- * generic protocol helper, so proto won't *ever* be NULL */
- proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
if (likely(proto->tuple_to_nfattr))
ret = proto->tuple_to_nfattr(skb, tuple);
- nf_ct_proto_put(proto);
+ NFA_NEST_END(skb, nest_parms);
return ret;
@@ -77,33 +75,44 @@ nfattr_failure:
}
static inline int
-ctnetlink_dump_tuples(struct sk_buff *skb,
- const struct nf_conntrack_tuple *tuple)
+ctnetlink_dump_tuples_ip(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple,
+ struct nf_conntrack_l3proto *l3proto)
{
- struct nfattr *nest_parms;
- struct nf_conntrack_l3proto *l3proto;
int ret = 0;
-
- l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
-
- nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+
if (likely(l3proto->tuple_to_nfattr))
ret = l3proto->tuple_to_nfattr(skb, tuple);
+
NFA_NEST_END(skb, nest_parms);
+ return ret;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple)
+{
+ int ret;
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_protocol *proto;
+
+ l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+ ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
nf_ct_l3proto_put(l3proto);
if (unlikely(ret < 0))
return ret;
- nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
- ret = ctnetlink_dump_tuples_proto(skb, tuple);
- NFA_NEST_END(skb, nest_parms);
+ proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
+ nf_ct_proto_put(proto);
return ret;
-
-nfattr_failure:
- return -1;
}
static inline int
@@ -1153,6 +1162,37 @@ nfattr_failure:
}
static inline int
+ctnetlink_exp_dump_mask(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *mask)
+{
+ int ret;
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_protocol *proto;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+
+ l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+ ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
+ nf_ct_l3proto_put(l3proto);
+
+ if (unlikely(ret < 0))
+ goto nfattr_failure;
+
+ proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
+ nf_ct_proto_put(proto);
+ if (unlikely(ret < 0))
+ goto nfattr_failure;
+
+ NFA_NEST_END(skb, nest_parms);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
ctnetlink_exp_dump_expect(struct sk_buff *skb,
const struct nf_conntrack_expect *exp)
{
@@ -1162,7 +1202,7 @@ ctnetlink_exp_dump_expect(struct sk_buff
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
goto nfattr_failure;
- if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
+ if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
goto nfattr_failure;
if (ctnetlink_exp_dump_tuple(skb,
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 03/09]: nfnetlink_queue: fix nfnetlink message size
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 01/09]: Fix Kconfig typos Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 02/09]: ctnetlink: Fix expectaction mask dumping Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 04/09]: conntrack: cleanup the conntrack ID initialization Patrick McHardy
` (6 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: nfnetlink_queue: fix nfnetlink message size
Fix oversized message, use NLMSG_SPACE just one since it reserves space
for the netlink header and NFA_SPACE for every attribute.
Thanks to Harald Welte for the feedback
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 443b1bf80678fcd789ce5c984a3240108bec4736
tree e73cbb17af7e245958829d4583564c7aa9552cb8
parent daab7149ce33d1782bb37355aea08993219bac99
author Pablo Neira Ayuso <pablo@netfilter.org> Mon, 20 Mar 2006 14:06:17 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:17 +0100
net/netfilter/nfnetlink_queue.c | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 2cf5fb8..b570166 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -354,16 +354,17 @@ nfqnl_build_packet_message(struct nfqnl_
QDEBUG("entered\n");
/* all macros expand to constant values at compile time */
- size = NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hdr))
- + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
+ size = NLMSG_SPACE(sizeof(struct nfgenmsg)) +
+ + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hdr))
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
#ifdef CONFIG_BRIDGE_NETFILTER
- + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NLMSG_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
#endif
- + NLMSG_SPACE(sizeof(u_int32_t)) /* mark */
- + NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hw))
- + NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
+ + NFA_SPACE(sizeof(u_int32_t)) /* mark */
+ + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hw))
+ + NFA_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
outdev = entinf->outdev;
@@ -388,7 +389,7 @@ nfqnl_build_packet_message(struct nfqnl_
else
data_len = queue->copy_range;
- size += NLMSG_SPACE(data_len);
+ size += NFA_SPACE(data_len);
break;
default:
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 04/09]: conntrack: cleanup the conntrack ID initialization
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (2 preceding siblings ...)
2006-03-21 1:55 ` [NETFILTER 03/09]: nfnetlink_queue: fix nfnetlink message size Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 05/09]: x_tables: set the protocol family in x_tables targets/matches Patrick McHardy
` (5 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: conntrack: cleanup the conntrack ID initialization
Currently the first conntrack ID assigned is 2, use 1 instead.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit b15cd1a2d0f3d67450b9738c071ec1fa74541305
tree 975cad31827b20e16f43e5c79ccaf29276c8fab5
parent 443b1bf80678fcd789ce5c984a3240108bec4736
author Pablo Neira Ayuso <pablo@netfilter.org> Mon, 20 Mar 2006 14:06:18 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:18 +0100
net/ipv4/netfilter/ip_conntrack_core.c | 4 ++--
net/netfilter/nf_conntrack_core.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 84c66db..9e34034 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -77,8 +77,8 @@ unsigned int ip_ct_log_invalid;
static LIST_HEAD(unconfirmed);
static int ip_conntrack_vmalloc;
-static unsigned int ip_conntrack_next_id = 1;
-static unsigned int ip_conntrack_expect_next_id = 1;
+static unsigned int ip_conntrack_next_id;
+static unsigned int ip_conntrack_expect_next_id;
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
struct notifier_block *ip_conntrack_chain;
struct notifier_block *ip_conntrack_expect_chain;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 29dfd0e..8dbca5d 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -85,8 +85,8 @@ unsigned int nf_ct_log_invalid;
static LIST_HEAD(unconfirmed);
static int nf_conntrack_vmalloc;
-static unsigned int nf_conntrack_next_id = 1;
-static unsigned int nf_conntrack_expect_next_id = 1;
+static unsigned int nf_conntrack_next_id;
+static unsigned int nf_conntrack_expect_next_id;
#ifdef CONFIG_NF_CONNTRACK_EVENTS
struct notifier_block *nf_conntrack_chain;
struct notifier_block *nf_conntrack_expect_chain;
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 05/09]: x_tables: set the protocol family in x_tables targets/matches
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (3 preceding siblings ...)
2006-03-21 1:55 ` [NETFILTER 04/09]: conntrack: cleanup the conntrack ID initialization Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 06/09]: nf_conntrack: support for layer 3 protocol load on demand Patrick McHardy
` (4 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: x_tables: set the protocol family in x_tables targets/matches
Set the family field in xt_[matches|targets] registered.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit b90f0dbdce18ac0ce97a09f428c05b9852a5e248
tree 86e1ab8fb7cb2a675637706d7a12ae52f54cf5b2
parent b15cd1a2d0f3d67450b9738c071ec1fa74541305
author Pablo Neira Ayuso <pablo@netfilter.org> Mon, 20 Mar 2006 14:06:20 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:20 +0100
include/linux/netfilter/x_tables.h | 8 ++++----
include/linux/netfilter_arp/arp_tables.h | 6 ++++--
include/linux/netfilter_ipv4/ip_tables.h | 14 +++++++++-----
include/linux/netfilter_ipv6/ip6_tables.h | 14 +++++++++-----
net/ipv4/netfilter/arp_tables.c | 6 ++++--
net/ipv4/netfilter/ip_tables.c | 15 +++++++++------
net/ipv6/netfilter/ip6_tables.c | 15 +++++++++------
net/netfilter/x_tables.c | 16 ++++++++++------
net/netfilter/xt_CLASSIFY.c | 12 +++++++-----
net/netfilter/xt_CONNMARK.c | 12 +++++++-----
net/netfilter/xt_MARK.c | 21 ++++++++++++---------
net/netfilter/xt_NFQUEUE.c | 19 +++++++++++--------
net/netfilter/xt_NOTRACK.c | 12 +++++++-----
net/netfilter/xt_comment.c | 12 +++++++-----
net/netfilter/xt_connbytes.c | 12 +++++++-----
net/netfilter/xt_connmark.c | 12 +++++++-----
net/netfilter/xt_conntrack.c | 5 +++--
net/netfilter/xt_dccp.c | 12 +++++++-----
net/netfilter/xt_helper.c | 12 +++++++-----
net/netfilter/xt_length.c | 12 +++++++-----
net/netfilter/xt_limit.c | 12 +++++++-----
net/netfilter/xt_mac.c | 12 +++++++-----
net/netfilter/xt_mark.c | 12 +++++++-----
net/netfilter/xt_physdev.c | 12 +++++++-----
net/netfilter/xt_pkttype.c | 12 +++++++-----
net/netfilter/xt_policy.c | 12 +++++++-----
net/netfilter/xt_realm.c | 5 +++--
net/netfilter/xt_sctp.c | 12 +++++++-----
net/netfilter/xt_state.c | 12 +++++++-----
net/netfilter/xt_string.c | 12 +++++++-----
net/netfilter/xt_tcpmss.c | 12 +++++++-----
net/netfilter/xt_tcpudp.c | 26 +++++++++++++++-----------
32 files changed, 235 insertions(+), 163 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 46a0f97..bf71efb 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -220,10 +220,10 @@ struct xt_table_info
char *entries[NR_CPUS];
};
-extern int xt_register_target(int af, struct xt_target *target);
-extern void xt_unregister_target(int af, struct xt_target *target);
-extern int xt_register_match(int af, struct xt_match *target);
-extern void xt_unregister_match(int af, struct xt_match *target);
+extern int xt_register_target(struct xt_target *target);
+extern void xt_unregister_target(struct xt_target *target);
+extern int xt_register_match(struct xt_match *target);
+extern void xt_unregister_match(struct xt_match *target);
extern int xt_check_match(const struct xt_match *match, unsigned short family,
unsigned int size, const char *table, unsigned int hook,
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index fd21796..a27be05 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -263,8 +263,10 @@ static __inline__ struct arpt_entry_targ
*/
#ifdef __KERNEL__
-#define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt)
-#define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt)
+#define arpt_register_target(tgt) \
+({ (tgt)->family = NF_ARP; \
+ xt_register_target(tgt); })
+#define arpt_unregister_target(tgt) xt_unregister_target(tgt)
extern int arpt_register_table(struct arpt_table *table,
const struct arpt_replace *repl);
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 76ba24b..ee262b5 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -321,11 +321,15 @@ ipt_get_target(struct ipt_entry *e)
#include <linux/init.h>
extern void ipt_init(void) __init;
-#define ipt_register_target(tgt) xt_register_target(AF_INET, tgt)
-#define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt)
-
-#define ipt_register_match(mtch) xt_register_match(AF_INET, mtch)
-#define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch)
+#define ipt_register_target(tgt) \
+({ (tgt)->family = AF_INET; \
+ xt_register_target(tgt); })
+#define ipt_unregister_target(tgt) xt_unregister_target(tgt)
+
+#define ipt_register_match(mtch) \
+({ (mtch)->family = AF_INET; \
+ xt_register_match(mtch); })
+#define ipt_unregister_match(mtch) xt_unregister_match(mtch)
//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl)
//#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl)
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index f249b57..7107f94 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -334,11 +334,15 @@ ip6t_get_target(struct ip6t_entry *e)
#include <linux/init.h>
extern void ip6t_init(void) __init;
-#define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt)
-#define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt)
-
-#define ip6t_register_match(match) xt_register_match(AF_INET6, match)
-#define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match)
+#define ip6t_register_target(tgt) \
+({ (tgt)->family = AF_INET6; \
+ xt_register_target(tgt); })
+#define ip6t_unregister_target(tgt) xt_unregister_target(tgt)
+
+#define ip6t_register_match(match) \
+({ (match)->family = AF_INET6; \
+ xt_register_match(match); })
+#define ip6t_unregister_match(match) xt_unregister_match(match)
extern int ip6t_register_table(struct ip6t_table *table,
const struct ip6t_replace *repl);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index b017375..dd80661 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1146,12 +1146,14 @@ void arpt_unregister_table(struct arpt_t
static struct arpt_target arpt_standard_target = {
.name = ARPT_STANDARD_TARGET,
.targetsize = sizeof(int),
+ .family = NF_ARP,
};
static struct arpt_target arpt_error_target = {
.name = ARPT_ERROR_TARGET,
.target = arpt_error,
.targetsize = ARPT_FUNCTION_MAXNAMELEN,
+ .family = NF_ARP,
};
static struct nf_sockopt_ops arpt_sockopts = {
@@ -1171,8 +1173,8 @@ static int __init init(void)
xt_proto_init(NF_ARP);
/* Noone else will be downing sem now, so we won't sleep */
- xt_register_target(NF_ARP, &arpt_standard_target);
- xt_register_target(NF_ARP, &arpt_error_target);
+ xt_register_target(&arpt_standard_target);
+ xt_register_target(&arpt_error_target);
/* Register setsockopt */
ret = nf_register_sockopt(&arpt_sockopts);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 39705f9..a7b194c 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1335,12 +1335,14 @@ icmp_checkentry(const char *tablename,
static struct ipt_target ipt_standard_target = {
.name = IPT_STANDARD_TARGET,
.targetsize = sizeof(int),
+ .family = AF_INET,
};
static struct ipt_target ipt_error_target = {
.name = IPT_ERROR_TARGET,
.target = ipt_error,
.targetsize = IPT_FUNCTION_MAXNAMELEN,
+ .family = AF_INET,
};
static struct nf_sockopt_ops ipt_sockopts = {
@@ -1358,6 +1360,7 @@ static struct ipt_match icmp_matchstruct
.match = icmp_match,
.matchsize = sizeof(struct ipt_icmp),
.proto = IPPROTO_ICMP,
+ .family = AF_INET,
.checkentry = icmp_checkentry,
};
@@ -1368,9 +1371,9 @@ static int __init init(void)
xt_proto_init(AF_INET);
/* Noone else will be downing sem now, so we won't sleep */
- xt_register_target(AF_INET, &ipt_standard_target);
- xt_register_target(AF_INET, &ipt_error_target);
- xt_register_match(AF_INET, &icmp_matchstruct);
+ xt_register_target(&ipt_standard_target);
+ xt_register_target(&ipt_error_target);
+ xt_register_match(&icmp_matchstruct);
/* Register setsockopt */
ret = nf_register_sockopt(&ipt_sockopts);
@@ -1387,9 +1390,9 @@ static void __exit fini(void)
{
nf_unregister_sockopt(&ipt_sockopts);
- xt_unregister_match(AF_INET, &icmp_matchstruct);
- xt_unregister_target(AF_INET, &ipt_error_target);
- xt_unregister_target(AF_INET, &ipt_standard_target);
+ xt_unregister_match(&icmp_matchstruct);
+ xt_unregister_target(&ipt_error_target);
+ xt_unregister_target(&ipt_standard_target);
xt_proto_fini(AF_INET);
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 8d68cad..7fae22f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1377,12 +1377,14 @@ icmp6_checkentry(const char *tablename,
static struct ip6t_target ip6t_standard_target = {
.name = IP6T_STANDARD_TARGET,
.targetsize = sizeof(int),
+ .family = AF_INET6,
};
static struct ip6t_target ip6t_error_target = {
.name = IP6T_ERROR_TARGET,
.target = ip6t_error,
.targetsize = IP6T_FUNCTION_MAXNAMELEN,
+ .family = AF_INET6,
};
static struct nf_sockopt_ops ip6t_sockopts = {
@@ -1401,6 +1403,7 @@ static struct ip6t_match icmp6_matchstru
.matchsize = sizeof(struct ip6t_icmp),
.checkentry = icmp6_checkentry,
.proto = IPPROTO_ICMPV6,
+ .family = AF_INET6,
};
static int __init init(void)
@@ -1410,9 +1413,9 @@ static int __init init(void)
xt_proto_init(AF_INET6);
/* Noone else will be downing sem now, so we won't sleep */
- xt_register_target(AF_INET6, &ip6t_standard_target);
- xt_register_target(AF_INET6, &ip6t_error_target);
- xt_register_match(AF_INET6, &icmp6_matchstruct);
+ xt_register_target(&ip6t_standard_target);
+ xt_register_target(&ip6t_error_target);
+ xt_register_match(&icmp6_matchstruct);
/* Register setsockopt */
ret = nf_register_sockopt(&ip6t_sockopts);
@@ -1429,9 +1432,9 @@ static int __init init(void)
static void __exit fini(void)
{
nf_unregister_sockopt(&ip6t_sockopts);
- xt_unregister_match(AF_INET6, &icmp6_matchstruct);
- xt_unregister_target(AF_INET6, &ip6t_error_target);
- xt_unregister_target(AF_INET6, &ip6t_standard_target);
+ xt_unregister_match(&icmp6_matchstruct);
+ xt_unregister_target(&ip6t_error_target);
+ xt_unregister_target(&ip6t_standard_target);
xt_proto_fini(AF_INET6);
}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 750b928..0a29a24 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -60,9 +60,9 @@ static const char *xt_prefix[NPROTO] = {
/* Registration hooks for targets. */
int
-xt_register_target(int af, struct xt_target *target)
+xt_register_target(struct xt_target *target)
{
- int ret;
+ int ret, af = target->family;
ret = down_interruptible(&xt[af].mutex);
if (ret != 0)
@@ -74,8 +74,10 @@ xt_register_target(int af, struct xt_tar
EXPORT_SYMBOL(xt_register_target);
void
-xt_unregister_target(int af, struct xt_target *target)
+xt_unregister_target(struct xt_target *target)
{
+ int af = target->family;
+
down(&xt[af].mutex);
LIST_DELETE(&xt[af].target, target);
up(&xt[af].mutex);
@@ -83,9 +85,9 @@ xt_unregister_target(int af, struct xt_t
EXPORT_SYMBOL(xt_unregister_target);
int
-xt_register_match(int af, struct xt_match *match)
+xt_register_match(struct xt_match *match)
{
- int ret;
+ int ret, af = match->family;
ret = down_interruptible(&xt[af].mutex);
if (ret != 0)
@@ -99,8 +101,10 @@ xt_register_match(int af, struct xt_matc
EXPORT_SYMBOL(xt_register_match);
void
-xt_unregister_match(int af, struct xt_match *match)
+xt_unregister_match(struct xt_match *match)
{
+ int af = match->family;
+
down(&xt[af].mutex);
LIST_DELETE(&xt[af].match, match);
up(&xt[af].mutex);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 3224ed8..3cd2ac9 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -47,6 +47,7 @@ static struct xt_target classify_reg = {
.table = "mangle",
.hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
(1 << NF_IP_POST_ROUTING),
+ .family = AF_INET,
.me = THIS_MODULE,
};
static struct xt_target classify6_reg = {
@@ -56,6 +57,7 @@ static struct xt_target classify6_reg =
.table = "mangle",
.hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
(1 << NF_IP_POST_ROUTING),
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -64,21 +66,21 @@ static int __init init(void)
{
int ret;
- ret = xt_register_target(AF_INET, &classify_reg);
+ ret = xt_register_target(&classify_reg);
if (ret)
return ret;
- ret = xt_register_target(AF_INET6, &classify6_reg);
+ ret = xt_register_target(&classify6_reg);
if (ret)
- xt_unregister_target(AF_INET, &classify_reg);
+ xt_unregister_target(&classify_reg);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_target(AF_INET, &classify_reg);
- xt_unregister_target(AF_INET6, &classify6_reg);
+ xt_unregister_target(&classify_reg);
+ xt_unregister_target(&classify6_reg);
}
module_init(init);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index df2486a..35448b8 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -102,6 +102,7 @@ static struct xt_target connmark_reg = {
.target = target,
.targetsize = sizeof(struct xt_connmark_target_info),
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE
};
@@ -110,6 +111,7 @@ static struct xt_target connmark6_reg =
.target = target,
.targetsize = sizeof(struct xt_connmark_target_info),
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE
};
@@ -119,21 +121,21 @@ static int __init init(void)
need_conntrack();
- ret = xt_register_target(AF_INET, &connmark_reg);
+ ret = xt_register_target(&connmark_reg);
if (ret)
return ret;
- ret = xt_register_target(AF_INET6, &connmark6_reg);
+ ret = xt_register_target(&connmark6_reg);
if (ret)
- xt_unregister_target(AF_INET, &connmark_reg);
+ xt_unregister_target(&connmark_reg);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_target(AF_INET, &connmark_reg);
- xt_unregister_target(AF_INET6, &connmark6_reg);
+ xt_unregister_target(&connmark_reg);
+ xt_unregister_target(&connmark6_reg);
}
module_init(init);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index dcb5266..73bdd5c 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -119,6 +119,7 @@ static struct xt_target ipt_mark_reg_v0
.table = "mangle",
.checkentry = checkentry_v0,
.me = THIS_MODULE,
+ .family = AF_INET,
.revision = 0,
};
@@ -129,6 +130,7 @@ static struct xt_target ipt_mark_reg_v1
.table = "mangle",
.checkentry = checkentry_v1,
.me = THIS_MODULE,
+ .family = AF_INET,
.revision = 1,
};
@@ -139,6 +141,7 @@ static struct xt_target ip6t_mark_reg_v0
.table = "mangle",
.checkentry = checkentry_v0,
.me = THIS_MODULE,
+ .family = AF_INET6,
.revision = 0,
};
@@ -146,18 +149,18 @@ static int __init init(void)
{
int err;
- err = xt_register_target(AF_INET, &ipt_mark_reg_v0);
+ err = xt_register_target(&ipt_mark_reg_v0);
if (err)
return err;
- err = xt_register_target(AF_INET, &ipt_mark_reg_v1);
+ err = xt_register_target(&ipt_mark_reg_v1);
if (err)
- xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
+ xt_unregister_target(&ipt_mark_reg_v0);
- err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0);
+ err = xt_register_target(&ip6t_mark_reg_v0);
if (err) {
- xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
- xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
+ xt_unregister_target(&ipt_mark_reg_v0);
+ xt_unregister_target(&ipt_mark_reg_v1);
}
return err;
@@ -165,9 +168,9 @@ static int __init init(void)
static void __exit fini(void)
{
- xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
- xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
- xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0);
+ xt_unregister_target(&ipt_mark_reg_v0);
+ xt_unregister_target(&ipt_mark_reg_v1);
+ xt_unregister_target(&ip6t_mark_reg_v0);
}
module_init(init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 39a963e..2873e1c 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -41,6 +41,7 @@ static struct xt_target ipt_NFQ_reg = {
.name = "NFQUEUE",
.target = target,
.targetsize = sizeof(struct xt_NFQ_info),
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -48,6 +49,7 @@ static struct xt_target ip6t_NFQ_reg = {
.name = "NFQUEUE",
.target = target,
.targetsize = sizeof(struct xt_NFQ_info),
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -55,36 +57,37 @@ static struct xt_target arpt_NFQ_reg = {
.name = "NFQUEUE",
.target = target,
.targetsize = sizeof(struct xt_NFQ_info),
+ .family = NF_ARP,
.me = THIS_MODULE,
};
static int __init init(void)
{
int ret;
- ret = xt_register_target(AF_INET, &ipt_NFQ_reg);
+ ret = xt_register_target(&ipt_NFQ_reg);
if (ret)
return ret;
- ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg);
+ ret = xt_register_target(&ip6t_NFQ_reg);
if (ret)
goto out_ip;
- ret = xt_register_target(NF_ARP, &arpt_NFQ_reg);
+ ret = xt_register_target(&arpt_NFQ_reg);
if (ret)
goto out_ip6;
return ret;
out_ip6:
- xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
+ xt_unregister_target(&ip6t_NFQ_reg);
out_ip:
- xt_unregister_target(AF_INET, &ipt_NFQ_reg);
+ xt_unregister_target(&ipt_NFQ_reg);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_target(NF_ARP, &arpt_NFQ_reg);
- xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
- xt_unregister_target(AF_INET, &ipt_NFQ_reg);
+ xt_unregister_target(&arpt_NFQ_reg);
+ xt_unregister_target(&ip6t_NFQ_reg);
+ xt_unregister_target(&ipt_NFQ_reg);
}
module_init(init);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index b8634e3..cf2ebd7 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -39,6 +39,7 @@ static struct xt_target notrack_reg = {
.target = target,
.targetsize = 0,
.table = "raw",
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -47,6 +48,7 @@ static struct xt_target notrack6_reg = {
.target = target,
.targetsize = 0,
.table = "raw",
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -54,21 +56,21 @@ static int __init init(void)
{
int ret;
- ret = xt_register_target(AF_INET, ¬rack_reg);
+ ret = xt_register_target(¬rack_reg);
if (ret)
return ret;
- ret = xt_register_target(AF_INET6, ¬rack6_reg);
+ ret = xt_register_target(¬rack6_reg);
if (ret)
- xt_unregister_target(AF_INET, ¬rack_reg);
+ xt_unregister_target(¬rack_reg);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_target(AF_INET6, ¬rack6_reg);
- xt_unregister_target(AF_INET, ¬rack_reg);
+ xt_unregister_target(¬rack6_reg);
+ xt_unregister_target(¬rack_reg);
}
module_init(init);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 03d9d74..2637724 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -33,6 +33,7 @@ static struct xt_match comment_match = {
.name = "comment",
.match = match,
.matchsize = sizeof(struct xt_comment_info),
+ .family = AF_INET,
.me = THIS_MODULE
};
@@ -40,6 +41,7 @@ static struct xt_match comment6_match =
.name = "comment",
.match = match,
.matchsize = sizeof(struct xt_comment_info),
+ .family = AF_INET6,
.me = THIS_MODULE
};
@@ -47,21 +49,21 @@ static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &comment_match);
+ ret = xt_register_match(&comment_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &comment6_match);
+ ret = xt_register_match(&comment6_match);
if (ret)
- xt_unregister_match(AF_INET, &comment_match);
+ xt_unregister_match(&comment_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &comment_match);
- xt_unregister_match(AF_INET6, &comment6_match);
+ xt_unregister_match(&comment_match);
+ xt_unregister_match(&comment6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index f34ecb9..4985f5e 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -148,6 +148,7 @@ static struct xt_match connbytes_match =
.match = match,
.checkentry = check,
.matchsize = sizeof(struct xt_connbytes_info),
+ .family = AF_INET,
.me = THIS_MODULE
};
static struct xt_match connbytes6_match = {
@@ -155,26 +156,27 @@ static struct xt_match connbytes6_match
.match = match,
.checkentry = check,
.matchsize = sizeof(struct xt_connbytes_info),
+ .family = AF_INET6,
.me = THIS_MODULE
};
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &connbytes_match);
+ ret = xt_register_match(&connbytes_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &connbytes6_match);
+ ret = xt_register_match(&connbytes6_match);
if (ret)
- xt_unregister_match(AF_INET, &connbytes_match);
+ xt_unregister_match(&connbytes_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &connbytes_match);
- xt_unregister_match(AF_INET6, &connbytes6_match);
+ xt_unregister_match(&connbytes_match);
+ xt_unregister_match(&connbytes6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 5182247..e810600 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -72,6 +72,7 @@ static struct xt_match connmark_match =
.match = match,
.matchsize = sizeof(struct xt_connmark_info),
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE
};
@@ -80,6 +81,7 @@ static struct xt_match connmark6_match =
.match = match,
.matchsize = sizeof(struct xt_connmark_info),
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE
};
@@ -89,20 +91,20 @@ static int __init init(void)
need_conntrack();
- ret = xt_register_match(AF_INET, &connmark_match);
+ ret = xt_register_match(&connmark_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &connmark6_match);
+ ret = xt_register_match(&connmark6_match);
if (ret)
- xt_unregister_match(AF_INET, &connmark_match);
+ xt_unregister_match(&connmark_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET6, &connmark6_match);
- xt_unregister_match(AF_INET, &connmark_match);
+ xt_unregister_match(&connmark6_match);
+ xt_unregister_match(&connmark_match);
}
module_init(init);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 39fc294..7d20caa 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -207,6 +207,7 @@ static struct xt_match conntrack_match =
.name = "conntrack",
.match = match,
.matchsize = sizeof(struct xt_conntrack_info),
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -214,14 +215,14 @@ static int __init init(void)
{
int ret;
need_conntrack();
- ret = xt_register_match(AF_INET, &conntrack_match);
+ ret = xt_register_match(&conntrack_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &conntrack_match);
+ xt_unregister_match(&conntrack_match);
}
module_init(init);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index db6b70c..2f331de 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -149,6 +149,7 @@ static struct xt_match dccp_match =
.matchsize = sizeof(struct xt_dccp_info),
.proto = IPPROTO_DCCP,
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE,
};
static struct xt_match dccp6_match =
@@ -158,6 +159,7 @@ static struct xt_match dccp6_match =
.matchsize = sizeof(struct xt_dccp_info),
.proto = IPPROTO_DCCP,
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -172,17 +174,17 @@ static int __init init(void)
dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
if (!dccp_optbuf)
return -ENOMEM;
- ret = xt_register_match(AF_INET, &dccp_match);
+ ret = xt_register_match(&dccp_match);
if (ret)
goto out_kfree;
- ret = xt_register_match(AF_INET6, &dccp6_match);
+ ret = xt_register_match(&dccp6_match);
if (ret)
goto out_unreg;
return ret;
out_unreg:
- xt_unregister_match(AF_INET, &dccp_match);
+ xt_unregister_match(&dccp_match);
out_kfree:
kfree(dccp_optbuf);
@@ -191,8 +193,8 @@ out_kfree:
static void __exit fini(void)
{
- xt_unregister_match(AF_INET6, &dccp6_match);
- xt_unregister_match(AF_INET, &dccp_match);
+ xt_unregister_match(&dccp6_match);
+ xt_unregister_match(&dccp_match);
kfree(dccp_optbuf);
}
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 79c3d2a..af549bd 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -153,6 +153,7 @@ static struct xt_match helper_match = {
.match = match,
.matchsize = sizeof(struct xt_helper_info),
.checkentry = check,
+ .family = AF_INET,
.me = THIS_MODULE,
};
static struct xt_match helper6_match = {
@@ -160,6 +161,7 @@ static struct xt_match helper6_match = {
.match = match,
.matchsize = sizeof(struct xt_helper_info),
.checkentry = check,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -168,21 +170,21 @@ static int __init init(void)
int ret;
need_conntrack();
- ret = xt_register_match(AF_INET, &helper_match);
+ ret = xt_register_match(&helper_match);
if (ret < 0)
return ret;
- ret = xt_register_match(AF_INET6, &helper6_match);
+ ret = xt_register_match(&helper6_match);
if (ret < 0)
- xt_unregister_match(AF_INET, &helper_match);
+ xt_unregister_match(&helper_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &helper_match);
- xt_unregister_match(AF_INET6, &helper6_match);
+ xt_unregister_match(&helper_match);
+ xt_unregister_match(&helper6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index b9e60f0..38560ca 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -56,6 +56,7 @@ static struct xt_match length_match = {
.name = "length",
.match = match,
.matchsize = sizeof(struct xt_length_info),
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -63,26 +64,27 @@ static struct xt_match length6_match = {
.name = "length",
.match = match6,
.matchsize = sizeof(struct xt_length_info),
+ .family = AF_INET6,
.me = THIS_MODULE,
};
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &length_match);
+ ret = xt_register_match(&length_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &length6_match);
+ ret = xt_register_match(&length6_match);
if (ret)
- xt_unregister_match(AF_INET, &length_match);
+ xt_unregister_match(&length_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &length_match);
- xt_unregister_match(AF_INET6, &length6_match);
+ xt_unregister_match(&length_match);
+ xt_unregister_match(&length6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 3049e6f..e91c1a4 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -141,6 +141,7 @@ static struct xt_match ipt_limit_reg = {
.match = ipt_limit_match,
.matchsize = sizeof(struct xt_rateinfo),
.checkentry = ipt_limit_checkentry,
+ .family = AF_INET,
.me = THIS_MODULE,
};
static struct xt_match limit6_reg = {
@@ -148,6 +149,7 @@ static struct xt_match limit6_reg = {
.match = ipt_limit_match,
.matchsize = sizeof(struct xt_rateinfo),
.checkentry = ipt_limit_checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -155,21 +157,21 @@ static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &ipt_limit_reg);
+ ret = xt_register_match(&ipt_limit_reg);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &limit6_reg);
+ ret = xt_register_match(&limit6_reg);
if (ret)
- xt_unregister_match(AF_INET, &ipt_limit_reg);
+ xt_unregister_match(&ipt_limit_reg);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &ipt_limit_reg);
- xt_unregister_match(AF_INET6, &limit6_reg);
+ xt_unregister_match(&ipt_limit_reg);
+ xt_unregister_match(&limit6_reg);
}
module_init(init);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index b4559a4..f4defa2 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -49,6 +49,7 @@ static struct xt_match mac_match = {
.matchsize = sizeof(struct xt_mac_info),
.hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
(1 << NF_IP_FORWARD),
+ .family = AF_INET,
.me = THIS_MODULE,
};
static struct xt_match mac6_match = {
@@ -57,27 +58,28 @@ static struct xt_match mac6_match = {
.matchsize = sizeof(struct xt_mac_info),
.hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
(1 << NF_IP_FORWARD),
+ .family = AF_INET6,
.me = THIS_MODULE,
};
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &mac_match);
+ ret = xt_register_match(&mac_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &mac6_match);
+ ret = xt_register_match(&mac6_match);
if (ret)
- xt_unregister_match(AF_INET, &mac_match);
+ xt_unregister_match(&mac_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &mac_match);
- xt_unregister_match(AF_INET6, &mac6_match);
+ xt_unregister_match(&mac_match);
+ xt_unregister_match(&mac6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index c1a8f0f..ce0badf 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -56,6 +56,7 @@ static struct xt_match mark_match = {
.match = match,
.matchsize = sizeof(struct xt_mark_info),
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -64,27 +65,28 @@ static struct xt_match mark6_match = {
.match = match,
.matchsize = sizeof(struct xt_mark_info),
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &mark_match);
+ ret = xt_register_match(&mark_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &mark6_match);
+ ret = xt_register_match(&mark6_match);
if (ret)
- xt_unregister_match(AF_INET, &mark_match);
+ xt_unregister_match(&mark_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &mark_match);
- xt_unregister_match(AF_INET6, &mark6_match);
+ xt_unregister_match(&mark_match);
+ xt_unregister_match(&mark6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index f788e8e..089f4f7 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -121,6 +121,7 @@ static struct xt_match physdev_match = {
.match = match,
.matchsize = sizeof(struct xt_physdev_info),
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -129,6 +130,7 @@ static struct xt_match physdev6_match =
.match = match,
.matchsize = sizeof(struct xt_physdev_info),
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -136,21 +138,21 @@ static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &physdev_match);
+ ret = xt_register_match(&physdev_match);
if (ret < 0)
return ret;
- ret = xt_register_match(AF_INET6, &physdev6_match);
+ ret = xt_register_match(&physdev6_match);
if (ret < 0)
- xt_unregister_match(AF_INET, &physdev_match);
+ xt_unregister_match(&physdev_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &physdev_match);
- xt_unregister_match(AF_INET6, &physdev6_match);
+ xt_unregister_match(&physdev_match);
+ xt_unregister_match(&physdev6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index f38638d..8b8bca9 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -37,6 +37,7 @@ static struct xt_match pkttype_match = {
.name = "pkttype",
.match = match,
.matchsize = sizeof(struct xt_pkttype_info),
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -44,27 +45,28 @@ static struct xt_match pkttype6_match =
.name = "pkttype",
.match = match,
.matchsize = sizeof(struct xt_pkttype_info),
+ .family = AF_INET6,
.me = THIS_MODULE,
};
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &pkttype_match);
+ ret = xt_register_match(&pkttype_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &pkttype6_match);
+ ret = xt_register_match(&pkttype6_match);
if (ret)
- xt_unregister_match(AF_INET, &pkttype_match);
+ xt_unregister_match(&pkttype_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &pkttype_match);
- xt_unregister_match(AF_INET6, &pkttype6_match);
+ xt_unregister_match(&pkttype_match);
+ xt_unregister_match(&pkttype6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 1ec2208..d57a611 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -172,6 +172,7 @@ static struct xt_match policy_match = {
.match = match,
.matchsize = sizeof(struct xt_policy_info),
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -181,6 +182,7 @@ static struct xt_match policy6_match = {
.match = match,
.matchsize = sizeof(struct xt_policy_info),
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -188,19 +190,19 @@ static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &policy_match);
+ ret = xt_register_match(&policy_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &policy6_match);
+ ret = xt_register_match(&policy6_match);
if (ret)
- xt_unregister_match(AF_INET, &policy_match);
+ xt_unregister_match(&policy_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET6, &policy6_match);
- xt_unregister_match(AF_INET, &policy_match);
+ xt_unregister_match(&policy6_match);
+ xt_unregister_match(&policy_match);
}
module_init(init);
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index 57815a0..5e31a4a 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -45,17 +45,18 @@ static struct xt_match realm_match = {
.matchsize = sizeof(struct xt_realm_info),
.hooks = (1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
(1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN),
+ .family = AF_INET,
.me = THIS_MODULE
};
static int __init init(void)
{
- return xt_register_match(AF_INET, &realm_match);
+ return xt_register_match(&realm_match);
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &realm_match);
+ xt_unregister_match(&realm_match);
}
module_init(init);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index f5d698b..c6eb24a 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -186,6 +186,7 @@ static struct xt_match sctp_match = {
.matchsize = sizeof(struct xt_sctp_info),
.proto = IPPROTO_SCTP,
.checkentry = checkentry,
+ .family = AF_INET,
.me = THIS_MODULE
};
@@ -195,27 +196,28 @@ static struct xt_match sctp6_match = {
.matchsize = sizeof(struct xt_sctp_info),
.proto = IPPROTO_SCTP,
.checkentry = checkentry,
+ .family = AF_INET6,
.me = THIS_MODULE
};
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &sctp_match);
+ ret = xt_register_match(&sctp_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &sctp6_match);
+ ret = xt_register_match(&sctp6_match);
if (ret)
- xt_unregister_match(AF_INET, &sctp_match);
+ xt_unregister_match(&sctp_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET6, &sctp6_match);
- xt_unregister_match(AF_INET, &sctp_match);
+ xt_unregister_match(&sctp6_match);
+ xt_unregister_match(&sctp_match);
}
module_init(init);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index b8ec00c..7cd557c 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -48,6 +48,7 @@ static struct xt_match state_match = {
.name = "state",
.match = match,
.matchsize = sizeof(struct xt_state_info),
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -55,6 +56,7 @@ static struct xt_match state6_match = {
.name = "state",
.match = match,
.matchsize = sizeof(struct xt_state_info),
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -64,21 +66,21 @@ static int __init init(void)
need_conntrack();
- ret = xt_register_match(AF_INET, &state_match);
+ ret = xt_register_match(&state_match);
if (ret < 0)
return ret;
- ret = xt_register_match(AF_INET6, &state6_match);
+ ret = xt_register_match(&state6_match);
if (ret < 0)
- xt_unregister_match(AF_INET,&state_match);
+ xt_unregister_match(&state_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &state_match);
- xt_unregister_match(AF_INET6, &state6_match);
+ xt_unregister_match(&state_match);
+ xt_unregister_match(&state6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index fccbad6..703d80f 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -78,6 +78,7 @@ static struct xt_match string_match = {
.matchsize = sizeof(struct xt_string_info),
.checkentry = checkentry,
.destroy = destroy,
+ .family = AF_INET,
.me = THIS_MODULE
};
static struct xt_match string6_match = {
@@ -86,6 +87,7 @@ static struct xt_match string6_match = {
.matchsize = sizeof(struct xt_string_info),
.checkentry = checkentry,
.destroy = destroy,
+ .family = AF_INET6,
.me = THIS_MODULE
};
@@ -93,20 +95,20 @@ static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &string_match);
+ ret = xt_register_match(&string_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &string6_match);
+ ret = xt_register_match(&string6_match);
if (ret)
- xt_unregister_match(AF_INET, &string_match);
+ xt_unregister_match(&string_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET, &string_match);
- xt_unregister_match(AF_INET6, &string6_match);
+ xt_unregister_match(&string_match);
+ xt_unregister_match(&string6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 4925fc9..70a8858 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -98,6 +98,7 @@ static struct xt_match tcpmss_match = {
.match = match,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
+ .family = AF_INET,
.me = THIS_MODULE,
};
@@ -106,6 +107,7 @@ static struct xt_match tcpmss6_match = {
.match = match,
.matchsize = sizeof(struct xt_tcpmss_match_info),
.proto = IPPROTO_TCP,
+ .family = AF_INET6,
.me = THIS_MODULE,
};
@@ -113,21 +115,21 @@ static struct xt_match tcpmss6_match = {
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &tcpmss_match);
+ ret = xt_register_match(&tcpmss_match);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &tcpmss6_match);
+ ret = xt_register_match(&tcpmss6_match);
if (ret)
- xt_unregister_match(AF_INET, &tcpmss_match);
+ xt_unregister_match(&tcpmss_match);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET6, &tcpmss6_match);
- xt_unregister_match(AF_INET, &tcpmss_match);
+ xt_unregister_match(&tcpmss6_match);
+ xt_unregister_match(&tcpmss_match);
}
module_init(init);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index b5cd0dd..14a990e 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -204,6 +204,7 @@ static struct xt_match tcp_matchstruct =
.match = tcp_match,
.matchsize = sizeof(struct xt_tcp),
.proto = IPPROTO_TCP,
+ .family = AF_INET,
.checkentry = tcp_checkentry,
.me = THIS_MODULE,
};
@@ -213,6 +214,7 @@ static struct xt_match tcp6_matchstruct
.match = tcp_match,
.matchsize = sizeof(struct xt_tcp),
.proto = IPPROTO_TCP,
+ .family = AF_INET6,
.checkentry = tcp_checkentry,
.me = THIS_MODULE,
};
@@ -222,6 +224,7 @@ static struct xt_match udp_matchstruct =
.match = udp_match,
.matchsize = sizeof(struct xt_udp),
.proto = IPPROTO_UDP,
+ .family = AF_INET,
.checkentry = udp_checkentry,
.me = THIS_MODULE,
};
@@ -230,6 +233,7 @@ static struct xt_match udp6_matchstruct
.match = udp_match,
.matchsize = sizeof(struct xt_udp),
.proto = IPPROTO_UDP,
+ .family = AF_INET6,
.checkentry = udp_checkentry,
.me = THIS_MODULE,
};
@@ -237,39 +241,39 @@ static struct xt_match udp6_matchstruct
static int __init init(void)
{
int ret;
- ret = xt_register_match(AF_INET, &tcp_matchstruct);
+ ret = xt_register_match(&tcp_matchstruct);
if (ret)
return ret;
- ret = xt_register_match(AF_INET6, &tcp6_matchstruct);
+ ret = xt_register_match(&tcp6_matchstruct);
if (ret)
goto out_unreg_tcp;
- ret = xt_register_match(AF_INET, &udp_matchstruct);
+ ret = xt_register_match(&udp_matchstruct);
if (ret)
goto out_unreg_tcp6;
- ret = xt_register_match(AF_INET6, &udp6_matchstruct);
+ ret = xt_register_match(&udp6_matchstruct);
if (ret)
goto out_unreg_udp;
return ret;
out_unreg_udp:
- xt_unregister_match(AF_INET, &tcp_matchstruct);
+ xt_unregister_match(&tcp_matchstruct);
out_unreg_tcp6:
- xt_unregister_match(AF_INET6, &tcp6_matchstruct);
+ xt_unregister_match(&tcp6_matchstruct);
out_unreg_tcp:
- xt_unregister_match(AF_INET, &tcp_matchstruct);
+ xt_unregister_match(&tcp_matchstruct);
return ret;
}
static void __exit fini(void)
{
- xt_unregister_match(AF_INET6, &udp6_matchstruct);
- xt_unregister_match(AF_INET, &udp_matchstruct);
- xt_unregister_match(AF_INET6, &tcp6_matchstruct);
- xt_unregister_match(AF_INET, &tcp_matchstruct);
+ xt_unregister_match(&udp6_matchstruct);
+ xt_unregister_match(&udp_matchstruct);
+ xt_unregister_match(&tcp6_matchstruct);
+ xt_unregister_match(&tcp_matchstruct);
}
module_init(init);
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 06/09]: nf_conntrack: support for layer 3 protocol load on demand
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (4 preceding siblings ...)
2006-03-21 1:55 ` [NETFILTER 05/09]: x_tables: set the protocol family in x_tables targets/matches Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 07/09]: Fix xt_policy address matching Patrick McHardy
` (3 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: nf_conntrack: support for layer 3 protocol load on demand
x_tables matches and targets that require nf_conntrack_ipv[4|6] to work
don't have enough information to load on demand these modules. This
patch introduces the following changes to solve this issue:
o nf_ct_l3proto_try_module_get: try to load the layer 3 connection
tracker module and increases the refcount.
o nf_ct_l3proto_module put: drop the refcount of the module.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 9f037d96029cc5aad5c61969eeb52ebcb71957d5
tree 6ae0f776c82ee652c4046e2d38cfda90565f8517
parent b90f0dbdce18ac0ce97a09f428c05b9852a5e248
author Pablo Neira Ayuso <pablo@netfilter.org> Mon, 20 Mar 2006 14:06:21 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:21 +0100
include/net/netfilter/nf_conntrack.h | 4 +++
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 1 +
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 1 +
net/netfilter/nf_conntrack_core.c | 31 ++++++++++++++++++++++++
net/netfilter/nf_conntrack_standalone.c | 2 ++
net/netfilter/xt_connmark.c | 17 +++++++++++++
net/netfilter/xt_conntrack.c | 28 ++++++++++++++++++++++
net/netfilter/xt_helper.c | 17 +++++++++++++
net/netfilter/xt_state.c | 29 ++++++++++++++++++++++
9 files changed, 130 insertions(+), 0 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 9d1f0e6..d1cb88b 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -195,6 +195,10 @@ static inline void nf_ct_put(struct nf_c
nf_conntrack_put(&ct->ct_general);
}
+/* Protocol module loading */
+extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
+extern void nf_ct_l3proto_module_put(unsigned short l3proto);
+
extern struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index cb9c661..c8abc9d 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -568,6 +568,7 @@ static int init_or_cleanup(int init)
return ret;
}
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_LICENSE("GPL");
static int __init init(void)
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index ac35f95..c16f629 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -584,6 +584,7 @@ static int init_or_cleanup(int init)
return ret;
}
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8dbca5d..de0e3af 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -23,6 +23,8 @@
* 26 Jan 2006: Harald Welte <laforge@netfilter.org>
* - restructure nf_conn (introduce nf_conn_help)
* - redesign 'features' how they were originally intended
+ * 26 Feb 2006: Pablo Neira Ayuso <pablo@eurodev.net>
+ * - add support for L3 protocol module load on demand.
*
* Derived from net/ipv4/netfilter/ip_conntrack_core.c
*/
@@ -241,6 +243,35 @@ void nf_ct_l3proto_put(struct nf_conntra
module_put(p->me);
}
+int
+nf_ct_l3proto_try_module_get(unsigned short l3proto)
+{
+ int ret;
+ struct nf_conntrack_l3proto *p;
+
+retry: p = nf_ct_l3proto_find_get(l3proto);
+ if (p == &nf_conntrack_generic_l3proto) {
+ ret = request_module("nf_conntrack-%d", l3proto);
+ if (!ret)
+ goto retry;
+
+ return -EPROTOTYPE;
+ }
+
+ return 0;
+}
+
+void nf_ct_l3proto_module_put(unsigned short l3proto)
+{
+ struct nf_conntrack_l3proto *p;
+
+ preempt_disable();
+ p = __nf_ct_l3proto_find(l3proto);
+ preempt_enable();
+
+ module_put(p->me);
+}
+
static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 290d5a0..75577e1 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -834,6 +834,8 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_in
EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
#endif
+EXPORT_SYMBOL(nf_ct_l3proto_try_module_get);
+EXPORT_SYMBOL(nf_ct_l3proto_module_put);
EXPORT_SYMBOL(nf_conntrack_l3proto_register);
EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
EXPORT_SYMBOL(nf_conntrack_protocol_register);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index e810600..7b16f1e 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -64,14 +64,30 @@ checkentry(const char *tablename,
printk(KERN_WARNING "connmark: only support 32bit mark\n");
return 0;
}
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "can't load nf_conntrack support for "
+ "proto=%d\n", match->family);
+ return 0;
+ }
+#endif
return 1;
}
+static void
+destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_ct_l3proto_module_put(match->family);
+#endif
+}
+
static struct xt_match connmark_match = {
.name = "connmark",
.match = match,
.matchsize = sizeof(struct xt_connmark_info),
.checkentry = checkentry,
+ .destroy = destroy,
.family = AF_INET,
.me = THIS_MODULE
};
@@ -81,6 +97,7 @@ static struct xt_match connmark6_match =
.match = match,
.matchsize = sizeof(struct xt_connmark_info),
.checkentry = checkentry,
+ .destroy = destroy,
.family = AF_INET6,
.me = THIS_MODULE
};
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 7d20caa..a6c7e93 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -203,9 +203,37 @@ match(const struct sk_buff *skb,
#endif /* CONFIG_NF_IP_CONNTRACK */
+static int
+checkentry(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "can't load nf_conntrack support for "
+ "proto=%d\n", match->family);
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+static void
+destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_ct_l3proto_module_put(match->family);
+#endif
+}
+
static struct xt_match conntrack_match = {
.name = "conntrack",
.match = match,
+ .checkentry = checkentry,
+ .destroy = destroy,
.matchsize = sizeof(struct xt_conntrack_info),
.family = AF_INET,
.me = THIS_MODULE,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index af549bd..18f524e 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -144,15 +144,31 @@ static int check(const char *tablename,
{
struct xt_helper_info *info = matchinfo;
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "can't load nf_conntrack support for "
+ "proto=%d\n", match->family);
+ return 0;
+ }
+#endif
info->name[29] = '\0';
return 1;
}
+static void
+destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_ct_l3proto_module_put(match->family);
+#endif
+}
+
static struct xt_match helper_match = {
.name = "helper",
.match = match,
.matchsize = sizeof(struct xt_helper_info),
.checkentry = check,
+ .destroy = destroy,
.family = AF_INET,
.me = THIS_MODULE,
};
@@ -161,6 +177,7 @@ static struct xt_match helper6_match = {
.match = match,
.matchsize = sizeof(struct xt_helper_info),
.checkentry = check,
+ .destroy = destroy,
.family = AF_INET6,
.me = THIS_MODULE,
};
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 7cd557c..e6c0be9 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -44,9 +44,36 @@ match(const struct sk_buff *skb,
return (sinfo->statemask & statebit);
}
+static int check(const char *tablename,
+ const void *inf,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "can't load nf_conntrack support for "
+ "proto=%d\n", match->family);
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+static void
+destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+{
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_ct_l3proto_module_put(match->family);
+#endif
+}
+
static struct xt_match state_match = {
.name = "state",
.match = match,
+ .checkentry = check,
+ .destroy = destroy,
.matchsize = sizeof(struct xt_state_info),
.family = AF_INET,
.me = THIS_MODULE,
@@ -55,6 +82,8 @@ static struct xt_match state_match = {
static struct xt_match state6_match = {
.name = "state",
.match = match,
+ .checkentry = check,
+ .destroy = destroy,
.matchsize = sizeof(struct xt_state_info),
.family = AF_INET6,
.me = THIS_MODULE,
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 07/09]: Fix xt_policy address matching
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (5 preceding siblings ...)
2006-03-21 1:55 ` [NETFILTER 06/09]: nf_conntrack: support for layer 3 protocol load on demand Patrick McHardy
@ 2006-03-21 1:55 ` Patrick McHardy
2006-03-21 1:56 ` [NETFILTER 08/09]: Add H.323 conntrack/NAT helper Patrick McHardy
` (2 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:55 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: Fix xt_policy address matching
Fix missing inversion in address matching, it was broken during the
conversion to x_tables.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit d64ab19c8c265eb3defd20d3fa993df52542ad00
tree 2724b6ba5c06a490a1fdfa8fef7b55f05a9240d1
parent 9f037d96029cc5aad5c61969eeb52ebcb71957d5
author Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:22 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 14:06:22 +0100
net/netfilter/xt_policy.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index d57a611..1099cb0 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -27,9 +27,9 @@ xt_addr_cmp(const union xt_policy_addr *
{
switch (family) {
case AF_INET:
- return (a1->a4.s_addr ^ a2->a4.s_addr) & m->a4.s_addr;
+ return !((a1->a4.s_addr ^ a2->a4.s_addr) & m->a4.s_addr);
case AF_INET6:
- return ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
+ return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
}
return 0;
}
@@ -44,7 +44,7 @@ match_xfrm_state(struct xfrm_state *x, c
#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
return MATCH_ADDR(saddr, smask, (union xt_policy_addr *)&x->props.saddr) &&
- MATCH_ADDR(daddr, dmask, (union xt_policy_addr *)&x->id.daddr.a4) &&
+ MATCH_ADDR(daddr, dmask, (union xt_policy_addr *)&x->id.daddr) &&
MATCH(proto, x->id.proto) &&
MATCH(mode, x->props.mode) &&
MATCH(spi, x->id.spi) &&
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 08/09]: Add H.323 conntrack/NAT helper
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (6 preceding siblings ...)
2006-03-21 1:55 ` [NETFILTER 07/09]: Fix xt_policy address matching Patrick McHardy
@ 2006-03-21 1:56 ` Patrick McHardy
2006-03-21 2:03 ` Patrick McHardy
2006-03-21 1:56 ` [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification Patrick McHardy
2006-03-21 2:18 ` [NETFILTER 00/09]: Netfilter update Patrick McHardy
9 siblings, 1 reply; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:56 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: Add H.323 conntrack/NAT helper
Signed-off-by: Jing Min Zhao <zhaojignmin@hotmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit c55bc9d2751de011679d2b18df12075d1c7590c5
tree cb9ea9d0004ce9275e8db9e4745e9db499613729
parent d64ab19c8c265eb3defd20d3fa993df52542ad00
author Jing Min Zhao <zhaojignmin@hotmail.com> Mon, 20 Mar 2006 15:18:54 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 15:18:54 +0100
include/linux/netfilter_ipv4/ip_conntrack.h | 2
include/linux/netfilter_ipv4/ip_conntrack_h323.h | 30
net/ipv4/netfilter/Kconfig | 26
net/ipv4/netfilter/Makefile | 5
net/ipv4/netfilter/ip_conntrack_helper_h323.c | 1731 ++++++++++++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 870 +++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h | 98 +
.../netfilter/ip_conntrack_helper_h323_types.c | 1926 +++++++++++++++++++++++
.../netfilter/ip_conntrack_helper_h323_types.h | 938 +++++++++++
net/ipv4/netfilter/ip_nat_helper_h323.c | 605 ++++++
scripts/Kbuild.include | 6
11 files changed, 6234 insertions(+), 3 deletions(-)
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 215765f..f32d75c 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -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;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
new file mode 100644
index 0000000..0987cea
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -0,0 +1,30 @@
+#ifndef _IP_CONNTRACK_H323_H
+#define _IP_CONNTRACK_H323_H
+
+#ifdef __KERNEL__
+
+#define RAS_PORT 1719
+#define Q931_PORT 1720
+#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
+
+/* This structure exists only once per master */
+struct ip_ct_h323_master {
+
+ /* Original and NATed Q.931 or H.245 signal ports */
+ u_int16_t sig_port[IP_CT_DIR_MAX];
+
+ /* Original and NATed RTP ports */
+ u_int16_t rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX];
+
+ union {
+ /* RAS connection timeout */
+ u_int32_t timeout;
+
+ /* Next TPKT length (for separate TPKT header and data) */
+ u_int16_t tpkt_len[IP_CT_DIR_MAX];
+ };
+};
+
+#endif
+
+#endif
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 933ee7a..aefd3fe 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -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"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 3fe8092..f2cd9a6 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -10,6 +10,9 @@ iptable_nat-objs := ip_nat_rule.o ip_nat
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) +=
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_
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
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
new file mode 100644
index 0000000..c8292c9
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -0,0 +1,1731 @@
+/*
+ * 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");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
new file mode 100644
index 0000000..3c6b34f
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -0,0 +1,870 @@
+/****************************************************************************
+ * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
+ * conntrack/NAT module.
+ *
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ * See ip_conntrack_helper_h323_asn1.h for details.
+ *
+ ****************************************************************************/
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#else
+#include <stdio.h>
+#endif
+#include "ip_conntrack_helper_h323_asn1.h"
+
+/* Trace Flag */
+#ifndef H323_TRACE
+#define H323_TRACE 0
+#endif
+
+#if H323_TRACE
+#define TAB_SIZE 4
+#define IFTHEN(cond, act) if(cond){act;}
+#ifdef __KERNEL__
+#define PRINT printk
+#else
+#define PRINT printf
+#endif
+#define FNAME(name) name,
+#else
+#define IFTHEN(cond, act)
+#define PRINT(fmt, args...)
+#define FNAME(name)
+#endif
+
+/* ASN.1 Types */
+#define NUL 0
+#define BOOL 1
+#define OID 2
+#define INT 3
+#define ENUM 4
+#define BITSTR 5
+#define NUMSTR 6
+#define NUMDGT 6
+#define TBCDSTR 6
+#define OCTSTR 7
+#define PRTSTR 7
+#define IA5STR 7
+#define GENSTR 7
+#define BMPSTR 8
+#define SEQ 9
+#define SET 9
+#define SEQOF 10
+#define SETOF 10
+#define CHOICE 11
+
+/* Constraint Types */
+#define FIXD 0
+/* #define BITS 1-8 */
+#define BYTE 9
+#define WORD 10
+#define CONS 11
+#define SEMI 12
+#define UNCO 13
+
+/* ASN.1 Type Attributes */
+#define SKIP 0
+#define STOP 1
+#define DECODE 2
+#define EXT 4
+#define OPEN 8
+#define OPT 16
+
+
+/* ASN.1 Field Structure */
+typedef struct field_t {
+#if H323_TRACE
+ char *name;
+#endif
+ unsigned char type;
+ unsigned char sz;
+ unsigned char lb;
+ unsigned char ub;
+ unsigned short attr;
+ unsigned short offset;
+ struct field_t *fields;
+} field_t;
+
+/* Bit Stream */
+typedef struct {
+ unsigned char *buf;
+ unsigned char *beg;
+ unsigned char *end;
+ unsigned char *cur;
+ unsigned bit;
+} bitstr_t;
+
+/* Tool Functions */
+#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;}
+#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;}
+#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;}
+#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND)
+static unsigned get_len(bitstr_t * bs);
+static unsigned get_bit(bitstr_t * bs);
+static unsigned get_bits(bitstr_t * bs, unsigned b);
+static unsigned get_bitmap(bitstr_t * bs, unsigned b);
+static unsigned get_uint(bitstr_t * bs, int b);
+
+/* Decoder Functions */
+static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_int(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level);
+
+/* Decoder Functions Vector */
+typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int);
+static decoder_t Decoders[] = {
+ decode_nul,
+ decode_bool,
+ decode_oid,
+ decode_int,
+ decode_enum,
+ decode_bitstr,
+ decode_numstr,
+ decode_octstr,
+ decode_bmpstr,
+ decode_seq,
+ decode_seqof,
+ decode_choice,
+};
+
+/****************************************************************************
+ * H.323 Types
+ ****************************************************************************/
+#include "ip_conntrack_helper_h323_types.c"
+
+/****************************************************************************
+ * Functions
+ ****************************************************************************/
+/* Assume bs is aligned && v < 16384 */
+unsigned get_len(bitstr_t * bs)
+{
+ unsigned v;
+
+ v = *bs->cur++;
+
+ if (v & 0x80) {
+ v &= 0x3f;
+ v <<= 8;
+ v += *bs->cur++;
+ }
+
+ return v;
+}
+
+/****************************************************************************/
+unsigned get_bit(bitstr_t * bs)
+{
+ unsigned b = (*bs->cur) & (0x80 >> bs->bit);
+
+ INC_BIT(bs);
+
+ return b;
+}
+
+/****************************************************************************/
+/* Assume b <= 8 */
+unsigned get_bits(bitstr_t * bs, unsigned b)
+{
+ unsigned v, l;
+
+ v = (*bs->cur) & (0xffU >> bs->bit);
+ l = b + bs->bit;
+
+ if (l < 8) {
+ v >>= 8 - l;
+ bs->bit = l;
+ } else if (l == 8) {
+ bs->cur++;
+ bs->bit = 0;
+ } else { /* l > 8 */
+
+ v <<= 8;
+ v += *(++bs->cur);
+ v >>= 16 - l;
+ bs->bit = l - 8;
+ }
+
+ return v;
+}
+
+/****************************************************************************/
+/* Assume b <= 32 */
+unsigned get_bitmap(bitstr_t * bs, unsigned b)
+{
+ unsigned v, l, shift, bytes;
+
+ if (!b)
+ return 0;
+
+ l = bs->bit + b;
+
+ if (l < 8) {
+ v = (unsigned) (*bs->cur) << (bs->bit + 24);
+ bs->bit = l;
+ } else if (l == 8) {
+ v = (unsigned) (*bs->cur++) << (bs->bit + 24);
+ bs->bit = 0;
+ } else {
+ for (bytes = l >> 3, shift = 24, v = 0; bytes;
+ bytes--, shift -= 8)
+ v |= (unsigned) (*bs->cur++) << shift;
+
+ if (l < 32) {
+ v |= (unsigned) (*bs->cur) << shift;
+ v <<= bs->bit;
+ } else if (l > 32) {
+ v <<= bs->bit;
+ v |= (*bs->cur) >> (8 - bs->bit);
+ }
+
+ bs->bit = l & 0x7;
+ }
+
+ v &= 0xffffffff << (32 - b);
+
+ return v;
+}
+
+/****************************************************************************
+ * Assume bs is aligned and sizeof(unsigned int) == 4
+ ****************************************************************************/
+unsigned get_uint(bitstr_t * bs, int b)
+{
+ unsigned v = 0;
+
+ switch (b) {
+ case 4:
+ v |= *bs->cur++;
+ v <<= 8;
+ case 3:
+ v |= *bs->cur++;
+ v <<= 8;
+ case 2:
+ v |= *bs->cur++;
+ v <<= 8;
+ case 1:
+ v |= *bs->cur++;
+ break;
+ }
+ return v;
+}
+
+/****************************************************************************/
+int decode_nul(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_bool(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ INC_BIT(bs);
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_oid(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ int len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ len = *bs->cur++;
+ bs->cur += len;
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_int(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
+
+ switch (f->sz) {
+ case BYTE: /* Range == 256 */
+ BYTE_ALIGN(bs);
+ bs->cur++;
+ break;
+ case WORD: /* 257 <= Range <= 64K */
+ BYTE_ALIGN(bs);
+ bs->cur += 2;
+ break;
+ case CONS: /* 64K < Range < 4G */
+ len = get_bits(bs, 2) + 1;
+ BYTE_ALIGN(bs);
+ if (base && (f->attr & DECODE)) { /* timeToLive */
+ unsigned v = get_uint(bs, len) + f->lb;
+ PRINT(" = %u", v);
+ *((unsigned *) (base + f->offset)) = v;
+ }
+ bs->cur += len;
+ break;
+ case UNCO:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ bs->cur += len;
+ break;
+ default: /* 2 <= Range <= 255 */
+ INC_BITS(bs, f->sz);
+ break;
+ }
+
+ PRINT("\n");
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_enum(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ if ((f->attr & EXT) && get_bit(bs)) {
+ INC_BITS(bs, 7);
+ } else {
+ INC_BITS(bs, f->sz);
+ }
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ BYTE_ALIGN(bs);
+ switch (f->sz) {
+ case FIXD: /* fixed length > 16 */
+ len = f->lb;
+ break;
+ case WORD: /* 2-byte length */
+ CHECK_BOUND(bs, 2);
+ len = (*bs->cur++) << 8;
+ len += (*bs->cur++) + f->lb;
+ break;
+ case SEMI:
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ break;
+ default:
+ len = 0;
+ break;
+ }
+
+ bs->cur += len >> 3;
+ bs->bit = len & 7;
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* 2 <= Range <= 255 */
+ len = get_bits(bs, f->sz) + f->lb;
+
+ BYTE_ALIGN(bs);
+ INC_BITS(bs, (len << 2));
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
+
+ switch (f->sz) {
+ case FIXD: /* Range == 1 */
+ if (f->lb > 2) {
+ BYTE_ALIGN(bs);
+ if (base && (f->attr & DECODE)) {
+ /* The IP Address */
+ IFTHEN(f->lb == 4,
+ PRINT(" = %d.%d.%d.%d:%d",
+ bs->cur[0], bs->cur[1],
+ bs->cur[2], bs->cur[3],
+ bs->cur[4] * 256 + bs->cur[5]));
+ *((unsigned *) (base + f->offset)) =
+ bs->cur - bs->buf;
+ }
+ }
+ len = f->lb;
+ break;
+ case BYTE: /* Range == 256 */
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ len = (*bs->cur++) + f->lb;
+ break;
+ case SEMI:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs) + f->lb;
+ break;
+ default: /* 2 <= Range <= 255 */
+ len = get_bits(bs, f->sz) + f->lb;
+ BYTE_ALIGN(bs);
+ break;
+ }
+
+ bs->cur += len;
+
+ PRINT("\n");
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ switch (f->sz) {
+ case BYTE: /* Range == 256 */
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ len = (*bs->cur++) + f->lb;
+ break;
+ default: /* 2 <= Range <= 255 */
+ len = get_bits(bs, f->sz) + f->lb;
+ BYTE_ALIGN(bs);
+ break;
+ }
+
+ bs->cur += len << 1;
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
+ int err;
+ field_t *son;
+ unsigned char *beg = NULL;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* Decode? */
+ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
+
+ /* Extensible? */
+ ext = (f->attr & EXT) ? get_bit(bs) : 0;
+
+ /* Get fields bitmap */
+ bmp = get_bitmap(bs, f->sz);
+ if (base)
+ *(unsigned *) base = bmp;
+
+ /* Decode the root components */
+ for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (son->attr & OPT) { /* Optional component */
+ if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */
+ continue;
+ }
+
+ /* Decode */
+ if (son->attr & OPEN) { /* Open field */
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
+ " ", son->name);
+ bs->cur += len;
+ continue;
+ }
+ beg = bs->cur;
+
+ /* Decode */
+ if ((err = (Decoders[son->type]) (bs, son, base,
+ level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ } else if ((err = (Decoders[son->type]) (bs, son, base,
+ level + 1)))
+ return err;
+ }
+
+ /* No extension? */
+ if (!ext)
+ return H323_ERROR_NONE;
+
+ /* Get the extension bitmap */
+ bmp2_len = get_bits(bs, 7) + 1;
+ CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
+ bmp2 = get_bitmap(bs, bmp2_len);
+ bmp |= bmp2 >> f->sz;
+ if (base)
+ *(unsigned *) base = bmp;
+ BYTE_ALIGN(bs);
+
+ /* Decode the extension components */
+ for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (!((0x80000000 >> opt) & bmp2)) /* Not present */
+ continue;
+
+ /* Check Range */
+ if (i >= f->ub) { /* Newer Version? */
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ bs->cur += len;
+ continue;
+ }
+
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base || !(son->attr & DECODE)) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ bs->cur += len;
+ continue;
+ }
+ beg = bs->cur;
+
+ if ((err = (Decoders[son->type]) (bs, son, base,
+ level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ }
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned count, effective_count = 0, i, len = 0;
+ int err;
+ field_t *son;
+ unsigned char *beg = NULL;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* Decode? */
+ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
+
+ /* Decode item count */
+ switch (f->sz) {
+ case BYTE:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ count = *bs->cur++;
+ break;
+ case WORD:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ count = *bs->cur++;
+ count <<= 8;
+ count = *bs->cur++;
+ break;
+ case SEMI:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ count = get_len(bs);
+ break;
+ default:
+ count = get_bits(bs, f->sz);
+ break;
+ }
+ count += f->lb;
+
+ /* Write Count */
+ if (base) {
+ effective_count = count > f->ub ? f->ub : count;
+ *(unsigned *) base = effective_count;
+ base += sizeof(unsigned);
+ }
+
+ /* Decode nested field */
+ son = f->fields;
+ if (base)
+ base -= son->offset;
+ for (i = 0; i < count; i++) {
+ if (son->attr & OPEN) {
+ BYTE_ALIGN(bs);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base || !(son->attr & DECODE)) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
+ " ", son->name);
+ bs->cur += len;
+ continue;
+ }
+ beg = bs->cur;
+
+ if ((err = (Decoders[son->type]) (bs, son,
+ i <
+ effective_count ?
+ base : NULL,
+ level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ } else
+ if ((err = (Decoders[son->type]) (bs, son,
+ i < effective_count ?
+ base : NULL,
+ level + 1)))
+ return err;
+
+ if (base)
+ base += son->offset;
+ }
+
+ return H323_ERROR_NONE;
+}
+
+
+/****************************************************************************/
+int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned type, ext, len = 0;
+ int err;
+ field_t *son;
+ unsigned char *beg = NULL;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* Decode? */
+ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
+
+ /* Decode the choice index number */
+ if ((f->attr & EXT) && get_bit(bs)) {
+ ext = 1;
+ type = get_bits(bs, 7) + f->lb;
+ } else {
+ ext = 0;
+ type = get_bits(bs, f->sz);
+ }
+
+ /* Check Range */
+ if (type >= f->ub) { /* Newer version? */
+ BYTE_ALIGN(bs);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ bs->cur += len;
+ return H323_ERROR_NONE;
+ }
+
+ /* Write Type */
+ if (base)
+ *(unsigned *) base = type;
+
+ /* Transfer to son level */
+ son = &f->fields[type];
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (ext || (son->attr & OPEN)) {
+ BYTE_ALIGN(bs);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base || !(son->attr & DECODE)) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ bs->cur += len;
+ return H323_ERROR_NONE;
+ }
+ beg = bs->cur;
+
+ if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)))
+ return err;
+
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras)
+{
+ static field_t ras_message = {
+ FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
+ 0, _RasMessage
+ };
+ bitstr_t bs;
+
+ bs.buf = bs.beg = bs.cur = buf;
+ bs.end = buf + sz;
+ bs.bit = 0;
+
+ return decode_choice(&bs, &ras_message, (char *) ras, 0);
+}
+
+/****************************************************************************/
+static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
+ size_t sz, H323_UserInformation * uuie)
+{
+ static field_t h323_userinformation = {
+ FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
+ 0, _H323_UserInformation
+ };
+ bitstr_t bs;
+
+ bs.buf = buf;
+ bs.beg = bs.cur = beg;
+ bs.end = beg + sz;
+ bs.bit = 0;
+
+ return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
+}
+
+/****************************************************************************/
+int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
+ MultimediaSystemControlMessage *
+ mscm)
+{
+ static field_t multimediasystemcontrolmessage = {
+ FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
+ DECODE | EXT, 0, _MultimediaSystemControlMessage
+ };
+ bitstr_t bs;
+
+ bs.buf = bs.beg = bs.cur = buf;
+ bs.end = buf + sz;
+ bs.bit = 0;
+
+ return decode_choice(&bs, &multimediasystemcontrolmessage,
+ (char *) mscm, 0);
+}
+
+/****************************************************************************/
+int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931)
+{
+ unsigned char *p = buf;
+ int len;
+
+ if (!p || sz < 1)
+ return H323_ERROR_BOUND;
+
+ /* Protocol Discriminator */
+ if (*p != 0x08) {
+ PRINT("Unknown Protocol Discriminator\n");
+ return H323_ERROR_RANGE;
+ }
+ p++;
+ sz--;
+
+ /* CallReferenceValue */
+ if (sz < 1)
+ return H323_ERROR_BOUND;
+ len = *p++;
+ sz--;
+ if (sz < len)
+ return H323_ERROR_BOUND;
+ p += len;
+ sz -= len;
+
+ /* Message Type */
+ if (sz < 1)
+ return H323_ERROR_BOUND;
+ q931->MessageType = *p++;
+ PRINT("MessageType = %02X\n", q931->MessageType);
+ if (*p & 0x80) {
+ p++;
+ sz--;
+ }
+
+ /* Decode Information Elements */
+ while (sz > 0) {
+ if (*p == 0x7e) { /* UserUserIE */
+ if (sz < 3)
+ break;
+ p++;
+ len = *p++ << 8;
+ len |= *p++;
+ sz -= 3;
+ if (sz < len)
+ break;
+ p++;
+ len--;
+ return DecodeH323_UserInformation(buf, p, len,
+ &q931->UUIE);
+ }
+ p++;
+ sz--;
+ if (sz < 1)
+ break;
+ len = *p++;
+ if (sz < len)
+ break;
+ p += len;
+ sz -= len;
+ }
+
+ PRINT("Q.931 UUIE not found\n");
+
+ return H323_ERROR_BOUND;
+}
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
new file mode 100644
index 0000000..2556b84
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+ * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
+ * conntrack/NAT module.
+ *
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ *
+ * This library is based on H.225 version 4, H.235 version 2 and H.245
+ * version 7. It is extremely optimized to decode only the absolutely
+ * necessary objects in a signal for Linux kernel NAT module use, so don't
+ * expect it to be a full ASN.1 library.
+ *
+ * Features:
+ *
+ * 1. Small. The total size of code plus data is less than 20 KB (IA32).
+ * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866
+ * takes only 3.9 seconds.
+ * 3. No memory allocation. It uses a static object. No need to initialize or
+ * cleanup.
+ * 4. Thread safe.
+ * 5. Support embedded architectures that has no misaligned memory access
+ * support.
+ *
+ * Limitations:
+ *
+ * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU.
+ * If a Setup signal contains more than 30 faststart, the packet size will
+ * very likely exceed the MTU size, then the TPKT will be fragmented. I
+ * don't know how to handle this in a Netfilter module. Anybody can help?
+ * Although I think 30 is enough for most of the cases.
+ * 2. IPv4 addresses only.
+ *
+ ****************************************************************************/
+
+#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
+#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
+
+/*****************************************************************************
+ * H.323 Types
+ ****************************************************************************/
+#include "ip_conntrack_helper_h323_types.h"
+
+typedef struct {
+ enum {
+ Q931_NationalEscape = 0x00,
+ Q931_Alerting = 0x01,
+ Q931_CallProceeding = 0x02,
+ Q931_Connect = 0x07,
+ Q931_ConnectAck = 0x0F,
+ Q931_Progress = 0x03,
+ Q931_Setup = 0x05,
+ Q931_SetupAck = 0x0D,
+ Q931_Resume = 0x26,
+ Q931_ResumeAck = 0x2E,
+ Q931_ResumeReject = 0x22,
+ Q931_Suspend = 0x25,
+ Q931_SuspendAck = 0x2D,
+ Q931_SuspendReject = 0x21,
+ Q931_UserInformation = 0x20,
+ Q931_Disconnect = 0x45,
+ Q931_Release = 0x4D,
+ Q931_ReleaseComplete = 0x5A,
+ Q931_Restart = 0x46,
+ Q931_RestartAck = 0x4E,
+ Q931_Segment = 0x60,
+ Q931_CongestionCtrl = 0x79,
+ Q931_Information = 0x7B,
+ Q931_Notify = 0x6E,
+ Q931_Status = 0x7D,
+ Q931_StatusEnquiry = 0x75,
+ Q931_Facility = 0x62
+ } MessageType;
+ H323_UserInformation UUIE;
+} Q931;
+
+/*****************************************************************************
+ * Decode Functions Return Codes
+ ****************************************************************************/
+
+#define H323_ERROR_NONE 0 /* Decoded successfully */
+#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */
+#define H323_ERROR_BOUND -1
+#define H323_ERROR_RANGE -2
+
+
+/*****************************************************************************
+ * Decode Functions
+ ****************************************************************************/
+
+int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras);
+int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931);
+int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
+ MultimediaSystemControlMessage *
+ mscm);
+
+#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
new file mode 100644
index 0000000..022c47b
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
@@ -0,0 +1,1926 @@
+/* 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},
+};
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
new file mode 100644
index 0000000..cc98f7a
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
@@ -0,0 +1,938 @@
+/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+ *
+ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
+ *
+ * This source code is licensed under General Public License version 2.
+ */
+
+typedef struct TransportAddress_ipAddress { /* SEQUENCE */
+ int options; /* No use */
+ unsigned ip;
+} TransportAddress_ipAddress;
+
+typedef struct TransportAddress { /* CHOICE */
+ enum {
+ eTransportAddress_ipAddress,
+ eTransportAddress_ipSourceRoute,
+ eTransportAddress_ipxAddress,
+ eTransportAddress_ip6Address,
+ eTransportAddress_netBios,
+ eTransportAddress_nsap,
+ eTransportAddress_nonStandardAddress,
+ } choice;
+ union {
+ TransportAddress_ipAddress ipAddress;
+ };
+} TransportAddress;
+
+typedef struct DataProtocolCapability { /* CHOICE */
+ enum {
+ eDataProtocolCapability_nonStandard,
+ eDataProtocolCapability_v14buffered,
+ eDataProtocolCapability_v42lapm,
+ eDataProtocolCapability_hdlcFrameTunnelling,
+ eDataProtocolCapability_h310SeparateVCStack,
+ eDataProtocolCapability_h310SingleVCStack,
+ eDataProtocolCapability_transparent,
+ eDataProtocolCapability_segmentationAndReassembly,
+ eDataProtocolCapability_hdlcFrameTunnelingwSAR,
+ eDataProtocolCapability_v120,
+ eDataProtocolCapability_separateLANStack,
+ eDataProtocolCapability_v76wCompression,
+ eDataProtocolCapability_tcp,
+ eDataProtocolCapability_udp,
+ } choice;
+} DataProtocolCapability;
+
+typedef struct DataApplicationCapability_application { /* CHOICE */
+ enum {
+ eDataApplicationCapability_application_nonStandard,
+ eDataApplicationCapability_application_t120,
+ eDataApplicationCapability_application_dsm_cc,
+ eDataApplicationCapability_application_userData,
+ eDataApplicationCapability_application_t84,
+ eDataApplicationCapability_application_t434,
+ eDataApplicationCapability_application_h224,
+ eDataApplicationCapability_application_nlpid,
+ eDataApplicationCapability_application_dsvdControl,
+ eDataApplicationCapability_application_h222DataPartitioning,
+ eDataApplicationCapability_application_t30fax,
+ eDataApplicationCapability_application_t140,
+ eDataApplicationCapability_application_t38fax,
+ eDataApplicationCapability_application_genericDataCapability,
+ } choice;
+ union {
+ DataProtocolCapability t120;
+ };
+} DataApplicationCapability_application;
+
+typedef struct DataApplicationCapability { /* SEQUENCE */
+ int options; /* No use */
+ DataApplicationCapability_application application;
+} DataApplicationCapability;
+
+typedef struct DataType { /* CHOICE */
+ enum {
+ eDataType_nonStandard,
+ eDataType_nullData,
+ eDataType_videoData,
+ eDataType_audioData,
+ eDataType_data,
+ eDataType_encryptionData,
+ eDataType_h235Control,
+ eDataType_h235Media,
+ eDataType_multiplexedStream,
+ } choice;
+ union {
+ DataApplicationCapability data;
+ };
+} DataType;
+
+typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
+ int options; /* No use */
+ unsigned network;
+} UnicastAddress_iPAddress;
+
+typedef struct UnicastAddress { /* CHOICE */
+ enum {
+ eUnicastAddress_iPAddress,
+ eUnicastAddress_iPXAddress,
+ eUnicastAddress_iP6Address,
+ eUnicastAddress_netBios,
+ eUnicastAddress_iPSourceRouteAddress,
+ eUnicastAddress_nsap,
+ eUnicastAddress_nonStandardAddress,
+ } choice;
+ union {
+ UnicastAddress_iPAddress iPAddress;
+ };
+} UnicastAddress;
+
+typedef struct H245_TransportAddress { /* CHOICE */
+ enum {
+ eH245_TransportAddress_unicastAddress,
+ eH245_TransportAddress_multicastAddress,
+ } choice;
+ union {
+ UnicastAddress unicastAddress;
+ };
+} H245_TransportAddress;
+
+typedef struct H2250LogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eH2250LogicalChannelParameters_nonStandard = (1 << 31),
+ eH2250LogicalChannelParameters_associatedSessionID =
+ (1 << 30),
+ eH2250LogicalChannelParameters_mediaChannel = (1 << 29),
+ eH2250LogicalChannelParameters_mediaGuaranteedDelivery =
+ (1 << 28),
+ eH2250LogicalChannelParameters_mediaControlChannel =
+ (1 << 27),
+ eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery
+ = (1 << 26),
+ eH2250LogicalChannelParameters_silenceSuppression = (1 << 25),
+ eH2250LogicalChannelParameters_destination = (1 << 24),
+ eH2250LogicalChannelParameters_dynamicRTPPayloadType =
+ (1 << 23),
+ eH2250LogicalChannelParameters_mediaPacketization = (1 << 22),
+ eH2250LogicalChannelParameters_transportCapability =
+ (1 << 21),
+ eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20),
+ eH2250LogicalChannelParameters_source = (1 << 19),
+ } options;
+ H245_TransportAddress mediaChannel;
+ H245_TransportAddress mediaControlChannel;
+} H2250LogicalChannelParameters;
+
+typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none,
+ } choice;
+ union {
+ H2250LogicalChannelParameters h2250LogicalChannelParameters;
+ };
+} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters;
+
+typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber
+ = (1 << 31),
+ eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency
+ = (1 << 30),
+ eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor
+ = (1 << 29),
+ } options;
+ DataType dataType;
+ OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
+ multiplexParameters;
+} OpenLogicalChannel_forwardLogicalChannelParameters;
+
+typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
+ } choice;
+ union {
+ H2250LogicalChannelParameters h2250LogicalChannelParameters;
+ };
+} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters;
+
+typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
+ = (1 << 31),
+ eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency
+ = (1 << 30),
+ eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor
+ = (1 << 29),
+ } options;
+ OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
+ multiplexParameters;
+} OpenLogicalChannel_reverseLogicalChannelParameters;
+
+typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */
+ enum {
+ eNetworkAccessParameters_networkAddress_q2931Address,
+ eNetworkAccessParameters_networkAddress_e164Address,
+ eNetworkAccessParameters_networkAddress_localAreaAddress,
+ } choice;
+ union {
+ H245_TransportAddress localAreaAddress;
+ };
+} NetworkAccessParameters_networkAddress;
+
+typedef struct NetworkAccessParameters { /* SEQUENCE */
+ enum {
+ eNetworkAccessParameters_distribution = (1 << 31),
+ eNetworkAccessParameters_externalReference = (1 << 30),
+ eNetworkAccessParameters_t120SetupProcedure = (1 << 29),
+ } options;
+ NetworkAccessParameters_networkAddress networkAddress;
+} NetworkAccessParameters;
+
+typedef struct OpenLogicalChannel { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannel_reverseLogicalChannelParameters =
+ (1 << 31),
+ eOpenLogicalChannel_separateStack = (1 << 30),
+ eOpenLogicalChannel_encryptionSync = (1 << 29),
+ } options;
+ OpenLogicalChannel_forwardLogicalChannelParameters
+ forwardLogicalChannelParameters;
+ OpenLogicalChannel_reverseLogicalChannelParameters
+ reverseLogicalChannelParameters;
+ NetworkAccessParameters separateStack;
+} OpenLogicalChannel;
+
+typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Setup_UUIE_fastStart;
+
+typedef struct Setup_UUIE { /* SEQUENCE */
+ enum {
+ eSetup_UUIE_h245Address = (1 << 31),
+ eSetup_UUIE_sourceAddress = (1 << 30),
+ eSetup_UUIE_destinationAddress = (1 << 29),
+ eSetup_UUIE_destCallSignalAddress = (1 << 28),
+ eSetup_UUIE_destExtraCallInfo = (1 << 27),
+ eSetup_UUIE_destExtraCRV = (1 << 26),
+ eSetup_UUIE_callServices = (1 << 25),
+ eSetup_UUIE_sourceCallSignalAddress = (1 << 24),
+ eSetup_UUIE_remoteExtensionAddress = (1 << 23),
+ eSetup_UUIE_callIdentifier = (1 << 22),
+ eSetup_UUIE_h245SecurityCapability = (1 << 21),
+ eSetup_UUIE_tokens = (1 << 20),
+ eSetup_UUIE_cryptoTokens = (1 << 19),
+ eSetup_UUIE_fastStart = (1 << 18),
+ eSetup_UUIE_mediaWaitForConnect = (1 << 17),
+ eSetup_UUIE_canOverlapSend = (1 << 16),
+ eSetup_UUIE_endpointIdentifier = (1 << 15),
+ eSetup_UUIE_multipleCalls = (1 << 14),
+ eSetup_UUIE_maintainConnection = (1 << 13),
+ eSetup_UUIE_connectionParameters = (1 << 12),
+ eSetup_UUIE_language = (1 << 11),
+ eSetup_UUIE_presentationIndicator = (1 << 10),
+ eSetup_UUIE_screeningIndicator = (1 << 9),
+ eSetup_UUIE_serviceControl = (1 << 8),
+ eSetup_UUIE_symmetricOperationRequired = (1 << 7),
+ eSetup_UUIE_capacity = (1 << 6),
+ eSetup_UUIE_circuitInfo = (1 << 5),
+ eSetup_UUIE_desiredProtocols = (1 << 4),
+ eSetup_UUIE_neededFeatures = (1 << 3),
+ eSetup_UUIE_desiredFeatures = (1 << 2),
+ eSetup_UUIE_supportedFeatures = (1 << 1),
+ eSetup_UUIE_parallelH245Control = (1 << 0),
+ } options;
+ TransportAddress h245Address;
+ TransportAddress destCallSignalAddress;
+ TransportAddress sourceCallSignalAddress;
+ Setup_UUIE_fastStart fastStart;
+} Setup_UUIE;
+
+typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} CallProceeding_UUIE_fastStart;
+
+typedef struct CallProceeding_UUIE { /* SEQUENCE */
+ enum {
+ eCallProceeding_UUIE_h245Address = (1 << 31),
+ eCallProceeding_UUIE_callIdentifier = (1 << 30),
+ eCallProceeding_UUIE_h245SecurityMode = (1 << 29),
+ eCallProceeding_UUIE_tokens = (1 << 28),
+ eCallProceeding_UUIE_cryptoTokens = (1 << 27),
+ eCallProceeding_UUIE_fastStart = (1 << 26),
+ eCallProceeding_UUIE_multipleCalls = (1 << 25),
+ eCallProceeding_UUIE_maintainConnection = (1 << 24),
+ eCallProceeding_UUIE_fastConnectRefused = (1 << 23),
+ eCallProceeding_UUIE_featureSet = (1 << 22),
+ } options;
+ TransportAddress h245Address;
+ CallProceeding_UUIE_fastStart fastStart;
+} CallProceeding_UUIE;
+
+typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Connect_UUIE_fastStart;
+
+typedef struct Connect_UUIE { /* SEQUENCE */
+ enum {
+ eConnect_UUIE_h245Address = (1 << 31),
+ eConnect_UUIE_callIdentifier = (1 << 30),
+ eConnect_UUIE_h245SecurityMode = (1 << 29),
+ eConnect_UUIE_tokens = (1 << 28),
+ eConnect_UUIE_cryptoTokens = (1 << 27),
+ eConnect_UUIE_fastStart = (1 << 26),
+ eConnect_UUIE_multipleCalls = (1 << 25),
+ eConnect_UUIE_maintainConnection = (1 << 24),
+ eConnect_UUIE_language = (1 << 23),
+ eConnect_UUIE_connectedAddress = (1 << 22),
+ eConnect_UUIE_presentationIndicator = (1 << 21),
+ eConnect_UUIE_screeningIndicator = (1 << 20),
+ eConnect_UUIE_fastConnectRefused = (1 << 19),
+ eConnect_UUIE_serviceControl = (1 << 18),
+ eConnect_UUIE_capacity = (1 << 17),
+ eConnect_UUIE_featureSet = (1 << 16),
+ } options;
+ TransportAddress h245Address;
+ Connect_UUIE_fastStart fastStart;
+} Connect_UUIE;
+
+typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Alerting_UUIE_fastStart;
+
+typedef struct Alerting_UUIE { /* SEQUENCE */
+ enum {
+ eAlerting_UUIE_h245Address = (1 << 31),
+ eAlerting_UUIE_callIdentifier = (1 << 30),
+ eAlerting_UUIE_h245SecurityMode = (1 << 29),
+ eAlerting_UUIE_tokens = (1 << 28),
+ eAlerting_UUIE_cryptoTokens = (1 << 27),
+ eAlerting_UUIE_fastStart = (1 << 26),
+ eAlerting_UUIE_multipleCalls = (1 << 25),
+ eAlerting_UUIE_maintainConnection = (1 << 24),
+ eAlerting_UUIE_alertingAddress = (1 << 23),
+ eAlerting_UUIE_presentationIndicator = (1 << 22),
+ eAlerting_UUIE_screeningIndicator = (1 << 21),
+ eAlerting_UUIE_fastConnectRefused = (1 << 20),
+ eAlerting_UUIE_serviceControl = (1 << 19),
+ eAlerting_UUIE_capacity = (1 << 18),
+ eAlerting_UUIE_featureSet = (1 << 17),
+ } options;
+ TransportAddress h245Address;
+ Alerting_UUIE_fastStart fastStart;
+} Alerting_UUIE;
+
+typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Information_UUIE_fastStart;
+
+typedef struct Information_UUIE { /* SEQUENCE */
+ enum {
+ eInformation_UUIE_callIdentifier = (1 << 31),
+ eInformation_UUIE_tokens = (1 << 30),
+ eInformation_UUIE_cryptoTokens = (1 << 29),
+ eInformation_UUIE_fastStart = (1 << 28),
+ eInformation_UUIE_fastConnectRefused = (1 << 27),
+ eInformation_UUIE_circuitInfo = (1 << 26),
+ } options;
+ Information_UUIE_fastStart fastStart;
+} Information_UUIE;
+
+typedef struct FacilityReason { /* CHOICE */
+ enum {
+ eFacilityReason_routeCallToGatekeeper,
+ eFacilityReason_callForwarded,
+ eFacilityReason_routeCallToMC,
+ eFacilityReason_undefinedReason,
+ eFacilityReason_conferenceListChoice,
+ eFacilityReason_startH245,
+ eFacilityReason_noH245,
+ eFacilityReason_newTokens,
+ eFacilityReason_featureSetUpdate,
+ eFacilityReason_forwardedElements,
+ eFacilityReason_transportedInformation,
+ } choice;
+} FacilityReason;
+
+typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Facility_UUIE_fastStart;
+
+typedef struct Facility_UUIE { /* SEQUENCE */
+ enum {
+ eFacility_UUIE_alternativeAddress = (1 << 31),
+ eFacility_UUIE_alternativeAliasAddress = (1 << 30),
+ eFacility_UUIE_conferenceID = (1 << 29),
+ eFacility_UUIE_callIdentifier = (1 << 28),
+ eFacility_UUIE_destExtraCallInfo = (1 << 27),
+ eFacility_UUIE_remoteExtensionAddress = (1 << 26),
+ eFacility_UUIE_tokens = (1 << 25),
+ eFacility_UUIE_cryptoTokens = (1 << 24),
+ eFacility_UUIE_conferences = (1 << 23),
+ eFacility_UUIE_h245Address = (1 << 22),
+ eFacility_UUIE_fastStart = (1 << 21),
+ eFacility_UUIE_multipleCalls = (1 << 20),
+ eFacility_UUIE_maintainConnection = (1 << 19),
+ eFacility_UUIE_fastConnectRefused = (1 << 18),
+ eFacility_UUIE_serviceControl = (1 << 17),
+ eFacility_UUIE_circuitInfo = (1 << 16),
+ eFacility_UUIE_featureSet = (1 << 15),
+ eFacility_UUIE_destinationInfo = (1 << 14),
+ eFacility_UUIE_h245SecurityMode = (1 << 13),
+ } options;
+ FacilityReason reason;
+ TransportAddress h245Address;
+ Facility_UUIE_fastStart fastStart;
+} Facility_UUIE;
+
+typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Progress_UUIE_fastStart;
+
+typedef struct Progress_UUIE { /* SEQUENCE */
+ enum {
+ eProgress_UUIE_h245Address = (1 << 31),
+ eProgress_UUIE_h245SecurityMode = (1 << 30),
+ eProgress_UUIE_tokens = (1 << 29),
+ eProgress_UUIE_cryptoTokens = (1 << 28),
+ eProgress_UUIE_fastStart = (1 << 27),
+ eProgress_UUIE_multipleCalls = (1 << 26),
+ eProgress_UUIE_maintainConnection = (1 << 25),
+ eProgress_UUIE_fastConnectRefused = (1 << 24),
+ } options;
+ TransportAddress h245Address;
+ Progress_UUIE_fastStart fastStart;
+} Progress_UUIE;
+
+typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */
+ enum {
+ eH323_UU_PDU_h323_message_body_setup,
+ eH323_UU_PDU_h323_message_body_callProceeding,
+ eH323_UU_PDU_h323_message_body_connect,
+ eH323_UU_PDU_h323_message_body_alerting,
+ eH323_UU_PDU_h323_message_body_information,
+ eH323_UU_PDU_h323_message_body_releaseComplete,
+ eH323_UU_PDU_h323_message_body_facility,
+ eH323_UU_PDU_h323_message_body_progress,
+ eH323_UU_PDU_h323_message_body_empty,
+ eH323_UU_PDU_h323_message_body_status,
+ eH323_UU_PDU_h323_message_body_statusInquiry,
+ eH323_UU_PDU_h323_message_body_setupAcknowledge,
+ eH323_UU_PDU_h323_message_body_notify,
+ } choice;
+ union {
+ Setup_UUIE setup;
+ CallProceeding_UUIE callProceeding;
+ Connect_UUIE connect;
+ Alerting_UUIE alerting;
+ Information_UUIE information;
+ Facility_UUIE facility;
+ Progress_UUIE progress;
+ };
+} H323_UU_PDU_h323_message_body;
+
+typedef struct RequestMessage { /* CHOICE */
+ enum {
+ eRequestMessage_nonStandard,
+ eRequestMessage_masterSlaveDetermination,
+ eRequestMessage_terminalCapabilitySet,
+ eRequestMessage_openLogicalChannel,
+ eRequestMessage_closeLogicalChannel,
+ eRequestMessage_requestChannelClose,
+ eRequestMessage_multiplexEntrySend,
+ eRequestMessage_requestMultiplexEntry,
+ eRequestMessage_requestMode,
+ eRequestMessage_roundTripDelayRequest,
+ eRequestMessage_maintenanceLoopRequest,
+ eRequestMessage_communicationModeRequest,
+ eRequestMessage_conferenceRequest,
+ eRequestMessage_multilinkRequest,
+ eRequestMessage_logicalChannelRateRequest,
+ } choice;
+ union {
+ OpenLogicalChannel openLogicalChannel;
+ };
+} RequestMessage;
+
+typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
+ } choice;
+ union {
+ H2250LogicalChannelParameters h2250LogicalChannelParameters;
+ };
+} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters;
+
+typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber
+ = (1 << 31),
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
+ = (1 << 30),
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor
+ = (1 << 29),
+ } options;
+ OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
+ multiplexParameters;
+} OpenLogicalChannelAck_reverseLogicalChannelParameters;
+
+typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */
+ enum {
+ eH2250LogicalChannelAckParameters_nonStandard = (1 << 31),
+ eH2250LogicalChannelAckParameters_sessionID = (1 << 30),
+ eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29),
+ eH2250LogicalChannelAckParameters_mediaControlChannel =
+ (1 << 28),
+ eH2250LogicalChannelAckParameters_dynamicRTPPayloadType =
+ (1 << 27),
+ eH2250LogicalChannelAckParameters_flowControlToZero =
+ (1 << 26),
+ eH2250LogicalChannelAckParameters_portNumber = (1 << 25),
+ } options;
+ H245_TransportAddress mediaChannel;
+ H245_TransportAddress mediaControlChannel;
+} H2250LogicalChannelAckParameters;
+
+typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters,
+ } choice;
+ union {
+ H2250LogicalChannelAckParameters
+ h2250LogicalChannelAckParameters;
+ };
+} OpenLogicalChannelAck_forwardMultiplexAckParameters;
+
+typedef struct OpenLogicalChannelAck { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters =
+ (1 << 31),
+ eOpenLogicalChannelAck_separateStack = (1 << 30),
+ eOpenLogicalChannelAck_forwardMultiplexAckParameters =
+ (1 << 29),
+ eOpenLogicalChannelAck_encryptionSync = (1 << 28),
+ } options;
+ OpenLogicalChannelAck_reverseLogicalChannelParameters
+ reverseLogicalChannelParameters;
+ OpenLogicalChannelAck_forwardMultiplexAckParameters
+ forwardMultiplexAckParameters;
+} OpenLogicalChannelAck;
+
+typedef struct ResponseMessage { /* CHOICE */
+ enum {
+ eResponseMessage_nonStandard,
+ eResponseMessage_masterSlaveDeterminationAck,
+ eResponseMessage_masterSlaveDeterminationReject,
+ eResponseMessage_terminalCapabilitySetAck,
+ eResponseMessage_terminalCapabilitySetReject,
+ eResponseMessage_openLogicalChannelAck,
+ eResponseMessage_openLogicalChannelReject,
+ eResponseMessage_closeLogicalChannelAck,
+ eResponseMessage_requestChannelCloseAck,
+ eResponseMessage_requestChannelCloseReject,
+ eResponseMessage_multiplexEntrySendAck,
+ eResponseMessage_multiplexEntrySendReject,
+ eResponseMessage_requestMultiplexEntryAck,
+ eResponseMessage_requestMultiplexEntryReject,
+ eResponseMessage_requestModeAck,
+ eResponseMessage_requestModeReject,
+ eResponseMessage_roundTripDelayResponse,
+ eResponseMessage_maintenanceLoopAck,
+ eResponseMessage_maintenanceLoopReject,
+ eResponseMessage_communicationModeResponse,
+ eResponseMessage_conferenceResponse,
+ eResponseMessage_multilinkResponse,
+ eResponseMessage_logicalChannelRateAcknowledge,
+ eResponseMessage_logicalChannelRateReject,
+ } choice;
+ union {
+ OpenLogicalChannelAck openLogicalChannelAck;
+ };
+} ResponseMessage;
+
+typedef struct MultimediaSystemControlMessage { /* CHOICE */
+ enum {
+ eMultimediaSystemControlMessage_request,
+ eMultimediaSystemControlMessage_response,
+ eMultimediaSystemControlMessage_command,
+ eMultimediaSystemControlMessage_indication,
+ } choice;
+ union {
+ RequestMessage request;
+ ResponseMessage response;
+ };
+} MultimediaSystemControlMessage;
+
+typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */
+ int count;
+ MultimediaSystemControlMessage item[4];
+} H323_UU_PDU_h245Control;
+
+typedef struct H323_UU_PDU { /* SEQUENCE */
+ enum {
+ eH323_UU_PDU_nonStandardData = (1 << 31),
+ eH323_UU_PDU_h4501SupplementaryService = (1 << 30),
+ eH323_UU_PDU_h245Tunneling = (1 << 29),
+ eH323_UU_PDU_h245Control = (1 << 28),
+ eH323_UU_PDU_nonStandardControl = (1 << 27),
+ eH323_UU_PDU_callLinkage = (1 << 26),
+ eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25),
+ eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24),
+ eH323_UU_PDU_stimulusControl = (1 << 23),
+ eH323_UU_PDU_genericData = (1 << 22),
+ } options;
+ H323_UU_PDU_h323_message_body h323_message_body;
+ H323_UU_PDU_h245Control h245Control;
+} H323_UU_PDU;
+
+typedef struct H323_UserInformation { /* SEQUENCE */
+ enum {
+ eH323_UserInformation_user_data = (1 << 31),
+ } options;
+ H323_UU_PDU h323_uu_pdu;
+} H323_UserInformation;
+
+typedef struct GatekeeperRequest { /* SEQUENCE */
+ enum {
+ eGatekeeperRequest_nonStandardData = (1 << 31),
+ eGatekeeperRequest_gatekeeperIdentifier = (1 << 30),
+ eGatekeeperRequest_callServices = (1 << 29),
+ eGatekeeperRequest_endpointAlias = (1 << 28),
+ eGatekeeperRequest_alternateEndpoints = (1 << 27),
+ eGatekeeperRequest_tokens = (1 << 26),
+ eGatekeeperRequest_cryptoTokens = (1 << 25),
+ eGatekeeperRequest_authenticationCapability = (1 << 24),
+ eGatekeeperRequest_algorithmOIDs = (1 << 23),
+ eGatekeeperRequest_integrity = (1 << 22),
+ eGatekeeperRequest_integrityCheckValue = (1 << 21),
+ eGatekeeperRequest_supportsAltGK = (1 << 20),
+ eGatekeeperRequest_featureSet = (1 << 19),
+ eGatekeeperRequest_genericData = (1 << 18),
+ } options;
+ TransportAddress rasAddress;
+} GatekeeperRequest;
+
+typedef struct GatekeeperConfirm { /* SEQUENCE */
+ enum {
+ eGatekeeperConfirm_nonStandardData = (1 << 31),
+ eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30),
+ eGatekeeperConfirm_alternateGatekeeper = (1 << 29),
+ eGatekeeperConfirm_authenticationMode = (1 << 28),
+ eGatekeeperConfirm_tokens = (1 << 27),
+ eGatekeeperConfirm_cryptoTokens = (1 << 26),
+ eGatekeeperConfirm_algorithmOID = (1 << 25),
+ eGatekeeperConfirm_integrity = (1 << 24),
+ eGatekeeperConfirm_integrityCheckValue = (1 << 23),
+ eGatekeeperConfirm_featureSet = (1 << 22),
+ eGatekeeperConfirm_genericData = (1 << 21),
+ } options;
+ TransportAddress rasAddress;
+} GatekeeperConfirm;
+
+typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} RegistrationRequest_callSignalAddress;
+
+typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} RegistrationRequest_rasAddress;
+
+typedef struct RegistrationRequest { /* SEQUENCE */
+ enum {
+ eRegistrationRequest_nonStandardData = (1 << 31),
+ eRegistrationRequest_terminalAlias = (1 << 30),
+ eRegistrationRequest_gatekeeperIdentifier = (1 << 29),
+ eRegistrationRequest_alternateEndpoints = (1 << 28),
+ eRegistrationRequest_timeToLive = (1 << 27),
+ eRegistrationRequest_tokens = (1 << 26),
+ eRegistrationRequest_cryptoTokens = (1 << 25),
+ eRegistrationRequest_integrityCheckValue = (1 << 24),
+ eRegistrationRequest_keepAlive = (1 << 23),
+ eRegistrationRequest_endpointIdentifier = (1 << 22),
+ eRegistrationRequest_willSupplyUUIEs = (1 << 21),
+ eRegistrationRequest_maintainConnection = (1 << 20),
+ eRegistrationRequest_alternateTransportAddresses = (1 << 19),
+ eRegistrationRequest_additiveRegistration = (1 << 18),
+ eRegistrationRequest_terminalAliasPattern = (1 << 17),
+ eRegistrationRequest_supportsAltGK = (1 << 16),
+ eRegistrationRequest_usageReportingCapability = (1 << 15),
+ eRegistrationRequest_multipleCalls = (1 << 14),
+ eRegistrationRequest_supportedH248Packages = (1 << 13),
+ eRegistrationRequest_callCreditCapability = (1 << 12),
+ eRegistrationRequest_capacityReportingCapability = (1 << 11),
+ eRegistrationRequest_capacity = (1 << 10),
+ eRegistrationRequest_featureSet = (1 << 9),
+ eRegistrationRequest_genericData = (1 << 8),
+ } options;
+ RegistrationRequest_callSignalAddress callSignalAddress;
+ RegistrationRequest_rasAddress rasAddress;
+ unsigned timeToLive;
+} RegistrationRequest;
+
+typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} RegistrationConfirm_callSignalAddress;
+
+typedef struct RegistrationConfirm { /* SEQUENCE */
+ enum {
+ eRegistrationConfirm_nonStandardData = (1 << 31),
+ eRegistrationConfirm_terminalAlias = (1 << 30),
+ eRegistrationConfirm_gatekeeperIdentifier = (1 << 29),
+ eRegistrationConfirm_alternateGatekeeper = (1 << 28),
+ eRegistrationConfirm_timeToLive = (1 << 27),
+ eRegistrationConfirm_tokens = (1 << 26),
+ eRegistrationConfirm_cryptoTokens = (1 << 25),
+ eRegistrationConfirm_integrityCheckValue = (1 << 24),
+ eRegistrationConfirm_willRespondToIRR = (1 << 23),
+ eRegistrationConfirm_preGrantedARQ = (1 << 22),
+ eRegistrationConfirm_maintainConnection = (1 << 21),
+ eRegistrationConfirm_serviceControl = (1 << 20),
+ eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19),
+ eRegistrationConfirm_terminalAliasPattern = (1 << 18),
+ eRegistrationConfirm_supportedPrefixes = (1 << 17),
+ eRegistrationConfirm_usageSpec = (1 << 16),
+ eRegistrationConfirm_featureServerAlias = (1 << 15),
+ eRegistrationConfirm_capacityReportingSpec = (1 << 14),
+ eRegistrationConfirm_featureSet = (1 << 13),
+ eRegistrationConfirm_genericData = (1 << 12),
+ } options;
+ RegistrationConfirm_callSignalAddress callSignalAddress;
+ unsigned timeToLive;
+} RegistrationConfirm;
+
+typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} UnregistrationRequest_callSignalAddress;
+
+typedef struct UnregistrationRequest { /* SEQUENCE */
+ enum {
+ eUnregistrationRequest_endpointAlias = (1 << 31),
+ eUnregistrationRequest_nonStandardData = (1 << 30),
+ eUnregistrationRequest_endpointIdentifier = (1 << 29),
+ eUnregistrationRequest_alternateEndpoints = (1 << 28),
+ eUnregistrationRequest_gatekeeperIdentifier = (1 << 27),
+ eUnregistrationRequest_tokens = (1 << 26),
+ eUnregistrationRequest_cryptoTokens = (1 << 25),
+ eUnregistrationRequest_integrityCheckValue = (1 << 24),
+ eUnregistrationRequest_reason = (1 << 23),
+ eUnregistrationRequest_endpointAliasPattern = (1 << 22),
+ eUnregistrationRequest_supportedPrefixes = (1 << 21),
+ eUnregistrationRequest_alternateGatekeeper = (1 << 20),
+ eUnregistrationRequest_genericData = (1 << 19),
+ } options;
+ UnregistrationRequest_callSignalAddress callSignalAddress;
+} UnregistrationRequest;
+
+typedef struct AdmissionRequest { /* SEQUENCE */
+ enum {
+ eAdmissionRequest_callModel = (1 << 31),
+ eAdmissionRequest_destinationInfo = (1 << 30),
+ eAdmissionRequest_destCallSignalAddress = (1 << 29),
+ eAdmissionRequest_destExtraCallInfo = (1 << 28),
+ eAdmissionRequest_srcCallSignalAddress = (1 << 27),
+ eAdmissionRequest_nonStandardData = (1 << 26),
+ eAdmissionRequest_callServices = (1 << 25),
+ eAdmissionRequest_canMapAlias = (1 << 24),
+ eAdmissionRequest_callIdentifier = (1 << 23),
+ eAdmissionRequest_srcAlternatives = (1 << 22),
+ eAdmissionRequest_destAlternatives = (1 << 21),
+ eAdmissionRequest_gatekeeperIdentifier = (1 << 20),
+ eAdmissionRequest_tokens = (1 << 19),
+ eAdmissionRequest_cryptoTokens = (1 << 18),
+ eAdmissionRequest_integrityCheckValue = (1 << 17),
+ eAdmissionRequest_transportQOS = (1 << 16),
+ eAdmissionRequest_willSupplyUUIEs = (1 << 15),
+ eAdmissionRequest_callLinkage = (1 << 14),
+ eAdmissionRequest_gatewayDataRate = (1 << 13),
+ eAdmissionRequest_capacity = (1 << 12),
+ eAdmissionRequest_circuitInfo = (1 << 11),
+ eAdmissionRequest_desiredProtocols = (1 << 10),
+ eAdmissionRequest_desiredTunnelledProtocol = (1 << 9),
+ eAdmissionRequest_featureSet = (1 << 8),
+ eAdmissionRequest_genericData = (1 << 7),
+ } options;
+ TransportAddress destCallSignalAddress;
+ TransportAddress srcCallSignalAddress;
+} AdmissionRequest;
+
+typedef struct AdmissionConfirm { /* SEQUENCE */
+ enum {
+ eAdmissionConfirm_irrFrequency = (1 << 31),
+ eAdmissionConfirm_nonStandardData = (1 << 30),
+ eAdmissionConfirm_destinationInfo = (1 << 29),
+ eAdmissionConfirm_destExtraCallInfo = (1 << 28),
+ eAdmissionConfirm_destinationType = (1 << 27),
+ eAdmissionConfirm_remoteExtensionAddress = (1 << 26),
+ eAdmissionConfirm_alternateEndpoints = (1 << 25),
+ eAdmissionConfirm_tokens = (1 << 24),
+ eAdmissionConfirm_cryptoTokens = (1 << 23),
+ eAdmissionConfirm_integrityCheckValue = (1 << 22),
+ eAdmissionConfirm_transportQOS = (1 << 21),
+ eAdmissionConfirm_willRespondToIRR = (1 << 20),
+ eAdmissionConfirm_uuiesRequested = (1 << 19),
+ eAdmissionConfirm_language = (1 << 18),
+ eAdmissionConfirm_alternateTransportAddresses = (1 << 17),
+ eAdmissionConfirm_useSpecifiedTransport = (1 << 16),
+ eAdmissionConfirm_circuitInfo = (1 << 15),
+ eAdmissionConfirm_usageSpec = (1 << 14),
+ eAdmissionConfirm_supportedProtocols = (1 << 13),
+ eAdmissionConfirm_serviceControl = (1 << 12),
+ eAdmissionConfirm_multipleCalls = (1 << 11),
+ eAdmissionConfirm_featureSet = (1 << 10),
+ eAdmissionConfirm_genericData = (1 << 9),
+ } options;
+ TransportAddress destCallSignalAddress;
+} AdmissionConfirm;
+
+typedef struct LocationRequest { /* SEQUENCE */
+ enum {
+ eLocationRequest_endpointIdentifier = (1 << 31),
+ eLocationRequest_nonStandardData = (1 << 30),
+ eLocationRequest_sourceInfo = (1 << 29),
+ eLocationRequest_canMapAlias = (1 << 28),
+ eLocationRequest_gatekeeperIdentifier = (1 << 27),
+ eLocationRequest_tokens = (1 << 26),
+ eLocationRequest_cryptoTokens = (1 << 25),
+ eLocationRequest_integrityCheckValue = (1 << 24),
+ eLocationRequest_desiredProtocols = (1 << 23),
+ eLocationRequest_desiredTunnelledProtocol = (1 << 22),
+ eLocationRequest_featureSet = (1 << 21),
+ eLocationRequest_genericData = (1 << 20),
+ eLocationRequest_hopCount = (1 << 19),
+ eLocationRequest_circuitInfo = (1 << 18),
+ } options;
+ TransportAddress replyAddress;
+} LocationRequest;
+
+typedef struct LocationConfirm { /* SEQUENCE */
+ enum {
+ eLocationConfirm_nonStandardData = (1 << 31),
+ eLocationConfirm_destinationInfo = (1 << 30),
+ eLocationConfirm_destExtraCallInfo = (1 << 29),
+ eLocationConfirm_destinationType = (1 << 28),
+ eLocationConfirm_remoteExtensionAddress = (1 << 27),
+ eLocationConfirm_alternateEndpoints = (1 << 26),
+ eLocationConfirm_tokens = (1 << 25),
+ eLocationConfirm_cryptoTokens = (1 << 24),
+ eLocationConfirm_integrityCheckValue = (1 << 23),
+ eLocationConfirm_alternateTransportAddresses = (1 << 22),
+ eLocationConfirm_supportedProtocols = (1 << 21),
+ eLocationConfirm_multipleCalls = (1 << 20),
+ eLocationConfirm_featureSet = (1 << 19),
+ eLocationConfirm_genericData = (1 << 18),
+ eLocationConfirm_circuitInfo = (1 << 17),
+ eLocationConfirm_serviceControl = (1 << 16),
+ } options;
+ TransportAddress callSignalAddress;
+ TransportAddress rasAddress;
+} LocationConfirm;
+
+typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} InfoRequestResponse_callSignalAddress;
+
+typedef struct InfoRequestResponse { /* SEQUENCE */
+ enum {
+ eInfoRequestResponse_nonStandardData = (1 << 31),
+ eInfoRequestResponse_endpointAlias = (1 << 30),
+ eInfoRequestResponse_perCallInfo = (1 << 29),
+ eInfoRequestResponse_tokens = (1 << 28),
+ eInfoRequestResponse_cryptoTokens = (1 << 27),
+ eInfoRequestResponse_integrityCheckValue = (1 << 26),
+ eInfoRequestResponse_needResponse = (1 << 25),
+ eInfoRequestResponse_capacity = (1 << 24),
+ eInfoRequestResponse_irrStatus = (1 << 23),
+ eInfoRequestResponse_unsolicited = (1 << 22),
+ eInfoRequestResponse_genericData = (1 << 21),
+ } options;
+ TransportAddress rasAddress;
+ InfoRequestResponse_callSignalAddress callSignalAddress;
+} InfoRequestResponse;
+
+typedef struct RasMessage { /* CHOICE */
+ enum {
+ eRasMessage_gatekeeperRequest,
+ eRasMessage_gatekeeperConfirm,
+ eRasMessage_gatekeeperReject,
+ eRasMessage_registrationRequest,
+ eRasMessage_registrationConfirm,
+ eRasMessage_registrationReject,
+ eRasMessage_unregistrationRequest,
+ eRasMessage_unregistrationConfirm,
+ eRasMessage_unregistrationReject,
+ eRasMessage_admissionRequest,
+ eRasMessage_admissionConfirm,
+ eRasMessage_admissionReject,
+ eRasMessage_bandwidthRequest,
+ eRasMessage_bandwidthConfirm,
+ eRasMessage_bandwidthReject,
+ eRasMessage_disengageRequest,
+ eRasMessage_disengageConfirm,
+ eRasMessage_disengageReject,
+ eRasMessage_locationRequest,
+ eRasMessage_locationConfirm,
+ eRasMessage_locationReject,
+ eRasMessage_infoRequest,
+ eRasMessage_infoRequestResponse,
+ eRasMessage_nonStandardMessage,
+ eRasMessage_unknownMessageResponse,
+ eRasMessage_requestInProgress,
+ eRasMessage_resourcesAvailableIndicate,
+ eRasMessage_resourcesAvailableConfirm,
+ eRasMessage_infoRequestAck,
+ eRasMessage_infoRequestNak,
+ eRasMessage_serviceControlIndication,
+ eRasMessage_serviceControlResponse,
+ } choice;
+ union {
+ GatekeeperRequest gatekeeperRequest;
+ GatekeeperConfirm gatekeeperConfirm;
+ RegistrationRequest registrationRequest;
+ RegistrationConfirm registrationConfirm;
+ UnregistrationRequest unregistrationRequest;
+ AdmissionRequest admissionRequest;
+ AdmissionConfirm admissionConfirm;
+ LocationRequest locationRequest;
+ LocationConfirm locationConfirm;
+ InfoRequestResponse infoRequestResponse;
+ };
+} RasMessage;
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
new file mode 100644
index 0000000..1d60c6e
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -0,0 +1,605 @@
+/*
+ * H.323 extension for NAT alteration.
+ *
+ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ * Based on the 'brute force' H.323 NAT module by
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * Changes:
+ * 2006-02-01 - initial version 0.1
+ *
+ * 2006-02-20 - version 0.2
+ * 1. Changed source format to follow kernel conventions
+ * 2. Deleted some unnecessary structures
+ * 3. Minor fixes
+ *
+ * 2006-03-10 - version 0.3
+ * 1. Added support for multiple TPKTs in one packet (suggested by
+ * Patrick McHardy)
+ * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
+ * 3. Eliminated unnecessary return code
+ *
+ * 2006-03-15 - version 0.4
+ * 1. Added support for T.120 channels
+ * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/moduleparam.h>
+#include <net/tcp.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+#include "ip_conntrack_helper_h323_asn1.h"
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port);
+extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port);
+extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int16_t port, u_int16_t rtp_port,
+ struct ip_conntrack_expect * rtp_exp,
+ struct ip_conntrack_expect * rtcp_exp);
+extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress * addr,
+ int idx, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+
+
+/****************************************************************************/
+static int set_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ unsigned int addroff, u_int32_t ip, u_int16_t port)
+{
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
+ struct {
+ u_int32_t ip;
+ u_int16_t port;
+ } __attribute__ ((__packed__)) buf;
+ struct tcphdr _tcph, *th;
+
+ buf.ip = ip;
+ buf.port = htons(port);
+ addroff += dataoff;
+
+ if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ addroff, sizeof(buf),
+ (char *) &buf, sizeof(buf))) {
+ if (net_ratelimit())
+ printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
+ " error\n");
+ return -1;
+ }
+
+ /* Relocate data pointer */
+ th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
+ sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ return -1;
+ *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
+ th->doff * 4 + dataoff;
+ } else {
+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ addroff, sizeof(buf),
+ (char *) &buf, sizeof(buf))) {
+ if (net_ratelimit())
+ printk("ip_nat_h323: ip_nat_mangle_udp_packet"
+ " error\n");
+ return -1;
+ }
+ /* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
+ * or pull everything in a linear buffer, so we can safely
+ * use the skb pointers now */
+ *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
+ sizeof(struct udphdr);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int set_h225_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr,
+ u_int32_t ip, u_int16_t port)
+{
+ return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
+}
+
+/****************************************************************************/
+static int set_h245_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int32_t ip, u_int16_t port)
+{
+ return set_addr(pskb, data, dataoff,
+ addr->unicastAddress.iPAddress.network, ip, port);
+}
+
+/****************************************************************************/
+static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(*data, &addr[i], &ip, &port)) {
+ if (ip == ct->tuplehash[dir].tuple.src.ip &&
+ port == info->sig_port[dir]) {
+ /* GW->GK */
+
+ /* Fix for Gnomemeeting */
+ if (i > 0 &&
+ get_h225_addr(*data, &addr[0],
+ &ip, &port) &&
+ (ntohl(ip) & 0xff000000) == 0x7f000000)
+ i = 0;
+
+ DEBUGP
+ ("ip_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.
+ ip), info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0, &addr[i],
+ ct->tuplehash[!dir].
+ tuple.dst.ip,
+ info->sig_port[!dir]);
+ } else if (ip == ct->tuplehash[dir].tuple.dst.ip &&
+ port == info->sig_port[dir]) {
+ /* GK->GW */
+ DEBUGP
+ ("ip_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.src.
+ ip), info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0, &addr[i],
+ ct->tuplehash[!dir].
+ tuple.src.ip,
+ info->sig_port[!dir]);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(*data, &addr[i], &ip, &port) &&
+ ip == ct->tuplehash[dir].tuple.src.ip &&
+ port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) {
+ DEBUGP("ip_nat_ras: set rasAddress "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
+ ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
+ port));
+ return set_h225_addr(pskb, data, 0, &addr[i],
+ ct->tuplehash[!dir].tuple.dst.ip,
+ ntohs(ct->tuplehash[!dir].tuple.
+ dst.u.udp.port));
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int16_t port, u_int16_t rtp_port,
+ struct ip_conntrack_expect *rtp_exp,
+ struct ip_conntrack_expect *rtcp_exp)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int16_t nated_port;
+
+ /* Set expectations for NAT */
+ rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
+ rtp_exp->expectfn = ip_nat_follow_master;
+ rtp_exp->dir = !dir;
+ rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
+ rtcp_exp->expectfn = ip_nat_follow_master;
+ rtcp_exp->dir = !dir;
+
+ /* Lookup existing expects */
+ for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
+ if (info->rtp_port[i][dir] == rtp_port) {
+ /* Expected */
+
+ /* Use allocated ports first. This will refresh
+ * the expects */
+ rtp_exp->tuple.dst.u.udp.port =
+ htons(info->rtp_port[i][dir]);
+ rtcp_exp->tuple.dst.u.udp.port =
+ htons(info->rtp_port[i][dir] + 1);
+ break;
+ } else if (info->rtp_port[i][dir] == 0) {
+ /* Not expected */
+ break;
+ }
+ }
+
+ /* Run out of expectations */
+ if (i >= H323_RTP_CHANNEL_MAX) {
+ if (net_ratelimit())
+ printk("ip_nat_h323: out of expectations\n");
+ return 0;
+ }
+
+ /* Try to get a pair of ports. */
+ for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
+ nated_port != 0; nated_port += 2) {
+ rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(rtp_exp) == 0) {
+ rtcp_exp->tuple.dst.u.udp.port =
+ htons(nated_port + 1);
+ if (ip_conntrack_expect_related(rtcp_exp) == 0)
+ break;
+ ip_conntrack_unexpect_related(rtp_exp);
+ }
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_h323: out of RTP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h245_addr(pskb, data, dataoff, addr,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ (port & 1) ? nated_port + 1 : nated_port) == 0) {
+ /* Save ports */
+ info->rtp_port[i][dir] = rtp_port;
+ info->rtp_port[i][!dir] = nated_port;
+ } else {
+ ip_conntrack_unexpect_related(rtp_exp);
+ ip_conntrack_unexpect_related(rtcp_exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("ip_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtp_exp->tuple.src.ip),
+ ntohs(rtp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtp_exp->tuple.dst.ip),
+ ntohs(rtp_exp->tuple.dst.u.udp.port));
+ DEBUGP("ip_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtcp_exp->tuple.src.ip),
+ ntohs(rtcp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtcp_exp->tuple.dst.ip),
+ ntohs(rtcp_exp->tuple.dst.u.udp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect *exp)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = port;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_follow_master;
+ exp->dir = !dir;
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_h323: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h245_addr(pskb, data, dataoff, addr,
+ ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) {
+ ip_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************
+ * This conntrack expect function replaces ip_conntrack_h245_expect()
+ * which was set by ip_conntrack_helper_h323.c. It calls both
+ * ip_nat_follow_master() and ip_conntrack_h245_expect()
+ ****************************************************************************/
+static void ip_nat_h245_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this)
+{
+ ip_nat_follow_master(new, this);
+ ip_conntrack_h245_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect *exp)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = port;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_h245_expect;
+ exp->dir = !dir;
+
+ /* Check existing expects */
+ if (info->sig_port[dir] == port)
+ nated_port = info->sig_port[!dir];
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_q931: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h225_addr(pskb, data, dataoff, addr,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ nated_port) == 0) {
+ /* Save ports */
+ info->sig_port[dir] = port;
+ info->sig_port[!dir] = nated_port;
+ } else {
+ ip_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************
+ * This conntrack expect function replaces ip_conntrack_q931_expect()
+ * which was set by ip_conntrack_helper_h323.c.
+ ****************************************************************************/
+static void ip_nat_q931_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this)
+{
+ struct ip_nat_range range;
+
+ if (this->tuple.src.ip != 0) { /* Only accept calls from GK */
+ ip_nat_follow_master(new, this);
+ goto out;
+ }
+
+ /* This must be a fresh one. */
+ BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+ /* Change src to where master sends to */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
+
+ /* hook doesn't matter, but it has to do source manip */
+ ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+ /* For DST manip, map port here to where it's expected. */
+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+ range.min = range.max = this->saved_proto;
+ range.min_ip = range.max_ip =
+ new->master->tuplehash[!this->dir].tuple.src.ip;
+
+ /* hook doesn't matter, but it has to do destination manip */
+ ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+
+ out:
+ ip_conntrack_q931_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress * addr, int idx,
+ u_int16_t port, struct ip_conntrack_expect *exp)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = port;
+ u_int32_t ip;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_q931_expect;
+ exp->dir = !dir;
+
+ /* Check existing expects */
+ if (info->sig_port[dir] == port)
+ nated_port = info->sig_port[!dir];
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_ras: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h225_addr(pskb, data, 0, &addr[idx],
+ ct->tuplehash[!dir].tuple.dst.ip,
+ nated_port) == 0) {
+ /* Save ports */
+ info->sig_port[dir] = port;
+ info->sig_port[!dir] = nated_port;
+
+ /* Fix for Gnomemeeting */
+ if (idx > 0 &&
+ get_h225_addr(*data, &addr[0], &ip, &port) &&
+ (ntohl(ip) & 0xff000000) == 0x7f000000) {
+ set_h225_addr_hook(pskb, data, 0, &addr[0],
+ ct->tuplehash[!dir].tuple.dst.ip,
+ info->sig_port[!dir]);
+ }
+ } else {
+ ip_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int __init init(void)
+{
+ BUG_ON(set_h245_addr_hook != NULL);
+ BUG_ON(set_h225_addr_hook != NULL);
+ BUG_ON(set_sig_addr_hook != NULL);
+ BUG_ON(set_ras_addr_hook != NULL);
+ BUG_ON(nat_rtp_rtcp_hook != NULL);
+ BUG_ON(nat_t120_hook != NULL);
+ BUG_ON(nat_h245_hook != NULL);
+ BUG_ON(nat_q931_hook != NULL);
+
+ set_h245_addr_hook = set_h245_addr;
+ set_h225_addr_hook = set_h225_addr;
+ set_sig_addr_hook = set_sig_addr;
+ set_ras_addr_hook = set_ras_addr;
+ nat_rtp_rtcp_hook = nat_rtp_rtcp;
+ nat_t120_hook = nat_t120;
+ nat_h245_hook = nat_h245;
+ nat_q931_hook = nat_q931;
+
+ DEBUGP("ip_nat_h323: init success\n");
+ return 0;
+}
+
+/****************************************************************************/
+static void __exit fini(void)
+{
+ set_h245_addr_hook = NULL;
+ set_h225_addr_hook = NULL;
+ set_sig_addr_hook = NULL;
+ set_ras_addr_hook = NULL;
+ nat_rtp_rtcp_hook = NULL;
+ nat_t120_hook = NULL;
+ nat_h245_hook = NULL;
+ nat_q931_hook = NULL;
+ synchronize_net();
+}
+
+/****************************************************************************/
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
+MODULE_DESCRIPTION("H.323 NAT helper");
+MODULE_LICENSE("GPL");
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 0168d6c..c847744 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -79,7 +79,7 @@ echo-cmd = $(if $($(quiet)cmd_$(1)), \
# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
#
-if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+if_changed = $(if $(strip $(filter-out FORCE,$?) $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
@set -e; \
$(echo-cmd) \
$(cmd_$(1)); \
@@ -87,7 +87,7 @@ if_changed = $(if $(strip $? $(call arg-
# execute the command and also postprocess generated .d dependencies
# file
-if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
+if_changed_dep = $(if $(strip $(filter-out FORCE,$? $(filter-out $(wildcard $^),$^))\
$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
@set -e; \
$(echo-cmd) \
@@ -99,6 +99,6 @@ if_changed_dep = $(if $(strip $? $(filte
# Usage: $(call if_changed_rule,foo)
# will check if $(cmd_foo) changed, or any of the prequisites changed,
# and if so will execute $(rule_foo)
-if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
+if_changed_rule = $(if $(strip $(filter-out FORCE,$?) $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
@set -e; \
$(rule_$(1)))
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (7 preceding siblings ...)
2006-03-21 1:56 ` [NETFILTER 08/09]: Add H.323 conntrack/NAT helper Patrick McHardy
@ 2006-03-21 1:56 ` Patrick McHardy
2006-03-21 2:11 ` Patrick McHardy
2006-03-21 2:18 ` [NETFILTER 00/09]: Netfilter update Patrick McHardy
9 siblings, 1 reply; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 1:56 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, Patrick McHardy
[NETFILTER]: futher {ip,ip6,arp}_tables unification
This patch moves {ip,ip6,arp}t_entry_{match,target} definitions to
x_tables.h. This move simplifies code and future compatibility fixes.
Signed-off-by: Dmitry Mishin <dim@openvz.org>
Acked-off-by: Kirill Korotaev <dev@openvz.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit 7220ff91af131f790589bcb3068f53a56bf52863
tree dff9af08daa6a7f7ae540975876f67c741b2af48
parent c55bc9d2751de011679d2b18df12075d1c7590c5
author Dmitry Mishin <dim@openvz.org> Mon, 20 Mar 2006 15:38:33 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 15:38:33 +0100
include/linux/netfilter/x_tables.h | 56 ++++++++++++++++++++++++++++
include/linux/netfilter_arp/arp_tables.h | 31 +---------------
include/linux/netfilter_ipv4/ip_tables.h | 58 ++---------------------------
include/linux/netfilter_ipv6/ip6_tables.h | 57 ++---------------------------
include/net/tc_act/tc_ipt.h | 4 +-
5 files changed, 66 insertions(+), 140 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index bf71efb..1350e47 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -4,6 +4,62 @@
#define XT_FUNCTION_MAXNAMELEN 30
#define XT_TABLE_MAXNAMELEN 32
+struct xt_entry_match
+{
+ union {
+ struct {
+ u_int16_t match_size;
+
+ /* Used by userspace */
+ char name[XT_FUNCTION_MAXNAMELEN-1];
+
+ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t match_size;
+
+ /* Used inside the kernel */
+ struct xt_match *match;
+ } kernel;
+
+ /* Total length */
+ u_int16_t match_size;
+ } u;
+
+ unsigned char data[0];
+};
+
+struct xt_entry_target
+{
+ union {
+ struct {
+ u_int16_t target_size;
+
+ /* Used by userspace */
+ char name[XT_FUNCTION_MAXNAMELEN-1];
+
+ u_int8_t revision;
+ } user;
+ struct {
+ u_int16_t target_size;
+
+ /* Used inside the kernel */
+ struct xt_target *target;
+ } kernel;
+
+ /* Total length */
+ u_int16_t target_size;
+ } u;
+
+ unsigned char data[0];
+};
+
+struct xt_standard_target
+{
+ struct xt_entry_target target;
+ int verdict;
+};
+
/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision
* kernel supports, if >= revision. */
struct xt_get_revision
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index a27be05..62cc27d 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -65,35 +65,8 @@ struct arpt_arp {
u_int16_t invflags;
};
-struct arpt_entry_target
-{
- union {
- struct {
- u_int16_t target_size;
-
- /* Used by userspace */
- char name[ARPT_FUNCTION_MAXNAMELEN-1];
- u_int8_t revision;
- } user;
- struct {
- u_int16_t target_size;
-
- /* Used inside the kernel */
- struct arpt_target *target;
- } kernel;
-
- /* Total length */
- u_int16_t target_size;
- } u;
-
- unsigned char data[0];
-};
-
-struct arpt_standard_target
-{
- struct arpt_entry_target target;
- int verdict;
-};
+#define arpt_entry_target xt_entry_target
+#define arpt_standard_target xt_standard_target
/* Values for "flag" field in struct arpt_ip (general arp structure).
* No flags defined yet.
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index ee262b5..d5b8c0d 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -52,61 +52,9 @@ struct ipt_ip {
u_int8_t invflags;
};
-struct ipt_entry_match
-{
- union {
- struct {
- u_int16_t match_size;
-
- /* Used by userspace */
- char name[IPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
- } user;
- struct {
- u_int16_t match_size;
-
- /* Used inside the kernel */
- struct ipt_match *match;
- } kernel;
-
- /* Total length */
- u_int16_t match_size;
- } u;
-
- unsigned char data[0];
-};
-
-struct ipt_entry_target
-{
- union {
- struct {
- u_int16_t target_size;
-
- /* Used by userspace */
- char name[IPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
- } user;
- struct {
- u_int16_t target_size;
-
- /* Used inside the kernel */
- struct ipt_target *target;
- } kernel;
-
- /* Total length */
- u_int16_t target_size;
- } u;
-
- unsigned char data[0];
-};
-
-struct ipt_standard_target
-{
- struct ipt_entry_target target;
- int verdict;
-};
+#define ipt_entry_match xt_entry_match
+#define ipt_entry_target xt_entry_target
+#define ipt_standard_target xt_standard_target
#define ipt_counters xt_counters
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 7107f94..d0d5d1e 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -56,60 +56,9 @@ struct ip6t_ip6 {
u_int8_t invflags;
};
-/* FIXME: If alignment in kernel different from userspace? --RR */
-struct ip6t_entry_match
-{
- union {
- struct {
- u_int16_t match_size;
-
- /* Used by userspace */
- char name[IP6T_FUNCTION_MAXNAMELEN-1];
- u_int8_t revision;
- } user;
- struct {
- u_int16_t match_size;
-
- /* Used inside the kernel */
- struct ip6t_match *match;
- } kernel;
-
- /* Total length */
- u_int16_t match_size;
- } u;
-
- unsigned char data[0];
-};
-
-struct ip6t_entry_target
-{
- union {
- struct {
- u_int16_t target_size;
-
- /* Used by userspace */
- char name[IP6T_FUNCTION_MAXNAMELEN-1];
- u_int8_t revision;
- } user;
- struct {
- u_int16_t target_size;
-
- /* Used inside the kernel */
- struct ip6t_target *target;
- } kernel;
-
- /* Total length */
- u_int16_t target_size;
- } u;
-
- unsigned char data[0];
-};
-
-struct ip6t_standard_target
-{
- struct ip6t_entry_target target;
- int verdict;
-};
+#define ip6t_entry_match xt_entry_match
+#define ip6t_entry_target xt_entry_target
+#define ip6t_standard_target xt_standard_target
#define ip6t_counters xt_counters
diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h
index 02ecceb..cb37ad0 100644
--- a/include/net/tc_act/tc_ipt.h
+++ b/include/net/tc_act/tc_ipt.h
@@ -3,14 +3,14 @@
#include <net/act_api.h>
-struct ipt_entry_target;
+struct xt_entry_target;
struct tcf_ipt
{
tca_gen(ipt);
u32 hook;
char *tname;
- struct ipt_entry_target *t;
+ struct xt_entry_target *t;
};
#endif
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [NETFILTER 08/09]: Add H.323 conntrack/NAT helper
2006-03-21 1:56 ` [NETFILTER 08/09]: Add H.323 conntrack/NAT helper Patrick McHardy
@ 2006-03-21 2:03 ` Patrick McHardy
0 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 2:03 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 1671 bytes --]
Patrick McHardy wrote:
> [NETFILTER]: Add H.323 conntrack/NAT helper
>
Sorry, I accidentally committed the make-rebuilds-all fix. This is
the correct patch.
> diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> index 0168d6c..c847744 100644
> --- a/scripts/Kbuild.include
> +++ b/scripts/Kbuild.include
> @@ -79,7 +79,7 @@ echo-cmd = $(if $($(quiet)cmd_$(1)), \
> # >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
> # note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
> #
> -if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
> +if_changed = $(if $(strip $(filter-out FORCE,$?) $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
> @set -e; \
> $(echo-cmd) \
> $(cmd_$(1)); \
> @@ -87,7 +87,7 @@ if_changed = $(if $(strip $? $(call arg-
>
> # execute the command and also postprocess generated .d dependencies
> # file
> -if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
> +if_changed_dep = $(if $(strip $(filter-out FORCE,$? $(filter-out $(wildcard $^),$^))\
> $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
> @set -e; \
> $(echo-cmd) \
> @@ -99,6 +99,6 @@ if_changed_dep = $(if $(strip $? $(filte
> # Usage: $(call if_changed_rule,foo)
> # will check if $(cmd_foo) changed, or any of the prequisites changed,
> # and if so will execute $(rule_foo)
> -if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
> +if_changed_rule = $(if $(strip $(filter-out FORCE,$?) $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
> @set -e; \
> $(rule_$(1)))
>
[-- Attachment #2: 08.diff --]
[-- Type: text/plain, Size: 228065 bytes --]
[NETFILTER]: Add H.323 conntrack/NAT helper
Signed-off-by: Jing Min Zhao <zhaojignmin@hotmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
commit c55bc9d2751de011679d2b18df12075d1c7590c5
tree cb9ea9d0004ce9275e8db9e4745e9db499613729
parent d64ab19c8c265eb3defd20d3fa993df52542ad00
author Jing Min Zhao <zhaojignmin@hotmail.com> Mon, 20 Mar 2006 15:18:54 +0100
committer Patrick McHardy <kaber@trash.net> Mon, 20 Mar 2006 15:18:54 +0100
include/linux/netfilter_ipv4/ip_conntrack.h | 2
include/linux/netfilter_ipv4/ip_conntrack_h323.h | 30
net/ipv4/netfilter/Kconfig | 26
net/ipv4/netfilter/Makefile | 5
net/ipv4/netfilter/ip_conntrack_helper_h323.c | 1731 ++++++++++++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 870 +++++++++
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h | 98 +
.../netfilter/ip_conntrack_helper_h323_types.c | 1926 +++++++++++++++++++++++
.../netfilter/ip_conntrack_helper_h323_types.h | 938 +++++++++++
net/ipv4/netfilter/ip_nat_helper_h323.c | 605 ++++++
10 files changed, 6231 insertions(+), 3 deletions(-)
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 215765f..f32d75c 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -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;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
new file mode 100644
index 0000000..0987cea
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -0,0 +1,30 @@
+#ifndef _IP_CONNTRACK_H323_H
+#define _IP_CONNTRACK_H323_H
+
+#ifdef __KERNEL__
+
+#define RAS_PORT 1719
+#define Q931_PORT 1720
+#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
+
+/* This structure exists only once per master */
+struct ip_ct_h323_master {
+
+ /* Original and NATed Q.931 or H.245 signal ports */
+ u_int16_t sig_port[IP_CT_DIR_MAX];
+
+ /* Original and NATed RTP ports */
+ u_int16_t rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX];
+
+ union {
+ /* RAS connection timeout */
+ u_int32_t timeout;
+
+ /* Next TPKT length (for separate TPKT header and data) */
+ u_int16_t tpkt_len[IP_CT_DIR_MAX];
+ };
+};
+
+#endif
+
+#endif
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 933ee7a..aefd3fe 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -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"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 3fe8092..f2cd9a6 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -10,6 +10,9 @@ iptable_nat-objs := ip_nat_rule.o ip_nat
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) +=
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_
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
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
new file mode 100644
index 0000000..c8292c9
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -0,0 +1,1731 @@
+/*
+ * 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");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
new file mode 100644
index 0000000..3c6b34f
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -0,0 +1,870 @@
+/****************************************************************************
+ * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
+ * conntrack/NAT module.
+ *
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ * See ip_conntrack_helper_h323_asn1.h for details.
+ *
+ ****************************************************************************/
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#else
+#include <stdio.h>
+#endif
+#include "ip_conntrack_helper_h323_asn1.h"
+
+/* Trace Flag */
+#ifndef H323_TRACE
+#define H323_TRACE 0
+#endif
+
+#if H323_TRACE
+#define TAB_SIZE 4
+#define IFTHEN(cond, act) if(cond){act;}
+#ifdef __KERNEL__
+#define PRINT printk
+#else
+#define PRINT printf
+#endif
+#define FNAME(name) name,
+#else
+#define IFTHEN(cond, act)
+#define PRINT(fmt, args...)
+#define FNAME(name)
+#endif
+
+/* ASN.1 Types */
+#define NUL 0
+#define BOOL 1
+#define OID 2
+#define INT 3
+#define ENUM 4
+#define BITSTR 5
+#define NUMSTR 6
+#define NUMDGT 6
+#define TBCDSTR 6
+#define OCTSTR 7
+#define PRTSTR 7
+#define IA5STR 7
+#define GENSTR 7
+#define BMPSTR 8
+#define SEQ 9
+#define SET 9
+#define SEQOF 10
+#define SETOF 10
+#define CHOICE 11
+
+/* Constraint Types */
+#define FIXD 0
+/* #define BITS 1-8 */
+#define BYTE 9
+#define WORD 10
+#define CONS 11
+#define SEMI 12
+#define UNCO 13
+
+/* ASN.1 Type Attributes */
+#define SKIP 0
+#define STOP 1
+#define DECODE 2
+#define EXT 4
+#define OPEN 8
+#define OPT 16
+
+
+/* ASN.1 Field Structure */
+typedef struct field_t {
+#if H323_TRACE
+ char *name;
+#endif
+ unsigned char type;
+ unsigned char sz;
+ unsigned char lb;
+ unsigned char ub;
+ unsigned short attr;
+ unsigned short offset;
+ struct field_t *fields;
+} field_t;
+
+/* Bit Stream */
+typedef struct {
+ unsigned char *buf;
+ unsigned char *beg;
+ unsigned char *end;
+ unsigned char *cur;
+ unsigned bit;
+} bitstr_t;
+
+/* Tool Functions */
+#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;}
+#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;}
+#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;}
+#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND)
+static unsigned get_len(bitstr_t * bs);
+static unsigned get_bit(bitstr_t * bs);
+static unsigned get_bits(bitstr_t * bs, unsigned b);
+static unsigned get_bitmap(bitstr_t * bs, unsigned b);
+static unsigned get_uint(bitstr_t * bs, int b);
+
+/* Decoder Functions */
+static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_int(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level);
+static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level);
+
+/* Decoder Functions Vector */
+typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int);
+static decoder_t Decoders[] = {
+ decode_nul,
+ decode_bool,
+ decode_oid,
+ decode_int,
+ decode_enum,
+ decode_bitstr,
+ decode_numstr,
+ decode_octstr,
+ decode_bmpstr,
+ decode_seq,
+ decode_seqof,
+ decode_choice,
+};
+
+/****************************************************************************
+ * H.323 Types
+ ****************************************************************************/
+#include "ip_conntrack_helper_h323_types.c"
+
+/****************************************************************************
+ * Functions
+ ****************************************************************************/
+/* Assume bs is aligned && v < 16384 */
+unsigned get_len(bitstr_t * bs)
+{
+ unsigned v;
+
+ v = *bs->cur++;
+
+ if (v & 0x80) {
+ v &= 0x3f;
+ v <<= 8;
+ v += *bs->cur++;
+ }
+
+ return v;
+}
+
+/****************************************************************************/
+unsigned get_bit(bitstr_t * bs)
+{
+ unsigned b = (*bs->cur) & (0x80 >> bs->bit);
+
+ INC_BIT(bs);
+
+ return b;
+}
+
+/****************************************************************************/
+/* Assume b <= 8 */
+unsigned get_bits(bitstr_t * bs, unsigned b)
+{
+ unsigned v, l;
+
+ v = (*bs->cur) & (0xffU >> bs->bit);
+ l = b + bs->bit;
+
+ if (l < 8) {
+ v >>= 8 - l;
+ bs->bit = l;
+ } else if (l == 8) {
+ bs->cur++;
+ bs->bit = 0;
+ } else { /* l > 8 */
+
+ v <<= 8;
+ v += *(++bs->cur);
+ v >>= 16 - l;
+ bs->bit = l - 8;
+ }
+
+ return v;
+}
+
+/****************************************************************************/
+/* Assume b <= 32 */
+unsigned get_bitmap(bitstr_t * bs, unsigned b)
+{
+ unsigned v, l, shift, bytes;
+
+ if (!b)
+ return 0;
+
+ l = bs->bit + b;
+
+ if (l < 8) {
+ v = (unsigned) (*bs->cur) << (bs->bit + 24);
+ bs->bit = l;
+ } else if (l == 8) {
+ v = (unsigned) (*bs->cur++) << (bs->bit + 24);
+ bs->bit = 0;
+ } else {
+ for (bytes = l >> 3, shift = 24, v = 0; bytes;
+ bytes--, shift -= 8)
+ v |= (unsigned) (*bs->cur++) << shift;
+
+ if (l < 32) {
+ v |= (unsigned) (*bs->cur) << shift;
+ v <<= bs->bit;
+ } else if (l > 32) {
+ v <<= bs->bit;
+ v |= (*bs->cur) >> (8 - bs->bit);
+ }
+
+ bs->bit = l & 0x7;
+ }
+
+ v &= 0xffffffff << (32 - b);
+
+ return v;
+}
+
+/****************************************************************************
+ * Assume bs is aligned and sizeof(unsigned int) == 4
+ ****************************************************************************/
+unsigned get_uint(bitstr_t * bs, int b)
+{
+ unsigned v = 0;
+
+ switch (b) {
+ case 4:
+ v |= *bs->cur++;
+ v <<= 8;
+ case 3:
+ v |= *bs->cur++;
+ v <<= 8;
+ case 2:
+ v |= *bs->cur++;
+ v <<= 8;
+ case 1:
+ v |= *bs->cur++;
+ break;
+ }
+ return v;
+}
+
+/****************************************************************************/
+int decode_nul(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_bool(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ INC_BIT(bs);
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_oid(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ int len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ len = *bs->cur++;
+ bs->cur += len;
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_int(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
+
+ switch (f->sz) {
+ case BYTE: /* Range == 256 */
+ BYTE_ALIGN(bs);
+ bs->cur++;
+ break;
+ case WORD: /* 257 <= Range <= 64K */
+ BYTE_ALIGN(bs);
+ bs->cur += 2;
+ break;
+ case CONS: /* 64K < Range < 4G */
+ len = get_bits(bs, 2) + 1;
+ BYTE_ALIGN(bs);
+ if (base && (f->attr & DECODE)) { /* timeToLive */
+ unsigned v = get_uint(bs, len) + f->lb;
+ PRINT(" = %u", v);
+ *((unsigned *) (base + f->offset)) = v;
+ }
+ bs->cur += len;
+ break;
+ case UNCO:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ bs->cur += len;
+ break;
+ default: /* 2 <= Range <= 255 */
+ INC_BITS(bs, f->sz);
+ break;
+ }
+
+ PRINT("\n");
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_enum(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ if ((f->attr & EXT) && get_bit(bs)) {
+ INC_BITS(bs, 7);
+ } else {
+ INC_BITS(bs, f->sz);
+ }
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ BYTE_ALIGN(bs);
+ switch (f->sz) {
+ case FIXD: /* fixed length > 16 */
+ len = f->lb;
+ break;
+ case WORD: /* 2-byte length */
+ CHECK_BOUND(bs, 2);
+ len = (*bs->cur++) << 8;
+ len += (*bs->cur++) + f->lb;
+ break;
+ case SEMI:
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ break;
+ default:
+ len = 0;
+ break;
+ }
+
+ bs->cur += len >> 3;
+ bs->bit = len & 7;
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* 2 <= Range <= 255 */
+ len = get_bits(bs, f->sz) + f->lb;
+
+ BYTE_ALIGN(bs);
+ INC_BITS(bs, (len << 2));
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
+
+ switch (f->sz) {
+ case FIXD: /* Range == 1 */
+ if (f->lb > 2) {
+ BYTE_ALIGN(bs);
+ if (base && (f->attr & DECODE)) {
+ /* The IP Address */
+ IFTHEN(f->lb == 4,
+ PRINT(" = %d.%d.%d.%d:%d",
+ bs->cur[0], bs->cur[1],
+ bs->cur[2], bs->cur[3],
+ bs->cur[4] * 256 + bs->cur[5]));
+ *((unsigned *) (base + f->offset)) =
+ bs->cur - bs->buf;
+ }
+ }
+ len = f->lb;
+ break;
+ case BYTE: /* Range == 256 */
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ len = (*bs->cur++) + f->lb;
+ break;
+ case SEMI:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs) + f->lb;
+ break;
+ default: /* 2 <= Range <= 255 */
+ len = get_bits(bs, f->sz) + f->lb;
+ BYTE_ALIGN(bs);
+ break;
+ }
+
+ bs->cur += len;
+
+ PRINT("\n");
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned len;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ switch (f->sz) {
+ case BYTE: /* Range == 256 */
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ len = (*bs->cur++) + f->lb;
+ break;
+ default: /* 2 <= Range <= 255 */
+ len = get_bits(bs, f->sz) + f->lb;
+ BYTE_ALIGN(bs);
+ break;
+ }
+
+ bs->cur += len << 1;
+
+ CHECK_BOUND(bs, 0);
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
+ int err;
+ field_t *son;
+ unsigned char *beg = NULL;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* Decode? */
+ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
+
+ /* Extensible? */
+ ext = (f->attr & EXT) ? get_bit(bs) : 0;
+
+ /* Get fields bitmap */
+ bmp = get_bitmap(bs, f->sz);
+ if (base)
+ *(unsigned *) base = bmp;
+
+ /* Decode the root components */
+ for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (son->attr & OPT) { /* Optional component */
+ if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */
+ continue;
+ }
+
+ /* Decode */
+ if (son->attr & OPEN) { /* Open field */
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
+ " ", son->name);
+ bs->cur += len;
+ continue;
+ }
+ beg = bs->cur;
+
+ /* Decode */
+ if ((err = (Decoders[son->type]) (bs, son, base,
+ level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ } else if ((err = (Decoders[son->type]) (bs, son, base,
+ level + 1)))
+ return err;
+ }
+
+ /* No extension? */
+ if (!ext)
+ return H323_ERROR_NONE;
+
+ /* Get the extension bitmap */
+ bmp2_len = get_bits(bs, 7) + 1;
+ CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
+ bmp2 = get_bitmap(bs, bmp2_len);
+ bmp |= bmp2 >> f->sz;
+ if (base)
+ *(unsigned *) base = bmp;
+ BYTE_ALIGN(bs);
+
+ /* Decode the extension components */
+ for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (!((0x80000000 >> opt) & bmp2)) /* Not present */
+ continue;
+
+ /* Check Range */
+ if (i >= f->ub) { /* Newer Version? */
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ bs->cur += len;
+ continue;
+ }
+
+ CHECK_BOUND(bs, 2);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base || !(son->attr & DECODE)) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ bs->cur += len;
+ continue;
+ }
+ beg = bs->cur;
+
+ if ((err = (Decoders[son->type]) (bs, son, base,
+ level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ }
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned count, effective_count = 0, i, len = 0;
+ int err;
+ field_t *son;
+ unsigned char *beg = NULL;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* Decode? */
+ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
+
+ /* Decode item count */
+ switch (f->sz) {
+ case BYTE:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 1);
+ count = *bs->cur++;
+ break;
+ case WORD:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ count = *bs->cur++;
+ count <<= 8;
+ count = *bs->cur++;
+ break;
+ case SEMI:
+ BYTE_ALIGN(bs);
+ CHECK_BOUND(bs, 2);
+ count = get_len(bs);
+ break;
+ default:
+ count = get_bits(bs, f->sz);
+ break;
+ }
+ count += f->lb;
+
+ /* Write Count */
+ if (base) {
+ effective_count = count > f->ub ? f->ub : count;
+ *(unsigned *) base = effective_count;
+ base += sizeof(unsigned);
+ }
+
+ /* Decode nested field */
+ son = f->fields;
+ if (base)
+ base -= son->offset;
+ for (i = 0; i < count; i++) {
+ if (son->attr & OPEN) {
+ BYTE_ALIGN(bs);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base || !(son->attr & DECODE)) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
+ " ", son->name);
+ bs->cur += len;
+ continue;
+ }
+ beg = bs->cur;
+
+ if ((err = (Decoders[son->type]) (bs, son,
+ i <
+ effective_count ?
+ base : NULL,
+ level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ } else
+ if ((err = (Decoders[son->type]) (bs, son,
+ i < effective_count ?
+ base : NULL,
+ level + 1)))
+ return err;
+
+ if (base)
+ base += son->offset;
+ }
+
+ return H323_ERROR_NONE;
+}
+
+
+/****************************************************************************/
+int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
+{
+ unsigned type, ext, len = 0;
+ int err;
+ field_t *son;
+ unsigned char *beg = NULL;
+
+ PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
+
+ /* Decode? */
+ base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
+
+ /* Decode the choice index number */
+ if ((f->attr & EXT) && get_bit(bs)) {
+ ext = 1;
+ type = get_bits(bs, 7) + f->lb;
+ } else {
+ ext = 0;
+ type = get_bits(bs, f->sz);
+ }
+
+ /* Check Range */
+ if (type >= f->ub) { /* Newer version? */
+ BYTE_ALIGN(bs);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ bs->cur += len;
+ return H323_ERROR_NONE;
+ }
+
+ /* Write Type */
+ if (base)
+ *(unsigned *) base = type;
+
+ /* Transfer to son level */
+ son = &f->fields[type];
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (ext || (son->attr & OPEN)) {
+ BYTE_ALIGN(bs);
+ len = get_len(bs);
+ CHECK_BOUND(bs, len);
+ if (!base || !(son->attr & DECODE)) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ bs->cur += len;
+ return H323_ERROR_NONE;
+ }
+ beg = bs->cur;
+
+ if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) >
+ H323_ERROR_STOP)
+ return err;
+
+ bs->cur = beg + len;
+ bs->bit = 0;
+ } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)))
+ return err;
+
+ return H323_ERROR_NONE;
+}
+
+/****************************************************************************/
+int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras)
+{
+ static field_t ras_message = {
+ FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
+ 0, _RasMessage
+ };
+ bitstr_t bs;
+
+ bs.buf = bs.beg = bs.cur = buf;
+ bs.end = buf + sz;
+ bs.bit = 0;
+
+ return decode_choice(&bs, &ras_message, (char *) ras, 0);
+}
+
+/****************************************************************************/
+static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
+ size_t sz, H323_UserInformation * uuie)
+{
+ static field_t h323_userinformation = {
+ FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
+ 0, _H323_UserInformation
+ };
+ bitstr_t bs;
+
+ bs.buf = buf;
+ bs.beg = bs.cur = beg;
+ bs.end = beg + sz;
+ bs.bit = 0;
+
+ return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
+}
+
+/****************************************************************************/
+int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
+ MultimediaSystemControlMessage *
+ mscm)
+{
+ static field_t multimediasystemcontrolmessage = {
+ FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
+ DECODE | EXT, 0, _MultimediaSystemControlMessage
+ };
+ bitstr_t bs;
+
+ bs.buf = bs.beg = bs.cur = buf;
+ bs.end = buf + sz;
+ bs.bit = 0;
+
+ return decode_choice(&bs, &multimediasystemcontrolmessage,
+ (char *) mscm, 0);
+}
+
+/****************************************************************************/
+int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931)
+{
+ unsigned char *p = buf;
+ int len;
+
+ if (!p || sz < 1)
+ return H323_ERROR_BOUND;
+
+ /* Protocol Discriminator */
+ if (*p != 0x08) {
+ PRINT("Unknown Protocol Discriminator\n");
+ return H323_ERROR_RANGE;
+ }
+ p++;
+ sz--;
+
+ /* CallReferenceValue */
+ if (sz < 1)
+ return H323_ERROR_BOUND;
+ len = *p++;
+ sz--;
+ if (sz < len)
+ return H323_ERROR_BOUND;
+ p += len;
+ sz -= len;
+
+ /* Message Type */
+ if (sz < 1)
+ return H323_ERROR_BOUND;
+ q931->MessageType = *p++;
+ PRINT("MessageType = %02X\n", q931->MessageType);
+ if (*p & 0x80) {
+ p++;
+ sz--;
+ }
+
+ /* Decode Information Elements */
+ while (sz > 0) {
+ if (*p == 0x7e) { /* UserUserIE */
+ if (sz < 3)
+ break;
+ p++;
+ len = *p++ << 8;
+ len |= *p++;
+ sz -= 3;
+ if (sz < len)
+ break;
+ p++;
+ len--;
+ return DecodeH323_UserInformation(buf, p, len,
+ &q931->UUIE);
+ }
+ p++;
+ sz--;
+ if (sz < 1)
+ break;
+ len = *p++;
+ if (sz < len)
+ break;
+ p += len;
+ sz -= len;
+ }
+
+ PRINT("Q.931 UUIE not found\n");
+
+ return H323_ERROR_BOUND;
+}
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
new file mode 100644
index 0000000..2556b84
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+ * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
+ * conntrack/NAT module.
+ *
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ *
+ * This library is based on H.225 version 4, H.235 version 2 and H.245
+ * version 7. It is extremely optimized to decode only the absolutely
+ * necessary objects in a signal for Linux kernel NAT module use, so don't
+ * expect it to be a full ASN.1 library.
+ *
+ * Features:
+ *
+ * 1. Small. The total size of code plus data is less than 20 KB (IA32).
+ * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866
+ * takes only 3.9 seconds.
+ * 3. No memory allocation. It uses a static object. No need to initialize or
+ * cleanup.
+ * 4. Thread safe.
+ * 5. Support embedded architectures that has no misaligned memory access
+ * support.
+ *
+ * Limitations:
+ *
+ * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU.
+ * If a Setup signal contains more than 30 faststart, the packet size will
+ * very likely exceed the MTU size, then the TPKT will be fragmented. I
+ * don't know how to handle this in a Netfilter module. Anybody can help?
+ * Although I think 30 is enough for most of the cases.
+ * 2. IPv4 addresses only.
+ *
+ ****************************************************************************/
+
+#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
+#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
+
+/*****************************************************************************
+ * H.323 Types
+ ****************************************************************************/
+#include "ip_conntrack_helper_h323_types.h"
+
+typedef struct {
+ enum {
+ Q931_NationalEscape = 0x00,
+ Q931_Alerting = 0x01,
+ Q931_CallProceeding = 0x02,
+ Q931_Connect = 0x07,
+ Q931_ConnectAck = 0x0F,
+ Q931_Progress = 0x03,
+ Q931_Setup = 0x05,
+ Q931_SetupAck = 0x0D,
+ Q931_Resume = 0x26,
+ Q931_ResumeAck = 0x2E,
+ Q931_ResumeReject = 0x22,
+ Q931_Suspend = 0x25,
+ Q931_SuspendAck = 0x2D,
+ Q931_SuspendReject = 0x21,
+ Q931_UserInformation = 0x20,
+ Q931_Disconnect = 0x45,
+ Q931_Release = 0x4D,
+ Q931_ReleaseComplete = 0x5A,
+ Q931_Restart = 0x46,
+ Q931_RestartAck = 0x4E,
+ Q931_Segment = 0x60,
+ Q931_CongestionCtrl = 0x79,
+ Q931_Information = 0x7B,
+ Q931_Notify = 0x6E,
+ Q931_Status = 0x7D,
+ Q931_StatusEnquiry = 0x75,
+ Q931_Facility = 0x62
+ } MessageType;
+ H323_UserInformation UUIE;
+} Q931;
+
+/*****************************************************************************
+ * Decode Functions Return Codes
+ ****************************************************************************/
+
+#define H323_ERROR_NONE 0 /* Decoded successfully */
+#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */
+#define H323_ERROR_BOUND -1
+#define H323_ERROR_RANGE -2
+
+
+/*****************************************************************************
+ * Decode Functions
+ ****************************************************************************/
+
+int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras);
+int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931);
+int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
+ MultimediaSystemControlMessage *
+ mscm);
+
+#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
new file mode 100644
index 0000000..022c47b
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
@@ -0,0 +1,1926 @@
+/* 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},
+};
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
new file mode 100644
index 0000000..cc98f7a
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
@@ -0,0 +1,938 @@
+/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+ *
+ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
+ *
+ * This source code is licensed under General Public License version 2.
+ */
+
+typedef struct TransportAddress_ipAddress { /* SEQUENCE */
+ int options; /* No use */
+ unsigned ip;
+} TransportAddress_ipAddress;
+
+typedef struct TransportAddress { /* CHOICE */
+ enum {
+ eTransportAddress_ipAddress,
+ eTransportAddress_ipSourceRoute,
+ eTransportAddress_ipxAddress,
+ eTransportAddress_ip6Address,
+ eTransportAddress_netBios,
+ eTransportAddress_nsap,
+ eTransportAddress_nonStandardAddress,
+ } choice;
+ union {
+ TransportAddress_ipAddress ipAddress;
+ };
+} TransportAddress;
+
+typedef struct DataProtocolCapability { /* CHOICE */
+ enum {
+ eDataProtocolCapability_nonStandard,
+ eDataProtocolCapability_v14buffered,
+ eDataProtocolCapability_v42lapm,
+ eDataProtocolCapability_hdlcFrameTunnelling,
+ eDataProtocolCapability_h310SeparateVCStack,
+ eDataProtocolCapability_h310SingleVCStack,
+ eDataProtocolCapability_transparent,
+ eDataProtocolCapability_segmentationAndReassembly,
+ eDataProtocolCapability_hdlcFrameTunnelingwSAR,
+ eDataProtocolCapability_v120,
+ eDataProtocolCapability_separateLANStack,
+ eDataProtocolCapability_v76wCompression,
+ eDataProtocolCapability_tcp,
+ eDataProtocolCapability_udp,
+ } choice;
+} DataProtocolCapability;
+
+typedef struct DataApplicationCapability_application { /* CHOICE */
+ enum {
+ eDataApplicationCapability_application_nonStandard,
+ eDataApplicationCapability_application_t120,
+ eDataApplicationCapability_application_dsm_cc,
+ eDataApplicationCapability_application_userData,
+ eDataApplicationCapability_application_t84,
+ eDataApplicationCapability_application_t434,
+ eDataApplicationCapability_application_h224,
+ eDataApplicationCapability_application_nlpid,
+ eDataApplicationCapability_application_dsvdControl,
+ eDataApplicationCapability_application_h222DataPartitioning,
+ eDataApplicationCapability_application_t30fax,
+ eDataApplicationCapability_application_t140,
+ eDataApplicationCapability_application_t38fax,
+ eDataApplicationCapability_application_genericDataCapability,
+ } choice;
+ union {
+ DataProtocolCapability t120;
+ };
+} DataApplicationCapability_application;
+
+typedef struct DataApplicationCapability { /* SEQUENCE */
+ int options; /* No use */
+ DataApplicationCapability_application application;
+} DataApplicationCapability;
+
+typedef struct DataType { /* CHOICE */
+ enum {
+ eDataType_nonStandard,
+ eDataType_nullData,
+ eDataType_videoData,
+ eDataType_audioData,
+ eDataType_data,
+ eDataType_encryptionData,
+ eDataType_h235Control,
+ eDataType_h235Media,
+ eDataType_multiplexedStream,
+ } choice;
+ union {
+ DataApplicationCapability data;
+ };
+} DataType;
+
+typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
+ int options; /* No use */
+ unsigned network;
+} UnicastAddress_iPAddress;
+
+typedef struct UnicastAddress { /* CHOICE */
+ enum {
+ eUnicastAddress_iPAddress,
+ eUnicastAddress_iPXAddress,
+ eUnicastAddress_iP6Address,
+ eUnicastAddress_netBios,
+ eUnicastAddress_iPSourceRouteAddress,
+ eUnicastAddress_nsap,
+ eUnicastAddress_nonStandardAddress,
+ } choice;
+ union {
+ UnicastAddress_iPAddress iPAddress;
+ };
+} UnicastAddress;
+
+typedef struct H245_TransportAddress { /* CHOICE */
+ enum {
+ eH245_TransportAddress_unicastAddress,
+ eH245_TransportAddress_multicastAddress,
+ } choice;
+ union {
+ UnicastAddress unicastAddress;
+ };
+} H245_TransportAddress;
+
+typedef struct H2250LogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eH2250LogicalChannelParameters_nonStandard = (1 << 31),
+ eH2250LogicalChannelParameters_associatedSessionID =
+ (1 << 30),
+ eH2250LogicalChannelParameters_mediaChannel = (1 << 29),
+ eH2250LogicalChannelParameters_mediaGuaranteedDelivery =
+ (1 << 28),
+ eH2250LogicalChannelParameters_mediaControlChannel =
+ (1 << 27),
+ eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery
+ = (1 << 26),
+ eH2250LogicalChannelParameters_silenceSuppression = (1 << 25),
+ eH2250LogicalChannelParameters_destination = (1 << 24),
+ eH2250LogicalChannelParameters_dynamicRTPPayloadType =
+ (1 << 23),
+ eH2250LogicalChannelParameters_mediaPacketization = (1 << 22),
+ eH2250LogicalChannelParameters_transportCapability =
+ (1 << 21),
+ eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20),
+ eH2250LogicalChannelParameters_source = (1 << 19),
+ } options;
+ H245_TransportAddress mediaChannel;
+ H245_TransportAddress mediaControlChannel;
+} H2250LogicalChannelParameters;
+
+typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
+ eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none,
+ } choice;
+ union {
+ H2250LogicalChannelParameters h2250LogicalChannelParameters;
+ };
+} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters;
+
+typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber
+ = (1 << 31),
+ eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency
+ = (1 << 30),
+ eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor
+ = (1 << 29),
+ } options;
+ DataType dataType;
+ OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
+ multiplexParameters;
+} OpenLogicalChannel_forwardLogicalChannelParameters;
+
+typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
+ } choice;
+ union {
+ H2250LogicalChannelParameters h2250LogicalChannelParameters;
+ };
+} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters;
+
+typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
+ = (1 << 31),
+ eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency
+ = (1 << 30),
+ eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor
+ = (1 << 29),
+ } options;
+ OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
+ multiplexParameters;
+} OpenLogicalChannel_reverseLogicalChannelParameters;
+
+typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */
+ enum {
+ eNetworkAccessParameters_networkAddress_q2931Address,
+ eNetworkAccessParameters_networkAddress_e164Address,
+ eNetworkAccessParameters_networkAddress_localAreaAddress,
+ } choice;
+ union {
+ H245_TransportAddress localAreaAddress;
+ };
+} NetworkAccessParameters_networkAddress;
+
+typedef struct NetworkAccessParameters { /* SEQUENCE */
+ enum {
+ eNetworkAccessParameters_distribution = (1 << 31),
+ eNetworkAccessParameters_externalReference = (1 << 30),
+ eNetworkAccessParameters_t120SetupProcedure = (1 << 29),
+ } options;
+ NetworkAccessParameters_networkAddress networkAddress;
+} NetworkAccessParameters;
+
+typedef struct OpenLogicalChannel { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannel_reverseLogicalChannelParameters =
+ (1 << 31),
+ eOpenLogicalChannel_separateStack = (1 << 30),
+ eOpenLogicalChannel_encryptionSync = (1 << 29),
+ } options;
+ OpenLogicalChannel_forwardLogicalChannelParameters
+ forwardLogicalChannelParameters;
+ OpenLogicalChannel_reverseLogicalChannelParameters
+ reverseLogicalChannelParameters;
+ NetworkAccessParameters separateStack;
+} OpenLogicalChannel;
+
+typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Setup_UUIE_fastStart;
+
+typedef struct Setup_UUIE { /* SEQUENCE */
+ enum {
+ eSetup_UUIE_h245Address = (1 << 31),
+ eSetup_UUIE_sourceAddress = (1 << 30),
+ eSetup_UUIE_destinationAddress = (1 << 29),
+ eSetup_UUIE_destCallSignalAddress = (1 << 28),
+ eSetup_UUIE_destExtraCallInfo = (1 << 27),
+ eSetup_UUIE_destExtraCRV = (1 << 26),
+ eSetup_UUIE_callServices = (1 << 25),
+ eSetup_UUIE_sourceCallSignalAddress = (1 << 24),
+ eSetup_UUIE_remoteExtensionAddress = (1 << 23),
+ eSetup_UUIE_callIdentifier = (1 << 22),
+ eSetup_UUIE_h245SecurityCapability = (1 << 21),
+ eSetup_UUIE_tokens = (1 << 20),
+ eSetup_UUIE_cryptoTokens = (1 << 19),
+ eSetup_UUIE_fastStart = (1 << 18),
+ eSetup_UUIE_mediaWaitForConnect = (1 << 17),
+ eSetup_UUIE_canOverlapSend = (1 << 16),
+ eSetup_UUIE_endpointIdentifier = (1 << 15),
+ eSetup_UUIE_multipleCalls = (1 << 14),
+ eSetup_UUIE_maintainConnection = (1 << 13),
+ eSetup_UUIE_connectionParameters = (1 << 12),
+ eSetup_UUIE_language = (1 << 11),
+ eSetup_UUIE_presentationIndicator = (1 << 10),
+ eSetup_UUIE_screeningIndicator = (1 << 9),
+ eSetup_UUIE_serviceControl = (1 << 8),
+ eSetup_UUIE_symmetricOperationRequired = (1 << 7),
+ eSetup_UUIE_capacity = (1 << 6),
+ eSetup_UUIE_circuitInfo = (1 << 5),
+ eSetup_UUIE_desiredProtocols = (1 << 4),
+ eSetup_UUIE_neededFeatures = (1 << 3),
+ eSetup_UUIE_desiredFeatures = (1 << 2),
+ eSetup_UUIE_supportedFeatures = (1 << 1),
+ eSetup_UUIE_parallelH245Control = (1 << 0),
+ } options;
+ TransportAddress h245Address;
+ TransportAddress destCallSignalAddress;
+ TransportAddress sourceCallSignalAddress;
+ Setup_UUIE_fastStart fastStart;
+} Setup_UUIE;
+
+typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} CallProceeding_UUIE_fastStart;
+
+typedef struct CallProceeding_UUIE { /* SEQUENCE */
+ enum {
+ eCallProceeding_UUIE_h245Address = (1 << 31),
+ eCallProceeding_UUIE_callIdentifier = (1 << 30),
+ eCallProceeding_UUIE_h245SecurityMode = (1 << 29),
+ eCallProceeding_UUIE_tokens = (1 << 28),
+ eCallProceeding_UUIE_cryptoTokens = (1 << 27),
+ eCallProceeding_UUIE_fastStart = (1 << 26),
+ eCallProceeding_UUIE_multipleCalls = (1 << 25),
+ eCallProceeding_UUIE_maintainConnection = (1 << 24),
+ eCallProceeding_UUIE_fastConnectRefused = (1 << 23),
+ eCallProceeding_UUIE_featureSet = (1 << 22),
+ } options;
+ TransportAddress h245Address;
+ CallProceeding_UUIE_fastStart fastStart;
+} CallProceeding_UUIE;
+
+typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Connect_UUIE_fastStart;
+
+typedef struct Connect_UUIE { /* SEQUENCE */
+ enum {
+ eConnect_UUIE_h245Address = (1 << 31),
+ eConnect_UUIE_callIdentifier = (1 << 30),
+ eConnect_UUIE_h245SecurityMode = (1 << 29),
+ eConnect_UUIE_tokens = (1 << 28),
+ eConnect_UUIE_cryptoTokens = (1 << 27),
+ eConnect_UUIE_fastStart = (1 << 26),
+ eConnect_UUIE_multipleCalls = (1 << 25),
+ eConnect_UUIE_maintainConnection = (1 << 24),
+ eConnect_UUIE_language = (1 << 23),
+ eConnect_UUIE_connectedAddress = (1 << 22),
+ eConnect_UUIE_presentationIndicator = (1 << 21),
+ eConnect_UUIE_screeningIndicator = (1 << 20),
+ eConnect_UUIE_fastConnectRefused = (1 << 19),
+ eConnect_UUIE_serviceControl = (1 << 18),
+ eConnect_UUIE_capacity = (1 << 17),
+ eConnect_UUIE_featureSet = (1 << 16),
+ } options;
+ TransportAddress h245Address;
+ Connect_UUIE_fastStart fastStart;
+} Connect_UUIE;
+
+typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Alerting_UUIE_fastStart;
+
+typedef struct Alerting_UUIE { /* SEQUENCE */
+ enum {
+ eAlerting_UUIE_h245Address = (1 << 31),
+ eAlerting_UUIE_callIdentifier = (1 << 30),
+ eAlerting_UUIE_h245SecurityMode = (1 << 29),
+ eAlerting_UUIE_tokens = (1 << 28),
+ eAlerting_UUIE_cryptoTokens = (1 << 27),
+ eAlerting_UUIE_fastStart = (1 << 26),
+ eAlerting_UUIE_multipleCalls = (1 << 25),
+ eAlerting_UUIE_maintainConnection = (1 << 24),
+ eAlerting_UUIE_alertingAddress = (1 << 23),
+ eAlerting_UUIE_presentationIndicator = (1 << 22),
+ eAlerting_UUIE_screeningIndicator = (1 << 21),
+ eAlerting_UUIE_fastConnectRefused = (1 << 20),
+ eAlerting_UUIE_serviceControl = (1 << 19),
+ eAlerting_UUIE_capacity = (1 << 18),
+ eAlerting_UUIE_featureSet = (1 << 17),
+ } options;
+ TransportAddress h245Address;
+ Alerting_UUIE_fastStart fastStart;
+} Alerting_UUIE;
+
+typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Information_UUIE_fastStart;
+
+typedef struct Information_UUIE { /* SEQUENCE */
+ enum {
+ eInformation_UUIE_callIdentifier = (1 << 31),
+ eInformation_UUIE_tokens = (1 << 30),
+ eInformation_UUIE_cryptoTokens = (1 << 29),
+ eInformation_UUIE_fastStart = (1 << 28),
+ eInformation_UUIE_fastConnectRefused = (1 << 27),
+ eInformation_UUIE_circuitInfo = (1 << 26),
+ } options;
+ Information_UUIE_fastStart fastStart;
+} Information_UUIE;
+
+typedef struct FacilityReason { /* CHOICE */
+ enum {
+ eFacilityReason_routeCallToGatekeeper,
+ eFacilityReason_callForwarded,
+ eFacilityReason_routeCallToMC,
+ eFacilityReason_undefinedReason,
+ eFacilityReason_conferenceListChoice,
+ eFacilityReason_startH245,
+ eFacilityReason_noH245,
+ eFacilityReason_newTokens,
+ eFacilityReason_featureSetUpdate,
+ eFacilityReason_forwardedElements,
+ eFacilityReason_transportedInformation,
+ } choice;
+} FacilityReason;
+
+typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Facility_UUIE_fastStart;
+
+typedef struct Facility_UUIE { /* SEQUENCE */
+ enum {
+ eFacility_UUIE_alternativeAddress = (1 << 31),
+ eFacility_UUIE_alternativeAliasAddress = (1 << 30),
+ eFacility_UUIE_conferenceID = (1 << 29),
+ eFacility_UUIE_callIdentifier = (1 << 28),
+ eFacility_UUIE_destExtraCallInfo = (1 << 27),
+ eFacility_UUIE_remoteExtensionAddress = (1 << 26),
+ eFacility_UUIE_tokens = (1 << 25),
+ eFacility_UUIE_cryptoTokens = (1 << 24),
+ eFacility_UUIE_conferences = (1 << 23),
+ eFacility_UUIE_h245Address = (1 << 22),
+ eFacility_UUIE_fastStart = (1 << 21),
+ eFacility_UUIE_multipleCalls = (1 << 20),
+ eFacility_UUIE_maintainConnection = (1 << 19),
+ eFacility_UUIE_fastConnectRefused = (1 << 18),
+ eFacility_UUIE_serviceControl = (1 << 17),
+ eFacility_UUIE_circuitInfo = (1 << 16),
+ eFacility_UUIE_featureSet = (1 << 15),
+ eFacility_UUIE_destinationInfo = (1 << 14),
+ eFacility_UUIE_h245SecurityMode = (1 << 13),
+ } options;
+ FacilityReason reason;
+ TransportAddress h245Address;
+ Facility_UUIE_fastStart fastStart;
+} Facility_UUIE;
+
+typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */
+ int count;
+ OpenLogicalChannel item[30];
+} Progress_UUIE_fastStart;
+
+typedef struct Progress_UUIE { /* SEQUENCE */
+ enum {
+ eProgress_UUIE_h245Address = (1 << 31),
+ eProgress_UUIE_h245SecurityMode = (1 << 30),
+ eProgress_UUIE_tokens = (1 << 29),
+ eProgress_UUIE_cryptoTokens = (1 << 28),
+ eProgress_UUIE_fastStart = (1 << 27),
+ eProgress_UUIE_multipleCalls = (1 << 26),
+ eProgress_UUIE_maintainConnection = (1 << 25),
+ eProgress_UUIE_fastConnectRefused = (1 << 24),
+ } options;
+ TransportAddress h245Address;
+ Progress_UUIE_fastStart fastStart;
+} Progress_UUIE;
+
+typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */
+ enum {
+ eH323_UU_PDU_h323_message_body_setup,
+ eH323_UU_PDU_h323_message_body_callProceeding,
+ eH323_UU_PDU_h323_message_body_connect,
+ eH323_UU_PDU_h323_message_body_alerting,
+ eH323_UU_PDU_h323_message_body_information,
+ eH323_UU_PDU_h323_message_body_releaseComplete,
+ eH323_UU_PDU_h323_message_body_facility,
+ eH323_UU_PDU_h323_message_body_progress,
+ eH323_UU_PDU_h323_message_body_empty,
+ eH323_UU_PDU_h323_message_body_status,
+ eH323_UU_PDU_h323_message_body_statusInquiry,
+ eH323_UU_PDU_h323_message_body_setupAcknowledge,
+ eH323_UU_PDU_h323_message_body_notify,
+ } choice;
+ union {
+ Setup_UUIE setup;
+ CallProceeding_UUIE callProceeding;
+ Connect_UUIE connect;
+ Alerting_UUIE alerting;
+ Information_UUIE information;
+ Facility_UUIE facility;
+ Progress_UUIE progress;
+ };
+} H323_UU_PDU_h323_message_body;
+
+typedef struct RequestMessage { /* CHOICE */
+ enum {
+ eRequestMessage_nonStandard,
+ eRequestMessage_masterSlaveDetermination,
+ eRequestMessage_terminalCapabilitySet,
+ eRequestMessage_openLogicalChannel,
+ eRequestMessage_closeLogicalChannel,
+ eRequestMessage_requestChannelClose,
+ eRequestMessage_multiplexEntrySend,
+ eRequestMessage_requestMultiplexEntry,
+ eRequestMessage_requestMode,
+ eRequestMessage_roundTripDelayRequest,
+ eRequestMessage_maintenanceLoopRequest,
+ eRequestMessage_communicationModeRequest,
+ eRequestMessage_conferenceRequest,
+ eRequestMessage_multilinkRequest,
+ eRequestMessage_logicalChannelRateRequest,
+ } choice;
+ union {
+ OpenLogicalChannel openLogicalChannel;
+ };
+} RequestMessage;
+
+typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
+ } choice;
+ union {
+ H2250LogicalChannelParameters h2250LogicalChannelParameters;
+ };
+} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters;
+
+typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber
+ = (1 << 31),
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
+ = (1 << 30),
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor
+ = (1 << 29),
+ } options;
+ OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
+ multiplexParameters;
+} OpenLogicalChannelAck_reverseLogicalChannelParameters;
+
+typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */
+ enum {
+ eH2250LogicalChannelAckParameters_nonStandard = (1 << 31),
+ eH2250LogicalChannelAckParameters_sessionID = (1 << 30),
+ eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29),
+ eH2250LogicalChannelAckParameters_mediaControlChannel =
+ (1 << 28),
+ eH2250LogicalChannelAckParameters_dynamicRTPPayloadType =
+ (1 << 27),
+ eH2250LogicalChannelAckParameters_flowControlToZero =
+ (1 << 26),
+ eH2250LogicalChannelAckParameters_portNumber = (1 << 25),
+ } options;
+ H245_TransportAddress mediaChannel;
+ H245_TransportAddress mediaControlChannel;
+} H2250LogicalChannelAckParameters;
+
+typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */
+ enum {
+ eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters,
+ } choice;
+ union {
+ H2250LogicalChannelAckParameters
+ h2250LogicalChannelAckParameters;
+ };
+} OpenLogicalChannelAck_forwardMultiplexAckParameters;
+
+typedef struct OpenLogicalChannelAck { /* SEQUENCE */
+ enum {
+ eOpenLogicalChannelAck_reverseLogicalChannelParameters =
+ (1 << 31),
+ eOpenLogicalChannelAck_separateStack = (1 << 30),
+ eOpenLogicalChannelAck_forwardMultiplexAckParameters =
+ (1 << 29),
+ eOpenLogicalChannelAck_encryptionSync = (1 << 28),
+ } options;
+ OpenLogicalChannelAck_reverseLogicalChannelParameters
+ reverseLogicalChannelParameters;
+ OpenLogicalChannelAck_forwardMultiplexAckParameters
+ forwardMultiplexAckParameters;
+} OpenLogicalChannelAck;
+
+typedef struct ResponseMessage { /* CHOICE */
+ enum {
+ eResponseMessage_nonStandard,
+ eResponseMessage_masterSlaveDeterminationAck,
+ eResponseMessage_masterSlaveDeterminationReject,
+ eResponseMessage_terminalCapabilitySetAck,
+ eResponseMessage_terminalCapabilitySetReject,
+ eResponseMessage_openLogicalChannelAck,
+ eResponseMessage_openLogicalChannelReject,
+ eResponseMessage_closeLogicalChannelAck,
+ eResponseMessage_requestChannelCloseAck,
+ eResponseMessage_requestChannelCloseReject,
+ eResponseMessage_multiplexEntrySendAck,
+ eResponseMessage_multiplexEntrySendReject,
+ eResponseMessage_requestMultiplexEntryAck,
+ eResponseMessage_requestMultiplexEntryReject,
+ eResponseMessage_requestModeAck,
+ eResponseMessage_requestModeReject,
+ eResponseMessage_roundTripDelayResponse,
+ eResponseMessage_maintenanceLoopAck,
+ eResponseMessage_maintenanceLoopReject,
+ eResponseMessage_communicationModeResponse,
+ eResponseMessage_conferenceResponse,
+ eResponseMessage_multilinkResponse,
+ eResponseMessage_logicalChannelRateAcknowledge,
+ eResponseMessage_logicalChannelRateReject,
+ } choice;
+ union {
+ OpenLogicalChannelAck openLogicalChannelAck;
+ };
+} ResponseMessage;
+
+typedef struct MultimediaSystemControlMessage { /* CHOICE */
+ enum {
+ eMultimediaSystemControlMessage_request,
+ eMultimediaSystemControlMessage_response,
+ eMultimediaSystemControlMessage_command,
+ eMultimediaSystemControlMessage_indication,
+ } choice;
+ union {
+ RequestMessage request;
+ ResponseMessage response;
+ };
+} MultimediaSystemControlMessage;
+
+typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */
+ int count;
+ MultimediaSystemControlMessage item[4];
+} H323_UU_PDU_h245Control;
+
+typedef struct H323_UU_PDU { /* SEQUENCE */
+ enum {
+ eH323_UU_PDU_nonStandardData = (1 << 31),
+ eH323_UU_PDU_h4501SupplementaryService = (1 << 30),
+ eH323_UU_PDU_h245Tunneling = (1 << 29),
+ eH323_UU_PDU_h245Control = (1 << 28),
+ eH323_UU_PDU_nonStandardControl = (1 << 27),
+ eH323_UU_PDU_callLinkage = (1 << 26),
+ eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25),
+ eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24),
+ eH323_UU_PDU_stimulusControl = (1 << 23),
+ eH323_UU_PDU_genericData = (1 << 22),
+ } options;
+ H323_UU_PDU_h323_message_body h323_message_body;
+ H323_UU_PDU_h245Control h245Control;
+} H323_UU_PDU;
+
+typedef struct H323_UserInformation { /* SEQUENCE */
+ enum {
+ eH323_UserInformation_user_data = (1 << 31),
+ } options;
+ H323_UU_PDU h323_uu_pdu;
+} H323_UserInformation;
+
+typedef struct GatekeeperRequest { /* SEQUENCE */
+ enum {
+ eGatekeeperRequest_nonStandardData = (1 << 31),
+ eGatekeeperRequest_gatekeeperIdentifier = (1 << 30),
+ eGatekeeperRequest_callServices = (1 << 29),
+ eGatekeeperRequest_endpointAlias = (1 << 28),
+ eGatekeeperRequest_alternateEndpoints = (1 << 27),
+ eGatekeeperRequest_tokens = (1 << 26),
+ eGatekeeperRequest_cryptoTokens = (1 << 25),
+ eGatekeeperRequest_authenticationCapability = (1 << 24),
+ eGatekeeperRequest_algorithmOIDs = (1 << 23),
+ eGatekeeperRequest_integrity = (1 << 22),
+ eGatekeeperRequest_integrityCheckValue = (1 << 21),
+ eGatekeeperRequest_supportsAltGK = (1 << 20),
+ eGatekeeperRequest_featureSet = (1 << 19),
+ eGatekeeperRequest_genericData = (1 << 18),
+ } options;
+ TransportAddress rasAddress;
+} GatekeeperRequest;
+
+typedef struct GatekeeperConfirm { /* SEQUENCE */
+ enum {
+ eGatekeeperConfirm_nonStandardData = (1 << 31),
+ eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30),
+ eGatekeeperConfirm_alternateGatekeeper = (1 << 29),
+ eGatekeeperConfirm_authenticationMode = (1 << 28),
+ eGatekeeperConfirm_tokens = (1 << 27),
+ eGatekeeperConfirm_cryptoTokens = (1 << 26),
+ eGatekeeperConfirm_algorithmOID = (1 << 25),
+ eGatekeeperConfirm_integrity = (1 << 24),
+ eGatekeeperConfirm_integrityCheckValue = (1 << 23),
+ eGatekeeperConfirm_featureSet = (1 << 22),
+ eGatekeeperConfirm_genericData = (1 << 21),
+ } options;
+ TransportAddress rasAddress;
+} GatekeeperConfirm;
+
+typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} RegistrationRequest_callSignalAddress;
+
+typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} RegistrationRequest_rasAddress;
+
+typedef struct RegistrationRequest { /* SEQUENCE */
+ enum {
+ eRegistrationRequest_nonStandardData = (1 << 31),
+ eRegistrationRequest_terminalAlias = (1 << 30),
+ eRegistrationRequest_gatekeeperIdentifier = (1 << 29),
+ eRegistrationRequest_alternateEndpoints = (1 << 28),
+ eRegistrationRequest_timeToLive = (1 << 27),
+ eRegistrationRequest_tokens = (1 << 26),
+ eRegistrationRequest_cryptoTokens = (1 << 25),
+ eRegistrationRequest_integrityCheckValue = (1 << 24),
+ eRegistrationRequest_keepAlive = (1 << 23),
+ eRegistrationRequest_endpointIdentifier = (1 << 22),
+ eRegistrationRequest_willSupplyUUIEs = (1 << 21),
+ eRegistrationRequest_maintainConnection = (1 << 20),
+ eRegistrationRequest_alternateTransportAddresses = (1 << 19),
+ eRegistrationRequest_additiveRegistration = (1 << 18),
+ eRegistrationRequest_terminalAliasPattern = (1 << 17),
+ eRegistrationRequest_supportsAltGK = (1 << 16),
+ eRegistrationRequest_usageReportingCapability = (1 << 15),
+ eRegistrationRequest_multipleCalls = (1 << 14),
+ eRegistrationRequest_supportedH248Packages = (1 << 13),
+ eRegistrationRequest_callCreditCapability = (1 << 12),
+ eRegistrationRequest_capacityReportingCapability = (1 << 11),
+ eRegistrationRequest_capacity = (1 << 10),
+ eRegistrationRequest_featureSet = (1 << 9),
+ eRegistrationRequest_genericData = (1 << 8),
+ } options;
+ RegistrationRequest_callSignalAddress callSignalAddress;
+ RegistrationRequest_rasAddress rasAddress;
+ unsigned timeToLive;
+} RegistrationRequest;
+
+typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} RegistrationConfirm_callSignalAddress;
+
+typedef struct RegistrationConfirm { /* SEQUENCE */
+ enum {
+ eRegistrationConfirm_nonStandardData = (1 << 31),
+ eRegistrationConfirm_terminalAlias = (1 << 30),
+ eRegistrationConfirm_gatekeeperIdentifier = (1 << 29),
+ eRegistrationConfirm_alternateGatekeeper = (1 << 28),
+ eRegistrationConfirm_timeToLive = (1 << 27),
+ eRegistrationConfirm_tokens = (1 << 26),
+ eRegistrationConfirm_cryptoTokens = (1 << 25),
+ eRegistrationConfirm_integrityCheckValue = (1 << 24),
+ eRegistrationConfirm_willRespondToIRR = (1 << 23),
+ eRegistrationConfirm_preGrantedARQ = (1 << 22),
+ eRegistrationConfirm_maintainConnection = (1 << 21),
+ eRegistrationConfirm_serviceControl = (1 << 20),
+ eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19),
+ eRegistrationConfirm_terminalAliasPattern = (1 << 18),
+ eRegistrationConfirm_supportedPrefixes = (1 << 17),
+ eRegistrationConfirm_usageSpec = (1 << 16),
+ eRegistrationConfirm_featureServerAlias = (1 << 15),
+ eRegistrationConfirm_capacityReportingSpec = (1 << 14),
+ eRegistrationConfirm_featureSet = (1 << 13),
+ eRegistrationConfirm_genericData = (1 << 12),
+ } options;
+ RegistrationConfirm_callSignalAddress callSignalAddress;
+ unsigned timeToLive;
+} RegistrationConfirm;
+
+typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} UnregistrationRequest_callSignalAddress;
+
+typedef struct UnregistrationRequest { /* SEQUENCE */
+ enum {
+ eUnregistrationRequest_endpointAlias = (1 << 31),
+ eUnregistrationRequest_nonStandardData = (1 << 30),
+ eUnregistrationRequest_endpointIdentifier = (1 << 29),
+ eUnregistrationRequest_alternateEndpoints = (1 << 28),
+ eUnregistrationRequest_gatekeeperIdentifier = (1 << 27),
+ eUnregistrationRequest_tokens = (1 << 26),
+ eUnregistrationRequest_cryptoTokens = (1 << 25),
+ eUnregistrationRequest_integrityCheckValue = (1 << 24),
+ eUnregistrationRequest_reason = (1 << 23),
+ eUnregistrationRequest_endpointAliasPattern = (1 << 22),
+ eUnregistrationRequest_supportedPrefixes = (1 << 21),
+ eUnregistrationRequest_alternateGatekeeper = (1 << 20),
+ eUnregistrationRequest_genericData = (1 << 19),
+ } options;
+ UnregistrationRequest_callSignalAddress callSignalAddress;
+} UnregistrationRequest;
+
+typedef struct AdmissionRequest { /* SEQUENCE */
+ enum {
+ eAdmissionRequest_callModel = (1 << 31),
+ eAdmissionRequest_destinationInfo = (1 << 30),
+ eAdmissionRequest_destCallSignalAddress = (1 << 29),
+ eAdmissionRequest_destExtraCallInfo = (1 << 28),
+ eAdmissionRequest_srcCallSignalAddress = (1 << 27),
+ eAdmissionRequest_nonStandardData = (1 << 26),
+ eAdmissionRequest_callServices = (1 << 25),
+ eAdmissionRequest_canMapAlias = (1 << 24),
+ eAdmissionRequest_callIdentifier = (1 << 23),
+ eAdmissionRequest_srcAlternatives = (1 << 22),
+ eAdmissionRequest_destAlternatives = (1 << 21),
+ eAdmissionRequest_gatekeeperIdentifier = (1 << 20),
+ eAdmissionRequest_tokens = (1 << 19),
+ eAdmissionRequest_cryptoTokens = (1 << 18),
+ eAdmissionRequest_integrityCheckValue = (1 << 17),
+ eAdmissionRequest_transportQOS = (1 << 16),
+ eAdmissionRequest_willSupplyUUIEs = (1 << 15),
+ eAdmissionRequest_callLinkage = (1 << 14),
+ eAdmissionRequest_gatewayDataRate = (1 << 13),
+ eAdmissionRequest_capacity = (1 << 12),
+ eAdmissionRequest_circuitInfo = (1 << 11),
+ eAdmissionRequest_desiredProtocols = (1 << 10),
+ eAdmissionRequest_desiredTunnelledProtocol = (1 << 9),
+ eAdmissionRequest_featureSet = (1 << 8),
+ eAdmissionRequest_genericData = (1 << 7),
+ } options;
+ TransportAddress destCallSignalAddress;
+ TransportAddress srcCallSignalAddress;
+} AdmissionRequest;
+
+typedef struct AdmissionConfirm { /* SEQUENCE */
+ enum {
+ eAdmissionConfirm_irrFrequency = (1 << 31),
+ eAdmissionConfirm_nonStandardData = (1 << 30),
+ eAdmissionConfirm_destinationInfo = (1 << 29),
+ eAdmissionConfirm_destExtraCallInfo = (1 << 28),
+ eAdmissionConfirm_destinationType = (1 << 27),
+ eAdmissionConfirm_remoteExtensionAddress = (1 << 26),
+ eAdmissionConfirm_alternateEndpoints = (1 << 25),
+ eAdmissionConfirm_tokens = (1 << 24),
+ eAdmissionConfirm_cryptoTokens = (1 << 23),
+ eAdmissionConfirm_integrityCheckValue = (1 << 22),
+ eAdmissionConfirm_transportQOS = (1 << 21),
+ eAdmissionConfirm_willRespondToIRR = (1 << 20),
+ eAdmissionConfirm_uuiesRequested = (1 << 19),
+ eAdmissionConfirm_language = (1 << 18),
+ eAdmissionConfirm_alternateTransportAddresses = (1 << 17),
+ eAdmissionConfirm_useSpecifiedTransport = (1 << 16),
+ eAdmissionConfirm_circuitInfo = (1 << 15),
+ eAdmissionConfirm_usageSpec = (1 << 14),
+ eAdmissionConfirm_supportedProtocols = (1 << 13),
+ eAdmissionConfirm_serviceControl = (1 << 12),
+ eAdmissionConfirm_multipleCalls = (1 << 11),
+ eAdmissionConfirm_featureSet = (1 << 10),
+ eAdmissionConfirm_genericData = (1 << 9),
+ } options;
+ TransportAddress destCallSignalAddress;
+} AdmissionConfirm;
+
+typedef struct LocationRequest { /* SEQUENCE */
+ enum {
+ eLocationRequest_endpointIdentifier = (1 << 31),
+ eLocationRequest_nonStandardData = (1 << 30),
+ eLocationRequest_sourceInfo = (1 << 29),
+ eLocationRequest_canMapAlias = (1 << 28),
+ eLocationRequest_gatekeeperIdentifier = (1 << 27),
+ eLocationRequest_tokens = (1 << 26),
+ eLocationRequest_cryptoTokens = (1 << 25),
+ eLocationRequest_integrityCheckValue = (1 << 24),
+ eLocationRequest_desiredProtocols = (1 << 23),
+ eLocationRequest_desiredTunnelledProtocol = (1 << 22),
+ eLocationRequest_featureSet = (1 << 21),
+ eLocationRequest_genericData = (1 << 20),
+ eLocationRequest_hopCount = (1 << 19),
+ eLocationRequest_circuitInfo = (1 << 18),
+ } options;
+ TransportAddress replyAddress;
+} LocationRequest;
+
+typedef struct LocationConfirm { /* SEQUENCE */
+ enum {
+ eLocationConfirm_nonStandardData = (1 << 31),
+ eLocationConfirm_destinationInfo = (1 << 30),
+ eLocationConfirm_destExtraCallInfo = (1 << 29),
+ eLocationConfirm_destinationType = (1 << 28),
+ eLocationConfirm_remoteExtensionAddress = (1 << 27),
+ eLocationConfirm_alternateEndpoints = (1 << 26),
+ eLocationConfirm_tokens = (1 << 25),
+ eLocationConfirm_cryptoTokens = (1 << 24),
+ eLocationConfirm_integrityCheckValue = (1 << 23),
+ eLocationConfirm_alternateTransportAddresses = (1 << 22),
+ eLocationConfirm_supportedProtocols = (1 << 21),
+ eLocationConfirm_multipleCalls = (1 << 20),
+ eLocationConfirm_featureSet = (1 << 19),
+ eLocationConfirm_genericData = (1 << 18),
+ eLocationConfirm_circuitInfo = (1 << 17),
+ eLocationConfirm_serviceControl = (1 << 16),
+ } options;
+ TransportAddress callSignalAddress;
+ TransportAddress rasAddress;
+} LocationConfirm;
+
+typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */
+ int count;
+ TransportAddress item[10];
+} InfoRequestResponse_callSignalAddress;
+
+typedef struct InfoRequestResponse { /* SEQUENCE */
+ enum {
+ eInfoRequestResponse_nonStandardData = (1 << 31),
+ eInfoRequestResponse_endpointAlias = (1 << 30),
+ eInfoRequestResponse_perCallInfo = (1 << 29),
+ eInfoRequestResponse_tokens = (1 << 28),
+ eInfoRequestResponse_cryptoTokens = (1 << 27),
+ eInfoRequestResponse_integrityCheckValue = (1 << 26),
+ eInfoRequestResponse_needResponse = (1 << 25),
+ eInfoRequestResponse_capacity = (1 << 24),
+ eInfoRequestResponse_irrStatus = (1 << 23),
+ eInfoRequestResponse_unsolicited = (1 << 22),
+ eInfoRequestResponse_genericData = (1 << 21),
+ } options;
+ TransportAddress rasAddress;
+ InfoRequestResponse_callSignalAddress callSignalAddress;
+} InfoRequestResponse;
+
+typedef struct RasMessage { /* CHOICE */
+ enum {
+ eRasMessage_gatekeeperRequest,
+ eRasMessage_gatekeeperConfirm,
+ eRasMessage_gatekeeperReject,
+ eRasMessage_registrationRequest,
+ eRasMessage_registrationConfirm,
+ eRasMessage_registrationReject,
+ eRasMessage_unregistrationRequest,
+ eRasMessage_unregistrationConfirm,
+ eRasMessage_unregistrationReject,
+ eRasMessage_admissionRequest,
+ eRasMessage_admissionConfirm,
+ eRasMessage_admissionReject,
+ eRasMessage_bandwidthRequest,
+ eRasMessage_bandwidthConfirm,
+ eRasMessage_bandwidthReject,
+ eRasMessage_disengageRequest,
+ eRasMessage_disengageConfirm,
+ eRasMessage_disengageReject,
+ eRasMessage_locationRequest,
+ eRasMessage_locationConfirm,
+ eRasMessage_locationReject,
+ eRasMessage_infoRequest,
+ eRasMessage_infoRequestResponse,
+ eRasMessage_nonStandardMessage,
+ eRasMessage_unknownMessageResponse,
+ eRasMessage_requestInProgress,
+ eRasMessage_resourcesAvailableIndicate,
+ eRasMessage_resourcesAvailableConfirm,
+ eRasMessage_infoRequestAck,
+ eRasMessage_infoRequestNak,
+ eRasMessage_serviceControlIndication,
+ eRasMessage_serviceControlResponse,
+ } choice;
+ union {
+ GatekeeperRequest gatekeeperRequest;
+ GatekeeperConfirm gatekeeperConfirm;
+ RegistrationRequest registrationRequest;
+ RegistrationConfirm registrationConfirm;
+ UnregistrationRequest unregistrationRequest;
+ AdmissionRequest admissionRequest;
+ AdmissionConfirm admissionConfirm;
+ LocationRequest locationRequest;
+ LocationConfirm locationConfirm;
+ InfoRequestResponse infoRequestResponse;
+ };
+} RasMessage;
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
new file mode 100644
index 0000000..1d60c6e
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -0,0 +1,605 @@
+/*
+ * H.323 extension for NAT alteration.
+ *
+ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
+ *
+ * This source code is licensed under General Public License version 2.
+ *
+ * Based on the 'brute force' H.323 NAT module by
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * Changes:
+ * 2006-02-01 - initial version 0.1
+ *
+ * 2006-02-20 - version 0.2
+ * 1. Changed source format to follow kernel conventions
+ * 2. Deleted some unnecessary structures
+ * 3. Minor fixes
+ *
+ * 2006-03-10 - version 0.3
+ * 1. Added support for multiple TPKTs in one packet (suggested by
+ * Patrick McHardy)
+ * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
+ * 3. Eliminated unnecessary return code
+ *
+ * 2006-03-15 - version 0.4
+ * 1. Added support for T.120 channels
+ * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/moduleparam.h>
+#include <net/tcp.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+#include "ip_conntrack_helper_h323_asn1.h"
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port);
+extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
+ u_int32_t * ip, u_int16_t * port);
+extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this);
+extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr,
+ u_int32_t ip, u_int16_t port);
+extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count);
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
+ struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int16_t port, u_int16_t rtp_port,
+ struct ip_conntrack_expect * rtp_exp,
+ struct ip_conntrack_expect * rtcp_exp);
+extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress * addr,
+ int idx, u_int16_t port,
+ struct ip_conntrack_expect * exp);
+
+
+/****************************************************************************/
+static int set_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ unsigned int addroff, u_int32_t ip, u_int16_t port)
+{
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
+ struct {
+ u_int32_t ip;
+ u_int16_t port;
+ } __attribute__ ((__packed__)) buf;
+ struct tcphdr _tcph, *th;
+
+ buf.ip = ip;
+ buf.port = htons(port);
+ addroff += dataoff;
+
+ if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ addroff, sizeof(buf),
+ (char *) &buf, sizeof(buf))) {
+ if (net_ratelimit())
+ printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
+ " error\n");
+ return -1;
+ }
+
+ /* Relocate data pointer */
+ th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
+ sizeof(_tcph), &_tcph);
+ if (th == NULL)
+ return -1;
+ *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
+ th->doff * 4 + dataoff;
+ } else {
+ if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+ addroff, sizeof(buf),
+ (char *) &buf, sizeof(buf))) {
+ if (net_ratelimit())
+ printk("ip_nat_h323: ip_nat_mangle_udp_packet"
+ " error\n");
+ return -1;
+ }
+ /* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
+ * or pull everything in a linear buffer, so we can safely
+ * use the skb pointers now */
+ *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
+ sizeof(struct udphdr);
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int set_h225_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr,
+ u_int32_t ip, u_int16_t port)
+{
+ return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
+}
+
+/****************************************************************************/
+static int set_h245_addr(struct sk_buff **pskb,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int32_t ip, u_int16_t port)
+{
+ return set_addr(pskb, data, dataoff,
+ addr->unicastAddress.iPAddress.network, ip, port);
+}
+
+/****************************************************************************/
+static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(*data, &addr[i], &ip, &port)) {
+ if (ip == ct->tuplehash[dir].tuple.src.ip &&
+ port == info->sig_port[dir]) {
+ /* GW->GK */
+
+ /* Fix for Gnomemeeting */
+ if (i > 0 &&
+ get_h225_addr(*data, &addr[0],
+ &ip, &port) &&
+ (ntohl(ip) & 0xff000000) == 0x7f000000)
+ i = 0;
+
+ DEBUGP
+ ("ip_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.
+ ip), info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0, &addr[i],
+ ct->tuplehash[!dir].
+ tuple.dst.ip,
+ info->sig_port[!dir]);
+ } else if (ip == ct->tuplehash[dir].tuple.dst.ip &&
+ port == info->sig_port[dir]) {
+ /* GK->GW */
+ DEBUGP
+ ("ip_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.src.
+ ip), info->sig_port[!dir]);
+ return set_h225_addr(pskb, data, 0, &addr[i],
+ ct->tuplehash[!dir].
+ tuple.src.ip,
+ info->sig_port[!dir]);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data,
+ TransportAddress * addr, int count)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int32_t ip;
+ u_int16_t port;
+
+ for (i = 0; i < count; i++) {
+ if (get_h225_addr(*data, &addr[i], &ip, &port) &&
+ ip == ct->tuplehash[dir].tuple.src.ip &&
+ port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) {
+ DEBUGP("ip_nat_ras: set rasAddress "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
+ ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
+ port));
+ return set_h225_addr(pskb, data, 0, &addr[i],
+ ct->tuplehash[!dir].tuple.dst.ip,
+ ntohs(ct->tuplehash[!dir].tuple.
+ dst.u.udp.port));
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr,
+ u_int16_t port, u_int16_t rtp_port,
+ struct ip_conntrack_expect *rtp_exp,
+ struct ip_conntrack_expect *rtcp_exp)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ int i;
+ u_int16_t nated_port;
+
+ /* Set expectations for NAT */
+ rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
+ rtp_exp->expectfn = ip_nat_follow_master;
+ rtp_exp->dir = !dir;
+ rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
+ rtcp_exp->expectfn = ip_nat_follow_master;
+ rtcp_exp->dir = !dir;
+
+ /* Lookup existing expects */
+ for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
+ if (info->rtp_port[i][dir] == rtp_port) {
+ /* Expected */
+
+ /* Use allocated ports first. This will refresh
+ * the expects */
+ rtp_exp->tuple.dst.u.udp.port =
+ htons(info->rtp_port[i][dir]);
+ rtcp_exp->tuple.dst.u.udp.port =
+ htons(info->rtp_port[i][dir] + 1);
+ break;
+ } else if (info->rtp_port[i][dir] == 0) {
+ /* Not expected */
+ break;
+ }
+ }
+
+ /* Run out of expectations */
+ if (i >= H323_RTP_CHANNEL_MAX) {
+ if (net_ratelimit())
+ printk("ip_nat_h323: out of expectations\n");
+ return 0;
+ }
+
+ /* Try to get a pair of ports. */
+ for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
+ nated_port != 0; nated_port += 2) {
+ rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(rtp_exp) == 0) {
+ rtcp_exp->tuple.dst.u.udp.port =
+ htons(nated_port + 1);
+ if (ip_conntrack_expect_related(rtcp_exp) == 0)
+ break;
+ ip_conntrack_unexpect_related(rtp_exp);
+ }
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_h323: out of RTP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h245_addr(pskb, data, dataoff, addr,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ (port & 1) ? nated_port + 1 : nated_port) == 0) {
+ /* Save ports */
+ info->rtp_port[i][dir] = rtp_port;
+ info->rtp_port[i][!dir] = nated_port;
+ } else {
+ ip_conntrack_unexpect_related(rtp_exp);
+ ip_conntrack_unexpect_related(rtcp_exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("ip_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtp_exp->tuple.src.ip),
+ ntohs(rtp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtp_exp->tuple.dst.ip),
+ ntohs(rtp_exp->tuple.dst.u.udp.port));
+ DEBUGP("ip_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtcp_exp->tuple.src.ip),
+ ntohs(rtcp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtcp_exp->tuple.dst.ip),
+ ntohs(rtcp_exp->tuple.dst.u.udp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ H245_TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect *exp)
+{
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = port;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_follow_master;
+ exp->dir = !dir;
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_h323: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h245_addr(pskb, data, dataoff, addr,
+ ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) {
+ ip_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************
+ * This conntrack expect function replaces ip_conntrack_h245_expect()
+ * which was set by ip_conntrack_helper_h323.c. It calls both
+ * ip_nat_follow_master() and ip_conntrack_h245_expect()
+ ****************************************************************************/
+static void ip_nat_h245_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this)
+{
+ ip_nat_follow_master(new, this);
+ ip_conntrack_h245_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, int dataoff,
+ TransportAddress * addr, u_int16_t port,
+ struct ip_conntrack_expect *exp)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = port;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_h245_expect;
+ exp->dir = !dir;
+
+ /* Check existing expects */
+ if (info->sig_port[dir] == port)
+ nated_port = info->sig_port[!dir];
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_q931: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h225_addr(pskb, data, dataoff, addr,
+ ct->tuplehash[!dir].tuple.dst.ip,
+ nated_port) == 0) {
+ /* Save ports */
+ info->sig_port[dir] = port;
+ info->sig_port[!dir] = nated_port;
+ } else {
+ ip_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************
+ * This conntrack expect function replaces ip_conntrack_q931_expect()
+ * which was set by ip_conntrack_helper_h323.c.
+ ****************************************************************************/
+static void ip_nat_q931_expect(struct ip_conntrack *new,
+ struct ip_conntrack_expect *this)
+{
+ struct ip_nat_range range;
+
+ if (this->tuple.src.ip != 0) { /* Only accept calls from GK */
+ ip_nat_follow_master(new, this);
+ goto out;
+ }
+
+ /* This must be a fresh one. */
+ BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+ /* Change src to where master sends to */
+ range.flags = IP_NAT_RANGE_MAP_IPS;
+ range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
+
+ /* hook doesn't matter, but it has to do source manip */
+ ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+ /* For DST manip, map port here to where it's expected. */
+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+ range.min = range.max = this->saved_proto;
+ range.min_ip = range.max_ip =
+ new->master->tuplehash[!this->dir].tuple.src.ip;
+
+ /* hook doesn't matter, but it has to do destination manip */
+ ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+
+ out:
+ ip_conntrack_q931_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned char **data, TransportAddress * addr, int idx,
+ u_int16_t port, struct ip_conntrack_expect *exp)
+{
+ struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
+ int dir = CTINFO2DIR(ctinfo);
+ u_int16_t nated_port = port;
+ u_int32_t ip;
+
+ /* Set expectations for NAT */
+ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+ exp->expectfn = ip_nat_q931_expect;
+ exp->dir = !dir;
+
+ /* Check existing expects */
+ if (info->sig_port[dir] == port)
+ nated_port = info->sig_port[!dir];
+
+ /* Try to get same port: if not, try to change it. */
+ for (; nated_port != 0; nated_port++) {
+ exp->tuple.dst.u.tcp.port = htons(nated_port);
+ if (ip_conntrack_expect_related(exp) == 0)
+ break;
+ }
+
+ if (nated_port == 0) { /* No port available */
+ if (net_ratelimit())
+ printk("ip_nat_ras: out of TCP ports\n");
+ return 0;
+ }
+
+ /* Modify signal */
+ if (set_h225_addr(pskb, data, 0, &addr[idx],
+ ct->tuplehash[!dir].tuple.dst.ip,
+ nated_port) == 0) {
+ /* Save ports */
+ info->sig_port[dir] = port;
+ info->sig_port[!dir] = nated_port;
+
+ /* Fix for Gnomemeeting */
+ if (idx > 0 &&
+ get_h225_addr(*data, &addr[0], &ip, &port) &&
+ (ntohl(ip) & 0xff000000) == 0x7f000000) {
+ set_h225_addr_hook(pskb, data, 0, &addr[0],
+ ct->tuplehash[!dir].tuple.dst.ip,
+ info->sig_port[!dir]);
+ }
+ } else {
+ ip_conntrack_unexpect_related(exp);
+ return -1;
+ }
+
+ /* Success */
+ DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+ return 0;
+}
+
+/****************************************************************************/
+static int __init init(void)
+{
+ BUG_ON(set_h245_addr_hook != NULL);
+ BUG_ON(set_h225_addr_hook != NULL);
+ BUG_ON(set_sig_addr_hook != NULL);
+ BUG_ON(set_ras_addr_hook != NULL);
+ BUG_ON(nat_rtp_rtcp_hook != NULL);
+ BUG_ON(nat_t120_hook != NULL);
+ BUG_ON(nat_h245_hook != NULL);
+ BUG_ON(nat_q931_hook != NULL);
+
+ set_h245_addr_hook = set_h245_addr;
+ set_h225_addr_hook = set_h225_addr;
+ set_sig_addr_hook = set_sig_addr;
+ set_ras_addr_hook = set_ras_addr;
+ nat_rtp_rtcp_hook = nat_rtp_rtcp;
+ nat_t120_hook = nat_t120;
+ nat_h245_hook = nat_h245;
+ nat_q931_hook = nat_q931;
+
+ DEBUGP("ip_nat_h323: init success\n");
+ return 0;
+}
+
+/****************************************************************************/
+static void __exit fini(void)
+{
+ set_h245_addr_hook = NULL;
+ set_h225_addr_hook = NULL;
+ set_sig_addr_hook = NULL;
+ set_ras_addr_hook = NULL;
+ nat_rtp_rtcp_hook = NULL;
+ nat_t120_hook = NULL;
+ nat_h245_hook = NULL;
+ nat_q931_hook = NULL;
+ synchronize_net();
+}
+
+/****************************************************************************/
+module_init(init);
+module_exit(fini);
+
+MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
+MODULE_DESCRIPTION("H.323 NAT helper");
+MODULE_LICENSE("GPL");
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification
2006-03-21 1:56 ` [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification Patrick McHardy
@ 2006-03-21 2:11 ` Patrick McHardy
[not found] ` <200603211056.02339.dim@sw.ru>
0 siblings, 1 reply; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 2:11 UTC (permalink / raw)
To: davem; +Cc: dim, dev, netfilter-devel
Patrick McHardy wrote:
> [NETFILTER]: futher {ip,ip6,arp}_tables unification
>
> This patch moves {ip,ip6,arp}t_entry_{match,target} definitions to
> x_tables.h. This move simplifies code and future compatibility fixes.
Dave, please drop this patch, I just noticed it breaks ip6tables
compatibility for some yet unknown reason. Sorry for not testing
it properly before.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [NETFILTER 00/09]: Netfilter update
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
` (8 preceding siblings ...)
2006-03-21 1:56 ` [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification Patrick McHardy
@ 2006-03-21 2:18 ` Patrick McHardy
2006-03-21 7:42 ` David S. Miller
9 siblings, 1 reply; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 2:18 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel
Patrick McHardy wrote:
> Hi Dave,
>
> following are my pending netfilter patches for 2.6.17, most notable is
> a very nice and clean H.323 connection tracking helper by Jing Min Zhao.
> Please apply.
Dave, I'm sorry for the annoyance, but please drop the entire patchset
except for the H.323 helper. Something is messing up ip6tables on
one of my systems and the only thing I'm sure of is that its not the
H.323 helper :)
I'll resubmit the remaining patches once I know whats going on.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [NETFILTER 00/09]: Netfilter update
2006-03-21 2:18 ` [NETFILTER 00/09]: Netfilter update Patrick McHardy
@ 2006-03-21 7:42 ` David S. Miller
2006-03-21 8:56 ` Patrick McHardy
0 siblings, 1 reply; 18+ messages in thread
From: David S. Miller @ 2006-03-21 7:42 UTC (permalink / raw)
To: kaber; +Cc: netfilter-devel
From: Patrick McHardy <kaber@trash.net>
Date: Tue, 21 Mar 2006 03:18:40 +0100
> Dave, I'm sorry for the annoyance, but please drop the entire patchset
> except for the H.323 helper. Something is messing up ip6tables on
> one of my systems and the only thing I'm sure of is that its not the
> H.323 helper :)
>
> I'll resubmit the remaining patches once I know whats going on.
Ok, but please kill trailing whitespace in patches, GIT even warns
about this now and you can check and fix it up before applying a patch
by using:
git apply --check --whitespace=error-all
So, for example, on this H323 patch we get:
+ git apply --check --whitespace=error-all diff
Adds trailing whitespace.
diff:73:
Adds trailing whitespace.
diff:146: *
Adds trailing whitespace.
diff:156: *
Adds trailing whitespace.
diff:171: *
Adds trailing whitespace.
diff:5747: *
fatal: 5 lines add trailing whitespaces.
I fixed it up by hand this time, but I may stop doing so in
the future and push it back to you instead :-)
Thanks!
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [NETFILTER 00/09]: Netfilter update
2006-03-21 7:42 ` David S. Miller
@ 2006-03-21 8:56 ` Patrick McHardy
0 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 8:56 UTC (permalink / raw)
To: David S. Miller; +Cc: netfilter-devel
David S. Miller wrote:
> Ok, but please kill trailing whitespace in patches, GIT even warns
> about this now and you can check and fix it up before applying a patch
> by using:
>
> git apply --check --whitespace=error-all
>
> So, for example, on this H323 patch we get:
>
> + git apply --check --whitespace=error-all diff
> Adds trailing whitespace.
> diff:73:
> Adds trailing whitespace.
> diff:146: *
> Adds trailing whitespace.
> diff:156: *
> Adds trailing whitespace.
> diff:171: *
> Adds trailing whitespace.
> diff:5747: *
> fatal: 5 lines add trailing whitespaces.
>
> I fixed it up by hand this time, but I may stop doing so in
> the future and push it back to you instead :-)
Thanks. Actually my scripts are supposed to take care of that (and
usually do), but I seem to have had bad fortune yesterday :)
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification
[not found] ` <200603211056.02339.dim@sw.ru>
@ 2006-03-21 8:59 ` Patrick McHardy
2006-03-21 9:21 ` Dmitry Mishin
0 siblings, 1 reply; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 8:59 UTC (permalink / raw)
To: Dmitry Mishin; +Cc: dev, netfilter-devel, davem
Dmitry Mishin wrote:
> Could you give more details on it in order to avoid such confusion next time?
Sorry, I haven't figured out the problem yet, but it seems your
patch wasn't responsible. Anyway, I'll fix it once I figure it
out, so don't worry.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification
2006-03-21 8:59 ` Patrick McHardy
@ 2006-03-21 9:21 ` Dmitry Mishin
2006-03-21 13:12 ` Patrick McHardy
0 siblings, 1 reply; 18+ messages in thread
From: Dmitry Mishin @ 2006-03-21 9:21 UTC (permalink / raw)
To: Patrick McHardy; +Cc: dev, netfilter-devel, davem
On Tuesday 21 March 2006 11:59, Patrick McHardy wrote:
> Dmitry Mishin wrote:
> > Could you give more details on it in order to avoid such confusion next
> > time?
>
> Sorry, I haven't figured out the problem yet, but it seems your
> patch wasn't responsible. Anyway, I'll fix it once I figure it
> out, so don't worry.
Could it be due to alignment checks in user or kernel space? I don't check it,
but think that current ip6_tables compatibility layer isn't sufficient, as it
is for ip_tables compatibility.
Quoting my answer from the respective discussion:
"
> What is the reason that you did not just address this in the
> compat_sys_setsockopt implementation?
Code above doesn't work. iptables with version >= 1.3 does alignment checks as
well as kernel does. So, we can't simply put entries with 8 bytes alignment
to userspace or with 4 bytes alignment to kernel - we need translate them
entry by entry. So, I tried to do this the most correct way - that userspace
will hide its alignment from kernel and vice versa, with not only
SET_REPLACE, but also GET_INFO, GET_ENTRIES and SET_COUNTERS translation.
"
--
Thanks,
Dmitry.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification
2006-03-21 9:21 ` Dmitry Mishin
@ 2006-03-21 13:12 ` Patrick McHardy
0 siblings, 0 replies; 18+ messages in thread
From: Patrick McHardy @ 2006-03-21 13:12 UTC (permalink / raw)
To: Dmitry Mishin; +Cc: dev, netfilter-devel, davem
[-- Attachment #1: Type: text/plain, Size: 618 bytes --]
Dmitry Mishin wrote:
> On Tuesday 21 March 2006 11:59, Patrick McHardy wrote:
>
>>Sorry, I haven't figured out the problem yet, but it seems your
>>patch wasn't responsible. Anyway, I'll fix it once I figure it
>>out, so don't worry.
>
> Could it be due to alignment checks in user or kernel space? I don't check it,
> but think that current ip6_tables compatibility layer isn't sufficient, as it
> is for ip_tables compatibility.
No, the problem is that nf_getsockopt is not called anymore because
do_ipv6_getsockopt doesn't return -ENOPROTOOPT but -EINVAL for
unknown options. I've queued this patch to fix it.
[-- Attachment #2: diff --]
[-- Type: text/plain, Size: 905 bytes --]
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 602feec..4c20eeb 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -907,7 +907,7 @@ int ipv6_getsockopt(struct sock *sk, int
err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible EINVALs except default case */
- if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM &&
+ if (err == -EINVAL && optname != IPV6_ADDRFORM &&
optname != MCAST_MSFILTER) {
int len;
@@ -944,7 +944,7 @@ int compat_ipv6_getsockopt(struct sock *
err = do_ipv6_getsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_NETFILTER
/* we need to exclude all possible EINVALs except default case */
- if (err == -ENOPROTOOPT && optname != IPV6_ADDRFORM &&
+ if (err == -EINVAL && optname != IPV6_ADDRFORM &&
optname != MCAST_MSFILTER) {
int len;
^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2006-03-21 13:12 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-21 1:55 [NETFILTER 00/09]: Netfilter update Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 01/09]: Fix Kconfig typos Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 02/09]: ctnetlink: Fix expectaction mask dumping Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 03/09]: nfnetlink_queue: fix nfnetlink message size Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 04/09]: conntrack: cleanup the conntrack ID initialization Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 05/09]: x_tables: set the protocol family in x_tables targets/matches Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 06/09]: nf_conntrack: support for layer 3 protocol load on demand Patrick McHardy
2006-03-21 1:55 ` [NETFILTER 07/09]: Fix xt_policy address matching Patrick McHardy
2006-03-21 1:56 ` [NETFILTER 08/09]: Add H.323 conntrack/NAT helper Patrick McHardy
2006-03-21 2:03 ` Patrick McHardy
2006-03-21 1:56 ` [NETFILTER 09/09]: futher {ip,ip6,arp}_tables unification Patrick McHardy
2006-03-21 2:11 ` Patrick McHardy
[not found] ` <200603211056.02339.dim@sw.ru>
2006-03-21 8:59 ` Patrick McHardy
2006-03-21 9:21 ` Dmitry Mishin
2006-03-21 13:12 ` Patrick McHardy
2006-03-21 2:18 ` [NETFILTER 00/09]: Netfilter update Patrick McHardy
2006-03-21 7:42 ` David S. Miller
2006-03-21 8:56 ` Patrick McHardy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.