aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/af_inet.c120
-rw-r--r--net/ipv4/ah4.c1
-rw-r--r--net/ipv4/arp.c20
-rw-r--r--net/ipv4/devinet.c8
-rw-r--r--net/ipv4/esp4.c1
-rw-r--r--net/ipv4/fib_rules.c140
-rw-r--r--net/ipv4/fib_trie.c24
-rw-r--r--net/ipv4/igmp.c26
-rw-r--r--net/ipv4/inet_connection_sock.c49
-rw-r--r--net/ipv4/ip_output.c6
-rw-r--r--net/ipv4/ip_sockglue.c170
-rw-r--r--net/ipv4/ipcomp.c17
-rw-r--r--net/ipv4/ipconfig.c10
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c19
-rw-r--r--net/ipv4/netfilter/Kconfig36
-rw-r--r--net/ipv4/netfilter/Makefile6
-rw-r--r--net/ipv4/netfilter/arp_tables.c27
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c1731
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c870
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h98
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.c1926
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.h938
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c79
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c605
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c45
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c5
-rw-r--r--net/ipv4/netfilter/ip_queue.c11
-rw-r--r--net/ipv4/netfilter/ip_tables.c84
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c27
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c17
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c18
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c11
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c18
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c19
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c17
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c28
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c19
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c16
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c17
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c25
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c12
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c20
-rw-r--r--net/ipv4/netfilter/ipt_ah.c25
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c19
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c14
-rw-r--r--net/ipv4/netfilter/ipt_esp.c25
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c21
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c28
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c31
-rw-r--r--net/ipv4/netfilter/ipt_owner.c21
-rw-r--r--net/ipv4/netfilter/ipt_policy.c176
-rw-r--r--net/ipv4/netfilter/ipt_recent.c22
-rw-r--r--net/ipv4/netfilter/ipt_tos.c18
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c19
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c23
-rw-r--r--net/ipv4/raw.c80
-rw-r--r--net/ipv4/sysctl_net_ipv4.c25
-rw-r--r--net/ipv4/tcp.c63
-rw-r--r--net/ipv4/tcp_htcp.c66
-rw-r--r--net/ipv4/tcp_input.c49
-rw-r--r--net/ipv4/tcp_ipv4.c44
-rw-r--r--net/ipv4/tcp_output.c259
-rw-r--r--net/ipv4/tcp_timer.c36
-rw-r--r--net/ipv4/udp.c83
-rw-r--r--net/ipv4/xfrm4_tunnel.c11
69 files changed, 7525 insertions, 1008 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 97c276f95b35..dc206f1f914f 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -788,45 +788,53 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
788} 788}
789 789
790const struct proto_ops inet_stream_ops = { 790const struct proto_ops inet_stream_ops = {
791 .family = PF_INET, 791 .family = PF_INET,
792 .owner = THIS_MODULE, 792 .owner = THIS_MODULE,
793 .release = inet_release, 793 .release = inet_release,
794 .bind = inet_bind, 794 .bind = inet_bind,
795 .connect = inet_stream_connect, 795 .connect = inet_stream_connect,
796 .socketpair = sock_no_socketpair, 796 .socketpair = sock_no_socketpair,
797 .accept = inet_accept, 797 .accept = inet_accept,
798 .getname = inet_getname, 798 .getname = inet_getname,
799 .poll = tcp_poll, 799 .poll = tcp_poll,
800 .ioctl = inet_ioctl, 800 .ioctl = inet_ioctl,
801 .listen = inet_listen, 801 .listen = inet_listen,
802 .shutdown = inet_shutdown, 802 .shutdown = inet_shutdown,
803 .setsockopt = sock_common_setsockopt, 803 .setsockopt = sock_common_setsockopt,
804 .getsockopt = sock_common_getsockopt, 804 .getsockopt = sock_common_getsockopt,
805 .sendmsg = inet_sendmsg, 805 .sendmsg = inet_sendmsg,
806 .recvmsg = sock_common_recvmsg, 806 .recvmsg = sock_common_recvmsg,
807 .mmap = sock_no_mmap, 807 .mmap = sock_no_mmap,
808 .sendpage = tcp_sendpage 808 .sendpage = tcp_sendpage,
809#ifdef CONFIG_COMPAT
810 .compat_setsockopt = compat_sock_common_setsockopt,
811 .compat_getsockopt = compat_sock_common_getsockopt,
812#endif
809}; 813};
810 814
811const struct proto_ops inet_dgram_ops = { 815const struct proto_ops inet_dgram_ops = {
812 .family = PF_INET, 816 .family = PF_INET,
813 .owner = THIS_MODULE, 817 .owner = THIS_MODULE,
814 .release = inet_release, 818 .release = inet_release,
815 .bind = inet_bind, 819 .bind = inet_bind,
816 .connect = inet_dgram_connect, 820 .connect = inet_dgram_connect,
817 .socketpair = sock_no_socketpair, 821 .socketpair = sock_no_socketpair,
818 .accept = sock_no_accept, 822 .accept = sock_no_accept,
819 .getname = inet_getname, 823 .getname = inet_getname,
820 .poll = udp_poll, 824 .poll = udp_poll,
821 .ioctl = inet_ioctl, 825 .ioctl = inet_ioctl,
822 .listen = sock_no_listen, 826 .listen = sock_no_listen,
823 .shutdown = inet_shutdown, 827 .shutdown = inet_shutdown,
824 .setsockopt = sock_common_setsockopt, 828 .setsockopt = sock_common_setsockopt,
825 .getsockopt = sock_common_getsockopt, 829 .getsockopt = sock_common_getsockopt,
826 .sendmsg = inet_sendmsg, 830 .sendmsg = inet_sendmsg,
827 .recvmsg = sock_common_recvmsg, 831 .recvmsg = sock_common_recvmsg,
828 .mmap = sock_no_mmap, 832 .mmap = sock_no_mmap,
829 .sendpage = inet_sendpage, 833 .sendpage = inet_sendpage,
834#ifdef CONFIG_COMPAT
835 .compat_setsockopt = compat_sock_common_setsockopt,
836 .compat_getsockopt = compat_sock_common_getsockopt,
837#endif
830}; 838};
831 839
832/* 840/*
@@ -834,24 +842,28 @@ const struct proto_ops inet_dgram_ops = {
834 * udp_poll 842 * udp_poll
835 */ 843 */
836static const struct proto_ops inet_sockraw_ops = { 844static const struct proto_ops inet_sockraw_ops = {
837 .family = PF_INET, 845 .family = PF_INET,
838 .owner = THIS_MODULE, 846 .owner = THIS_MODULE,
839 .release = inet_release, 847 .release = inet_release,
840 .bind = inet_bind, 848 .bind = inet_bind,
841 .connect = inet_dgram_connect, 849 .connect = inet_dgram_connect,
842 .socketpair = sock_no_socketpair, 850 .socketpair = sock_no_socketpair,
843 .accept = sock_no_accept, 851 .accept = sock_no_accept,
844 .getname = inet_getname, 852 .getname = inet_getname,
845 .poll = datagram_poll, 853 .poll = datagram_poll,
846 .ioctl = inet_ioctl, 854 .ioctl = inet_ioctl,
847 .listen = sock_no_listen, 855 .listen = sock_no_listen,
848 .shutdown = inet_shutdown, 856 .shutdown = inet_shutdown,
849 .setsockopt = sock_common_setsockopt, 857 .setsockopt = sock_common_setsockopt,
850 .getsockopt = sock_common_getsockopt, 858 .getsockopt = sock_common_getsockopt,
851 .sendmsg = inet_sendmsg, 859 .sendmsg = inet_sendmsg,
852 .recvmsg = sock_common_recvmsg, 860 .recvmsg = sock_common_recvmsg,
853 .mmap = sock_no_mmap, 861 .mmap = sock_no_mmap,
854 .sendpage = inet_sendpage, 862 .sendpage = inet_sendpage,
863#ifdef CONFIG_COMPAT
864 .compat_setsockopt = compat_sock_common_setsockopt,
865 .compat_getsockopt = compat_sock_common_getsockopt,
866#endif
855}; 867};
856 868
857static struct net_proto_family inet_family_ops = { 869static struct net_proto_family inet_family_ops = {
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index aed537fa2c88..e16d8b42b953 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -97,6 +97,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
97 ah->reserved = 0; 97 ah->reserved = 0;
98 ah->spi = x->id.spi; 98 ah->spi = x->id.spi;
99 ah->seq_no = htonl(++x->replay.oseq); 99 ah->seq_no = htonl(++x->replay.oseq);
100 xfrm_aevent_doreplay(x);
100 ahp->icv(ahp, skb, ah->auth_data); 101 ahp->icv(ahp, skb, ah->auth_data);
101 102
102 top_iph->tos = iph->tos; 103 top_iph->tos = iph->tos;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index accdefedfed7..041dadde31af 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -879,16 +879,16 @@ static int arp_process(struct sk_buff *skb)
879 879
880 n = __neigh_lookup(&arp_tbl, &sip, dev, 0); 880 n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
881 881
882#ifdef CONFIG_IP_ACCEPT_UNSOLICITED_ARP 882 if (ipv4_devconf.arp_accept) {
883 /* Unsolicited ARP is not accepted by default. 883 /* Unsolicited ARP is not accepted by default.
884 It is possible, that this option should be enabled for some 884 It is possible, that this option should be enabled for some
885 devices (strip is candidate) 885 devices (strip is candidate)
886 */ 886 */
887 if (n == NULL && 887 if (n == NULL &&
888 arp->ar_op == htons(ARPOP_REPLY) && 888 arp->ar_op == htons(ARPOP_REPLY) &&
889 inet_addr_type(sip) == RTN_UNICAST) 889 inet_addr_type(sip) == RTN_UNICAST)
890 n = __neigh_lookup(&arp_tbl, &sip, dev, -1); 890 n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
891#endif 891 }
892 892
893 if (n) { 893 if (n) {
894 int state = NUD_REACHABLE; 894 int state = NUD_REACHABLE;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 3ffa60dadc0c..44fdf1413e2c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1394,6 +1394,14 @@ static struct devinet_sysctl_table {
1394 .proc_handler = &proc_dointvec, 1394 .proc_handler = &proc_dointvec,
1395 }, 1395 },
1396 { 1396 {
1397 .ctl_name = NET_IPV4_CONF_ARP_ACCEPT,
1398 .procname = "arp_accept",
1399 .data = &ipv4_devconf.arp_accept,
1400 .maxlen = sizeof(int),
1401 .mode = 0644,
1402 .proc_handler = &proc_dointvec,
1403 },
1404 {
1397 .ctl_name = NET_IPV4_CONF_NOXFRM, 1405 .ctl_name = NET_IPV4_CONF_NOXFRM,
1398 .procname = "disable_xfrm", 1406 .procname = "disable_xfrm",
1399 .data = &ipv4_devconf.no_xfrm, 1407 .data = &ipv4_devconf.no_xfrm,
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 09590f356086..bf88c620a954 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -90,6 +90,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
90 90
91 esph->spi = x->id.spi; 91 esph->spi = x->id.spi;
92 esph->seq_no = htonl(++x->replay.oseq); 92 esph->seq_no = htonl(++x->replay.oseq);
93 xfrm_aevent_doreplay(x);
93 94
94 if (esp->conf.ivlen) 95 if (esp->conf.ivlen)
95 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); 96 crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm));
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 0dd4d06e456d..ec566f3e66c7 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -40,6 +40,8 @@
40#include <linux/skbuff.h> 40#include <linux/skbuff.h>
41#include <linux/netlink.h> 41#include <linux/netlink.h>
42#include <linux/init.h> 42#include <linux/init.h>
43#include <linux/list.h>
44#include <linux/rcupdate.h>
43 45
44#include <net/ip.h> 46#include <net/ip.h>
45#include <net/protocol.h> 47#include <net/protocol.h>
@@ -52,7 +54,7 @@
52 54
53struct fib_rule 55struct fib_rule
54{ 56{
55 struct fib_rule *r_next; 57 struct hlist_node hlist;
56 atomic_t r_clntref; 58 atomic_t r_clntref;
57 u32 r_preference; 59 u32 r_preference;
58 unsigned char r_table; 60 unsigned char r_table;
@@ -75,6 +77,7 @@ struct fib_rule
75#endif 77#endif
76 char r_ifname[IFNAMSIZ]; 78 char r_ifname[IFNAMSIZ];
77 int r_dead; 79 int r_dead;
80 struct rcu_head rcu;
78}; 81};
79 82
80static struct fib_rule default_rule = { 83static struct fib_rule default_rule = {
@@ -85,7 +88,6 @@ static struct fib_rule default_rule = {
85}; 88};
86 89
87static struct fib_rule main_rule = { 90static struct fib_rule main_rule = {
88 .r_next = &default_rule,
89 .r_clntref = ATOMIC_INIT(2), 91 .r_clntref = ATOMIC_INIT(2),
90 .r_preference = 0x7FFE, 92 .r_preference = 0x7FFE,
91 .r_table = RT_TABLE_MAIN, 93 .r_table = RT_TABLE_MAIN,
@@ -93,23 +95,26 @@ static struct fib_rule main_rule = {
93}; 95};
94 96
95static struct fib_rule local_rule = { 97static struct fib_rule local_rule = {
96 .r_next = &main_rule,
97 .r_clntref = ATOMIC_INIT(2), 98 .r_clntref = ATOMIC_INIT(2),
98 .r_table = RT_TABLE_LOCAL, 99 .r_table = RT_TABLE_LOCAL,
99 .r_action = RTN_UNICAST, 100 .r_action = RTN_UNICAST,
100}; 101};
101 102
102static struct fib_rule *fib_rules = &local_rule; 103static struct hlist_head fib_rules;
103static DEFINE_RWLOCK(fib_rules_lock); 104
105/* writer func called from netlink -- rtnl_sem hold*/
106
107static void rtmsg_rule(int, struct fib_rule *);
104 108
105int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 109int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
106{ 110{
107 struct rtattr **rta = arg; 111 struct rtattr **rta = arg;
108 struct rtmsg *rtm = NLMSG_DATA(nlh); 112 struct rtmsg *rtm = NLMSG_DATA(nlh);
109 struct fib_rule *r, **rp; 113 struct fib_rule *r;
114 struct hlist_node *node;
110 int err = -ESRCH; 115 int err = -ESRCH;
111 116
112 for (rp=&fib_rules; (r=*rp) != NULL; rp=&r->r_next) { 117 hlist_for_each_entry(r, node, &fib_rules, hlist) {
113 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) && 118 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) &&
114 rtm->rtm_src_len == r->r_src_len && 119 rtm->rtm_src_len == r->r_src_len &&
115 rtm->rtm_dst_len == r->r_dst_len && 120 rtm->rtm_dst_len == r->r_dst_len &&
@@ -126,10 +131,9 @@ int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
126 if (r == &local_rule) 131 if (r == &local_rule)
127 break; 132 break;
128 133
129 write_lock_bh(&fib_rules_lock); 134 hlist_del_rcu(&r->hlist);
130 *rp = r->r_next;
131 r->r_dead = 1; 135 r->r_dead = 1;
132 write_unlock_bh(&fib_rules_lock); 136 rtmsg_rule(RTM_DELRULE, r);
133 fib_rule_put(r); 137 fib_rule_put(r);
134 err = 0; 138 err = 0;
135 break; 139 break;
@@ -150,21 +154,30 @@ static struct fib_table *fib_empty_table(void)
150 return NULL; 154 return NULL;
151} 155}
152 156
157static inline void fib_rule_put_rcu(struct rcu_head *head)
158{
159 struct fib_rule *r = container_of(head, struct fib_rule, rcu);
160 kfree(r);
161}
162
153void fib_rule_put(struct fib_rule *r) 163void fib_rule_put(struct fib_rule *r)
154{ 164{
155 if (atomic_dec_and_test(&r->r_clntref)) { 165 if (atomic_dec_and_test(&r->r_clntref)) {
156 if (r->r_dead) 166 if (r->r_dead)
157 kfree(r); 167 call_rcu(&r->rcu, fib_rule_put_rcu);
158 else 168 else
159 printk("Freeing alive rule %p\n", r); 169 printk("Freeing alive rule %p\n", r);
160 } 170 }
161} 171}
162 172
173/* writer func called from netlink -- rtnl_sem hold*/
174
163int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 175int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
164{ 176{
165 struct rtattr **rta = arg; 177 struct rtattr **rta = arg;
166 struct rtmsg *rtm = NLMSG_DATA(nlh); 178 struct rtmsg *rtm = NLMSG_DATA(nlh);
167 struct fib_rule *r, *new_r, **rp; 179 struct fib_rule *r, *new_r, *last = NULL;
180 struct hlist_node *node = NULL;
168 unsigned char table_id; 181 unsigned char table_id;
169 182
170 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 || 183 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 ||
@@ -188,6 +201,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
188 if (!new_r) 201 if (!new_r)
189 return -ENOMEM; 202 return -ENOMEM;
190 memset(new_r, 0, sizeof(*new_r)); 203 memset(new_r, 0, sizeof(*new_r));
204
191 if (rta[RTA_SRC-1]) 205 if (rta[RTA_SRC-1])
192 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4); 206 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4);
193 if (rta[RTA_DST-1]) 207 if (rta[RTA_DST-1])
@@ -220,28 +234,29 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
220 if (rta[RTA_FLOW-1]) 234 if (rta[RTA_FLOW-1])
221 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4); 235 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4);
222#endif 236#endif
237 r = container_of(fib_rules.first, struct fib_rule, hlist);
223 238
224 rp = &fib_rules;
225 if (!new_r->r_preference) { 239 if (!new_r->r_preference) {
226 r = fib_rules; 240 if (r && r->hlist.next != NULL) {
227 if (r && (r = r->r_next) != NULL) { 241 r = container_of(r->hlist.next, struct fib_rule, hlist);
228 rp = &fib_rules->r_next;
229 if (r->r_preference) 242 if (r->r_preference)
230 new_r->r_preference = r->r_preference - 1; 243 new_r->r_preference = r->r_preference - 1;
231 } 244 }
232 } 245 }
233 246
234 while ( (r = *rp) != NULL ) { 247 hlist_for_each_entry(r, node, &fib_rules, hlist) {
235 if (r->r_preference > new_r->r_preference) 248 if (r->r_preference > new_r->r_preference)
236 break; 249 break;
237 rp = &r->r_next; 250 last = r;
238 } 251 }
239
240 new_r->r_next = r;
241 atomic_inc(&new_r->r_clntref); 252 atomic_inc(&new_r->r_clntref);
242 write_lock_bh(&fib_rules_lock); 253
243 *rp = new_r; 254 if (last)
244 write_unlock_bh(&fib_rules_lock); 255 hlist_add_after_rcu(&last->hlist, &new_r->hlist);
256 else
257 hlist_add_before_rcu(&new_r->hlist, &r->hlist);
258
259 rtmsg_rule(RTM_NEWRULE, new_r);
245 return 0; 260 return 0;
246} 261}
247 262
@@ -254,30 +269,30 @@ u32 fib_rules_tclass(struct fib_result *res)
254} 269}
255#endif 270#endif
256 271
272/* callers should hold rtnl semaphore */
257 273
258static void fib_rules_detach(struct net_device *dev) 274static void fib_rules_detach(struct net_device *dev)
259{ 275{
276 struct hlist_node *node;
260 struct fib_rule *r; 277 struct fib_rule *r;
261 278
262 for (r=fib_rules; r; r=r->r_next) { 279 hlist_for_each_entry(r, node, &fib_rules, hlist) {
263 if (r->r_ifindex == dev->ifindex) { 280 if (r->r_ifindex == dev->ifindex)
264 write_lock_bh(&fib_rules_lock);
265 r->r_ifindex = -1; 281 r->r_ifindex = -1;
266 write_unlock_bh(&fib_rules_lock); 282
267 }
268 } 283 }
269} 284}
270 285
286/* callers should hold rtnl semaphore */
287
271static void fib_rules_attach(struct net_device *dev) 288static void fib_rules_attach(struct net_device *dev)
272{ 289{
290 struct hlist_node *node;
273 struct fib_rule *r; 291 struct fib_rule *r;
274 292
275 for (r=fib_rules; r; r=r->r_next) { 293 hlist_for_each_entry(r, node, &fib_rules, hlist) {
276 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) { 294 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0)
277 write_lock_bh(&fib_rules_lock);
278 r->r_ifindex = dev->ifindex; 295 r->r_ifindex = dev->ifindex;
279 write_unlock_bh(&fib_rules_lock);
280 }
281 } 296 }
282} 297}
283 298
@@ -286,14 +301,17 @@ int fib_lookup(const struct flowi *flp, struct fib_result *res)
286 int err; 301 int err;
287 struct fib_rule *r, *policy; 302 struct fib_rule *r, *policy;
288 struct fib_table *tb; 303 struct fib_table *tb;
304 struct hlist_node *node;
289 305
290 u32 daddr = flp->fl4_dst; 306 u32 daddr = flp->fl4_dst;
291 u32 saddr = flp->fl4_src; 307 u32 saddr = flp->fl4_src;
292 308
293FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", 309FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
294 NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src)); 310 NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src));
295 read_lock(&fib_rules_lock); 311
296 for (r = fib_rules; r; r=r->r_next) { 312 rcu_read_lock();
313
314 hlist_for_each_entry_rcu(r, node, &fib_rules, hlist) {
297 if (((saddr^r->r_src) & r->r_srcmask) || 315 if (((saddr^r->r_src) & r->r_srcmask) ||
298 ((daddr^r->r_dst) & r->r_dstmask) || 316 ((daddr^r->r_dst) & r->r_dstmask) ||
299 (r->r_tos && r->r_tos != flp->fl4_tos) || 317 (r->r_tos && r->r_tos != flp->fl4_tos) ||
@@ -309,14 +327,14 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
309 policy = r; 327 policy = r;
310 break; 328 break;
311 case RTN_UNREACHABLE: 329 case RTN_UNREACHABLE:
312 read_unlock(&fib_rules_lock); 330 rcu_read_unlock();
313 return -ENETUNREACH; 331 return -ENETUNREACH;
314 default: 332 default:
315 case RTN_BLACKHOLE: 333 case RTN_BLACKHOLE:
316 read_unlock(&fib_rules_lock); 334 rcu_read_unlock();
317 return -EINVAL; 335 return -EINVAL;
318 case RTN_PROHIBIT: 336 case RTN_PROHIBIT:
319 read_unlock(&fib_rules_lock); 337 rcu_read_unlock();
320 return -EACCES; 338 return -EACCES;
321 } 339 }
322 340
@@ -327,16 +345,16 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
327 res->r = policy; 345 res->r = policy;
328 if (policy) 346 if (policy)
329 atomic_inc(&policy->r_clntref); 347 atomic_inc(&policy->r_clntref);
330 read_unlock(&fib_rules_lock); 348 rcu_read_unlock();
331 return 0; 349 return 0;
332 } 350 }
333 if (err < 0 && err != -EAGAIN) { 351 if (err < 0 && err != -EAGAIN) {
334 read_unlock(&fib_rules_lock); 352 rcu_read_unlock();
335 return err; 353 return err;
336 } 354 }
337 } 355 }
338FRprintk("FAILURE\n"); 356FRprintk("FAILURE\n");
339 read_unlock(&fib_rules_lock); 357 rcu_read_unlock();
340 return -ENETUNREACH; 358 return -ENETUNREACH;
341} 359}
342 360
@@ -368,14 +386,14 @@ static struct notifier_block fib_rules_notifier = {
368 386
369static __inline__ int inet_fill_rule(struct sk_buff *skb, 387static __inline__ int inet_fill_rule(struct sk_buff *skb,
370 struct fib_rule *r, 388 struct fib_rule *r,
371 struct netlink_callback *cb, 389 u32 pid, u32 seq, int event,
372 unsigned int flags) 390 unsigned int flags)
373{ 391{
374 struct rtmsg *rtm; 392 struct rtmsg *rtm;
375 struct nlmsghdr *nlh; 393 struct nlmsghdr *nlh;
376 unsigned char *b = skb->tail; 394 unsigned char *b = skb->tail;
377 395
378 nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags); 396 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
379 rtm = NLMSG_DATA(nlh); 397 rtm = NLMSG_DATA(nlh);
380 rtm->rtm_family = AF_INET; 398 rtm->rtm_family = AF_INET;
381 rtm->rtm_dst_len = r->r_dst_len; 399 rtm->rtm_dst_len = r->r_dst_len;
@@ -414,20 +432,42 @@ rtattr_failure:
414 return -1; 432 return -1;
415} 433}
416 434
435/* callers should hold rtnl semaphore */
436
437static void rtmsg_rule(int event, struct fib_rule *r)
438{
439 int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128);
440 struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
441
442 if (!skb)
443 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS);
444 else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) {
445 kfree_skb(skb);
446 netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL);
447 } else {
448 netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL);
449 }
450}
451
417int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 452int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
418{ 453{
419 int idx; 454 int idx = 0;
420 int s_idx = cb->args[0]; 455 int s_idx = cb->args[0];
421 struct fib_rule *r; 456 struct fib_rule *r;
457 struct hlist_node *node;
458
459 rcu_read_lock();
460 hlist_for_each_entry(r, node, &fib_rules, hlist) {
422 461
423 read_lock(&fib_rules_lock);
424 for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
425 if (idx < s_idx) 462 if (idx < s_idx)
426 continue; 463 continue;
427 if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) 464 if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
465 cb->nlh->nlmsg_seq,
466 RTM_NEWRULE, NLM_F_MULTI) < 0)
428 break; 467 break;
468 idx++;
429 } 469 }
430 read_unlock(&fib_rules_lock); 470 rcu_read_unlock();
431 cb->args[0] = idx; 471 cb->args[0] = idx;
432 472
433 return skb->len; 473 return skb->len;
@@ -435,5 +475,9 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
435 475
436void __init fib_rules_init(void) 476void __init fib_rules_init(void)
437{ 477{
478 INIT_HLIST_HEAD(&fib_rules);
479 hlist_add_head(&local_rule.hlist, &fib_rules);
480 hlist_add_after(&local_rule.hlist, &main_rule.hlist);
481 hlist_add_after(&main_rule.hlist, &default_rule.hlist);
438 register_netdevice_notifier(&fib_rules_notifier); 482 register_netdevice_notifier(&fib_rules_notifier);
439} 483}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index e320b32373e5..ccd3efc6a173 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
50 * Patrick McHardy <kaber@trash.net> 50 * Patrick McHardy <kaber@trash.net>
51 */ 51 */
52 52
53#define VERSION "0.404" 53#define VERSION "0.406"
54 54
55#include <linux/config.h> 55#include <linux/config.h>
56#include <asm/uaccess.h> 56#include <asm/uaccess.h>
@@ -84,7 +84,7 @@
84#include "fib_lookup.h" 84#include "fib_lookup.h"
85 85
86#undef CONFIG_IP_FIB_TRIE_STATS 86#undef CONFIG_IP_FIB_TRIE_STATS
87#define MAX_CHILDS 16384 87#define MAX_STAT_DEPTH 32
88 88
89#define KEYLENGTH (8*sizeof(t_key)) 89#define KEYLENGTH (8*sizeof(t_key))
90#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l)) 90#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
@@ -154,7 +154,7 @@ struct trie_stat {
154 unsigned int tnodes; 154 unsigned int tnodes;
155 unsigned int leaves; 155 unsigned int leaves;
156 unsigned int nullpointers; 156 unsigned int nullpointers;
157 unsigned int nodesizes[MAX_CHILDS]; 157 unsigned int nodesizes[MAX_STAT_DEPTH];
158}; 158};
159 159
160struct trie { 160struct trie {
@@ -2040,7 +2040,15 @@ rescan:
2040static struct node *fib_trie_get_first(struct fib_trie_iter *iter, 2040static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
2041 struct trie *t) 2041 struct trie *t)
2042{ 2042{
2043 struct node *n = rcu_dereference(t->trie); 2043 struct node *n ;
2044
2045 if(!t)
2046 return NULL;
2047
2048 n = rcu_dereference(t->trie);
2049
2050 if(!iter)
2051 return NULL;
2044 2052
2045 if (n && IS_TNODE(n)) { 2053 if (n && IS_TNODE(n)) {
2046 iter->tnode = (struct tnode *) n; 2054 iter->tnode = (struct tnode *) n;
@@ -2072,7 +2080,9 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
2072 int i; 2080 int i;
2073 2081
2074 s->tnodes++; 2082 s->tnodes++;
2075 s->nodesizes[tn->bits]++; 2083 if(tn->bits < MAX_STAT_DEPTH)
2084 s->nodesizes[tn->bits]++;
2085
2076 for (i = 0; i < (1<<tn->bits); i++) 2086 for (i = 0; i < (1<<tn->bits); i++)
2077 if (!tn->child[i]) 2087 if (!tn->child[i])
2078 s->nullpointers++; 2088 s->nullpointers++;
@@ -2102,8 +2112,8 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
2102 seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes); 2112 seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes);
2103 bytes += sizeof(struct tnode) * stat->tnodes; 2113 bytes += sizeof(struct tnode) * stat->tnodes;
2104 2114
2105 max = MAX_CHILDS-1; 2115 max = MAX_STAT_DEPTH;
2106 while (max >= 0 && stat->nodesizes[max] == 0) 2116 while (max > 0 && stat->nodesizes[max-1] == 0)
2107 max--; 2117 max--;
2108 2118
2109 pointers = 0; 2119 pointers = 0;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 64ce52bf0485..d512239a1473 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1382,7 +1382,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
1382 dev = ip_dev_find(imr->imr_address.s_addr); 1382 dev = ip_dev_find(imr->imr_address.s_addr);
1383 if (!dev) 1383 if (!dev)
1384 return NULL; 1384 return NULL;
1385 __dev_put(dev); 1385 dev_put(dev);
1386 } 1386 }
1387 1387
1388 if (!dev && !ip_route_output_key(&rt, &fl)) { 1388 if (!dev && !ip_route_output_key(&rt, &fl)) {
@@ -1730,7 +1730,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1730 if (!MULTICAST(addr)) 1730 if (!MULTICAST(addr))
1731 return -EINVAL; 1731 return -EINVAL;
1732 1732
1733 rtnl_shlock(); 1733 rtnl_lock();
1734 1734
1735 in_dev = ip_mc_find_dev(imr); 1735 in_dev = ip_mc_find_dev(imr);
1736 1736
@@ -1763,7 +1763,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1763 ip_mc_inc_group(in_dev, addr); 1763 ip_mc_inc_group(in_dev, addr);
1764 err = 0; 1764 err = 0;
1765done: 1765done:
1766 rtnl_shunlock(); 1766 rtnl_unlock();
1767 return err; 1767 return err;
1768} 1768}
1769 1769
@@ -1837,7 +1837,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
1837 if (!MULTICAST(addr)) 1837 if (!MULTICAST(addr))
1838 return -EINVAL; 1838 return -EINVAL;
1839 1839
1840 rtnl_shlock(); 1840 rtnl_lock();
1841 1841
1842 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; 1842 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
1843 imr.imr_address.s_addr = mreqs->imr_interface; 1843 imr.imr_address.s_addr = mreqs->imr_interface;
@@ -1947,7 +1947,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
1947 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, 1947 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
1948 &mreqs->imr_sourceaddr, 1); 1948 &mreqs->imr_sourceaddr, 1);
1949done: 1949done:
1950 rtnl_shunlock(); 1950 rtnl_unlock();
1951 if (leavegroup) 1951 if (leavegroup)
1952 return ip_mc_leave_group(sk, &imr); 1952 return ip_mc_leave_group(sk, &imr);
1953 return err; 1953 return err;
@@ -1970,7 +1970,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
1970 msf->imsf_fmode != MCAST_EXCLUDE) 1970 msf->imsf_fmode != MCAST_EXCLUDE)
1971 return -EINVAL; 1971 return -EINVAL;
1972 1972
1973 rtnl_shlock(); 1973 rtnl_lock();
1974 1974
1975 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; 1975 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
1976 imr.imr_address.s_addr = msf->imsf_interface; 1976 imr.imr_address.s_addr = msf->imsf_interface;
@@ -2030,7 +2030,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
2030 pmc->sfmode = msf->imsf_fmode; 2030 pmc->sfmode = msf->imsf_fmode;
2031 err = 0; 2031 err = 0;
2032done: 2032done:
2033 rtnl_shunlock(); 2033 rtnl_unlock();
2034 if (leavegroup) 2034 if (leavegroup)
2035 err = ip_mc_leave_group(sk, &imr); 2035 err = ip_mc_leave_group(sk, &imr);
2036 return err; 2036 return err;
@@ -2050,7 +2050,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2050 if (!MULTICAST(addr)) 2050 if (!MULTICAST(addr))
2051 return -EINVAL; 2051 return -EINVAL;
2052 2052
2053 rtnl_shlock(); 2053 rtnl_lock();
2054 2054
2055 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; 2055 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
2056 imr.imr_address.s_addr = msf->imsf_interface; 2056 imr.imr_address.s_addr = msf->imsf_interface;
@@ -2072,7 +2072,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2072 goto done; 2072 goto done;
2073 msf->imsf_fmode = pmc->sfmode; 2073 msf->imsf_fmode = pmc->sfmode;
2074 psl = pmc->sflist; 2074 psl = pmc->sflist;
2075 rtnl_shunlock(); 2075 rtnl_unlock();
2076 if (!psl) { 2076 if (!psl) {
2077 len = 0; 2077 len = 0;
2078 count = 0; 2078 count = 0;
@@ -2091,7 +2091,7 @@ int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2091 return -EFAULT; 2091 return -EFAULT;
2092 return 0; 2092 return 0;
2093done: 2093done:
2094 rtnl_shunlock(); 2094 rtnl_unlock();
2095 return err; 2095 return err;
2096} 2096}
2097 2097
@@ -2112,7 +2112,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2112 if (!MULTICAST(addr)) 2112 if (!MULTICAST(addr))
2113 return -EINVAL; 2113 return -EINVAL;
2114 2114
2115 rtnl_shlock(); 2115 rtnl_lock();
2116 2116
2117 err = -EADDRNOTAVAIL; 2117 err = -EADDRNOTAVAIL;
2118 2118
@@ -2125,7 +2125,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2125 goto done; 2125 goto done;
2126 gsf->gf_fmode = pmc->sfmode; 2126 gsf->gf_fmode = pmc->sfmode;
2127 psl = pmc->sflist; 2127 psl = pmc->sflist;
2128 rtnl_shunlock(); 2128 rtnl_unlock();
2129 count = psl ? psl->sl_count : 0; 2129 count = psl ? psl->sl_count : 0;
2130 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; 2130 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
2131 gsf->gf_numsrc = count; 2131 gsf->gf_numsrc = count;
@@ -2146,7 +2146,7 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2146 } 2146 }
2147 return 0; 2147 return 0;
2148done: 2148done:
2149 rtnl_shunlock(); 2149 rtnl_unlock();
2150 return err; 2150 return err;
2151} 2151}
2152 2152
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index ae20281d8deb..9a01bb81f8bf 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -648,3 +648,52 @@ void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)
648} 648}
649 649
650EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr); 650EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr);
651
652int inet_csk_ctl_sock_create(struct socket **sock, unsigned short family,
653 unsigned short type, unsigned char protocol)
654{
655 int rc = sock_create_kern(family, type, protocol, sock);
656
657 if (rc == 0) {
658 (*sock)->sk->sk_allocation = GFP_ATOMIC;
659 inet_sk((*sock)->sk)->uc_ttl = -1;
660 /*
661 * Unhash it so that IP input processing does not even see it,
662 * we do not wish this socket to see incoming packets.
663 */
664 (*sock)->sk->sk_prot->unhash((*sock)->sk);
665 }
666 return rc;
667}
668
669EXPORT_SYMBOL_GPL(inet_csk_ctl_sock_create);
670
671#ifdef CONFIG_COMPAT
672int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
673 char __user *optval, int __user *optlen)
674{
675 const struct inet_connection_sock *icsk = inet_csk(sk);
676
677 if (icsk->icsk_af_ops->compat_getsockopt != NULL)
678 return icsk->icsk_af_ops->compat_getsockopt(sk, level, optname,
679 optval, optlen);
680 return icsk->icsk_af_ops->getsockopt(sk, level, optname,
681 optval, optlen);
682}
683
684EXPORT_SYMBOL_GPL(inet_csk_compat_getsockopt);
685
686int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
687 char __user *optval, int optlen)
688{
689 const struct inet_connection_sock *icsk = inet_csk(sk);
690
691 if (icsk->icsk_af_ops->compat_setsockopt != NULL)
692 return icsk->icsk_af_ops->compat_setsockopt(sk, level, optname,
693 optval, optlen);
694 return icsk->icsk_af_ops->setsockopt(sk, level, optname,
695 optval, optlen);
696}
697
698EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt);
699#endif
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8ee4d016740d..f75ff1d96551 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1249,11 +1249,7 @@ int ip_push_pending_frames(struct sock *sk)
1249 iph->tos = inet->tos; 1249 iph->tos = inet->tos;
1250 iph->tot_len = htons(skb->len); 1250 iph->tot_len = htons(skb->len);
1251 iph->frag_off = df; 1251 iph->frag_off = df;
1252 if (!df) { 1252 ip_select_ident(iph, &rt->u.dst, sk);
1253 __ip_select_ident(iph, &rt->u.dst, 0);
1254 } else {
1255 iph->id = htons(inet->id++);
1256 }
1257 iph->ttl = ttl; 1253 iph->ttl = ttl;
1258 iph->protocol = sk->sk_protocol; 1254 iph->protocol = sk->sk_protocol;
1259 iph->saddr = rt->rt_src; 1255 iph->saddr = rt->rt_src;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 2bf8d782f678..12e0bf19f24a 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -50,6 +50,7 @@
50#define IP_CMSG_TOS 4 50#define IP_CMSG_TOS 4
51#define IP_CMSG_RECVOPTS 8 51#define IP_CMSG_RECVOPTS 8
52#define IP_CMSG_RETOPTS 16 52#define IP_CMSG_RETOPTS 16
53#define IP_CMSG_PASSSEC 32
53 54
54/* 55/*
55 * SOL_IP control messages. 56 * SOL_IP control messages.
@@ -109,6 +110,19 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
109 put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data); 110 put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
110} 111}
111 112
113static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
114{
115 char *secdata;
116 u32 seclen;
117 int err;
118
119 err = security_socket_getpeersec_dgram(skb, &secdata, &seclen);
120 if (err)
121 return;
122
123 put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
124}
125
112 126
113void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) 127void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
114{ 128{
@@ -138,6 +152,11 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
138 152
139 if (flags & 1) 153 if (flags & 1)
140 ip_cmsg_recv_retopts(msg, skb); 154 ip_cmsg_recv_retopts(msg, skb);
155 if ((flags>>=1) == 0)
156 return;
157
158 if (flags & 1)
159 ip_cmsg_recv_security(msg, skb);
141} 160}
142 161
143int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) 162int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc)
@@ -380,20 +399,19 @@ out:
380 * an IP socket. 399 * an IP socket.
381 */ 400 */
382 401
383int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) 402static int do_ip_setsockopt(struct sock *sk, int level,
403 int optname, char __user *optval, int optlen)
384{ 404{
385 struct inet_sock *inet = inet_sk(sk); 405 struct inet_sock *inet = inet_sk(sk);
386 int val=0,err; 406 int val=0,err;
387 407
388 if (level != SOL_IP)
389 return -ENOPROTOOPT;
390
391 if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | 408 if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
392 (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | 409 (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
393 (1<<IP_RETOPTS) | (1<<IP_TOS) | 410 (1<<IP_RETOPTS) | (1<<IP_TOS) |
394 (1<<IP_TTL) | (1<<IP_HDRINCL) | 411 (1<<IP_TTL) | (1<<IP_HDRINCL) |
395 (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | 412 (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
396 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND))) || 413 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
414 (1<<IP_PASSSEC))) ||
397 optname == IP_MULTICAST_TTL || 415 optname == IP_MULTICAST_TTL ||
398 optname == IP_MULTICAST_LOOP) { 416 optname == IP_MULTICAST_LOOP) {
399 if (optlen >= sizeof(int)) { 417 if (optlen >= sizeof(int)) {
@@ -478,6 +496,12 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
478 else 496 else
479 inet->cmsg_flags &= ~IP_CMSG_RETOPTS; 497 inet->cmsg_flags &= ~IP_CMSG_RETOPTS;
480 break; 498 break;
499 case IP_PASSSEC:
500 if (val)
501 inet->cmsg_flags |= IP_CMSG_PASSSEC;
502 else
503 inet->cmsg_flags &= ~IP_CMSG_PASSSEC;
504 break;
481 case IP_TOS: /* This sets both TOS and Precedence */ 505 case IP_TOS: /* This sets both TOS and Precedence */
482 if (sk->sk_type == SOCK_STREAM) { 506 if (sk->sk_type == SOCK_STREAM) {
483 val &= ~3; 507 val &= ~3;
@@ -849,12 +873,7 @@ mc_msf_out:
849 break; 873 break;
850 874
851 default: 875 default:
852#ifdef CONFIG_NETFILTER
853 err = nf_setsockopt(sk, PF_INET, optname, optval,
854 optlen);
855#else
856 err = -ENOPROTOOPT; 876 err = -ENOPROTOOPT;
857#endif
858 break; 877 break;
859 } 878 }
860 release_sock(sk); 879 release_sock(sk);
@@ -865,12 +884,68 @@ e_inval:
865 return -EINVAL; 884 return -EINVAL;
866} 885}
867 886
887int ip_setsockopt(struct sock *sk, int level,
888 int optname, char __user *optval, int optlen)
889{
890 int err;
891
892 if (level != SOL_IP)
893 return -ENOPROTOOPT;
894
895 err = do_ip_setsockopt(sk, level, optname, optval, optlen);
896#ifdef CONFIG_NETFILTER
897 /* we need to exclude all possible ENOPROTOOPTs except default case */
898 if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
899 optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY
900#ifdef CONFIG_IP_MROUTE
901 && (optname < MRT_BASE || optname > (MRT_BASE + 10))
902#endif
903 ) {
904 lock_sock(sk);
905 err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);
906 release_sock(sk);
907 }
908#endif
909 return err;
910}
911
912#ifdef CONFIG_COMPAT
913int compat_ip_setsockopt(struct sock *sk, int level, int optname,
914 char __user *optval, int optlen)
915{
916 int err;
917
918 if (level != SOL_IP)
919 return -ENOPROTOOPT;
920
921 err = do_ip_setsockopt(sk, level, optname, optval, optlen);
922#ifdef CONFIG_NETFILTER
923 /* we need to exclude all possible ENOPROTOOPTs except default case */
924 if (err == -ENOPROTOOPT && optname != IP_HDRINCL &&
925 optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY
926#ifdef CONFIG_IP_MROUTE
927 && (optname < MRT_BASE || optname > (MRT_BASE + 10))
928#endif
929 ) {
930 lock_sock(sk);
931 err = compat_nf_setsockopt(sk, PF_INET, optname,
932 optval, optlen);
933 release_sock(sk);
934 }
935#endif
936 return err;
937}
938
939EXPORT_SYMBOL(compat_ip_setsockopt);
940#endif
941
868/* 942/*
869 * Get the options. Note for future reference. The GET of IP options gets the 943 * Get the options. Note for future reference. The GET of IP options gets the
870 * _received_ ones. The set sets the _sent_ ones. 944 * _received_ ones. The set sets the _sent_ ones.
871 */ 945 */
872 946
873int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) 947static int do_ip_getsockopt(struct sock *sk, int level, int optname,
948 char __user *optval, int __user *optlen)
874{ 949{
875 struct inet_sock *inet = inet_sk(sk); 950 struct inet_sock *inet = inet_sk(sk);
876 int val; 951 int val;
@@ -932,6 +1007,9 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
932 case IP_RETOPTS: 1007 case IP_RETOPTS:
933 val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0; 1008 val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;
934 break; 1009 break;
1010 case IP_PASSSEC:
1011 val = (inet->cmsg_flags & IP_CMSG_PASSSEC) != 0;
1012 break;
935 case IP_TOS: 1013 case IP_TOS:
936 val = inet->tos; 1014 val = inet->tos;
937 break; 1015 break;
@@ -1051,17 +1129,8 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
1051 val = inet->freebind; 1129 val = inet->freebind;
1052 break; 1130 break;
1053 default: 1131 default:
1054#ifdef CONFIG_NETFILTER
1055 val = nf_getsockopt(sk, PF_INET, optname, optval,
1056 &len);
1057 release_sock(sk);
1058 if (val >= 0)
1059 val = put_user(len, optlen);
1060 return val;
1061#else
1062 release_sock(sk); 1132 release_sock(sk);
1063 return -ENOPROTOOPT; 1133 return -ENOPROTOOPT;
1064#endif
1065 } 1134 }
1066 release_sock(sk); 1135 release_sock(sk);
1067 1136
@@ -1082,6 +1151,67 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
1082 return 0; 1151 return 0;
1083} 1152}
1084 1153
1154int ip_getsockopt(struct sock *sk, int level,
1155 int optname, char __user *optval, int __user *optlen)
1156{
1157 int err;
1158
1159 err = do_ip_getsockopt(sk, level, optname, optval, optlen);
1160#ifdef CONFIG_NETFILTER
1161 /* we need to exclude all possible ENOPROTOOPTs except default case */
1162 if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS
1163#ifdef CONFIG_IP_MROUTE
1164 && (optname < MRT_BASE || optname > MRT_BASE+10)
1165#endif
1166 ) {
1167 int len;
1168
1169 if(get_user(len,optlen))
1170 return -EFAULT;
1171
1172 lock_sock(sk);
1173 err = nf_getsockopt(sk, PF_INET, optname, optval,
1174 &len);
1175 release_sock(sk);
1176 if (err >= 0)
1177 err = put_user(len, optlen);
1178 return err;
1179 }
1180#endif
1181 return err;
1182}
1183
1184#ifdef CONFIG_COMPAT
1185int compat_ip_getsockopt(struct sock *sk, int level, int optname,
1186 char __user *optval, int __user *optlen)
1187{
1188 int err = do_ip_getsockopt(sk, level, optname, optval, optlen);
1189#ifdef CONFIG_NETFILTER
1190 /* we need to exclude all possible ENOPROTOOPTs except default case */
1191 if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS
1192#ifdef CONFIG_IP_MROUTE
1193 && (optname < MRT_BASE || optname > MRT_BASE+10)
1194#endif
1195 ) {
1196 int len;
1197
1198 if (get_user(len, optlen))
1199 return -EFAULT;
1200
1201 lock_sock(sk);
1202 err = compat_nf_getsockopt(sk, PF_INET, optname, optval, &len);
1203 release_sock(sk);
1204 if (err >= 0)
1205 err = put_user(len, optlen);
1206 return err;
1207 }
1208#endif
1209 return err;
1210}
1211
1212EXPORT_SYMBOL(compat_ip_getsockopt);
1213#endif
1214
1085EXPORT_SYMBOL(ip_cmsg_recv); 1215EXPORT_SYMBOL(ip_cmsg_recv);
1086 1216
1087EXPORT_SYMBOL(ip_getsockopt); 1217EXPORT_SYMBOL(ip_getsockopt);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index d64e2ec8da7b..c95020f7c81e 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -24,6 +24,7 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/vmalloc.h> 25#include <linux/vmalloc.h>
26#include <linux/rtnetlink.h> 26#include <linux/rtnetlink.h>
27#include <linux/mutex.h>
27#include <net/ip.h> 28#include <net/ip.h>
28#include <net/xfrm.h> 29#include <net/xfrm.h>
29#include <net/icmp.h> 30#include <net/icmp.h>
@@ -36,7 +37,7 @@ struct ipcomp_tfms {
36 int users; 37 int users;
37}; 38};
38 39
39static DECLARE_MUTEX(ipcomp_resource_sem); 40static DEFINE_MUTEX(ipcomp_resource_mutex);
40static void **ipcomp_scratches; 41static void **ipcomp_scratches;
41static int ipcomp_scratch_users; 42static int ipcomp_scratch_users;
42static LIST_HEAD(ipcomp_tfms_list); 43static LIST_HEAD(ipcomp_tfms_list);
@@ -253,7 +254,7 @@ error:
253} 254}
254 255
255/* 256/*
256 * Must be protected by xfrm_cfg_sem. State and tunnel user references are 257 * Must be protected by xfrm_cfg_mutex. State and tunnel user references are
257 * always incremented on success. 258 * always incremented on success.
258 */ 259 */
259static int ipcomp_tunnel_attach(struct xfrm_state *x) 260static int ipcomp_tunnel_attach(struct xfrm_state *x)
@@ -411,9 +412,9 @@ static void ipcomp_destroy(struct xfrm_state *x)
411 if (!ipcd) 412 if (!ipcd)
412 return; 413 return;
413 xfrm_state_delete_tunnel(x); 414 xfrm_state_delete_tunnel(x);
414 down(&ipcomp_resource_sem); 415 mutex_lock(&ipcomp_resource_mutex);
415 ipcomp_free_data(ipcd); 416 ipcomp_free_data(ipcd);
416 up(&ipcomp_resource_sem); 417 mutex_unlock(&ipcomp_resource_mutex);
417 kfree(ipcd); 418 kfree(ipcd);
418} 419}
419 420
@@ -440,14 +441,14 @@ static int ipcomp_init_state(struct xfrm_state *x)
440 if (x->props.mode) 441 if (x->props.mode)
441 x->props.header_len += sizeof(struct iphdr); 442 x->props.header_len += sizeof(struct iphdr);
442 443
443 down(&ipcomp_resource_sem); 444 mutex_lock(&ipcomp_resource_mutex);
444 if (!ipcomp_alloc_scratches()) 445 if (!ipcomp_alloc_scratches())
445 goto error; 446 goto error;
446 447
447 ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name); 448 ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
448 if (!ipcd->tfms) 449 if (!ipcd->tfms)
449 goto error; 450 goto error;
450 up(&ipcomp_resource_sem); 451 mutex_unlock(&ipcomp_resource_mutex);
451 452
452 if (x->props.mode) { 453 if (x->props.mode) {
453 err = ipcomp_tunnel_attach(x); 454 err = ipcomp_tunnel_attach(x);
@@ -464,10 +465,10 @@ out:
464 return err; 465 return err;
465 466
466error_tunnel: 467error_tunnel:
467 down(&ipcomp_resource_sem); 468 mutex_lock(&ipcomp_resource_mutex);
468error: 469error:
469 ipcomp_free_data(ipcd); 470 ipcomp_free_data(ipcd);
470 up(&ipcomp_resource_sem); 471 mutex_unlock(&ipcomp_resource_mutex);
471 kfree(ipcd); 472 kfree(ipcd);
472 goto out; 473 goto out;
473} 474}
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index bb3613ec448c..cb8a92f18ef6 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -186,7 +186,7 @@ static int __init ic_open_devs(void)
186 unsigned short oflags; 186 unsigned short oflags;
187 187
188 last = &ic_first_dev; 188 last = &ic_first_dev;
189 rtnl_shlock(); 189 rtnl_lock();
190 190
191 /* bring loopback device up first */ 191 /* bring loopback device up first */
192 if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0) 192 if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
@@ -215,7 +215,7 @@ static int __init ic_open_devs(void)
215 continue; 215 continue;
216 } 216 }
217 if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { 217 if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
218 rtnl_shunlock(); 218 rtnl_unlock();
219 return -1; 219 return -1;
220 } 220 }
221 d->dev = dev; 221 d->dev = dev;
@@ -232,7 +232,7 @@ static int __init ic_open_devs(void)
232 dev->name, able, d->xid)); 232 dev->name, able, d->xid));
233 } 233 }
234 } 234 }
235 rtnl_shunlock(); 235 rtnl_unlock();
236 236
237 *last = NULL; 237 *last = NULL;
238 238
@@ -251,7 +251,7 @@ static void __init ic_close_devs(void)
251 struct ic_device *d, *next; 251 struct ic_device *d, *next;
252 struct net_device *dev; 252 struct net_device *dev;
253 253
254 rtnl_shlock(); 254 rtnl_lock();
255 next = ic_first_dev; 255 next = ic_first_dev;
256 while ((d = next)) { 256 while ((d = next)) {
257 next = d->next; 257 next = d->next;
@@ -262,7 +262,7 @@ static void __init ic_close_devs(void)
262 } 262 }
263 kfree(d); 263 kfree(d);
264 } 264 }
265 rtnl_shunlock(); 265 rtnl_unlock();
266} 266}
267 267
268/* 268/*
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 5c94c222e3f3..717ab7d6d7b6 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -415,10 +415,10 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
415 return -ENOBUFS; 415 return -ENOBUFS;
416 break; 416 break;
417 case 0: 417 case 0:
418 dev=ip_dev_find(vifc->vifc_lcl_addr.s_addr); 418 dev = ip_dev_find(vifc->vifc_lcl_addr.s_addr);
419 if (!dev) 419 if (!dev)
420 return -EADDRNOTAVAIL; 420 return -EADDRNOTAVAIL;
421 __dev_put(dev); 421 dev_put(dev);
422 break; 422 break;
423 default: 423 default:
424 return -EINVAL; 424 return -EINVAL;
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 9b176a942ac5..e7752334d296 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -31,6 +31,7 @@
31#include <linux/stat.h> 31#include <linux/stat.h>
32#include <linux/proc_fs.h> 32#include <linux/proc_fs.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#include <linux/mutex.h>
34 35
35#include <net/ip_vs.h> 36#include <net/ip_vs.h>
36 37
@@ -40,7 +41,7 @@ EXPORT_SYMBOL(register_ip_vs_app_inc);
40 41
41/* ipvs application list head */ 42/* ipvs application list head */
42static LIST_HEAD(ip_vs_app_list); 43static LIST_HEAD(ip_vs_app_list);
43static DECLARE_MUTEX(__ip_vs_app_mutex); 44static DEFINE_MUTEX(__ip_vs_app_mutex);
44 45
45 46
46/* 47/*
@@ -173,11 +174,11 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port)
173{ 174{
174 int result; 175 int result;
175 176
176 down(&__ip_vs_app_mutex); 177 mutex_lock(&__ip_vs_app_mutex);
177 178
178 result = ip_vs_app_inc_new(app, proto, port); 179 result = ip_vs_app_inc_new(app, proto, port);
179 180
180 up(&__ip_vs_app_mutex); 181 mutex_unlock(&__ip_vs_app_mutex);
181 182
182 return result; 183 return result;
183} 184}
@@ -191,11 +192,11 @@ int register_ip_vs_app(struct ip_vs_app *app)
191 /* increase the module use count */ 192 /* increase the module use count */
192 ip_vs_use_count_inc(); 193 ip_vs_use_count_inc();
193 194
194 down(&__ip_vs_app_mutex); 195 mutex_lock(&__ip_vs_app_mutex);
195 196
196 list_add(&app->a_list, &ip_vs_app_list); 197 list_add(&app->a_list, &ip_vs_app_list);
197 198
198 up(&__ip_vs_app_mutex); 199 mutex_unlock(&__ip_vs_app_mutex);
199 200
200 return 0; 201 return 0;
201} 202}
@@ -209,7 +210,7 @@ void unregister_ip_vs_app(struct ip_vs_app *app)
209{ 210{
210 struct ip_vs_app *inc, *nxt; 211 struct ip_vs_app *inc, *nxt;
211 212
212 down(&__ip_vs_app_mutex); 213 mutex_lock(&__ip_vs_app_mutex);
213 214
214 list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { 215 list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) {
215 ip_vs_app_inc_release(inc); 216 ip_vs_app_inc_release(inc);
@@ -217,7 +218,7 @@ void unregister_ip_vs_app(struct ip_vs_app *app)
217 218
218 list_del(&app->a_list); 219 list_del(&app->a_list);
219 220
220 up(&__ip_vs_app_mutex); 221 mutex_unlock(&__ip_vs_app_mutex);
221 222
222 /* decrease the module use count */ 223 /* decrease the module use count */
223 ip_vs_use_count_dec(); 224 ip_vs_use_count_dec();
@@ -498,7 +499,7 @@ static struct ip_vs_app *ip_vs_app_idx(loff_t pos)
498 499
499static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos) 500static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos)
500{ 501{
501 down(&__ip_vs_app_mutex); 502 mutex_lock(&__ip_vs_app_mutex);
502 503
503 return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN; 504 return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN;
504} 505}
@@ -530,7 +531,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
530 531
531static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) 532static void ip_vs_app_seq_stop(struct seq_file *seq, void *v)
532{ 533{
533 up(&__ip_vs_app_mutex); 534 mutex_unlock(&__ip_vs_app_mutex);
534} 535}
535 536
536static int ip_vs_app_seq_show(struct seq_file *seq, void *v) 537static int ip_vs_app_seq_show(struct seq_file *seq, void *v)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index db783036e4d8..882b842c25d4 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -168,6 +168,26 @@ config IP_NF_PPTP
168 If you want to compile it as a module, say M here and read 168 If you want to compile it as a module, say M here and read
169 Documentation/modules.txt. If unsure, say `N'. 169 Documentation/modules.txt. If unsure, say `N'.
170 170
171config IP_NF_H323
172 tristate 'H.323 protocol support'
173 depends on IP_NF_CONNTRACK
174 help
175 H.323 is a VoIP signalling protocol from ITU-T. As one of the most
176 important VoIP protocols, it is widely used by voice hardware and
177 software including voice gateways, IP phones, Netmeeting, OpenPhone,
178 Gnomemeeting, etc.
179
180 With this module you can support H.323 on a connection tracking/NAT
181 firewall.
182
183 This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
184 and T.120 based data and applications including audio, video, FAX,
185 chat, whiteboard, file transfer, etc. For more information, please
186 see http://nath323.sourceforge.net/.
187
188 If you want to compile it as a module, say 'M' here and read
189 Documentation/modules.txt. If unsure, say 'N'.
190
171config IP_NF_QUEUE 191config IP_NF_QUEUE
172 tristate "IP Userspace queueing via NETLINK (OBSOLETE)" 192 tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
173 help 193 help
@@ -303,16 +323,6 @@ config IP_NF_MATCH_HASHLIMIT
303 destination IP' or `500pps from any given source IP' with a single 323 destination IP' or `500pps from any given source IP' with a single
304 IPtables rule. 324 IPtables rule.
305 325
306config IP_NF_MATCH_POLICY
307 tristate "IPsec policy match support"
308 depends on IP_NF_IPTABLES && XFRM
309 help
310 Policy matching allows you to match packets based on the
311 IPsec policy that was used during decapsulation/will
312 be used during encapsulation.
313
314 To compile it as a module, choose M here. If unsure, say N.
315
316# `filter', generic and specific targets 326# `filter', generic and specific targets
317config IP_NF_FILTER 327config IP_NF_FILTER
318 tristate "Packet filtering" 328 tristate "Packet filtering"
@@ -494,6 +504,12 @@ config IP_NF_NAT_PPTP
494 default IP_NF_NAT if IP_NF_PPTP=y 504 default IP_NF_NAT if IP_NF_PPTP=y
495 default m if IP_NF_PPTP=m 505 default m if IP_NF_PPTP=m
496 506
507config IP_NF_NAT_H323
508 tristate
509 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
510 default IP_NF_NAT if IP_NF_H323=y
511 default m if IP_NF_H323=m
512
497# mangle + specific targets 513# mangle + specific targets
498config IP_NF_MANGLE 514config IP_NF_MANGLE
499 tristate "Packet mangling" 515 tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index e5c5b3202f02..f2cd9a6c5b91 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -10,6 +10,9 @@ iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
10ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o 10ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
11ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o 11ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
12 12
13ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o
14ip_nat_h323-objs := ip_nat_helper_h323.o
15
13# connection tracking 16# connection tracking
14obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o 17obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
15obj-$(CONFIG_IP_NF_NAT) += ip_nat.o 18obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
@@ -22,6 +25,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
22obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o 25obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
23 26
24# connection tracking helpers 27# connection tracking helpers
28obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
25obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o 29obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
26obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o 30obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
27obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o 31obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
@@ -30,6 +34,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
30obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o 34obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
31 35
32# NAT helpers 36# NAT helpers
37obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
33obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o 38obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
34obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o 39obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
35obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o 40obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
@@ -57,7 +62,6 @@ obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
57obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 62obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
58obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 63obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
59obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 64obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
60obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
61 65
62# targets 66# targets
63obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 67obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 7d7ab94a7a2e..ff0c594a4198 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -22,7 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23 23
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/semaphore.h> 25#include <linux/mutex.h>
26 26
27#include <linux/netfilter/x_tables.h> 27#include <linux/netfilter/x_tables.h>
28#include <linux/netfilter_arp/arp_tables.h> 28#include <linux/netfilter_arp/arp_tables.h>
@@ -208,6 +208,7 @@ static unsigned int arpt_error(struct sk_buff **pskb,
208 const struct net_device *in, 208 const struct net_device *in,
209 const struct net_device *out, 209 const struct net_device *out,
210 unsigned int hooknum, 210 unsigned int hooknum,
211 const struct xt_target *target,
211 const void *targinfo, 212 const void *targinfo,
212 void *userinfo) 213 void *userinfo)
213{ 214{
@@ -300,6 +301,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
300 verdict = t->u.kernel.target->target(pskb, 301 verdict = t->u.kernel.target->target(pskb,
301 in, out, 302 in, out,
302 hook, 303 hook,
304 t->u.kernel.target,
303 t->data, 305 t->data,
304 userdata); 306 userdata);
305 307
@@ -480,26 +482,31 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
480 } 482 }
481 t->u.kernel.target = target; 483 t->u.kernel.target = target;
482 484
485 ret = xt_check_target(target, NF_ARP, t->u.target_size - sizeof(*t),
486 name, e->comefrom, 0, 0);
487 if (ret)
488 goto err;
489
483 if (t->u.kernel.target == &arpt_standard_target) { 490 if (t->u.kernel.target == &arpt_standard_target) {
484 if (!standard_check(t, size)) { 491 if (!standard_check(t, size)) {
485 ret = -EINVAL; 492 ret = -EINVAL;
486 goto out; 493 goto out;
487 } 494 }
488 } else if (t->u.kernel.target->checkentry 495 } else if (t->u.kernel.target->checkentry
489 && !t->u.kernel.target->checkentry(name, e, t->data, 496 && !t->u.kernel.target->checkentry(name, e, target, t->data,
490 t->u.target_size 497 t->u.target_size
491 - sizeof(*t), 498 - sizeof(*t),
492 e->comefrom)) { 499 e->comefrom)) {
493 module_put(t->u.kernel.target->me);
494 duprintf("arp_tables: check failed for `%s'.\n", 500 duprintf("arp_tables: check failed for `%s'.\n",
495 t->u.kernel.target->name); 501 t->u.kernel.target->name);
496 ret = -EINVAL; 502 ret = -EINVAL;
497 goto out; 503 goto err;
498 } 504 }
499 505
500 (*i)++; 506 (*i)++;
501 return 0; 507 return 0;
502 508err:
509 module_put(t->u.kernel.target->me);
503out: 510out:
504 return ret; 511 return ret;
505} 512}
@@ -555,7 +562,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
555 562
556 t = arpt_get_target(e); 563 t = arpt_get_target(e);
557 if (t->u.kernel.target->destroy) 564 if (t->u.kernel.target->destroy)
558 t->u.kernel.target->destroy(t->data, 565 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
559 t->u.target_size - sizeof(*t)); 566 t->u.target_size - sizeof(*t));
560 module_put(t->u.kernel.target->me); 567 module_put(t->u.kernel.target->me);
561 return 0; 568 return 0;
@@ -1138,11 +1145,15 @@ void arpt_unregister_table(struct arpt_table *table)
1138/* The built-in targets: standard (NULL) and error. */ 1145/* The built-in targets: standard (NULL) and error. */
1139static struct arpt_target arpt_standard_target = { 1146static struct arpt_target arpt_standard_target = {
1140 .name = ARPT_STANDARD_TARGET, 1147 .name = ARPT_STANDARD_TARGET,
1148 .targetsize = sizeof(int),
1149 .family = NF_ARP,
1141}; 1150};
1142 1151
1143static struct arpt_target arpt_error_target = { 1152static struct arpt_target arpt_error_target = {
1144 .name = ARPT_ERROR_TARGET, 1153 .name = ARPT_ERROR_TARGET,
1145 .target = arpt_error, 1154 .target = arpt_error,
1155 .targetsize = ARPT_FUNCTION_MAXNAMELEN,
1156 .family = NF_ARP,
1146}; 1157};
1147 1158
1148static struct nf_sockopt_ops arpt_sockopts = { 1159static struct nf_sockopt_ops arpt_sockopts = {
@@ -1162,8 +1173,8 @@ static int __init init(void)
1162 xt_proto_init(NF_ARP); 1173 xt_proto_init(NF_ARP);
1163 1174
1164 /* Noone else will be downing sem now, so we won't sleep */ 1175 /* Noone else will be downing sem now, so we won't sleep */
1165 xt_register_target(NF_ARP, &arpt_standard_target); 1176 xt_register_target(&arpt_standard_target);
1166 xt_register_target(NF_ARP, &arpt_error_target); 1177 xt_register_target(&arpt_error_target);
1167 1178
1168 /* Register setsockopt */ 1179 /* Register setsockopt */
1169 ret = nf_register_sockopt(&arpt_sockopts); 1180 ret = nf_register_sockopt(&arpt_sockopts);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index c97650a16a5b..0f2a95350e26 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -8,9 +8,10 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
8MODULE_DESCRIPTION("arptables arp payload mangle target"); 8MODULE_DESCRIPTION("arptables arp payload mangle target");
9 9
10static unsigned int 10static unsigned int
11target(struct sk_buff **pskb, const struct net_device *in, 11target(struct sk_buff **pskb,
12 const struct net_device *out, unsigned int hooknum, const void *targinfo, 12 const struct net_device *in, const struct net_device *out,
13 void *userinfo) 13 unsigned int hooknum, const struct xt_target *target,
14 const void *targinfo, void *userinfo)
14{ 15{
15 const struct arpt_mangle *mangle = targinfo; 16 const struct arpt_mangle *mangle = targinfo;
16 struct arphdr *arp; 17 struct arphdr *arp;
@@ -65,8 +66,8 @@ target(struct sk_buff **pskb, const struct net_device *in,
65} 66}
66 67
67static int 68static int
68checkentry(const char *tablename, const void *e, void *targinfo, 69checkentry(const char *tablename, const void *e, const struct xt_target *target,
69 unsigned int targinfosize, unsigned int hook_mask) 70 void *targinfo, unsigned int targinfosize, unsigned int hook_mask)
70{ 71{
71 const struct arpt_mangle *mangle = targinfo; 72 const struct arpt_mangle *mangle = targinfo;
72 73
@@ -80,12 +81,12 @@ checkentry(const char *tablename, const void *e, void *targinfo,
80 return 1; 81 return 1;
81} 82}
82 83
83static struct arpt_target arpt_mangle_reg 84static struct arpt_target arpt_mangle_reg = {
84= { 85 .name = "mangle",
85 .name = "mangle", 86 .target = target,
86 .target = target, 87 .targetsize = sizeof(struct arpt_mangle),
87 .checkentry = checkentry, 88 .checkentry = checkentry,
88 .me = THIS_MODULE, 89 .me = THIS_MODULE,
89}; 90};
90 91
91static int __init init(void) 92static int __init init(void)
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 84c66dbfedaf..9e34034729a6 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;
77static LIST_HEAD(unconfirmed); 77static LIST_HEAD(unconfirmed);
78static int ip_conntrack_vmalloc; 78static int ip_conntrack_vmalloc;
79 79
80static unsigned int ip_conntrack_next_id = 1; 80static unsigned int ip_conntrack_next_id;
81static unsigned int ip_conntrack_expect_next_id = 1; 81static unsigned int ip_conntrack_expect_next_id;
82#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS 82#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
83struct notifier_block *ip_conntrack_chain; 83struct notifier_block *ip_conntrack_chain;
84struct notifier_block *ip_conntrack_expect_chain; 84struct notifier_block *ip_conntrack_expect_chain;
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 000000000000..daeb1395faa4
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -0,0 +1,1731 @@
1/*
2 * H.323 connection tracking helper
3 *
4 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
5 *
6 * This source code is licensed under General Public License version 2.
7 *
8 * Based on the 'brute force' H.323 connection tracking module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 *
11 * For more information, please see http://nath323.sourceforge.net/
12 *
13 * Changes:
14 * 2006-02-01 - initial version 0.1
15 *
16 * 2006-02-20 - version 0.2
17 * 1. Changed source format to follow kernel conventions
18 * 2. Deleted some unnecessary structures
19 * 3. Minor fixes
20 *
21 * 2006-03-10 - version 0.3
22 * 1. Added support for multiple TPKTs in one packet (suggested by
23 * Patrick McHardy)
24 * 2. Avoid excessive stack usage (based on Patrick McHardy's patch)
25 * 3. Added support for non-linear skb (based on Patrick McHardy's patch)
26 * 4. Fixed missing H.245 module owner (Patrick McHardy)
27 * 5. Avoid long RAS expectation chains (Patrick McHardy)
28 * 6. Fixed incorrect __exit attribute (Patrick McHardy)
29 * 7. Eliminated unnecessary return code
30 * 8. Fixed incorrect use of NAT data from conntrack code (suggested by
31 * Patrick McHardy)
32 * 9. Fixed TTL calculation error in RCF
33 * 10. Added TTL support in RRQ
34 * 11. Better support for separate TPKT header and data
35 *
36 * 2006-03-15 - version 0.4
37 * 1. Added support for T.120 channels
38 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
39 * 3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
40 * 4. Sort ASN.1 data to avoid forwarding declarations (suggested by
41 * Patrick McHardy)
42 * 5. Reset next TPKT data length in get_tpkt_data()
43 */
44
45#include <linux/config.h>
46#include <linux/module.h>
47#include <linux/netfilter.h>
48#include <linux/ip.h>
49#include <net/tcp.h>
50#include <linux/netfilter_ipv4/ip_conntrack.h>
51#include <linux/netfilter_ipv4/ip_conntrack_core.h>
52#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
53#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
54#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
55#include <linux/moduleparam.h>
56
57#include "ip_conntrack_helper_h323_asn1.h"
58
59#if 0
60#define DEBUGP printk
61#else
62#define DEBUGP(format, args...)
63#endif
64
65/* Parameters */
66static int gkrouted_only = 1;
67module_param(gkrouted_only, int, 0600);
68MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
69
70/* Hooks for NAT */
71int (*set_h245_addr_hook) (struct sk_buff ** pskb,
72 unsigned char **data, int dataoff,
73 H245_TransportAddress * addr,
74 u_int32_t ip, u_int16_t port);
75int (*set_h225_addr_hook) (struct sk_buff ** pskb,
76 unsigned char **data, int dataoff,
77 TransportAddress * addr,
78 u_int32_t ip, u_int16_t port);
79int (*set_sig_addr_hook) (struct sk_buff ** pskb,
80 struct ip_conntrack * ct,
81 enum ip_conntrack_info ctinfo,
82 unsigned char **data,
83 TransportAddress * addr, int count);
84int (*set_ras_addr_hook) (struct sk_buff ** pskb,
85 struct ip_conntrack * ct,
86 enum ip_conntrack_info ctinfo,
87 unsigned char **data,
88 TransportAddress * addr, int count);
89int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
90 struct ip_conntrack * ct,
91 enum ip_conntrack_info ctinfo,
92 unsigned char **data, int dataoff,
93 H245_TransportAddress * addr,
94 u_int16_t port, u_int16_t rtp_port,
95 struct ip_conntrack_expect * rtp_exp,
96 struct ip_conntrack_expect * rtcp_exp);
97int (*nat_t120_hook) (struct sk_buff ** pskb,
98 struct ip_conntrack * ct,
99 enum ip_conntrack_info ctinfo,
100 unsigned char **data, int dataoff,
101 H245_TransportAddress * addr, u_int16_t port,
102 struct ip_conntrack_expect * exp);
103int (*nat_h245_hook) (struct sk_buff ** pskb,
104 struct ip_conntrack * ct,
105 enum ip_conntrack_info ctinfo,
106 unsigned char **data, int dataoff,
107 TransportAddress * addr, u_int16_t port,
108 struct ip_conntrack_expect * exp);
109int (*nat_q931_hook) (struct sk_buff ** pskb,
110 struct ip_conntrack * ct,
111 enum ip_conntrack_info ctinfo,
112 unsigned char **data, TransportAddress * addr, int idx,
113 u_int16_t port, struct ip_conntrack_expect * exp);
114
115
116static DEFINE_SPINLOCK(ip_h323_lock);
117static char *h323_buffer;
118
119/****************************************************************************/
120static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
121 enum ip_conntrack_info ctinfo,
122 unsigned char **data, int *datalen, int *dataoff)
123{
124 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
125 int dir = CTINFO2DIR(ctinfo);
126 struct tcphdr _tcph, *th;
127 int tcpdatalen;
128 int tcpdataoff;
129 unsigned char *tpkt;
130 int tpktlen;
131 int tpktoff;
132
133 /* Get TCP header */
134 th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
135 sizeof(_tcph), &_tcph);
136 if (th == NULL)
137 return 0;
138
139 /* Get TCP data offset */
140 tcpdataoff = (*pskb)->nh.iph->ihl * 4 + th->doff * 4;
141
142 /* Get TCP data length */
143 tcpdatalen = (*pskb)->len - tcpdataoff;
144 if (tcpdatalen <= 0) /* No TCP data */
145 goto clear_out;
146
147 if (*data == NULL) { /* first TPKT */
148 /* Get first TPKT pointer */
149 tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
150 h323_buffer);
151 BUG_ON(tpkt == NULL);
152
153 /* Validate TPKT identifier */
154 if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
155 /* Netmeeting sends TPKT header and data separately */
156 if (info->tpkt_len[dir] > 0) {
157 DEBUGP("ip_ct_h323: previous packet "
158 "indicated separate TPKT data of %hu "
159 "bytes\n", info->tpkt_len[dir]);
160 if (info->tpkt_len[dir] <= tcpdatalen) {
161 /* Yes, there was a TPKT header
162 * received */
163 *data = tpkt;
164 *datalen = info->tpkt_len[dir];
165 *dataoff = 0;
166 goto out;
167 }
168
169 /* Fragmented TPKT */
170 if (net_ratelimit())
171 printk("ip_ct_h323: "
172 "fragmented TPKT\n");
173 goto clear_out;
174 }
175
176 /* It is not even a TPKT */
177 return 0;
178 }
179 tpktoff = 0;
180 } else { /* Next TPKT */
181 tpktoff = *dataoff + *datalen;
182 tcpdatalen -= tpktoff;
183 if (tcpdatalen <= 4) /* No more TPKT */
184 goto clear_out;
185 tpkt = *data + *datalen;
186
187 /* Validate TPKT identifier */
188 if (tpkt[0] != 0x03 || tpkt[1] != 0)
189 goto clear_out;
190 }
191
192 /* Validate TPKT length */
193 tpktlen = tpkt[2] * 256 + tpkt[3];
194 if (tpktlen > tcpdatalen) {
195 if (tcpdatalen == 4) { /* Separate TPKT header */
196 /* Netmeeting sends TPKT header and data separately */
197 DEBUGP("ip_ct_h323: separate TPKT header indicates "
198 "there will be TPKT data of %hu bytes\n",
199 tpktlen - 4);
200 info->tpkt_len[dir] = tpktlen - 4;
201 return 0;
202 }
203
204 if (net_ratelimit())
205 printk("ip_ct_h323: incomplete TPKT (fragmented?)\n");
206 goto clear_out;
207 }
208
209 /* This is the encapsulated data */
210 *data = tpkt + 4;
211 *datalen = tpktlen - 4;
212 *dataoff = tpktoff + 4;
213
214 out:
215 /* Clear TPKT length */
216 info->tpkt_len[dir] = 0;
217 return 1;
218
219 clear_out:
220 info->tpkt_len[dir] = 0;
221 return 0;
222}
223
224/****************************************************************************/
225int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
226 u_int32_t * ip, u_int16_t * port)
227{
228 unsigned char *p;
229
230 if (addr->choice != eH245_TransportAddress_unicastAddress ||
231 addr->unicastAddress.choice != eUnicastAddress_iPAddress)
232 return 0;
233
234 p = data + addr->unicastAddress.iPAddress.network;
235 *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
236 *port = (p[4] << 8) | (p[5]);
237
238 return 1;
239}
240
241/****************************************************************************/
242static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
243 enum ip_conntrack_info ctinfo,
244 unsigned char **data, int dataoff,
245 H245_TransportAddress * addr)
246{
247 int dir = CTINFO2DIR(ctinfo);
248 int ret = 0;
249 u_int32_t ip;
250 u_int16_t port;
251 u_int16_t rtp_port;
252 struct ip_conntrack_expect *rtp_exp;
253 struct ip_conntrack_expect *rtcp_exp;
254
255 /* Read RTP or RTCP address */
256 if (!get_h245_addr(*data, addr, &ip, &port) ||
257 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
258 return 0;
259
260 /* RTP port is even */
261 rtp_port = port & (~1);
262
263 /* Create expect for RTP */
264 if ((rtp_exp = ip_conntrack_expect_alloc(ct)) == NULL)
265 return -1;
266 rtp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
267 rtp_exp->tuple.src.u.udp.port = 0;
268 rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
269 rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);
270 rtp_exp->tuple.dst.protonum = IPPROTO_UDP;
271 rtp_exp->mask.src.ip = 0xFFFFFFFF;
272 rtp_exp->mask.src.u.udp.port = 0;
273 rtp_exp->mask.dst.ip = 0xFFFFFFFF;
274 rtp_exp->mask.dst.u.udp.port = 0xFFFF;
275 rtp_exp->mask.dst.protonum = 0xFF;
276 rtp_exp->flags = 0;
277
278 /* Create expect for RTCP */
279 if ((rtcp_exp = ip_conntrack_expect_alloc(ct)) == NULL) {
280 ip_conntrack_expect_put(rtp_exp);
281 return -1;
282 }
283 rtcp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
284 rtcp_exp->tuple.src.u.udp.port = 0;
285 rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
286 rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);
287 rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;
288 rtcp_exp->mask.src.ip = 0xFFFFFFFF;
289 rtcp_exp->mask.src.u.udp.port = 0;
290 rtcp_exp->mask.dst.ip = 0xFFFFFFFF;
291 rtcp_exp->mask.dst.u.udp.port = 0xFFFF;
292 rtcp_exp->mask.dst.protonum = 0xFF;
293 rtcp_exp->flags = 0;
294
295 if (ct->tuplehash[dir].tuple.src.ip !=
296 ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) {
297 /* NAT needed */
298 ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff,
299 addr, port, rtp_port, rtp_exp,
300 rtcp_exp);
301 } else { /* Conntrack only */
302 rtp_exp->expectfn = NULL;
303 rtcp_exp->expectfn = NULL;
304
305 if (ip_conntrack_expect_related(rtp_exp) == 0) {
306 if (ip_conntrack_expect_related(rtcp_exp) == 0) {
307 DEBUGP("ip_ct_h323: expect RTP "
308 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
309 NIPQUAD(rtp_exp->tuple.src.ip),
310 ntohs(rtp_exp->tuple.src.u.udp.port),
311 NIPQUAD(rtp_exp->tuple.dst.ip),
312 ntohs(rtp_exp->tuple.dst.u.udp.port));
313 DEBUGP("ip_ct_h323: expect RTCP "
314 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
315 NIPQUAD(rtcp_exp->tuple.src.ip),
316 ntohs(rtcp_exp->tuple.src.u.udp.port),
317 NIPQUAD(rtcp_exp->tuple.dst.ip),
318 ntohs(rtcp_exp->tuple.dst.u.udp.port));
319 } else {
320 ip_conntrack_unexpect_related(rtp_exp);
321 ret = -1;
322 }
323 } else
324 ret = -1;
325 }
326
327 ip_conntrack_expect_put(rtp_exp);
328 ip_conntrack_expect_put(rtcp_exp);
329
330 return ret;
331}
332
333/****************************************************************************/
334static int expect_t120(struct sk_buff **pskb,
335 struct ip_conntrack *ct,
336 enum ip_conntrack_info ctinfo,
337 unsigned char **data, int dataoff,
338 H245_TransportAddress * addr)
339{
340 int dir = CTINFO2DIR(ctinfo);
341 int ret = 0;
342 u_int32_t ip;
343 u_int16_t port;
344 struct ip_conntrack_expect *exp = NULL;
345
346 /* Read T.120 address */
347 if (!get_h245_addr(*data, addr, &ip, &port) ||
348 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
349 return 0;
350
351 /* Create expect for T.120 connections */
352 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
353 return -1;
354 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
355 exp->tuple.src.u.tcp.port = 0;
356 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
357 exp->tuple.dst.u.tcp.port = htons(port);
358 exp->tuple.dst.protonum = IPPROTO_TCP;
359 exp->mask.src.ip = 0xFFFFFFFF;
360 exp->mask.src.u.tcp.port = 0;
361 exp->mask.dst.ip = 0xFFFFFFFF;
362 exp->mask.dst.u.tcp.port = 0xFFFF;
363 exp->mask.dst.protonum = 0xFF;
364 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */
365
366 if (ct->tuplehash[dir].tuple.src.ip !=
367 ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) {
368 /* NAT needed */
369 ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr,
370 port, exp);
371 } else { /* Conntrack only */
372 exp->expectfn = NULL;
373 if (ip_conntrack_expect_related(exp) == 0) {
374 DEBUGP("ip_ct_h323: expect T.120 "
375 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
376 NIPQUAD(exp->tuple.src.ip),
377 ntohs(exp->tuple.src.u.tcp.port),
378 NIPQUAD(exp->tuple.dst.ip),
379 ntohs(exp->tuple.dst.u.tcp.port));
380 } else
381 ret = -1;
382 }
383
384 ip_conntrack_expect_put(exp);
385
386 return ret;
387}
388
389/****************************************************************************/
390static int process_h245_channel(struct sk_buff **pskb,
391 struct ip_conntrack *ct,
392 enum ip_conntrack_info ctinfo,
393 unsigned char **data, int dataoff,
394 H2250LogicalChannelParameters * channel)
395{
396 int ret;
397
398 if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
399 /* RTP */
400 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
401 &channel->mediaChannel);
402 if (ret < 0)
403 return -1;
404 }
405
406 if (channel->
407 options & eH2250LogicalChannelParameters_mediaControlChannel) {
408 /* RTCP */
409 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
410 &channel->mediaControlChannel);
411 if (ret < 0)
412 return -1;
413 }
414
415 return 0;
416}
417
418/****************************************************************************/
419static int process_olc(struct sk_buff **pskb, struct ip_conntrack *ct,
420 enum ip_conntrack_info ctinfo,
421 unsigned char **data, int dataoff,
422 OpenLogicalChannel * olc)
423{
424 int ret;
425
426 DEBUGP("ip_ct_h323: OpenLogicalChannel\n");
427
428 if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
429 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
430 {
431 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
432 &olc->
433 forwardLogicalChannelParameters.
434 multiplexParameters.
435 h2250LogicalChannelParameters);
436 if (ret < 0)
437 return -1;
438 }
439
440 if ((olc->options &
441 eOpenLogicalChannel_reverseLogicalChannelParameters) &&
442 (olc->reverseLogicalChannelParameters.options &
443 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
444 && (olc->reverseLogicalChannelParameters.multiplexParameters.
445 choice ==
446 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
447 {
448 ret =
449 process_h245_channel(pskb, ct, ctinfo, data, dataoff,
450 &olc->
451 reverseLogicalChannelParameters.
452 multiplexParameters.
453 h2250LogicalChannelParameters);
454 if (ret < 0)
455 return -1;
456 }
457
458 if ((olc->options & eOpenLogicalChannel_separateStack) &&
459 olc->forwardLogicalChannelParameters.dataType.choice ==
460 eDataType_data &&
461 olc->forwardLogicalChannelParameters.dataType.data.application.
462 choice == eDataApplicationCapability_application_t120 &&
463 olc->forwardLogicalChannelParameters.dataType.data.application.
464 t120.choice == eDataProtocolCapability_separateLANStack &&
465 olc->separateStack.networkAddress.choice ==
466 eNetworkAccessParameters_networkAddress_localAreaAddress) {
467 ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
468 &olc->separateStack.networkAddress.
469 localAreaAddress);
470 if (ret < 0)
471 return -1;
472 }
473
474 return 0;
475}
476
477/****************************************************************************/
478static int process_olca(struct sk_buff **pskb, struct ip_conntrack *ct,
479 enum ip_conntrack_info ctinfo,
480 unsigned char **data, int dataoff,
481 OpenLogicalChannelAck * olca)
482{
483 H2250LogicalChannelAckParameters *ack;
484 int ret;
485
486 DEBUGP("ip_ct_h323: OpenLogicalChannelAck\n");
487
488 if ((olca->options &
489 eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
490 (olca->reverseLogicalChannelParameters.options &
491 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
492 && (olca->reverseLogicalChannelParameters.multiplexParameters.
493 choice ==
494 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
495 {
496 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
497 &olca->
498 reverseLogicalChannelParameters.
499 multiplexParameters.
500 h2250LogicalChannelParameters);
501 if (ret < 0)
502 return -1;
503 }
504
505 if ((olca->options &
506 eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
507 (olca->forwardMultiplexAckParameters.choice ==
508 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
509 {
510 ack = &olca->forwardMultiplexAckParameters.
511 h2250LogicalChannelAckParameters;
512 if (ack->options &
513 eH2250LogicalChannelAckParameters_mediaChannel) {
514 /* RTP */
515 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
516 &ack->mediaChannel);
517 if (ret < 0)
518 return -1;
519 }
520
521 if (ack->options &
522 eH2250LogicalChannelAckParameters_mediaControlChannel) {
523 /* RTCP */
524 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
525 &ack->mediaControlChannel);
526 if (ret < 0)
527 return -1;
528 }
529 }
530
531 return 0;
532}
533
534/****************************************************************************/
535static int process_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
536 enum ip_conntrack_info ctinfo,
537 unsigned char **data, int dataoff,
538 MultimediaSystemControlMessage * mscm)
539{
540 switch (mscm->choice) {
541 case eMultimediaSystemControlMessage_request:
542 if (mscm->request.choice ==
543 eRequestMessage_openLogicalChannel) {
544 return process_olc(pskb, ct, ctinfo, data, dataoff,
545 &mscm->request.openLogicalChannel);
546 }
547 DEBUGP("ip_ct_h323: H.245 Request %d\n",
548 mscm->request.choice);
549 break;
550 case eMultimediaSystemControlMessage_response:
551 if (mscm->response.choice ==
552 eResponseMessage_openLogicalChannelAck) {
553 return process_olca(pskb, ct, ctinfo, data, dataoff,
554 &mscm->response.
555 openLogicalChannelAck);
556 }
557 DEBUGP("ip_ct_h323: H.245 Response %d\n",
558 mscm->response.choice);
559 break;
560 default:
561 DEBUGP("ip_ct_h323: H.245 signal %d\n", mscm->choice);
562 break;
563 }
564
565 return 0;
566}
567
568/****************************************************************************/
569static int h245_help(struct sk_buff **pskb, struct ip_conntrack *ct,
570 enum ip_conntrack_info ctinfo)
571{
572 static MultimediaSystemControlMessage mscm;
573 unsigned char *data = NULL;
574 int datalen;
575 int dataoff;
576 int ret;
577
578 /* Until there's been traffic both ways, don't look in packets. */
579 if (ctinfo != IP_CT_ESTABLISHED
580 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
581 return NF_ACCEPT;
582 }
583 DEBUGP("ip_ct_h245: skblen = %u\n", (*pskb)->len);
584
585 spin_lock_bh(&ip_h323_lock);
586
587 /* Process each TPKT */
588 while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
589 DEBUGP("ip_ct_h245: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
590 NIPQUAD((*pskb)->nh.iph->saddr),
591 NIPQUAD((*pskb)->nh.iph->daddr), datalen);
592
593 /* Decode H.245 signal */
594 ret = DecodeMultimediaSystemControlMessage(data, datalen,
595 &mscm);
596 if (ret < 0) {
597 if (net_ratelimit())
598 printk("ip_ct_h245: decoding error: %s\n",
599 ret == H323_ERROR_BOUND ?
600 "out of bound" : "out of range");
601 /* We don't drop when decoding error */
602 break;
603 }
604
605 /* Process H.245 signal */
606 if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
607 goto drop;
608 }
609
610 spin_unlock_bh(&ip_h323_lock);
611 return NF_ACCEPT;
612
613 drop:
614 spin_unlock_bh(&ip_h323_lock);
615 if (net_ratelimit())
616 printk("ip_ct_h245: packet dropped\n");
617 return NF_DROP;
618}
619
620/****************************************************************************/
621static struct ip_conntrack_helper ip_conntrack_helper_h245 = {
622 .name = "H.245",
623 .me = THIS_MODULE,
624 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */ ,
625 .timeout = 240,
626 .tuple = {.dst = {.protonum = IPPROTO_TCP}},
627 .mask = {.src = {.u = {0xFFFF}},
628 .dst = {.protonum = 0xFF}},
629 .help = h245_help
630};
631
632/****************************************************************************/
633void ip_conntrack_h245_expect(struct ip_conntrack *new,
634 struct ip_conntrack_expect *this)
635{
636 write_lock_bh(&ip_conntrack_lock);
637 new->helper = &ip_conntrack_helper_h245;
638 write_unlock_bh(&ip_conntrack_lock);
639}
640
641/****************************************************************************/
642int get_h225_addr(unsigned char *data, TransportAddress * addr,
643 u_int32_t * ip, u_int16_t * port)
644{
645 unsigned char *p;
646
647 if (addr->choice != eTransportAddress_ipAddress)
648 return 0;
649
650 p = data + addr->ipAddress.ip;
651 *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
652 *port = (p[4] << 8) | (p[5]);
653
654 return 1;
655}
656
657/****************************************************************************/
658static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
659 enum ip_conntrack_info ctinfo,
660 unsigned char **data, int dataoff,
661 TransportAddress * addr)
662{
663 int dir = CTINFO2DIR(ctinfo);
664 int ret = 0;
665 u_int32_t ip;
666 u_int16_t port;
667 struct ip_conntrack_expect *exp = NULL;
668
669 /* Read h245Address */
670 if (!get_h225_addr(*data, addr, &ip, &port) ||
671 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
672 return 0;
673
674 /* Create expect for h245 connection */
675 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
676 return -1;
677 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
678 exp->tuple.src.u.tcp.port = 0;
679 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
680 exp->tuple.dst.u.tcp.port = htons(port);
681 exp->tuple.dst.protonum = IPPROTO_TCP;
682 exp->mask.src.ip = 0xFFFFFFFF;
683 exp->mask.src.u.tcp.port = 0;
684 exp->mask.dst.ip = 0xFFFFFFFF;
685 exp->mask.dst.u.tcp.port = 0xFFFF;
686 exp->mask.dst.protonum = 0xFF;
687 exp->flags = 0;
688
689 if (ct->tuplehash[dir].tuple.src.ip !=
690 ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) {
691 /* NAT needed */
692 ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr,
693 port, exp);
694 } else { /* Conntrack only */
695 exp->expectfn = ip_conntrack_h245_expect;
696
697 if (ip_conntrack_expect_related(exp) == 0) {
698 DEBUGP("ip_ct_q931: expect H.245 "
699 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
700 NIPQUAD(exp->tuple.src.ip),
701 ntohs(exp->tuple.src.u.tcp.port),
702 NIPQUAD(exp->tuple.dst.ip),
703 ntohs(exp->tuple.dst.u.tcp.port));
704 } else
705 ret = -1;
706 }
707
708 ip_conntrack_expect_put(exp);
709
710 return ret;
711}
712
713/****************************************************************************/
714static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
715 enum ip_conntrack_info ctinfo,
716 unsigned char **data, int dataoff,
717 Setup_UUIE * setup)
718{
719 int dir = CTINFO2DIR(ctinfo);
720 int ret;
721 int i;
722 u_int32_t ip;
723 u_int16_t port;
724
725 DEBUGP("ip_ct_q931: Setup\n");
726
727 if (setup->options & eSetup_UUIE_h245Address) {
728 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
729 &setup->h245Address);
730 if (ret < 0)
731 return -1;
732 }
733
734 if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
735 (set_h225_addr_hook) &&
736 get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
737 ip != ct->tuplehash[!dir].tuple.src.ip) {
738 DEBUGP("ip_ct_q931: set destCallSignalAddress "
739 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
740 NIPQUAD(ip), port,
741 NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
742 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
743 ret = set_h225_addr_hook(pskb, data, dataoff,
744 &setup->destCallSignalAddress,
745 ct->tuplehash[!dir].tuple.src.ip,
746 ntohs(ct->tuplehash[!dir].tuple.src.
747 u.tcp.port));
748 if (ret < 0)
749 return -1;
750 }
751
752 if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
753 (set_h225_addr_hook) &&
754 get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
755 && ip != ct->tuplehash[!dir].tuple.dst.ip) {
756 DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
757 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
758 NIPQUAD(ip), port,
759 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
760 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
761 ret = set_h225_addr_hook(pskb, data, dataoff,
762 &setup->sourceCallSignalAddress,
763 ct->tuplehash[!dir].tuple.dst.ip,
764 ntohs(ct->tuplehash[!dir].tuple.dst.
765 u.tcp.port));
766 if (ret < 0)
767 return -1;
768 }
769
770 if (setup->options & eSetup_UUIE_fastStart) {
771 for (i = 0; i < setup->fastStart.count; i++) {
772 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
773 &setup->fastStart.item[i]);
774 if (ret < 0)
775 return -1;
776 }
777 }
778
779 return 0;
780}
781
782/****************************************************************************/
783static int process_callproceeding(struct sk_buff **pskb,
784 struct ip_conntrack *ct,
785 enum ip_conntrack_info ctinfo,
786 unsigned char **data, int dataoff,
787 CallProceeding_UUIE * callproc)
788{
789 int ret;
790 int i;
791
792 DEBUGP("ip_ct_q931: CallProceeding\n");
793
794 if (callproc->options & eCallProceeding_UUIE_h245Address) {
795 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
796 &callproc->h245Address);
797 if (ret < 0)
798 return -1;
799 }
800
801 if (callproc->options & eCallProceeding_UUIE_fastStart) {
802 for (i = 0; i < callproc->fastStart.count; i++) {
803 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
804 &callproc->fastStart.item[i]);
805 if (ret < 0)
806 return -1;
807 }
808 }
809
810 return 0;
811}
812
813/****************************************************************************/
814static int process_connect(struct sk_buff **pskb, struct ip_conntrack *ct,
815 enum ip_conntrack_info ctinfo,
816 unsigned char **data, int dataoff,
817 Connect_UUIE * connect)
818{
819 int ret;
820 int i;
821
822 DEBUGP("ip_ct_q931: Connect\n");
823
824 if (connect->options & eConnect_UUIE_h245Address) {
825 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
826 &connect->h245Address);
827 if (ret < 0)
828 return -1;
829 }
830
831 if (connect->options & eConnect_UUIE_fastStart) {
832 for (i = 0; i < connect->fastStart.count; i++) {
833 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
834 &connect->fastStart.item[i]);
835 if (ret < 0)
836 return -1;
837 }
838 }
839
840 return 0;
841}
842
843/****************************************************************************/
844static int process_alerting(struct sk_buff **pskb, struct ip_conntrack *ct,
845 enum ip_conntrack_info ctinfo,
846 unsigned char **data, int dataoff,
847 Alerting_UUIE * alert)
848{
849 int ret;
850 int i;
851
852 DEBUGP("ip_ct_q931: Alerting\n");
853
854 if (alert->options & eAlerting_UUIE_h245Address) {
855 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
856 &alert->h245Address);
857 if (ret < 0)
858 return -1;
859 }
860
861 if (alert->options & eAlerting_UUIE_fastStart) {
862 for (i = 0; i < alert->fastStart.count; i++) {
863 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
864 &alert->fastStart.item[i]);
865 if (ret < 0)
866 return -1;
867 }
868 }
869
870 return 0;
871}
872
873/****************************************************************************/
874static int process_information(struct sk_buff **pskb,
875 struct ip_conntrack *ct,
876 enum ip_conntrack_info ctinfo,
877 unsigned char **data, int dataoff,
878 Information_UUIE * info)
879{
880 int ret;
881 int i;
882
883 DEBUGP("ip_ct_q931: Information\n");
884
885 if (info->options & eInformation_UUIE_fastStart) {
886 for (i = 0; i < info->fastStart.count; i++) {
887 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
888 &info->fastStart.item[i]);
889 if (ret < 0)
890 return -1;
891 }
892 }
893
894 return 0;
895}
896
897/****************************************************************************/
898static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
899 enum ip_conntrack_info ctinfo,
900 unsigned char **data, int dataoff,
901 Facility_UUIE * facility)
902{
903 int ret;
904 int i;
905
906 DEBUGP("ip_ct_q931: Facility\n");
907
908 if (facility->options & eFacility_UUIE_h245Address) {
909 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
910 &facility->h245Address);
911 if (ret < 0)
912 return -1;
913 }
914
915 if (facility->options & eFacility_UUIE_fastStart) {
916 for (i = 0; i < facility->fastStart.count; i++) {
917 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
918 &facility->fastStart.item[i]);
919 if (ret < 0)
920 return -1;
921 }
922 }
923
924 return 0;
925}
926
927/****************************************************************************/
928static int process_progress(struct sk_buff **pskb, struct ip_conntrack *ct,
929 enum ip_conntrack_info ctinfo,
930 unsigned char **data, int dataoff,
931 Progress_UUIE * progress)
932{
933 int ret;
934 int i;
935
936 DEBUGP("ip_ct_q931: Progress\n");
937
938 if (progress->options & eProgress_UUIE_h245Address) {
939 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
940 &progress->h245Address);
941 if (ret < 0)
942 return -1;
943 }
944
945 if (progress->options & eProgress_UUIE_fastStart) {
946 for (i = 0; i < progress->fastStart.count; i++) {
947 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
948 &progress->fastStart.item[i]);
949 if (ret < 0)
950 return -1;
951 }
952 }
953
954 return 0;
955}
956
957/****************************************************************************/
958static int process_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
959 enum ip_conntrack_info ctinfo,
960 unsigned char **data, int dataoff, Q931 * q931)
961{
962 H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
963 int i;
964 int ret = 0;
965
966 switch (pdu->h323_message_body.choice) {
967 case eH323_UU_PDU_h323_message_body_setup:
968 ret = process_setup(pskb, ct, ctinfo, data, dataoff,
969 &pdu->h323_message_body.setup);
970 break;
971 case eH323_UU_PDU_h323_message_body_callProceeding:
972 ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
973 &pdu->h323_message_body.
974 callProceeding);
975 break;
976 case eH323_UU_PDU_h323_message_body_connect:
977 ret = process_connect(pskb, ct, ctinfo, data, dataoff,
978 &pdu->h323_message_body.connect);
979 break;
980 case eH323_UU_PDU_h323_message_body_alerting:
981 ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
982 &pdu->h323_message_body.alerting);
983 break;
984 case eH323_UU_PDU_h323_message_body_information:
985 ret = process_information(pskb, ct, ctinfo, data, dataoff,
986 &pdu->h323_message_body.
987 information);
988 break;
989 case eH323_UU_PDU_h323_message_body_facility:
990 ret = process_facility(pskb, ct, ctinfo, data, dataoff,
991 &pdu->h323_message_body.facility);
992 break;
993 case eH323_UU_PDU_h323_message_body_progress:
994 ret = process_progress(pskb, ct, ctinfo, data, dataoff,
995 &pdu->h323_message_body.progress);
996 break;
997 default:
998 DEBUGP("ip_ct_q931: Q.931 signal %d\n",
999 pdu->h323_message_body.choice);
1000 break;
1001 }
1002
1003 if (ret < 0)
1004 return -1;
1005
1006 if (pdu->options & eH323_UU_PDU_h245Control) {
1007 for (i = 0; i < pdu->h245Control.count; i++) {
1008 ret = process_h245(pskb, ct, ctinfo, data, dataoff,
1009 &pdu->h245Control.item[i]);
1010 if (ret < 0)
1011 return -1;
1012 }
1013 }
1014
1015 return 0;
1016}
1017
1018/****************************************************************************/
1019static int q931_help(struct sk_buff **pskb, struct ip_conntrack *ct,
1020 enum ip_conntrack_info ctinfo)
1021{
1022 static Q931 q931;
1023 unsigned char *data = NULL;
1024 int datalen;
1025 int dataoff;
1026 int ret;
1027
1028 /* Until there's been traffic both ways, don't look in packets. */
1029 if (ctinfo != IP_CT_ESTABLISHED
1030 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1031 return NF_ACCEPT;
1032 }
1033 DEBUGP("ip_ct_q931: skblen = %u\n", (*pskb)->len);
1034
1035 spin_lock_bh(&ip_h323_lock);
1036
1037 /* Process each TPKT */
1038 while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
1039 DEBUGP("ip_ct_q931: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
1040 NIPQUAD((*pskb)->nh.iph->saddr),
1041 NIPQUAD((*pskb)->nh.iph->daddr), datalen);
1042
1043 /* Decode Q.931 signal */
1044 ret = DecodeQ931(data, datalen, &q931);
1045 if (ret < 0) {
1046 if (net_ratelimit())
1047 printk("ip_ct_q931: decoding error: %s\n",
1048 ret == H323_ERROR_BOUND ?
1049 "out of bound" : "out of range");
1050 /* We don't drop when decoding error */
1051 break;
1052 }
1053
1054 /* Process Q.931 signal */
1055 if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
1056 goto drop;
1057 }
1058
1059 spin_unlock_bh(&ip_h323_lock);
1060 return NF_ACCEPT;
1061
1062 drop:
1063 spin_unlock_bh(&ip_h323_lock);
1064 if (net_ratelimit())
1065 printk("ip_ct_q931: packet dropped\n");
1066 return NF_DROP;
1067}
1068
1069/****************************************************************************/
1070static struct ip_conntrack_helper ip_conntrack_helper_q931 = {
1071 .name = "Q.931",
1072 .me = THIS_MODULE,
1073 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ ,
1074 .timeout = 240,
1075 .tuple = {.src = {.u = {__constant_htons(Q931_PORT)}},
1076 .dst = {.protonum = IPPROTO_TCP}},
1077 .mask = {.src = {.u = {0xFFFF}},
1078 .dst = {.protonum = 0xFF}},
1079 .help = q931_help
1080};
1081
1082/****************************************************************************/
1083void ip_conntrack_q931_expect(struct ip_conntrack *new,
1084 struct ip_conntrack_expect *this)
1085{
1086 write_lock_bh(&ip_conntrack_lock);
1087 new->helper = &ip_conntrack_helper_q931;
1088 write_unlock_bh(&ip_conntrack_lock);
1089}
1090
1091/****************************************************************************/
1092static unsigned char *get_udp_data(struct sk_buff **pskb, int *datalen)
1093{
1094 struct udphdr _uh, *uh;
1095 int dataoff;
1096
1097 uh = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, sizeof(_uh),
1098 &_uh);
1099 if (uh == NULL)
1100 return NULL;
1101 dataoff = (*pskb)->nh.iph->ihl * 4 + sizeof(_uh);
1102 if (dataoff >= (*pskb)->len)
1103 return NULL;
1104 *datalen = (*pskb)->len - dataoff;
1105 return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
1106}
1107
1108/****************************************************************************/
1109static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct,
1110 u_int32_t ip, u_int16_t port)
1111{
1112 struct ip_conntrack_expect *exp;
1113 struct ip_conntrack_tuple tuple;
1114
1115 tuple.src.ip = 0;
1116 tuple.src.u.tcp.port = 0;
1117 tuple.dst.ip = ip;
1118 tuple.dst.u.tcp.port = htons(port);
1119 tuple.dst.protonum = IPPROTO_TCP;
1120
1121 exp = __ip_conntrack_expect_find(&tuple);
1122 if (exp->master == ct)
1123 return exp;
1124 return NULL;
1125}
1126
1127/****************************************************************************/
1128static int set_expect_timeout(struct ip_conntrack_expect *exp,
1129 unsigned timeout)
1130{
1131 if (!exp || !del_timer(&exp->timeout))
1132 return 0;
1133
1134 exp->timeout.expires = jiffies + timeout * HZ;
1135 add_timer(&exp->timeout);
1136
1137 return 1;
1138}
1139
1140/****************************************************************************/
1141static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
1142 enum ip_conntrack_info ctinfo,
1143 unsigned char **data,
1144 TransportAddress * addr, int count)
1145{
1146 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1147 int dir = CTINFO2DIR(ctinfo);
1148 int ret = 0;
1149 int i;
1150 u_int32_t ip;
1151 u_int16_t port;
1152 struct ip_conntrack_expect *exp;
1153
1154 /* Look for the first related address */
1155 for (i = 0; i < count; i++) {
1156 if (get_h225_addr(*data, &addr[i], &ip, &port) &&
1157 ip == ct->tuplehash[dir].tuple.src.ip && port != 0)
1158 break;
1159 }
1160
1161 if (i >= count) /* Not found */
1162 return 0;
1163
1164 /* Create expect for Q.931 */
1165 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1166 return -1;
1167 exp->tuple.src.ip = gkrouted_only ? /* only accept calls from GK? */
1168 ct->tuplehash[!dir].tuple.src.ip : 0;
1169 exp->tuple.src.u.tcp.port = 0;
1170 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
1171 exp->tuple.dst.u.tcp.port = htons(port);
1172 exp->tuple.dst.protonum = IPPROTO_TCP;
1173 exp->mask.src.ip = gkrouted_only ? 0xFFFFFFFF : 0;
1174 exp->mask.src.u.tcp.port = 0;
1175 exp->mask.dst.ip = 0xFFFFFFFF;
1176 exp->mask.dst.u.tcp.port = 0xFFFF;
1177 exp->mask.dst.protonum = 0xFF;
1178 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */
1179
1180 if (nat_q931_hook) { /* Need NAT */
1181 ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i,
1182 port, exp);
1183 } else { /* Conntrack only */
1184 exp->expectfn = ip_conntrack_q931_expect;
1185
1186 if (ip_conntrack_expect_related(exp) == 0) {
1187 DEBUGP("ip_ct_ras: expect Q.931 "
1188 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1189 NIPQUAD(exp->tuple.src.ip),
1190 ntohs(exp->tuple.src.u.tcp.port),
1191 NIPQUAD(exp->tuple.dst.ip),
1192 ntohs(exp->tuple.dst.u.tcp.port));
1193
1194 /* Save port for looking up expect in processing RCF */
1195 info->sig_port[dir] = port;
1196 } else
1197 ret = -1;
1198 }
1199
1200 ip_conntrack_expect_put(exp);
1201
1202 return ret;
1203}
1204
1205/****************************************************************************/
1206static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct,
1207 enum ip_conntrack_info ctinfo,
1208 unsigned char **data, GatekeeperRequest * grq)
1209{
1210 DEBUGP("ip_ct_ras: GRQ\n");
1211
1212 if (set_ras_addr_hook) /* NATed */
1213 return set_ras_addr_hook(pskb, ct, ctinfo, data,
1214 &grq->rasAddress, 1);
1215 return 0;
1216}
1217
1218/* Declare before using */
1219static void ip_conntrack_ras_expect(struct ip_conntrack *new,
1220 struct ip_conntrack_expect *this);
1221
1222/****************************************************************************/
1223static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1224 enum ip_conntrack_info ctinfo,
1225 unsigned char **data, GatekeeperConfirm * gcf)
1226{
1227 int dir = CTINFO2DIR(ctinfo);
1228 int ret = 0;
1229 u_int32_t ip;
1230 u_int16_t port;
1231 struct ip_conntrack_expect *exp;
1232
1233 DEBUGP("ip_ct_ras: GCF\n");
1234
1235 if (!get_h225_addr(*data, &gcf->rasAddress, &ip, &port))
1236 return 0;
1237
1238 /* Registration port is the same as discovery port */
1239 if (ip == ct->tuplehash[dir].tuple.src.ip &&
1240 port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port))
1241 return 0;
1242
1243 /* Avoid RAS expectation loops. A GCF is never expected. */
1244 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
1245 return 0;
1246
1247 /* Need new expect */
1248 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1249 return -1;
1250 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1251 exp->tuple.src.u.tcp.port = 0;
1252 exp->tuple.dst.ip = ip;
1253 exp->tuple.dst.u.tcp.port = htons(port);
1254 exp->tuple.dst.protonum = IPPROTO_UDP;
1255 exp->mask.src.ip = 0xFFFFFFFF;
1256 exp->mask.src.u.tcp.port = 0;
1257 exp->mask.dst.ip = 0xFFFFFFFF;
1258 exp->mask.dst.u.tcp.port = 0xFFFF;
1259 exp->mask.dst.protonum = 0xFF;
1260 exp->flags = 0;
1261 exp->expectfn = ip_conntrack_ras_expect;
1262 if (ip_conntrack_expect_related(exp) == 0) {
1263 DEBUGP("ip_ct_ras: expect RAS "
1264 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1265 NIPQUAD(exp->tuple.src.ip),
1266 ntohs(exp->tuple.src.u.tcp.port),
1267 NIPQUAD(exp->tuple.dst.ip),
1268 ntohs(exp->tuple.dst.u.tcp.port));
1269 } else
1270 ret = -1;
1271
1272 ip_conntrack_expect_put(exp);
1273
1274 return ret;
1275}
1276
1277/****************************************************************************/
1278static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1279 enum ip_conntrack_info ctinfo,
1280 unsigned char **data, RegistrationRequest * rrq)
1281{
1282 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1283 int ret;
1284
1285 DEBUGP("ip_ct_ras: RRQ\n");
1286
1287 ret = expect_q931(pskb, ct, ctinfo, data,
1288 rrq->callSignalAddress.item,
1289 rrq->callSignalAddress.count);
1290 if (ret < 0)
1291 return -1;
1292
1293 if (set_ras_addr_hook) {
1294 ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
1295 rrq->rasAddress.item,
1296 rrq->rasAddress.count);
1297 if (ret < 0)
1298 return -1;
1299 }
1300
1301 if (rrq->options & eRegistrationRequest_timeToLive) {
1302 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
1303 info->timeout = rrq->timeToLive;
1304 } else
1305 info->timeout = 0;
1306
1307 return 0;
1308}
1309
1310/****************************************************************************/
1311static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1312 enum ip_conntrack_info ctinfo,
1313 unsigned char **data, RegistrationConfirm * rcf)
1314{
1315 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1316 int dir = CTINFO2DIR(ctinfo);
1317 int ret;
1318 struct ip_conntrack_expect *exp;
1319
1320 DEBUGP("ip_ct_ras: RCF\n");
1321
1322 if (set_sig_addr_hook) {
1323 ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
1324 rcf->callSignalAddress.item,
1325 rcf->callSignalAddress.count);
1326 if (ret < 0)
1327 return -1;
1328 }
1329
1330 if (rcf->options & eRegistrationConfirm_timeToLive) {
1331 DEBUGP("ip_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
1332 info->timeout = rcf->timeToLive;
1333 }
1334
1335 if (info->timeout > 0) {
1336 DEBUGP
1337 ("ip_ct_ras: set RAS connection timeout to %u seconds\n",
1338 info->timeout);
1339 ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ);
1340
1341 /* Set expect timeout */
1342 read_lock_bh(&ip_conntrack_lock);
1343 exp = find_expect(ct, ct->tuplehash[dir].tuple.dst.ip,
1344 info->sig_port[!dir]);
1345 if (exp) {
1346 DEBUGP("ip_ct_ras: set Q.931 expect "
1347 "(%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu) "
1348 "timeout to %u seconds\n",
1349 NIPQUAD(exp->tuple.src.ip),
1350 ntohs(exp->tuple.src.u.tcp.port),
1351 NIPQUAD(exp->tuple.dst.ip),
1352 ntohs(exp->tuple.dst.u.tcp.port),
1353 info->timeout);
1354 set_expect_timeout(exp, info->timeout);
1355 }
1356 read_unlock_bh(&ip_conntrack_lock);
1357 }
1358
1359 return 0;
1360}
1361
1362/****************************************************************************/
1363static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
1364 enum ip_conntrack_info ctinfo,
1365 unsigned char **data, UnregistrationRequest * urq)
1366{
1367 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1368 int dir = CTINFO2DIR(ctinfo);
1369 int ret;
1370
1371 DEBUGP("ip_ct_ras: URQ\n");
1372
1373 if (set_sig_addr_hook) {
1374 ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
1375 urq->callSignalAddress.item,
1376 urq->callSignalAddress.count);
1377 if (ret < 0)
1378 return -1;
1379 }
1380
1381 /* Clear old expect */
1382 ip_ct_remove_expectations(ct);
1383 info->sig_port[dir] = 0;
1384 info->sig_port[!dir] = 0;
1385
1386 /* Give it 30 seconds for UCF or URJ */
1387 ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ);
1388
1389 return 0;
1390}
1391
1392/****************************************************************************/
1393static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
1394 enum ip_conntrack_info ctinfo,
1395 unsigned char **data, AdmissionRequest * arq)
1396{
1397 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1398 int dir = CTINFO2DIR(ctinfo);
1399 u_int32_t ip;
1400 u_int16_t port;
1401
1402 DEBUGP("ip_ct_ras: ARQ\n");
1403
1404 if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
1405 get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
1406 ip == ct->tuplehash[dir].tuple.src.ip &&
1407 port == info->sig_port[dir] && set_h225_addr_hook) {
1408 /* Answering ARQ */
1409 return set_h225_addr_hook(pskb, data, 0,
1410 &arq->destCallSignalAddress,
1411 ct->tuplehash[!dir].tuple.dst.ip,
1412 info->sig_port[!dir]);
1413 }
1414
1415 if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
1416 get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
1417 ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) {
1418 /* Calling ARQ */
1419 return set_h225_addr_hook(pskb, data, 0,
1420 &arq->srcCallSignalAddress,
1421 ct->tuplehash[!dir].tuple.dst.ip,
1422 port);
1423 }
1424
1425 return 0;
1426}
1427
1428/****************************************************************************/
1429static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
1430 enum ip_conntrack_info ctinfo,
1431 unsigned char **data, AdmissionConfirm * acf)
1432{
1433 int dir = CTINFO2DIR(ctinfo);
1434 int ret = 0;
1435 u_int32_t ip;
1436 u_int16_t port;
1437 struct ip_conntrack_expect *exp;
1438
1439 DEBUGP("ip_ct_ras: ACF\n");
1440
1441 if (!get_h225_addr(*data, &acf->destCallSignalAddress, &ip, &port))
1442 return 0;
1443
1444 if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */
1445 if (set_sig_addr_hook)
1446 return set_sig_addr_hook(pskb, ct, ctinfo, data,
1447 &acf->destCallSignalAddress,
1448 1);
1449 return 0;
1450 }
1451
1452 /* Need new expect */
1453 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1454 return -1;
1455 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1456 exp->tuple.src.u.tcp.port = 0;
1457 exp->tuple.dst.ip = ip;
1458 exp->tuple.dst.u.tcp.port = htons(port);
1459 exp->tuple.dst.protonum = IPPROTO_TCP;
1460 exp->mask.src.ip = 0xFFFFFFFF;
1461 exp->mask.src.u.tcp.port = 0;
1462 exp->mask.dst.ip = 0xFFFFFFFF;
1463 exp->mask.dst.u.tcp.port = 0xFFFF;
1464 exp->mask.dst.protonum = 0xFF;
1465 exp->flags = IP_CT_EXPECT_PERMANENT;
1466 exp->expectfn = ip_conntrack_q931_expect;
1467
1468 if (ip_conntrack_expect_related(exp) == 0) {
1469 DEBUGP("ip_ct_ras: expect Q.931 "
1470 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1471 NIPQUAD(exp->tuple.src.ip),
1472 ntohs(exp->tuple.src.u.tcp.port),
1473 NIPQUAD(exp->tuple.dst.ip),
1474 ntohs(exp->tuple.dst.u.tcp.port));
1475 } else
1476 ret = -1;
1477
1478 ip_conntrack_expect_put(exp);
1479
1480 return ret;
1481}
1482
1483/****************************************************************************/
1484static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1485 enum ip_conntrack_info ctinfo,
1486 unsigned char **data, LocationRequest * lrq)
1487{
1488 DEBUGP("ip_ct_ras: LRQ\n");
1489
1490 if (set_ras_addr_hook)
1491 return set_ras_addr_hook(pskb, ct, ctinfo, data,
1492 &lrq->replyAddress, 1);
1493 return 0;
1494}
1495
1496/****************************************************************************/
1497static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1498 enum ip_conntrack_info ctinfo,
1499 unsigned char **data, LocationConfirm * lcf)
1500{
1501 int dir = CTINFO2DIR(ctinfo);
1502 int ret = 0;
1503 u_int32_t ip;
1504 u_int16_t port;
1505 struct ip_conntrack_expect *exp = NULL;
1506
1507 DEBUGP("ip_ct_ras: LCF\n");
1508
1509 if (!get_h225_addr(*data, &lcf->callSignalAddress, &ip, &port))
1510 return 0;
1511
1512 /* Need new expect for call signal */
1513 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1514 return -1;
1515 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1516 exp->tuple.src.u.tcp.port = 0;
1517 exp->tuple.dst.ip = ip;
1518 exp->tuple.dst.u.tcp.port = htons(port);
1519 exp->tuple.dst.protonum = IPPROTO_TCP;
1520 exp->mask.src.ip = 0xFFFFFFFF;
1521 exp->mask.src.u.tcp.port = 0;
1522 exp->mask.dst.ip = 0xFFFFFFFF;
1523 exp->mask.dst.u.tcp.port = 0xFFFF;
1524 exp->mask.dst.protonum = 0xFF;
1525 exp->flags = IP_CT_EXPECT_PERMANENT;
1526 exp->expectfn = ip_conntrack_q931_expect;
1527
1528 if (ip_conntrack_expect_related(exp) == 0) {
1529 DEBUGP("ip_ct_ras: expect Q.931 "
1530 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1531 NIPQUAD(exp->tuple.src.ip),
1532 ntohs(exp->tuple.src.u.tcp.port),
1533 NIPQUAD(exp->tuple.dst.ip),
1534 ntohs(exp->tuple.dst.u.tcp.port));
1535 } else
1536 ret = -1;
1537
1538 ip_conntrack_expect_put(exp);
1539
1540 /* Ignore rasAddress */
1541
1542 return ret;
1543}
1544
1545/****************************************************************************/
1546static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct,
1547 enum ip_conntrack_info ctinfo,
1548 unsigned char **data, InfoRequestResponse * irr)
1549{
1550 int ret;
1551
1552 DEBUGP("ip_ct_ras: IRR\n");
1553
1554 if (set_ras_addr_hook) {
1555 ret = set_ras_addr_hook(pskb, ct, ctinfo, data,
1556 &irr->rasAddress, 1);
1557 if (ret < 0)
1558 return -1;
1559 }
1560
1561 if (set_sig_addr_hook) {
1562 ret = set_sig_addr_hook(pskb, ct, ctinfo, data,
1563 irr->callSignalAddress.item,
1564 irr->callSignalAddress.count);
1565 if (ret < 0)
1566 return -1;
1567 }
1568
1569 return 0;
1570}
1571
1572/****************************************************************************/
1573static int process_ras(struct sk_buff **pskb, struct ip_conntrack *ct,
1574 enum ip_conntrack_info ctinfo,
1575 unsigned char **data, RasMessage * ras)
1576{
1577 switch (ras->choice) {
1578 case eRasMessage_gatekeeperRequest:
1579 return process_grq(pskb, ct, ctinfo, data,
1580 &ras->gatekeeperRequest);
1581 case eRasMessage_gatekeeperConfirm:
1582 return process_gcf(pskb, ct, ctinfo, data,
1583 &ras->gatekeeperConfirm);
1584 case eRasMessage_registrationRequest:
1585 return process_rrq(pskb, ct, ctinfo, data,
1586 &ras->registrationRequest);
1587 case eRasMessage_registrationConfirm:
1588 return process_rcf(pskb, ct, ctinfo, data,
1589 &ras->registrationConfirm);
1590 case eRasMessage_unregistrationRequest:
1591 return process_urq(pskb, ct, ctinfo, data,
1592 &ras->unregistrationRequest);
1593 case eRasMessage_admissionRequest:
1594 return process_arq(pskb, ct, ctinfo, data,
1595 &ras->admissionRequest);
1596 case eRasMessage_admissionConfirm:
1597 return process_acf(pskb, ct, ctinfo, data,
1598 &ras->admissionConfirm);
1599 case eRasMessage_locationRequest:
1600 return process_lrq(pskb, ct, ctinfo, data,
1601 &ras->locationRequest);
1602 case eRasMessage_locationConfirm:
1603 return process_lcf(pskb, ct, ctinfo, data,
1604 &ras->locationConfirm);
1605 case eRasMessage_infoRequestResponse:
1606 return process_irr(pskb, ct, ctinfo, data,
1607 &ras->infoRequestResponse);
1608 default:
1609 DEBUGP("ip_ct_ras: RAS message %d\n", ras->choice);
1610 break;
1611 }
1612
1613 return 0;
1614}
1615
1616/****************************************************************************/
1617static int ras_help(struct sk_buff **pskb, struct ip_conntrack *ct,
1618 enum ip_conntrack_info ctinfo)
1619{
1620 static RasMessage ras;
1621 unsigned char *data;
1622 int datalen = 0;
1623 int ret;
1624
1625 DEBUGP("ip_ct_ras: skblen = %u\n", (*pskb)->len);
1626
1627 spin_lock_bh(&ip_h323_lock);
1628
1629 /* Get UDP data */
1630 data = get_udp_data(pskb, &datalen);
1631 if (data == NULL)
1632 goto accept;
1633 DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
1634 NIPQUAD((*pskb)->nh.iph->saddr),
1635 NIPQUAD((*pskb)->nh.iph->daddr), datalen);
1636
1637 /* Decode RAS message */
1638 ret = DecodeRasMessage(data, datalen, &ras);
1639 if (ret < 0) {
1640 if (net_ratelimit())
1641 printk("ip_ct_ras: decoding error: %s\n",
1642 ret == H323_ERROR_BOUND ?
1643 "out of bound" : "out of range");
1644 goto accept;
1645 }
1646
1647 /* Process RAS message */
1648 if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
1649 goto drop;
1650
1651 accept:
1652 spin_unlock_bh(&ip_h323_lock);
1653 return NF_ACCEPT;
1654
1655 drop:
1656 spin_unlock_bh(&ip_h323_lock);
1657 if (net_ratelimit())
1658 printk("ip_ct_ras: packet dropped\n");
1659 return NF_DROP;
1660}
1661
1662/****************************************************************************/
1663static struct ip_conntrack_helper ip_conntrack_helper_ras = {
1664 .name = "RAS",
1665 .me = THIS_MODULE,
1666 .max_expected = 32,
1667 .timeout = 240,
1668 .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}},
1669 .dst = {.protonum = IPPROTO_UDP}},
1670 .mask = {.src = {.u = {0xFFFE}},
1671 .dst = {.protonum = 0xFF}},
1672 .help = ras_help,
1673};
1674
1675/****************************************************************************/
1676static void ip_conntrack_ras_expect(struct ip_conntrack *new,
1677 struct ip_conntrack_expect *this)
1678{
1679 write_lock_bh(&ip_conntrack_lock);
1680 new->helper = &ip_conntrack_helper_ras;
1681 write_unlock_bh(&ip_conntrack_lock);
1682}
1683
1684/****************************************************************************/
1685/* Not __exit - called from init() */
1686static void fini(void)
1687{
1688 ip_conntrack_helper_unregister(&ip_conntrack_helper_ras);
1689 ip_conntrack_helper_unregister(&ip_conntrack_helper_q931);
1690 kfree(h323_buffer);
1691 DEBUGP("ip_ct_h323: fini\n");
1692}
1693
1694/****************************************************************************/
1695static int __init init(void)
1696{
1697 int ret;
1698
1699 h323_buffer = kmalloc(65536, GFP_KERNEL);
1700 if (!h323_buffer)
1701 return -ENOMEM;
1702 if ((ret = ip_conntrack_helper_register(&ip_conntrack_helper_q931)) ||
1703 (ret = ip_conntrack_helper_register(&ip_conntrack_helper_ras))) {
1704 fini();
1705 return ret;
1706 }
1707
1708 DEBUGP("ip_ct_h323: init success\n");
1709 return 0;
1710}
1711
1712/****************************************************************************/
1713module_init(init);
1714module_exit(fini);
1715
1716EXPORT_SYMBOL(get_h245_addr);
1717EXPORT_SYMBOL(get_h225_addr);
1718EXPORT_SYMBOL(ip_conntrack_h245_expect);
1719EXPORT_SYMBOL(ip_conntrack_q931_expect);
1720EXPORT_SYMBOL(set_h245_addr_hook);
1721EXPORT_SYMBOL(set_h225_addr_hook);
1722EXPORT_SYMBOL(set_sig_addr_hook);
1723EXPORT_SYMBOL(set_ras_addr_hook);
1724EXPORT_SYMBOL(nat_rtp_rtcp_hook);
1725EXPORT_SYMBOL(nat_t120_hook);
1726EXPORT_SYMBOL(nat_h245_hook);
1727EXPORT_SYMBOL(nat_q931_hook);
1728
1729MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
1730MODULE_DESCRIPTION("H.323 connection tracking helper");
1731MODULE_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 000000000000..afa525129b51
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -0,0 +1,870 @@
1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
3 * conntrack/NAT module.
4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
6 *
7 * This source code is licensed under General Public License version 2.
8 *
9 * See ip_conntrack_helper_h323_asn1.h for details.
10 *
11 ****************************************************************************/
12
13#ifdef __KERNEL__
14#include <linux/kernel.h>
15#else
16#include <stdio.h>
17#endif
18#include "ip_conntrack_helper_h323_asn1.h"
19
20/* Trace Flag */
21#ifndef H323_TRACE
22#define H323_TRACE 0
23#endif
24
25#if H323_TRACE
26#define TAB_SIZE 4
27#define IFTHEN(cond, act) if(cond){act;}
28#ifdef __KERNEL__
29#define PRINT printk
30#else
31#define PRINT printf
32#endif
33#define FNAME(name) name,
34#else
35#define IFTHEN(cond, act)
36#define PRINT(fmt, args...)
37#define FNAME(name)
38#endif
39
40/* ASN.1 Types */
41#define NUL 0
42#define BOOL 1
43#define OID 2
44#define INT 3
45#define ENUM 4
46#define BITSTR 5
47#define NUMSTR 6
48#define NUMDGT 6
49#define TBCDSTR 6
50#define OCTSTR 7
51#define PRTSTR 7
52#define IA5STR 7
53#define GENSTR 7
54#define BMPSTR 8
55#define SEQ 9
56#define SET 9
57#define SEQOF 10
58#define SETOF 10
59#define CHOICE 11
60
61/* Constraint Types */
62#define FIXD 0
63/* #define BITS 1-8 */
64#define BYTE 9
65#define WORD 10
66#define CONS 11
67#define SEMI 12
68#define UNCO 13
69
70/* ASN.1 Type Attributes */
71#define SKIP 0
72#define STOP 1
73#define DECODE 2
74#define EXT 4
75#define OPEN 8
76#define OPT 16
77
78
79/* ASN.1 Field Structure */
80typedef struct field_t {
81#if H323_TRACE
82 char *name;
83#endif
84 unsigned char type;
85 unsigned char sz;
86 unsigned char lb;
87 unsigned char ub;
88 unsigned short attr;
89 unsigned short offset;
90 struct field_t *fields;
91} field_t;
92
93/* Bit Stream */
94typedef struct {
95 unsigned char *buf;
96 unsigned char *beg;
97 unsigned char *end;
98 unsigned char *cur;
99 unsigned bit;
100} bitstr_t;
101
102/* Tool Functions */
103#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;}
104#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;}
105#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;}
106#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND)
107static unsigned get_len(bitstr_t * bs);
108static unsigned get_bit(bitstr_t * bs);
109static unsigned get_bits(bitstr_t * bs, unsigned b);
110static unsigned get_bitmap(bitstr_t * bs, unsigned b);
111static unsigned get_uint(bitstr_t * bs, int b);
112
113/* Decoder Functions */
114static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level);
115static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level);
116static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level);
117static int decode_int(bitstr_t * bs, field_t * f, char *base, int level);
118static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level);
119static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level);
120static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level);
121static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level);
122static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level);
123static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level);
124static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level);
125static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level);
126
127/* Decoder Functions Vector */
128typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int);
129static decoder_t Decoders[] = {
130 decode_nul,
131 decode_bool,
132 decode_oid,
133 decode_int,
134 decode_enum,
135 decode_bitstr,
136 decode_numstr,
137 decode_octstr,
138 decode_bmpstr,
139 decode_seq,
140 decode_seqof,
141 decode_choice,
142};
143
144/****************************************************************************
145 * H.323 Types
146 ****************************************************************************/
147#include "ip_conntrack_helper_h323_types.c"
148
149/****************************************************************************
150 * Functions
151 ****************************************************************************/
152/* Assume bs is aligned && v < 16384 */
153unsigned get_len(bitstr_t * bs)
154{
155 unsigned v;
156
157 v = *bs->cur++;
158
159 if (v & 0x80) {
160 v &= 0x3f;
161 v <<= 8;
162 v += *bs->cur++;
163 }
164
165 return v;
166}
167
168/****************************************************************************/
169unsigned get_bit(bitstr_t * bs)
170{
171 unsigned b = (*bs->cur) & (0x80 >> bs->bit);
172
173 INC_BIT(bs);
174
175 return b;
176}
177
178/****************************************************************************/
179/* Assume b <= 8 */
180unsigned get_bits(bitstr_t * bs, unsigned b)
181{
182 unsigned v, l;
183
184 v = (*bs->cur) & (0xffU >> bs->bit);
185 l = b + bs->bit;
186
187 if (l < 8) {
188 v >>= 8 - l;
189 bs->bit = l;
190 } else if (l == 8) {
191 bs->cur++;
192 bs->bit = 0;
193 } else { /* l > 8 */
194
195 v <<= 8;
196 v += *(++bs->cur);
197 v >>= 16 - l;
198 bs->bit = l - 8;
199 }
200
201 return v;
202}
203
204/****************************************************************************/
205/* Assume b <= 32 */
206unsigned get_bitmap(bitstr_t * bs, unsigned b)
207{
208 unsigned v, l, shift, bytes;
209
210 if (!b)
211 return 0;
212
213 l = bs->bit + b;
214
215 if (l < 8) {
216 v = (unsigned) (*bs->cur) << (bs->bit + 24);
217 bs->bit = l;
218 } else if (l == 8) {
219 v = (unsigned) (*bs->cur++) << (bs->bit + 24);
220 bs->bit = 0;
221 } else {
222 for (bytes = l >> 3, shift = 24, v = 0; bytes;
223 bytes--, shift -= 8)
224 v |= (unsigned) (*bs->cur++) << shift;
225
226 if (l < 32) {
227 v |= (unsigned) (*bs->cur) << shift;
228 v <<= bs->bit;
229 } else if (l > 32) {
230 v <<= bs->bit;
231 v |= (*bs->cur) >> (8 - bs->bit);
232 }
233
234 bs->bit = l & 0x7;
235 }
236
237 v &= 0xffffffff << (32 - b);
238
239 return v;
240}
241
242/****************************************************************************
243 * Assume bs is aligned and sizeof(unsigned int) == 4
244 ****************************************************************************/
245unsigned get_uint(bitstr_t * bs, int b)
246{
247 unsigned v = 0;
248
249 switch (b) {
250 case 4:
251 v |= *bs->cur++;
252 v <<= 8;
253 case 3:
254 v |= *bs->cur++;
255 v <<= 8;
256 case 2:
257 v |= *bs->cur++;
258 v <<= 8;
259 case 1:
260 v |= *bs->cur++;
261 break;
262 }
263 return v;
264}
265
266/****************************************************************************/
267int decode_nul(bitstr_t * bs, field_t * f, char *base, int level)
268{
269 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
270
271 return H323_ERROR_NONE;
272}
273
274/****************************************************************************/
275int decode_bool(bitstr_t * bs, field_t * f, char *base, int level)
276{
277 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
278
279 INC_BIT(bs);
280
281 CHECK_BOUND(bs, 0);
282 return H323_ERROR_NONE;
283}
284
285/****************************************************************************/
286int decode_oid(bitstr_t * bs, field_t * f, char *base, int level)
287{
288 int len;
289
290 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
291
292 BYTE_ALIGN(bs);
293 CHECK_BOUND(bs, 1);
294 len = *bs->cur++;
295 bs->cur += len;
296
297 CHECK_BOUND(bs, 0);
298 return H323_ERROR_NONE;
299}
300
301/****************************************************************************/
302int decode_int(bitstr_t * bs, field_t * f, char *base, int level)
303{
304 unsigned len;
305
306 PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
307
308 switch (f->sz) {
309 case BYTE: /* Range == 256 */
310 BYTE_ALIGN(bs);
311 bs->cur++;
312 break;
313 case WORD: /* 257 <= Range <= 64K */
314 BYTE_ALIGN(bs);
315 bs->cur += 2;
316 break;
317 case CONS: /* 64K < Range < 4G */
318 len = get_bits(bs, 2) + 1;
319 BYTE_ALIGN(bs);
320 if (base && (f->attr & DECODE)) { /* timeToLive */
321 unsigned v = get_uint(bs, len) + f->lb;
322 PRINT(" = %u", v);
323 *((unsigned *) (base + f->offset)) = v;
324 }
325 bs->cur += len;
326 break;
327 case UNCO:
328 BYTE_ALIGN(bs);
329 CHECK_BOUND(bs, 2);
330 len = get_len(bs);
331 bs->cur += len;
332 break;
333 default: /* 2 <= Range <= 255 */
334 INC_BITS(bs, f->sz);
335 break;
336 }
337
338 PRINT("\n");
339
340 CHECK_BOUND(bs, 0);
341 return H323_ERROR_NONE;
342}
343
344/****************************************************************************/
345int decode_enum(bitstr_t * bs, field_t * f, char *base, int level)
346{
347 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
348
349 if ((f->attr & EXT) && get_bit(bs)) {
350 INC_BITS(bs, 7);
351 } else {
352 INC_BITS(bs, f->sz);
353 }
354
355 CHECK_BOUND(bs, 0);
356 return H323_ERROR_NONE;
357}
358
359/****************************************************************************/
360int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level)
361{
362 unsigned len;
363
364 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
365
366 BYTE_ALIGN(bs);
367 switch (f->sz) {
368 case FIXD: /* fixed length > 16 */
369 len = f->lb;
370 break;
371 case WORD: /* 2-byte length */
372 CHECK_BOUND(bs, 2);
373 len = (*bs->cur++) << 8;
374 len += (*bs->cur++) + f->lb;
375 break;
376 case SEMI:
377 CHECK_BOUND(bs, 2);
378 len = get_len(bs);
379 break;
380 default:
381 len = 0;
382 break;
383 }
384
385 bs->cur += len >> 3;
386 bs->bit = len & 7;
387
388 CHECK_BOUND(bs, 0);
389 return H323_ERROR_NONE;
390}
391
392/****************************************************************************/
393int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level)
394{
395 unsigned len;
396
397 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
398
399 /* 2 <= Range <= 255 */
400 len = get_bits(bs, f->sz) + f->lb;
401
402 BYTE_ALIGN(bs);
403 INC_BITS(bs, (len << 2));
404
405 CHECK_BOUND(bs, 0);
406 return H323_ERROR_NONE;
407}
408
409/****************************************************************************/
410int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level)
411{
412 unsigned len;
413
414 PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
415
416 switch (f->sz) {
417 case FIXD: /* Range == 1 */
418 if (f->lb > 2) {
419 BYTE_ALIGN(bs);
420 if (base && (f->attr & DECODE)) {
421 /* The IP Address */
422 IFTHEN(f->lb == 4,
423 PRINT(" = %d.%d.%d.%d:%d",
424 bs->cur[0], bs->cur[1],
425 bs->cur[2], bs->cur[3],
426 bs->cur[4] * 256 + bs->cur[5]));
427 *((unsigned *) (base + f->offset)) =
428 bs->cur - bs->buf;
429 }
430 }
431 len = f->lb;
432 break;
433 case BYTE: /* Range == 256 */
434 BYTE_ALIGN(bs);
435 CHECK_BOUND(bs, 1);
436 len = (*bs->cur++) + f->lb;
437 break;
438 case SEMI:
439 BYTE_ALIGN(bs);
440 CHECK_BOUND(bs, 2);
441 len = get_len(bs) + f->lb;
442 break;
443 default: /* 2 <= Range <= 255 */
444 len = get_bits(bs, f->sz) + f->lb;
445 BYTE_ALIGN(bs);
446 break;
447 }
448
449 bs->cur += len;
450
451 PRINT("\n");
452
453 CHECK_BOUND(bs, 0);
454 return H323_ERROR_NONE;
455}
456
457/****************************************************************************/
458int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level)
459{
460 unsigned len;
461
462 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
463
464 switch (f->sz) {
465 case BYTE: /* Range == 256 */
466 BYTE_ALIGN(bs);
467 CHECK_BOUND(bs, 1);
468 len = (*bs->cur++) + f->lb;
469 break;
470 default: /* 2 <= Range <= 255 */
471 len = get_bits(bs, f->sz) + f->lb;
472 BYTE_ALIGN(bs);
473 break;
474 }
475
476 bs->cur += len << 1;
477
478 CHECK_BOUND(bs, 0);
479 return H323_ERROR_NONE;
480}
481
482/****************************************************************************/
483int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
484{
485 unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
486 int err;
487 field_t *son;
488 unsigned char *beg = NULL;
489
490 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
491
492 /* Decode? */
493 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
494
495 /* Extensible? */
496 ext = (f->attr & EXT) ? get_bit(bs) : 0;
497
498 /* Get fields bitmap */
499 bmp = get_bitmap(bs, f->sz);
500 if (base)
501 *(unsigned *) base = bmp;
502
503 /* Decode the root components */
504 for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
505 if (son->attr & STOP) {
506 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
507 son->name);
508 return H323_ERROR_STOP;
509 }
510
511 if (son->attr & OPT) { /* Optional component */
512 if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */
513 continue;
514 }
515
516 /* Decode */
517 if (son->attr & OPEN) { /* Open field */
518 CHECK_BOUND(bs, 2);
519 len = get_len(bs);
520 CHECK_BOUND(bs, len);
521 if (!base) {
522 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
523 " ", son->name);
524 bs->cur += len;
525 continue;
526 }
527 beg = bs->cur;
528
529 /* Decode */
530 if ((err = (Decoders[son->type]) (bs, son, base,
531 level + 1)) >
532 H323_ERROR_STOP)
533 return err;
534
535 bs->cur = beg + len;
536 bs->bit = 0;
537 } else if ((err = (Decoders[son->type]) (bs, son, base,
538 level + 1)))
539 return err;
540 }
541
542 /* No extension? */
543 if (!ext)
544 return H323_ERROR_NONE;
545
546 /* Get the extension bitmap */
547 bmp2_len = get_bits(bs, 7) + 1;
548 CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
549 bmp2 = get_bitmap(bs, bmp2_len);
550 bmp |= bmp2 >> f->sz;
551 if (base)
552 *(unsigned *) base = bmp;
553 BYTE_ALIGN(bs);
554
555 /* Decode the extension components */
556 for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
557 if (son->attr & STOP) {
558 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
559 son->name);
560 return H323_ERROR_STOP;
561 }
562
563 if (!((0x80000000 >> opt) & bmp2)) /* Not present */
564 continue;
565
566 /* Check Range */
567 if (i >= f->ub) { /* Newer Version? */
568 CHECK_BOUND(bs, 2);
569 len = get_len(bs);
570 CHECK_BOUND(bs, len);
571 bs->cur += len;
572 continue;
573 }
574
575 CHECK_BOUND(bs, 2);
576 len = get_len(bs);
577 CHECK_BOUND(bs, len);
578 if (!base || !(son->attr & DECODE)) {
579 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
580 son->name);
581 bs->cur += len;
582 continue;
583 }
584 beg = bs->cur;
585
586 if ((err = (Decoders[son->type]) (bs, son, base,
587 level + 1)) >
588 H323_ERROR_STOP)
589 return err;
590
591 bs->cur = beg + len;
592 bs->bit = 0;
593 }
594 return H323_ERROR_NONE;
595}
596
597/****************************************************************************/
598int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
599{
600 unsigned count, effective_count = 0, i, len = 0;
601 int err;
602 field_t *son;
603 unsigned char *beg = NULL;
604
605 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
606
607 /* Decode? */
608 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
609
610 /* Decode item count */
611 switch (f->sz) {
612 case BYTE:
613 BYTE_ALIGN(bs);
614 CHECK_BOUND(bs, 1);
615 count = *bs->cur++;
616 break;
617 case WORD:
618 BYTE_ALIGN(bs);
619 CHECK_BOUND(bs, 2);
620 count = *bs->cur++;
621 count <<= 8;
622 count = *bs->cur++;
623 break;
624 case SEMI:
625 BYTE_ALIGN(bs);
626 CHECK_BOUND(bs, 2);
627 count = get_len(bs);
628 break;
629 default:
630 count = get_bits(bs, f->sz);
631 break;
632 }
633 count += f->lb;
634
635 /* Write Count */
636 if (base) {
637 effective_count = count > f->ub ? f->ub : count;
638 *(unsigned *) base = effective_count;
639 base += sizeof(unsigned);
640 }
641
642 /* Decode nested field */
643 son = f->fields;
644 if (base)
645 base -= son->offset;
646 for (i = 0; i < count; i++) {
647 if (son->attr & OPEN) {
648 BYTE_ALIGN(bs);
649 len = get_len(bs);
650 CHECK_BOUND(bs, len);
651 if (!base || !(son->attr & DECODE)) {
652 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
653 " ", son->name);
654 bs->cur += len;
655 continue;
656 }
657 beg = bs->cur;
658
659 if ((err = (Decoders[son->type]) (bs, son,
660 i <
661 effective_count ?
662 base : NULL,
663 level + 1)) >
664 H323_ERROR_STOP)
665 return err;
666
667 bs->cur = beg + len;
668 bs->bit = 0;
669 } else
670 if ((err = (Decoders[son->type]) (bs, son,
671 i < effective_count ?
672 base : NULL,
673 level + 1)))
674 return err;
675
676 if (base)
677 base += son->offset;
678 }
679
680 return H323_ERROR_NONE;
681}
682
683
684/****************************************************************************/
685int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
686{
687 unsigned type, ext, len = 0;
688 int err;
689 field_t *son;
690 unsigned char *beg = NULL;
691
692 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
693
694 /* Decode? */
695 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
696
697 /* Decode the choice index number */
698 if ((f->attr & EXT) && get_bit(bs)) {
699 ext = 1;
700 type = get_bits(bs, 7) + f->lb;
701 } else {
702 ext = 0;
703 type = get_bits(bs, f->sz);
704 }
705
706 /* Check Range */
707 if (type >= f->ub) { /* Newer version? */
708 BYTE_ALIGN(bs);
709 len = get_len(bs);
710 CHECK_BOUND(bs, len);
711 bs->cur += len;
712 return H323_ERROR_NONE;
713 }
714
715 /* Write Type */
716 if (base)
717 *(unsigned *) base = type;
718
719 /* Transfer to son level */
720 son = &f->fields[type];
721 if (son->attr & STOP) {
722 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
723 return H323_ERROR_STOP;
724 }
725
726 if (ext || (son->attr & OPEN)) {
727 BYTE_ALIGN(bs);
728 len = get_len(bs);
729 CHECK_BOUND(bs, len);
730 if (!base || !(son->attr & DECODE)) {
731 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
732 son->name);
733 bs->cur += len;
734 return H323_ERROR_NONE;
735 }
736 beg = bs->cur;
737
738 if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) >
739 H323_ERROR_STOP)
740 return err;
741
742 bs->cur = beg + len;
743 bs->bit = 0;
744 } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)))
745 return err;
746
747 return H323_ERROR_NONE;
748}
749
750/****************************************************************************/
751int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras)
752{
753 static field_t ras_message = {
754 FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
755 0, _RasMessage
756 };
757 bitstr_t bs;
758
759 bs.buf = bs.beg = bs.cur = buf;
760 bs.end = buf + sz;
761 bs.bit = 0;
762
763 return decode_choice(&bs, &ras_message, (char *) ras, 0);
764}
765
766/****************************************************************************/
767static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
768 size_t sz, H323_UserInformation * uuie)
769{
770 static field_t h323_userinformation = {
771 FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
772 0, _H323_UserInformation
773 };
774 bitstr_t bs;
775
776 bs.buf = buf;
777 bs.beg = bs.cur = beg;
778 bs.end = beg + sz;
779 bs.bit = 0;
780
781 return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
782}
783
784/****************************************************************************/
785int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
786 MultimediaSystemControlMessage *
787 mscm)
788{
789 static field_t multimediasystemcontrolmessage = {
790 FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
791 DECODE | EXT, 0, _MultimediaSystemControlMessage
792 };
793 bitstr_t bs;
794
795 bs.buf = bs.beg = bs.cur = buf;
796 bs.end = buf + sz;
797 bs.bit = 0;
798
799 return decode_choice(&bs, &multimediasystemcontrolmessage,
800 (char *) mscm, 0);
801}
802
803/****************************************************************************/
804int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931)
805{
806 unsigned char *p = buf;
807 int len;
808
809 if (!p || sz < 1)
810 return H323_ERROR_BOUND;
811
812 /* Protocol Discriminator */
813 if (*p != 0x08) {
814 PRINT("Unknown Protocol Discriminator\n");
815 return H323_ERROR_RANGE;
816 }
817 p++;
818 sz--;
819
820 /* CallReferenceValue */
821 if (sz < 1)
822 return H323_ERROR_BOUND;
823 len = *p++;
824 sz--;
825 if (sz < len)
826 return H323_ERROR_BOUND;
827 p += len;
828 sz -= len;
829
830 /* Message Type */
831 if (sz < 1)
832 return H323_ERROR_BOUND;
833 q931->MessageType = *p++;
834 PRINT("MessageType = %02X\n", q931->MessageType);
835 if (*p & 0x80) {
836 p++;
837 sz--;
838 }
839
840 /* Decode Information Elements */
841 while (sz > 0) {
842 if (*p == 0x7e) { /* UserUserIE */
843 if (sz < 3)
844 break;
845 p++;
846 len = *p++ << 8;
847 len |= *p++;
848 sz -= 3;
849 if (sz < len)
850 break;
851 p++;
852 len--;
853 return DecodeH323_UserInformation(buf, p, len,
854 &q931->UUIE);
855 }
856 p++;
857 sz--;
858 if (sz < 1)
859 break;
860 len = *p++;
861 if (sz < len)
862 break;
863 p += len;
864 sz -= len;
865 }
866
867 PRINT("Q.931 UUIE not found\n");
868
869 return H323_ERROR_BOUND;
870}
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 000000000000..0bd828081c0c
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
@@ -0,0 +1,98 @@
1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
3 * conntrack/NAT module.
4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
6 *
7 * This source code is licensed under General Public License version 2.
8 *
9 *
10 * This library is based on H.225 version 4, H.235 version 2 and H.245
11 * version 7. It is extremely optimized to decode only the absolutely
12 * necessary objects in a signal for Linux kernel NAT module use, so don't
13 * expect it to be a full ASN.1 library.
14 *
15 * Features:
16 *
17 * 1. Small. The total size of code plus data is less than 20 KB (IA32).
18 * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866
19 * takes only 3.9 seconds.
20 * 3. No memory allocation. It uses a static object. No need to initialize or
21 * cleanup.
22 * 4. Thread safe.
23 * 5. Support embedded architectures that has no misaligned memory access
24 * support.
25 *
26 * Limitations:
27 *
28 * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU.
29 * If a Setup signal contains more than 30 faststart, the packet size will
30 * very likely exceed the MTU size, then the TPKT will be fragmented. I
31 * don't know how to handle this in a Netfilter module. Anybody can help?
32 * Although I think 30 is enough for most of the cases.
33 * 2. IPv4 addresses only.
34 *
35 ****************************************************************************/
36
37#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_
38#define _IP_CONNTRACK_HELPER_H323_ASN1_H_
39
40/*****************************************************************************
41 * H.323 Types
42 ****************************************************************************/
43#include "ip_conntrack_helper_h323_types.h"
44
45typedef struct {
46 enum {
47 Q931_NationalEscape = 0x00,
48 Q931_Alerting = 0x01,
49 Q931_CallProceeding = 0x02,
50 Q931_Connect = 0x07,
51 Q931_ConnectAck = 0x0F,
52 Q931_Progress = 0x03,
53 Q931_Setup = 0x05,
54 Q931_SetupAck = 0x0D,
55 Q931_Resume = 0x26,
56 Q931_ResumeAck = 0x2E,
57 Q931_ResumeReject = 0x22,
58 Q931_Suspend = 0x25,
59 Q931_SuspendAck = 0x2D,
60 Q931_SuspendReject = 0x21,
61 Q931_UserInformation = 0x20,
62 Q931_Disconnect = 0x45,
63 Q931_Release = 0x4D,
64 Q931_ReleaseComplete = 0x5A,
65 Q931_Restart = 0x46,
66 Q931_RestartAck = 0x4E,
67 Q931_Segment = 0x60,
68 Q931_CongestionCtrl = 0x79,
69 Q931_Information = 0x7B,
70 Q931_Notify = 0x6E,
71 Q931_Status = 0x7D,
72 Q931_StatusEnquiry = 0x75,
73 Q931_Facility = 0x62
74 } MessageType;
75 H323_UserInformation UUIE;
76} Q931;
77
78/*****************************************************************************
79 * Decode Functions Return Codes
80 ****************************************************************************/
81
82#define H323_ERROR_NONE 0 /* Decoded successfully */
83#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */
84#define H323_ERROR_BOUND -1
85#define H323_ERROR_RANGE -2
86
87
88/*****************************************************************************
89 * Decode Functions
90 ****************************************************************************/
91
92int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras);
93int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931);
94int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
95 MultimediaSystemControlMessage *
96 mscm);
97
98#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 000000000000..022c47b9f6c9
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
@@ -0,0 +1,1926 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 *
5 * This source code is licensed under General Public License version 2.
6 */
7
8static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */
9 {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE,
10 offsetof(TransportAddress_ipAddress, ip), NULL},
11 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
12};
13
14static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */
15 {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
16};
17
18static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */
19 {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
20 {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
21};
22
23static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */
24 {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
25 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
26 {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
27 _TransportAddress_ipSourceRoute_route},
28 {FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0,
29 _TransportAddress_ipSourceRoute_routing},
30};
31
32static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */
33 {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
34 {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
35 {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
36};
37
38static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */
39 {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
40 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
41};
42
43static field_t _H221NonStandard[] = { /* SEQUENCE */
44 {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
45 {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
46 {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
47};
48
49static field_t _NonStandardIdentifier[] = { /* CHOICE */
50 {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
51 {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0,
52 _H221NonStandard},
53};
54
55static field_t _NonStandardParameter[] = { /* SEQUENCE */
56 {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0,
57 _NonStandardIdentifier},
58 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
59};
60
61static field_t _TransportAddress[] = { /* CHOICE */
62 {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE,
63 offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress},
64 {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0,
65 _TransportAddress_ipSourceRoute},
66 {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
67 _TransportAddress_ipxAddress},
68 {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
69 _TransportAddress_ip6Address},
70 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
71 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
72 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
73 _NonStandardParameter},
74};
75
76static field_t _AliasAddress[] = { /* CHOICE */
77 {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
78 {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL},
79 {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
80 {FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL},
81 {FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
82 {FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL},
83 {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL},
84};
85
86static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */
87 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
88};
89
90static field_t _VendorIdentifier[] = { /* SEQUENCE */
91 {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard},
92 {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
93 {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
94};
95
96static field_t _GatekeeperInfo[] = { /* SEQUENCE */
97 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
98 _NonStandardParameter},
99};
100
101static field_t _H310Caps[] = { /* SEQUENCE */
102 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
103 _NonStandardParameter},
104 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
105 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
106};
107
108static field_t _H320Caps[] = { /* SEQUENCE */
109 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
110 _NonStandardParameter},
111 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
112 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
113};
114
115static field_t _H321Caps[] = { /* SEQUENCE */
116 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
117 _NonStandardParameter},
118 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
119 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
120};
121
122static field_t _H322Caps[] = { /* SEQUENCE */
123 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
124 _NonStandardParameter},
125 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
126 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
127};
128
129static field_t _H323Caps[] = { /* SEQUENCE */
130 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
131 _NonStandardParameter},
132 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
133 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
134};
135
136static field_t _H324Caps[] = { /* SEQUENCE */
137 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
138 _NonStandardParameter},
139 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
140 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
141};
142
143static field_t _VoiceCaps[] = { /* SEQUENCE */
144 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
145 _NonStandardParameter},
146 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
147 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
148};
149
150static field_t _T120OnlyCaps[] = { /* SEQUENCE */
151 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
152 _NonStandardParameter},
153 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
154 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
155};
156
157static field_t _SupportedProtocols[] = { /* CHOICE */
158 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0,
159 _NonStandardParameter},
160 {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps},
161 {FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps},
162 {FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps},
163 {FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps},
164 {FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps},
165 {FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps},
166 {FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps},
167 {FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps},
168 {FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL},
169 {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL},
170};
171
172static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */
173 {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols},
174};
175
176static field_t _GatewayInfo[] = { /* SEQUENCE */
177 {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
178 _GatewayInfo_protocol},
179 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
180 _NonStandardParameter},
181};
182
183static field_t _McuInfo[] = { /* SEQUENCE */
184 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
185 _NonStandardParameter},
186 {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
187};
188
189static field_t _TerminalInfo[] = { /* SEQUENCE */
190 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
191 _NonStandardParameter},
192};
193
194static field_t _EndpointType[] = { /* SEQUENCE */
195 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
196 _NonStandardParameter},
197 {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0,
198 _VendorIdentifier},
199 {FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0,
200 _GatekeeperInfo},
201 {FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo},
202 {FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo},
203 {FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo},
204 {FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
205 {FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
206 {FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL},
207 {FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT,
208 0, NULL},
209};
210
211static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */
212 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
213};
214
215static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */
216 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
217};
218
219static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */
220 {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL},
221};
222
223static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */
224 {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL},
225 {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL},
226 {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL},
227 {FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
228 {FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP,
229 0, NULL},
230};
231
232static field_t _Q954Details[] = { /* SEQUENCE */
233 {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
234 {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
235};
236
237static field_t _QseriesOptions[] = { /* SEQUENCE */
238 {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
239 {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
240 {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
241 {FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
242 {FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
243 {FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
244 {FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
245 {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details},
246};
247
248static field_t _CallType[] = { /* CHOICE */
249 {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL},
250 {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
251 {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL},
252 {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
253};
254
255static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */
256 {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
257 {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
258 {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
259};
260
261static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */
262 {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
263 {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0,
264 _H245_NonStandardIdentifier_h221NonStandard},
265};
266
267static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */
268 {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0,
269 _H245_NonStandardIdentifier},
270 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
271};
272
273static field_t _H261VideoCapability[] = { /* SEQUENCE */
274 {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
275 {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
276 {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
277 NULL},
278 {FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
279 {FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
280 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
281};
282
283static field_t _H262VideoCapability[] = { /* SEQUENCE */
284 {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
285 {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
286 {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
287 {FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
288 {FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
289 {FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
290 {FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
291 {FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0,
292 NULL},
293 {FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
294 {FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
295 {FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
296 {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
297 {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
298 {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
299 {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
300 {FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
301 {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
302 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
303};
304
305static field_t _H263VideoCapability[] = { /* SEQUENCE */
306 {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
307 {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
308 {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
309 {FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
310 {FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
311 {FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL},
312 {FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
313 {FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
314 {FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
315 {FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
316 {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
317 NULL},
318 {FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
319 {FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
320 {FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
321 {FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
322 {FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
323 {FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
324 {FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
325 {FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
326 {FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0,
327 NULL},
328 {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL},
329};
330
331static field_t _IS11172VideoCapability[] = { /* SEQUENCE */
332 {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
333 {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
334 {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
335 {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
336 {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
337 {FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
338 {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
339 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
340};
341
342static field_t _VideoCapability[] = { /* CHOICE */
343 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
344 _H245_NonStandardParameter},
345 {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0,
346 _H261VideoCapability},
347 {FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0,
348 _H262VideoCapability},
349 {FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0,
350 _H263VideoCapability},
351 {FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0,
352 _IS11172VideoCapability},
353 {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
354};
355
356static field_t _AudioCapability_g7231[] = { /* SEQUENCE */
357 {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL},
358 {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
359};
360
361static field_t _IS11172AudioCapability[] = { /* SEQUENCE */
362 {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
363 {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
364 {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
365 {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
366 {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
367 {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
368 {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
369 {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
370 {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
371};
372
373static field_t _IS13818AudioCapability[] = { /* SEQUENCE */
374 {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
375 {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
376 {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
377 {FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
378 {FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
379 {FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
380 {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
381 {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
382 {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
383 {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
384 {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
385 {FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
386 {FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
387 {FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
388 {FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
389 {FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
390 {FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
391 {FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
392 {FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
393 {FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
394 {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
395};
396
397static field_t _AudioCapability[] = { /* CHOICE */
398 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
399 _H245_NonStandardParameter},
400 {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
401 {FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
402 {FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
403 {FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
404 {FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
405 {FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
406 {FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL},
407 {FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231},
408 {FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL},
409 {FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL},
410 {FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL},
411 {FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0,
412 _IS11172AudioCapability},
413 {FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0,
414 _IS13818AudioCapability},
415 {FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
416 {FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
417 {FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL},
418 {FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
419 {FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
420 {FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
421 {FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
422 {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL},
423};
424
425static field_t _DataProtocolCapability[] = { /* CHOICE */
426 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
427 _H245_NonStandardParameter},
428 {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
429 {FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL},
430 {FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL},
431 {FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
432 {FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
433 {FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL},
434 {FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL},
435 {FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL},
436 {FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL},
437 {FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
438 {FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL},
439 {FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
440 {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
441};
442
443static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */
444 {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
445 {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
446 {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
447 {FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
448 {FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
449 {FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
450 {FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
451 {FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
452 {FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
453 {FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
454 {FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
455 {FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
456 {FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
457 {FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
458 {FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
459 {FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
460 {FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
461 {FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
462 {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
463};
464
465static field_t _T84Profile[] = { /* CHOICE */
466 {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
467 {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0,
468 _T84Profile_t84Restricted},
469};
470
471static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */
472 {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
473 _DataProtocolCapability},
474 {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile},
475};
476
477static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */
478 {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
479 _DataProtocolCapability},
480 {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
481};
482
483static field_t _DataApplicationCapability_application[] = { /* CHOICE */
484 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
485 _H245_NonStandardParameter},
486 {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT,
487 offsetof(DataApplicationCapability_application, t120),
488 _DataProtocolCapability},
489 {FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0,
490 _DataProtocolCapability},
491 {FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0,
492 _DataProtocolCapability},
493 {FNAME("t84") SEQ, 0, 2, 2, SKIP, 0,
494 _DataApplicationCapability_application_t84},
495 {FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0,
496 _DataProtocolCapability},
497 {FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0,
498 _DataProtocolCapability},
499 {FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0,
500 _DataApplicationCapability_application_nlpid},
501 {FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL},
502 {FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0,
503 _DataProtocolCapability},
504 {FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
505 {FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
506 {FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL},
507 {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
508};
509
510static field_t _DataApplicationCapability[] = { /* SEQUENCE */
511 {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT,
512 offsetof(DataApplicationCapability, application),
513 _DataApplicationCapability_application},
514 {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL},
515};
516
517static field_t _EncryptionMode[] = { /* CHOICE */
518 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
519 _H245_NonStandardParameter},
520 {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL},
521};
522
523static field_t _DataType[] = { /* CHOICE */
524 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
525 _H245_NonStandardParameter},
526 {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL},
527 {FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability},
528 {FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0,
529 _AudioCapability},
530 {FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data),
531 _DataApplicationCapability},
532 {FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0,
533 _EncryptionMode},
534 {FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL},
535 {FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
536 {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
537};
538
539static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */
540 {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL},
541 {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL},
542 {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
543 {FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
544 {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
545};
546
547static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */
548 {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL},
549 {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL},
550};
551
552static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */
553 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
554 _H245_NonStandardParameter},
555 {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
556 {FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
557 {FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
558 {FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
559 {FNAME("al3") SEQ, 0, 2, 2, SKIP, 0,
560 _H223LogicalChannelParameters_adaptationLayerType_al3},
561 {FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL},
562 {FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
563 {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL},
564};
565
566static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */
567 {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0,
568 _H223LogicalChannelParameters_adaptationLayerType},
569 {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
570};
571
572static field_t _CRCLength[] = { /* CHOICE */
573 {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
574 {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
575 {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
576};
577
578static field_t _V76HDLCParameters[] = { /* SEQUENCE */
579 {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength},
580 {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL},
581 {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
582};
583
584static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */
585 {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL},
586 {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
587 {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
588};
589
590static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */
591 {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL},
592 {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
593 {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
594};
595
596static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */
597 {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL},
598 {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0,
599 _V76LogicalChannelParameters_mode_eRM_recovery},
600};
601
602static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */
603 {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0,
604 _V76LogicalChannelParameters_mode_eRM},
605 {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL},
606};
607
608static field_t _V75Parameters[] = { /* SEQUENCE */
609 {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
610};
611
612static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */
613 {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0,
614 _V76HDLCParameters},
615 {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0,
616 _V76LogicalChannelParameters_suspendResume},
617 {FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
618 {FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0,
619 _V76LogicalChannelParameters_mode},
620 {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters},
621};
622
623static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */
624 {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
625};
626
627static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */
628 {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE,
629 offsetof(UnicastAddress_iPAddress, network), NULL},
630 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
631};
632
633static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */
634 {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
635 {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
636 {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
637};
638
639static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */
640 {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
641 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
642};
643
644static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */
645 {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
646 {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
647};
648
649static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */
650 {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
651};
652
653static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */
654 {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0,
655 _UnicastAddress_iPSourceRouteAddress_routing},
656 {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
657 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
658 {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
659 _UnicastAddress_iPSourceRouteAddress_route},
660};
661
662static field_t _UnicastAddress[] = { /* CHOICE */
663 {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT,
664 offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress},
665 {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0,
666 _UnicastAddress_iPXAddress},
667 {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
668 _UnicastAddress_iP6Address},
669 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
670 {FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0,
671 _UnicastAddress_iPSourceRouteAddress},
672 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
673 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
674};
675
676static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */
677 {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
678 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
679};
680
681static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */
682 {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
683 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
684};
685
686static field_t _MulticastAddress[] = { /* CHOICE */
687 {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0,
688 _MulticastAddress_iPAddress},
689 {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
690 _MulticastAddress_iP6Address},
691 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
692 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
693};
694
695static field_t _H245_TransportAddress[] = { /* CHOICE */
696 {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT,
697 offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress},
698 {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0,
699 _MulticastAddress},
700};
701
702static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */
703 {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
704 _H2250LogicalChannelParameters_nonStandard},
705 {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL},
706 {FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
707 {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
708 offsetof(H2250LogicalChannelParameters, mediaChannel),
709 _H245_TransportAddress},
710 {FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0,
711 NULL},
712 {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
713 offsetof(H2250LogicalChannelParameters, mediaControlChannel),
714 _H245_TransportAddress},
715 {FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT,
716 0, NULL},
717 {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
718 {FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
719 {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL},
720 {FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0,
721 NULL},
722 {FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0,
723 NULL},
724 {FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL},
725 {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL},
726};
727
728static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
729 {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
730 _H222LogicalChannelParameters},
731 {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
732 _H223LogicalChannelParameters},
733 {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
734 _V76LogicalChannelParameters},
735 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
736 offsetof
737 (OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters,
738 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
739 {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
740};
741
742static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */
743 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
744 {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT,
745 offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
746 dataType), _DataType},
747 {FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT,
748 offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
749 multiplexParameters),
750 _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters},
751 {FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
752 0, NULL},
753 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
754};
755
756static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
757 {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
758 _H223LogicalChannelParameters},
759 {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
760 _V76LogicalChannelParameters},
761 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
762 offsetof
763 (OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters,
764 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
765};
766
767static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */
768 {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType},
769 {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT,
770 offsetof(OpenLogicalChannel_reverseLogicalChannelParameters,
771 multiplexParameters),
772 _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters},
773 {FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
774 0, NULL},
775 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
776};
777
778static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */
779 {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
780 {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
781};
782
783static field_t _Q2931Address_address[] = { /* CHOICE */
784 {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL},
785 {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
786};
787
788static field_t _Q2931Address[] = { /* SEQUENCE */
789 {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0,
790 _Q2931Address_address},
791 {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL},
792};
793
794static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */
795 {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address},
796 {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
797 {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT,
798 offsetof(NetworkAccessParameters_networkAddress, localAreaAddress),
799 _H245_TransportAddress},
800};
801
802static field_t _NetworkAccessParameters[] = { /* SEQUENCE */
803 {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0,
804 _NetworkAccessParameters_distribution},
805 {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT,
806 offsetof(NetworkAccessParameters, networkAddress),
807 _NetworkAccessParameters_networkAddress},
808 {FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
809 {FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL},
810 {FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
811 NULL},
812};
813
814static field_t _OpenLogicalChannel[] = { /* SEQUENCE */
815 {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
816 {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT,
817 offsetof(OpenLogicalChannel, forwardLogicalChannelParameters),
818 _OpenLogicalChannel_forwardLogicalChannelParameters},
819 {FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4,
820 DECODE | EXT | OPT, offsetof(OpenLogicalChannel,
821 reverseLogicalChannelParameters),
822 _OpenLogicalChannel_reverseLogicalChannelParameters},
823 {FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT,
824 offsetof(OpenLogicalChannel, separateStack),
825 _NetworkAccessParameters},
826 {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
827};
828
829static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */
830 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
831 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
832 ,
833};
834
835static field_t _Setup_UUIE[] = { /* SEQUENCE */
836 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
837 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
838 offsetof(Setup_UUIE, h245Address), _TransportAddress},
839 {FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
840 _Setup_UUIE_sourceAddress},
841 {FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
842 {FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
843 _Setup_UUIE_destinationAddress},
844 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
845 offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress},
846 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
847 _Setup_UUIE_destExtraCallInfo},
848 {FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
849 _Setup_UUIE_destExtraCRV},
850 {FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
851 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
852 {FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0,
853 _Setup_UUIE_conferenceGoal},
854 {FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0,
855 _QseriesOptions},
856 {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
857 {FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
858 offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress},
859 {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
860 NULL},
861 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
862 {FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
863 NULL},
864 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
865 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
866 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
867 offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart},
868 {FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
869 {FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
870 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
871 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
872 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
873 {FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0,
874 NULL},
875 {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
876 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
877 NULL},
878 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
879 NULL},
880 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
881 {FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0,
882 NULL},
883 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
884 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
885 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
886 {FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
887 {FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
888 {FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
889 {FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
890 {FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
891 NULL},
892};
893
894static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */
895 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
896 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
897 ,
898};
899
900static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */
901 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
902 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
903 _EndpointType},
904 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
905 offsetof(CallProceeding_UUIE, h245Address), _TransportAddress},
906 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
907 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
908 NULL},
909 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
910 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
911 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
912 offsetof(CallProceeding_UUIE, fastStart),
913 _CallProceeding_UUIE_fastStart},
914 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
915 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
916 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
917 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
918};
919
920static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */
921 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
922 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
923 ,
924};
925
926static field_t _Connect_UUIE[] = { /* SEQUENCE */
927 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
928 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
929 offsetof(Connect_UUIE, h245Address), _TransportAddress},
930 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
931 _EndpointType},
932 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
933 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
934 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
935 NULL},
936 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
937 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
938 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
939 offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart},
940 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
941 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
942 {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
943 {FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
944 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
945 NULL},
946 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
947 NULL},
948 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
949 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
950 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
951 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
952};
953
954static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */
955 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
956 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
957 ,
958};
959
960static field_t _Alerting_UUIE[] = { /* SEQUENCE */
961 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
962 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
963 _EndpointType},
964 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
965 offsetof(Alerting_UUIE, h245Address), _TransportAddress},
966 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
967 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
968 NULL},
969 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
970 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
971 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
972 offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart},
973 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
974 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
975 {FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
976 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
977 NULL},
978 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
979 NULL},
980 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
981 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
982 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
983 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
984};
985
986static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */
987 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
988 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
989 ,
990};
991
992static field_t _Information_UUIE[] = { /* SEQUENCE */
993 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
994 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
995 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
996 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
997 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
998 offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart},
999 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1000 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
1001};
1002
1003static field_t _ReleaseCompleteReason[] = { /* CHOICE */
1004 {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1005 {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1006 {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1007 {FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1008 {FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1009 {FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1010 {FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1011 {FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1012 {FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1013 {FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1014 {FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1015 {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1016 {FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1017 {FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1018 {FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1019 {FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1020 {FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1021 {FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL},
1022 {FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0,
1023 NULL},
1024 {FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1025 {FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1026 {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1027};
1028
1029static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */
1030 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1031 {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0,
1032 _ReleaseCompleteReason},
1033 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
1034 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1035 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1036 {FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1037 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
1038 NULL},
1039 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
1040 NULL},
1041 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
1042 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1043 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
1044};
1045
1046static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */
1047 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1048};
1049
1050static field_t _FacilityReason[] = { /* CHOICE */
1051 {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1052 {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1053 {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1054 {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1055 {FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1056 {FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1057 {FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1058 {FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1059 {FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1060 {FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1061 {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1062};
1063
1064static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */
1065 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
1066 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
1067 ,
1068};
1069
1070static field_t _Facility_UUIE[] = { /* SEQUENCE */
1071 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1072 {FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0,
1073 _TransportAddress},
1074 {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1075 _Facility_UUIE_alternativeAliasAddress},
1076 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
1077 {FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT,
1078 offsetof(Facility_UUIE, reason), _FacilityReason},
1079 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
1080 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1081 {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
1082 NULL},
1083 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1084 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1085 {FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1086 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1087 offsetof(Facility_UUIE, h245Address), _TransportAddress},
1088 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
1089 offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart},
1090 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1091 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1092 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1093 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1094 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
1095 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
1096 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL},
1097 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
1098 NULL},
1099};
1100
1101static field_t _CallIdentifier[] = { /* SEQUENCE */
1102 {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
1103};
1104
1105static field_t _SecurityServiceMode[] = { /* CHOICE */
1106 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
1107 {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1108 {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1109};
1110
1111static field_t _SecurityCapabilities[] = { /* SEQUENCE */
1112 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
1113 _NonStandardParameter},
1114 {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1115 _SecurityServiceMode},
1116 {FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1117 _SecurityServiceMode},
1118 {FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1119 _SecurityServiceMode},
1120};
1121
1122static field_t _H245Security[] = { /* CHOICE */
1123 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
1124 {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1125 {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
1126 {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
1127};
1128
1129static field_t _DHset[] = { /* SEQUENCE */
1130 {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1131 {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1132 {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1133};
1134
1135static field_t _TypedCertificate[] = { /* SEQUENCE */
1136 {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL},
1137 {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1138};
1139
1140static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */
1141 {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1142 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1143};
1144
1145static field_t _ClearToken[] = { /* SEQUENCE */
1146 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1147 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL},
1148 {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1149 {FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset},
1150 {FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL},
1151 {FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
1152 {FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0,
1153 _TypedCertificate},
1154 {FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1155 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
1156 _H235_NonStandardParameter},
1157 {FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL},
1158 {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1159};
1160
1161static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */
1162 {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
1163};
1164
1165static field_t _Params[] = { /* SEQUENCE */
1166 {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
1167 {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL},
1168 {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
1169};
1170
1171static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */
1172 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1173 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1174 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1175};
1176
1177static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */
1178 {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1179 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
1180 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1181 _CryptoH323Token_cryptoEPPwdHash_token},
1182};
1183
1184static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */
1185 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1186 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1187 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1188};
1189
1190static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */
1191 {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1192 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
1193 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1194 _CryptoH323Token_cryptoGKPwdHash_token},
1195};
1196
1197static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */
1198 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1199 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1200 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1201};
1202
1203static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */
1204 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1205 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1206 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1207};
1208
1209static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */
1210 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1211 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1212 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1213 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1214};
1215
1216static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */
1217 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1218 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1219 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1220 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1221};
1222
1223static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */
1224 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1225 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1226 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1227 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1228};
1229
1230static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */
1231 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1232 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1233 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1234};
1235
1236static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */
1237 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1238 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1239 _CryptoToken_cryptoEncryptedToken_token},
1240};
1241
1242static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */
1243 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1244 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1245 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1246 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1247};
1248
1249static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */
1250 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1251 {FNAME("token") SEQ, 0, 4, 4, SKIP, 0,
1252 _CryptoToken_cryptoSignedToken_token},
1253};
1254
1255static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */
1256 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1257 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1258 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1259};
1260
1261static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */
1262 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1263 {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
1264 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1265 _CryptoToken_cryptoHashedToken_token},
1266};
1267
1268static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */
1269 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1270 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1271 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1272};
1273
1274static field_t _CryptoToken[] = { /* CHOICE */
1275 {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0,
1276 _CryptoToken_cryptoEncryptedToken},
1277 {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0,
1278 _CryptoToken_cryptoSignedToken},
1279 {FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0,
1280 _CryptoToken_cryptoHashedToken},
1281 {FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1282 _CryptoToken_cryptoPwdEncr},
1283};
1284
1285static field_t _CryptoH323Token[] = { /* CHOICE */
1286 {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0,
1287 _CryptoH323Token_cryptoEPPwdHash},
1288 {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0,
1289 _CryptoH323Token_cryptoGKPwdHash},
1290 {FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1291 _CryptoH323Token_cryptoEPPwdEncr},
1292 {FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1293 _CryptoH323Token_cryptoGKPwdEncr},
1294 {FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0,
1295 _CryptoH323Token_cryptoEPCert},
1296 {FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0,
1297 _CryptoH323Token_cryptoGKCert},
1298 {FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0,
1299 _CryptoH323Token_cryptoFastStart},
1300 {FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0,
1301 _CryptoToken},
1302};
1303
1304static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */
1305 {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token},
1306};
1307
1308static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */
1309 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
1310 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
1311 ,
1312};
1313
1314static field_t _Progress_UUIE[] = { /* SEQUENCE */
1315 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1316 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
1317 _EndpointType},
1318 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1319 offsetof(Progress_UUIE, h245Address), _TransportAddress},
1320 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0,
1321 _CallIdentifier},
1322 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
1323 _H245Security},
1324 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1325 _Progress_UUIE_tokens},
1326 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1327 _Progress_UUIE_cryptoTokens},
1328 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
1329 offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart},
1330 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1331 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1332 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1333};
1334
1335static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */
1336 {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT,
1337 offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE},
1338 {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT,
1339 offsetof(H323_UU_PDU_h323_message_body, callProceeding),
1340 _CallProceeding_UUIE},
1341 {FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT,
1342 offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE},
1343 {FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT,
1344 offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE},
1345 {FNAME("information") SEQ, 0, 1, 7, DECODE | EXT,
1346 offsetof(H323_UU_PDU_h323_message_body, information),
1347 _Information_UUIE},
1348 {FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0,
1349 _ReleaseComplete_UUIE},
1350 {FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT,
1351 offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE},
1352 {FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT,
1353 offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE},
1354 {FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1355 {FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1356 {FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1357 {FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1358 {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1359};
1360
1361static field_t _RequestMessage[] = { /* CHOICE */
1362 {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1363 {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1364 {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL},
1365 {FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT,
1366 offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel},
1367 {FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL},
1368 {FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL},
1369 {FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1370 {FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1371 {FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1372 {FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1373 {FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1374 {FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL},
1375 {FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
1376 {FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
1377 {FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0,
1378 NULL},
1379};
1380
1381static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
1382 {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
1383 _H222LogicalChannelParameters},
1384 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
1385 offsetof
1386 (OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters,
1387 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
1388};
1389
1390static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */
1391 {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
1392 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
1393 {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT,
1394 offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters,
1395 multiplexParameters),
1396 _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters},
1397 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
1398};
1399
1400static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */
1401 {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
1402};
1403
1404static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */
1405 {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1406 _H2250LogicalChannelAckParameters_nonStandard},
1407 {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
1408 {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
1409 offsetof(H2250LogicalChannelAckParameters, mediaChannel),
1410 _H245_TransportAddress},
1411 {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
1412 offsetof(H2250LogicalChannelAckParameters, mediaControlChannel),
1413 _H245_TransportAddress},
1414 {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL},
1415 {FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1416 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
1417};
1418
1419static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */
1420 {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT,
1421 offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters,
1422 h2250LogicalChannelAckParameters),
1423 _H2250LogicalChannelAckParameters},
1424};
1425
1426static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */
1427 {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
1428 {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4,
1429 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
1430 reverseLogicalChannelParameters),
1431 _OpenLogicalChannelAck_reverseLogicalChannelParameters},
1432 {FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL},
1433 {FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1,
1434 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
1435 forwardMultiplexAckParameters),
1436 _OpenLogicalChannelAck_forwardMultiplexAckParameters},
1437 {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
1438};
1439
1440static field_t _ResponseMessage[] = { /* CHOICE */
1441 {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1442 {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0,
1443 NULL},
1444 {FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0,
1445 NULL},
1446 {FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1447 {FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1448 NULL},
1449 {FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT,
1450 offsetof(ResponseMessage, openLogicalChannelAck),
1451 _OpenLogicalChannelAck},
1452 {FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1453 {FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1454 {FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1455 {FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1456 NULL},
1457 {FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1458 {FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1459 {FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1460 {FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1461 NULL},
1462 {FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1463 {FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1464 {FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1465 {FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1466 {FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1467 {FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0,
1468 NULL},
1469 {FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
1470 {FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
1471 {FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0,
1472 NULL},
1473 {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL},
1474};
1475
1476static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */
1477 {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT,
1478 offsetof(MultimediaSystemControlMessage, request), _RequestMessage},
1479 {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT,
1480 offsetof(MultimediaSystemControlMessage, response),
1481 _ResponseMessage},
1482 {FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL},
1483 {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL},
1484};
1485
1486static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */
1487 {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT,
1488 sizeof(MultimediaSystemControlMessage),
1489 _MultimediaSystemControlMessage}
1490 ,
1491};
1492
1493static field_t _H323_UU_PDU[] = { /* SEQUENCE */
1494 {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT,
1495 offsetof(H323_UU_PDU, h323_message_body),
1496 _H323_UU_PDU_h323_message_body},
1497 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1498 _NonStandardParameter},
1499 {FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1500 NULL},
1501 {FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1502 {FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT,
1503 offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control},
1504 {FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1505 {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1506 {FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT,
1507 0, NULL},
1508 {FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT,
1509 0, NULL},
1510 {FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1511 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1512};
1513
1514static field_t _H323_UserInformation[] = { /* SEQUENCE */
1515 {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT,
1516 offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU},
1517 {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
1518};
1519
1520static field_t _GatekeeperRequest[] = { /* SEQUENCE */
1521 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1522 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1523 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1524 _NonStandardParameter},
1525 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1526 offsetof(GatekeeperRequest, rasAddress), _TransportAddress},
1527 {FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL},
1528 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1529 {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
1530 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1531 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1532 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1533 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1534 {FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1535 NULL},
1536 {FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1537 {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1538 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1539 {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1540 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1541 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1542};
1543
1544static field_t _GatekeeperConfirm[] = { /* SEQUENCE */
1545 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1546 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1547 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1548 _NonStandardParameter},
1549 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1550 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1551 offsetof(GatekeeperConfirm, rasAddress), _TransportAddress},
1552 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1553 {FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0,
1554 NULL},
1555 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1556 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1557 {FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL},
1558 {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1559 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1560 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1561 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1562};
1563
1564static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
1565 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1566 sizeof(TransportAddress), _TransportAddress}
1567 ,
1568};
1569
1570static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */
1571 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1572 sizeof(TransportAddress), _TransportAddress}
1573 ,
1574};
1575
1576static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */
1577 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1578};
1579
1580static field_t _RegistrationRequest[] = { /* SEQUENCE */
1581 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1582 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1583 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1584 _NonStandardParameter},
1585 {FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1586 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1587 offsetof(RegistrationRequest, callSignalAddress),
1588 _RegistrationRequest_callSignalAddress},
1589 {FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE,
1590 offsetof(RegistrationRequest, rasAddress),
1591 _RegistrationRequest_rasAddress},
1592 {FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
1593 {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1594 _RegistrationRequest_terminalAlias},
1595 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1596 {FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0,
1597 _VendorIdentifier},
1598 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1599 {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
1600 offsetof(RegistrationRequest, timeToLive), NULL},
1601 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1602 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1603 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1604 {FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1605 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1606 {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1607 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1608 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1609 0, NULL},
1610 {FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1611 {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1612 NULL},
1613 {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1614 {FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0,
1615 NULL},
1616 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1617 {FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1618 NULL},
1619 {FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0,
1620 NULL},
1621 {FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT,
1622 0, NULL},
1623 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1624 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1625 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1626};
1627
1628static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */
1629 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1630 sizeof(TransportAddress), _TransportAddress}
1631 ,
1632};
1633
1634static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */
1635 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1636};
1637
1638static field_t _RegistrationConfirm[] = { /* SEQUENCE */
1639 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1640 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1641 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1642 _NonStandardParameter},
1643 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1644 offsetof(RegistrationConfirm, callSignalAddress),
1645 _RegistrationConfirm_callSignalAddress},
1646 {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1647 _RegistrationConfirm_terminalAlias},
1648 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1649 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1650 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1651 {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
1652 offsetof(RegistrationConfirm, timeToLive), NULL},
1653 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1654 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1655 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1656 {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1657 {FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL},
1658 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1659 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1660 {FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0,
1661 NULL},
1662 {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1663 NULL},
1664 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1665 {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1666 {FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0,
1667 NULL},
1668 {FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0,
1669 NULL},
1670 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1671 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1672};
1673
1674static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
1675 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1676 sizeof(TransportAddress), _TransportAddress}
1677 ,
1678};
1679
1680static field_t _UnregistrationRequest[] = { /* SEQUENCE */
1681 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1682 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1683 offsetof(UnregistrationRequest, callSignalAddress),
1684 _UnregistrationRequest_callSignalAddress},
1685 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1686 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1687 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1688 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1689 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1690 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1691 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1692 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1693 {FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL},
1694 {FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1695 NULL},
1696 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1697 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1698 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1699};
1700
1701static field_t _CallModel[] = { /* CHOICE */
1702 {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1703 {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1704};
1705
1706static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */
1707 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1708};
1709
1710static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */
1711 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1712};
1713
1714static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */
1715 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1716};
1717
1718static field_t _AdmissionRequest[] = { /* SEQUENCE */
1719 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1720 {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
1721 {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel},
1722 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1723 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1724 _AdmissionRequest_destinationInfo},
1725 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1726 offsetof(AdmissionRequest, destCallSignalAddress),
1727 _TransportAddress},
1728 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1729 _AdmissionRequest_destExtraCallInfo},
1730 {FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
1731 _AdmissionRequest_srcInfo},
1732 {FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1733 offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress},
1734 {FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL},
1735 {FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL},
1736 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1737 {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
1738 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL},
1739 {FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1740 {FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1741 {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1742 {FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1743 {FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1744 {FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1745 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1746 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1747 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1748 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1749 {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1750 {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1751 {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1752 {FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1753 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1754 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1755 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1756 {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
1757 NULL},
1758 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1759 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1760};
1761
1762static field_t _AdmissionConfirm[] = { /* SEQUENCE */
1763 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1764 {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL},
1765 {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel},
1766 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1767 offsetof(AdmissionConfirm, destCallSignalAddress),
1768 _TransportAddress},
1769 {FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL},
1770 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1771 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1772 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1773 {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
1774 {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1775 NULL},
1776 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1777 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1778 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1779 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1780 {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1781 {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1782 {FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL},
1783 {FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1784 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1785 0, NULL},
1786 {FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0,
1787 NULL},
1788 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1789 {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1790 {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1791 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1792 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1793 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1794 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1795};
1796
1797static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */
1798 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1799};
1800
1801static field_t _LocationRequest[] = { /* SEQUENCE */
1802 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1803 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1804 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
1805 _LocationRequest_destinationInfo},
1806 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1807 _NonStandardParameter},
1808 {FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1809 offsetof(LocationRequest, replyAddress), _TransportAddress},
1810 {FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1811 {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1812 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1813 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1814 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1815 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1816 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1817 {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
1818 NULL},
1819 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1820 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1821 {FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL},
1822 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1823};
1824
1825static field_t _LocationConfirm[] = { /* SEQUENCE */
1826 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1827 {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1828 offsetof(LocationConfirm, callSignalAddress), _TransportAddress},
1829 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1830 offsetof(LocationConfirm, rasAddress), _TransportAddress},
1831 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1832 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1833 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1834 {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
1835 {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1836 NULL},
1837 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1838 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1839 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1840 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1841 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1842 0, NULL},
1843 {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1844 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1845 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1846 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1847 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1848 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1849};
1850
1851static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */
1852 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1853 sizeof(TransportAddress), _TransportAddress}
1854 ,
1855};
1856
1857static field_t _InfoRequestResponse[] = { /* SEQUENCE */
1858 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1859 _NonStandardParameter},
1860 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1861 {FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
1862 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1863 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1864 offsetof(InfoRequestResponse, rasAddress), _TransportAddress},
1865 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1866 offsetof(InfoRequestResponse, callSignalAddress),
1867 _InfoRequestResponse_callSignalAddress},
1868 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1869 {FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1870 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1871 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1872 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1873 {FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1874 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1875 {FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
1876 {FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1877 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1878};
1879
1880static field_t _RasMessage[] = { /* CHOICE */
1881 {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT,
1882 offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest},
1883 {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT,
1884 offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm},
1885 {FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
1886 {FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT,
1887 offsetof(RasMessage, registrationRequest), _RegistrationRequest},
1888 {FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT,
1889 offsetof(RasMessage, registrationConfirm), _RegistrationConfirm},
1890 {FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
1891 {FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT,
1892 offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest},
1893 {FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL},
1894 {FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1895 {FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT,
1896 offsetof(RasMessage, admissionRequest), _AdmissionRequest},
1897 {FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT,
1898 offsetof(RasMessage, admissionConfirm), _AdmissionConfirm},
1899 {FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL},
1900 {FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL},
1901 {FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1902 {FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL},
1903 {FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL},
1904 {FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL},
1905 {FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1906 {FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT,
1907 offsetof(RasMessage, locationRequest), _LocationRequest},
1908 {FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT,
1909 offsetof(RasMessage, locationConfirm), _LocationConfirm},
1910 {FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL},
1911 {FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL},
1912 {FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT,
1913 offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse},
1914 {FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL},
1915 {FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL},
1916 {FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL},
1917 {FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0,
1918 NULL},
1919 {FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0,
1920 NULL},
1921 {FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL},
1922 {FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL},
1923 {FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0,
1924 NULL},
1925 {FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL},
1926};
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 000000000000..cc98f7aa5abe
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
@@ -0,0 +1,938 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 *
5 * This source code is licensed under General Public License version 2.
6 */
7
8typedef struct TransportAddress_ipAddress { /* SEQUENCE */
9 int options; /* No use */
10 unsigned ip;
11} TransportAddress_ipAddress;
12
13typedef struct TransportAddress { /* CHOICE */
14 enum {
15 eTransportAddress_ipAddress,
16 eTransportAddress_ipSourceRoute,
17 eTransportAddress_ipxAddress,
18 eTransportAddress_ip6Address,
19 eTransportAddress_netBios,
20 eTransportAddress_nsap,
21 eTransportAddress_nonStandardAddress,
22 } choice;
23 union {
24 TransportAddress_ipAddress ipAddress;
25 };
26} TransportAddress;
27
28typedef struct DataProtocolCapability { /* CHOICE */
29 enum {
30 eDataProtocolCapability_nonStandard,
31 eDataProtocolCapability_v14buffered,
32 eDataProtocolCapability_v42lapm,
33 eDataProtocolCapability_hdlcFrameTunnelling,
34 eDataProtocolCapability_h310SeparateVCStack,
35 eDataProtocolCapability_h310SingleVCStack,
36 eDataProtocolCapability_transparent,
37 eDataProtocolCapability_segmentationAndReassembly,
38 eDataProtocolCapability_hdlcFrameTunnelingwSAR,
39 eDataProtocolCapability_v120,
40 eDataProtocolCapability_separateLANStack,
41 eDataProtocolCapability_v76wCompression,
42 eDataProtocolCapability_tcp,
43 eDataProtocolCapability_udp,
44 } choice;
45} DataProtocolCapability;
46
47typedef struct DataApplicationCapability_application { /* CHOICE */
48 enum {
49 eDataApplicationCapability_application_nonStandard,
50 eDataApplicationCapability_application_t120,
51 eDataApplicationCapability_application_dsm_cc,
52 eDataApplicationCapability_application_userData,
53 eDataApplicationCapability_application_t84,
54 eDataApplicationCapability_application_t434,
55 eDataApplicationCapability_application_h224,
56 eDataApplicationCapability_application_nlpid,
57 eDataApplicationCapability_application_dsvdControl,
58 eDataApplicationCapability_application_h222DataPartitioning,
59 eDataApplicationCapability_application_t30fax,
60 eDataApplicationCapability_application_t140,
61 eDataApplicationCapability_application_t38fax,
62 eDataApplicationCapability_application_genericDataCapability,
63 } choice;
64 union {
65 DataProtocolCapability t120;
66 };
67} DataApplicationCapability_application;
68
69typedef struct DataApplicationCapability { /* SEQUENCE */
70 int options; /* No use */
71 DataApplicationCapability_application application;
72} DataApplicationCapability;
73
74typedef struct DataType { /* CHOICE */
75 enum {
76 eDataType_nonStandard,
77 eDataType_nullData,
78 eDataType_videoData,
79 eDataType_audioData,
80 eDataType_data,
81 eDataType_encryptionData,
82 eDataType_h235Control,
83 eDataType_h235Media,
84 eDataType_multiplexedStream,
85 } choice;
86 union {
87 DataApplicationCapability data;
88 };
89} DataType;
90
91typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
92 int options; /* No use */
93 unsigned network;
94} UnicastAddress_iPAddress;
95
96typedef struct UnicastAddress { /* CHOICE */
97 enum {
98 eUnicastAddress_iPAddress,
99 eUnicastAddress_iPXAddress,
100 eUnicastAddress_iP6Address,
101 eUnicastAddress_netBios,
102 eUnicastAddress_iPSourceRouteAddress,
103 eUnicastAddress_nsap,
104 eUnicastAddress_nonStandardAddress,
105 } choice;
106 union {
107 UnicastAddress_iPAddress iPAddress;
108 };
109} UnicastAddress;
110
111typedef struct H245_TransportAddress { /* CHOICE */
112 enum {
113 eH245_TransportAddress_unicastAddress,
114 eH245_TransportAddress_multicastAddress,
115 } choice;
116 union {
117 UnicastAddress unicastAddress;
118 };
119} H245_TransportAddress;
120
121typedef struct H2250LogicalChannelParameters { /* SEQUENCE */
122 enum {
123 eH2250LogicalChannelParameters_nonStandard = (1 << 31),
124 eH2250LogicalChannelParameters_associatedSessionID =
125 (1 << 30),
126 eH2250LogicalChannelParameters_mediaChannel = (1 << 29),
127 eH2250LogicalChannelParameters_mediaGuaranteedDelivery =
128 (1 << 28),
129 eH2250LogicalChannelParameters_mediaControlChannel =
130 (1 << 27),
131 eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery
132 = (1 << 26),
133 eH2250LogicalChannelParameters_silenceSuppression = (1 << 25),
134 eH2250LogicalChannelParameters_destination = (1 << 24),
135 eH2250LogicalChannelParameters_dynamicRTPPayloadType =
136 (1 << 23),
137 eH2250LogicalChannelParameters_mediaPacketization = (1 << 22),
138 eH2250LogicalChannelParameters_transportCapability =
139 (1 << 21),
140 eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20),
141 eH2250LogicalChannelParameters_source = (1 << 19),
142 } options;
143 H245_TransportAddress mediaChannel;
144 H245_TransportAddress mediaControlChannel;
145} H2250LogicalChannelParameters;
146
147typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */
148 enum {
149 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
150 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
151 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
152 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
153 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none,
154 } choice;
155 union {
156 H2250LogicalChannelParameters h2250LogicalChannelParameters;
157 };
158} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters;
159
160typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */
161 enum {
162 eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber
163 = (1 << 31),
164 eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency
165 = (1 << 30),
166 eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor
167 = (1 << 29),
168 } options;
169 DataType dataType;
170 OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters
171 multiplexParameters;
172} OpenLogicalChannel_forwardLogicalChannelParameters;
173
174typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
175 enum {
176 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters,
177 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters,
178 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
179 } choice;
180 union {
181 H2250LogicalChannelParameters h2250LogicalChannelParameters;
182 };
183} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters;
184
185typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */
186 enum {
187 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
188 = (1 << 31),
189 eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency
190 = (1 << 30),
191 eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor
192 = (1 << 29),
193 } options;
194 OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters
195 multiplexParameters;
196} OpenLogicalChannel_reverseLogicalChannelParameters;
197
198typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */
199 enum {
200 eNetworkAccessParameters_networkAddress_q2931Address,
201 eNetworkAccessParameters_networkAddress_e164Address,
202 eNetworkAccessParameters_networkAddress_localAreaAddress,
203 } choice;
204 union {
205 H245_TransportAddress localAreaAddress;
206 };
207} NetworkAccessParameters_networkAddress;
208
209typedef struct NetworkAccessParameters { /* SEQUENCE */
210 enum {
211 eNetworkAccessParameters_distribution = (1 << 31),
212 eNetworkAccessParameters_externalReference = (1 << 30),
213 eNetworkAccessParameters_t120SetupProcedure = (1 << 29),
214 } options;
215 NetworkAccessParameters_networkAddress networkAddress;
216} NetworkAccessParameters;
217
218typedef struct OpenLogicalChannel { /* SEQUENCE */
219 enum {
220 eOpenLogicalChannel_reverseLogicalChannelParameters =
221 (1 << 31),
222 eOpenLogicalChannel_separateStack = (1 << 30),
223 eOpenLogicalChannel_encryptionSync = (1 << 29),
224 } options;
225 OpenLogicalChannel_forwardLogicalChannelParameters
226 forwardLogicalChannelParameters;
227 OpenLogicalChannel_reverseLogicalChannelParameters
228 reverseLogicalChannelParameters;
229 NetworkAccessParameters separateStack;
230} OpenLogicalChannel;
231
232typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */
233 int count;
234 OpenLogicalChannel item[30];
235} Setup_UUIE_fastStart;
236
237typedef struct Setup_UUIE { /* SEQUENCE */
238 enum {
239 eSetup_UUIE_h245Address = (1 << 31),
240 eSetup_UUIE_sourceAddress = (1 << 30),
241 eSetup_UUIE_destinationAddress = (1 << 29),
242 eSetup_UUIE_destCallSignalAddress = (1 << 28),
243 eSetup_UUIE_destExtraCallInfo = (1 << 27),
244 eSetup_UUIE_destExtraCRV = (1 << 26),
245 eSetup_UUIE_callServices = (1 << 25),
246 eSetup_UUIE_sourceCallSignalAddress = (1 << 24),
247 eSetup_UUIE_remoteExtensionAddress = (1 << 23),
248 eSetup_UUIE_callIdentifier = (1 << 22),
249 eSetup_UUIE_h245SecurityCapability = (1 << 21),
250 eSetup_UUIE_tokens = (1 << 20),
251 eSetup_UUIE_cryptoTokens = (1 << 19),
252 eSetup_UUIE_fastStart = (1 << 18),
253 eSetup_UUIE_mediaWaitForConnect = (1 << 17),
254 eSetup_UUIE_canOverlapSend = (1 << 16),
255 eSetup_UUIE_endpointIdentifier = (1 << 15),
256 eSetup_UUIE_multipleCalls = (1 << 14),
257 eSetup_UUIE_maintainConnection = (1 << 13),
258 eSetup_UUIE_connectionParameters = (1 << 12),
259 eSetup_UUIE_language = (1 << 11),
260 eSetup_UUIE_presentationIndicator = (1 << 10),
261 eSetup_UUIE_screeningIndicator = (1 << 9),
262 eSetup_UUIE_serviceControl = (1 << 8),
263 eSetup_UUIE_symmetricOperationRequired = (1 << 7),
264 eSetup_UUIE_capacity = (1 << 6),
265 eSetup_UUIE_circuitInfo = (1 << 5),
266 eSetup_UUIE_desiredProtocols = (1 << 4),
267 eSetup_UUIE_neededFeatures = (1 << 3),
268 eSetup_UUIE_desiredFeatures = (1 << 2),
269 eSetup_UUIE_supportedFeatures = (1 << 1),
270 eSetup_UUIE_parallelH245Control = (1 << 0),
271 } options;
272 TransportAddress h245Address;
273 TransportAddress destCallSignalAddress;
274 TransportAddress sourceCallSignalAddress;
275 Setup_UUIE_fastStart fastStart;
276} Setup_UUIE;
277
278typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */
279 int count;
280 OpenLogicalChannel item[30];
281} CallProceeding_UUIE_fastStart;
282
283typedef struct CallProceeding_UUIE { /* SEQUENCE */
284 enum {
285 eCallProceeding_UUIE_h245Address = (1 << 31),
286 eCallProceeding_UUIE_callIdentifier = (1 << 30),
287 eCallProceeding_UUIE_h245SecurityMode = (1 << 29),
288 eCallProceeding_UUIE_tokens = (1 << 28),
289 eCallProceeding_UUIE_cryptoTokens = (1 << 27),
290 eCallProceeding_UUIE_fastStart = (1 << 26),
291 eCallProceeding_UUIE_multipleCalls = (1 << 25),
292 eCallProceeding_UUIE_maintainConnection = (1 << 24),
293 eCallProceeding_UUIE_fastConnectRefused = (1 << 23),
294 eCallProceeding_UUIE_featureSet = (1 << 22),
295 } options;
296 TransportAddress h245Address;
297 CallProceeding_UUIE_fastStart fastStart;
298} CallProceeding_UUIE;
299
300typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */
301 int count;
302 OpenLogicalChannel item[30];
303} Connect_UUIE_fastStart;
304
305typedef struct Connect_UUIE { /* SEQUENCE */
306 enum {
307 eConnect_UUIE_h245Address = (1 << 31),
308 eConnect_UUIE_callIdentifier = (1 << 30),
309 eConnect_UUIE_h245SecurityMode = (1 << 29),
310 eConnect_UUIE_tokens = (1 << 28),
311 eConnect_UUIE_cryptoTokens = (1 << 27),
312 eConnect_UUIE_fastStart = (1 << 26),
313 eConnect_UUIE_multipleCalls = (1 << 25),
314 eConnect_UUIE_maintainConnection = (1 << 24),
315 eConnect_UUIE_language = (1 << 23),
316 eConnect_UUIE_connectedAddress = (1 << 22),
317 eConnect_UUIE_presentationIndicator = (1 << 21),
318 eConnect_UUIE_screeningIndicator = (1 << 20),
319 eConnect_UUIE_fastConnectRefused = (1 << 19),
320 eConnect_UUIE_serviceControl = (1 << 18),
321 eConnect_UUIE_capacity = (1 << 17),
322 eConnect_UUIE_featureSet = (1 << 16),
323 } options;
324 TransportAddress h245Address;
325 Connect_UUIE_fastStart fastStart;
326} Connect_UUIE;
327
328typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */
329 int count;
330 OpenLogicalChannel item[30];
331} Alerting_UUIE_fastStart;
332
333typedef struct Alerting_UUIE { /* SEQUENCE */
334 enum {
335 eAlerting_UUIE_h245Address = (1 << 31),
336 eAlerting_UUIE_callIdentifier = (1 << 30),
337 eAlerting_UUIE_h245SecurityMode = (1 << 29),
338 eAlerting_UUIE_tokens = (1 << 28),
339 eAlerting_UUIE_cryptoTokens = (1 << 27),
340 eAlerting_UUIE_fastStart = (1 << 26),
341 eAlerting_UUIE_multipleCalls = (1 << 25),
342 eAlerting_UUIE_maintainConnection = (1 << 24),
343 eAlerting_UUIE_alertingAddress = (1 << 23),
344 eAlerting_UUIE_presentationIndicator = (1 << 22),
345 eAlerting_UUIE_screeningIndicator = (1 << 21),
346 eAlerting_UUIE_fastConnectRefused = (1 << 20),
347 eAlerting_UUIE_serviceControl = (1 << 19),
348 eAlerting_UUIE_capacity = (1 << 18),
349 eAlerting_UUIE_featureSet = (1 << 17),
350 } options;
351 TransportAddress h245Address;
352 Alerting_UUIE_fastStart fastStart;
353} Alerting_UUIE;
354
355typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */
356 int count;
357 OpenLogicalChannel item[30];
358} Information_UUIE_fastStart;
359
360typedef struct Information_UUIE { /* SEQUENCE */
361 enum {
362 eInformation_UUIE_callIdentifier = (1 << 31),
363 eInformation_UUIE_tokens = (1 << 30),
364 eInformation_UUIE_cryptoTokens = (1 << 29),
365 eInformation_UUIE_fastStart = (1 << 28),
366 eInformation_UUIE_fastConnectRefused = (1 << 27),
367 eInformation_UUIE_circuitInfo = (1 << 26),
368 } options;
369 Information_UUIE_fastStart fastStart;
370} Information_UUIE;
371
372typedef struct FacilityReason { /* CHOICE */
373 enum {
374 eFacilityReason_routeCallToGatekeeper,
375 eFacilityReason_callForwarded,
376 eFacilityReason_routeCallToMC,
377 eFacilityReason_undefinedReason,
378 eFacilityReason_conferenceListChoice,
379 eFacilityReason_startH245,
380 eFacilityReason_noH245,
381 eFacilityReason_newTokens,
382 eFacilityReason_featureSetUpdate,
383 eFacilityReason_forwardedElements,
384 eFacilityReason_transportedInformation,
385 } choice;
386} FacilityReason;
387
388typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */
389 int count;
390 OpenLogicalChannel item[30];
391} Facility_UUIE_fastStart;
392
393typedef struct Facility_UUIE { /* SEQUENCE */
394 enum {
395 eFacility_UUIE_alternativeAddress = (1 << 31),
396 eFacility_UUIE_alternativeAliasAddress = (1 << 30),
397 eFacility_UUIE_conferenceID = (1 << 29),
398 eFacility_UUIE_callIdentifier = (1 << 28),
399 eFacility_UUIE_destExtraCallInfo = (1 << 27),
400 eFacility_UUIE_remoteExtensionAddress = (1 << 26),
401 eFacility_UUIE_tokens = (1 << 25),
402 eFacility_UUIE_cryptoTokens = (1 << 24),
403 eFacility_UUIE_conferences = (1 << 23),
404 eFacility_UUIE_h245Address = (1 << 22),
405 eFacility_UUIE_fastStart = (1 << 21),
406 eFacility_UUIE_multipleCalls = (1 << 20),
407 eFacility_UUIE_maintainConnection = (1 << 19),
408 eFacility_UUIE_fastConnectRefused = (1 << 18),
409 eFacility_UUIE_serviceControl = (1 << 17),
410 eFacility_UUIE_circuitInfo = (1 << 16),
411 eFacility_UUIE_featureSet = (1 << 15),
412 eFacility_UUIE_destinationInfo = (1 << 14),
413 eFacility_UUIE_h245SecurityMode = (1 << 13),
414 } options;
415 FacilityReason reason;
416 TransportAddress h245Address;
417 Facility_UUIE_fastStart fastStart;
418} Facility_UUIE;
419
420typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */
421 int count;
422 OpenLogicalChannel item[30];
423} Progress_UUIE_fastStart;
424
425typedef struct Progress_UUIE { /* SEQUENCE */
426 enum {
427 eProgress_UUIE_h245Address = (1 << 31),
428 eProgress_UUIE_h245SecurityMode = (1 << 30),
429 eProgress_UUIE_tokens = (1 << 29),
430 eProgress_UUIE_cryptoTokens = (1 << 28),
431 eProgress_UUIE_fastStart = (1 << 27),
432 eProgress_UUIE_multipleCalls = (1 << 26),
433 eProgress_UUIE_maintainConnection = (1 << 25),
434 eProgress_UUIE_fastConnectRefused = (1 << 24),
435 } options;
436 TransportAddress h245Address;
437 Progress_UUIE_fastStart fastStart;
438} Progress_UUIE;
439
440typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */
441 enum {
442 eH323_UU_PDU_h323_message_body_setup,
443 eH323_UU_PDU_h323_message_body_callProceeding,
444 eH323_UU_PDU_h323_message_body_connect,
445 eH323_UU_PDU_h323_message_body_alerting,
446 eH323_UU_PDU_h323_message_body_information,
447 eH323_UU_PDU_h323_message_body_releaseComplete,
448 eH323_UU_PDU_h323_message_body_facility,
449 eH323_UU_PDU_h323_message_body_progress,
450 eH323_UU_PDU_h323_message_body_empty,
451 eH323_UU_PDU_h323_message_body_status,
452 eH323_UU_PDU_h323_message_body_statusInquiry,
453 eH323_UU_PDU_h323_message_body_setupAcknowledge,
454 eH323_UU_PDU_h323_message_body_notify,
455 } choice;
456 union {
457 Setup_UUIE setup;
458 CallProceeding_UUIE callProceeding;
459 Connect_UUIE connect;
460 Alerting_UUIE alerting;
461 Information_UUIE information;
462 Facility_UUIE facility;
463 Progress_UUIE progress;
464 };
465} H323_UU_PDU_h323_message_body;
466
467typedef struct RequestMessage { /* CHOICE */
468 enum {
469 eRequestMessage_nonStandard,
470 eRequestMessage_masterSlaveDetermination,
471 eRequestMessage_terminalCapabilitySet,
472 eRequestMessage_openLogicalChannel,
473 eRequestMessage_closeLogicalChannel,
474 eRequestMessage_requestChannelClose,
475 eRequestMessage_multiplexEntrySend,
476 eRequestMessage_requestMultiplexEntry,
477 eRequestMessage_requestMode,
478 eRequestMessage_roundTripDelayRequest,
479 eRequestMessage_maintenanceLoopRequest,
480 eRequestMessage_communicationModeRequest,
481 eRequestMessage_conferenceRequest,
482 eRequestMessage_multilinkRequest,
483 eRequestMessage_logicalChannelRateRequest,
484 } choice;
485 union {
486 OpenLogicalChannel openLogicalChannel;
487 };
488} RequestMessage;
489
490typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */
491 enum {
492 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters,
493 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters,
494 } choice;
495 union {
496 H2250LogicalChannelParameters h2250LogicalChannelParameters;
497 };
498} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters;
499
500typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */
501 enum {
502 eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber
503 = (1 << 31),
504 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
505 = (1 << 30),
506 eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor
507 = (1 << 29),
508 } options;
509 OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters
510 multiplexParameters;
511} OpenLogicalChannelAck_reverseLogicalChannelParameters;
512
513typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */
514 enum {
515 eH2250LogicalChannelAckParameters_nonStandard = (1 << 31),
516 eH2250LogicalChannelAckParameters_sessionID = (1 << 30),
517 eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29),
518 eH2250LogicalChannelAckParameters_mediaControlChannel =
519 (1 << 28),
520 eH2250LogicalChannelAckParameters_dynamicRTPPayloadType =
521 (1 << 27),
522 eH2250LogicalChannelAckParameters_flowControlToZero =
523 (1 << 26),
524 eH2250LogicalChannelAckParameters_portNumber = (1 << 25),
525 } options;
526 H245_TransportAddress mediaChannel;
527 H245_TransportAddress mediaControlChannel;
528} H2250LogicalChannelAckParameters;
529
530typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */
531 enum {
532 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters,
533 } choice;
534 union {
535 H2250LogicalChannelAckParameters
536 h2250LogicalChannelAckParameters;
537 };
538} OpenLogicalChannelAck_forwardMultiplexAckParameters;
539
540typedef struct OpenLogicalChannelAck { /* SEQUENCE */
541 enum {
542 eOpenLogicalChannelAck_reverseLogicalChannelParameters =
543 (1 << 31),
544 eOpenLogicalChannelAck_separateStack = (1 << 30),
545 eOpenLogicalChannelAck_forwardMultiplexAckParameters =
546 (1 << 29),
547 eOpenLogicalChannelAck_encryptionSync = (1 << 28),
548 } options;
549 OpenLogicalChannelAck_reverseLogicalChannelParameters
550 reverseLogicalChannelParameters;
551 OpenLogicalChannelAck_forwardMultiplexAckParameters
552 forwardMultiplexAckParameters;
553} OpenLogicalChannelAck;
554
555typedef struct ResponseMessage { /* CHOICE */
556 enum {
557 eResponseMessage_nonStandard,
558 eResponseMessage_masterSlaveDeterminationAck,
559 eResponseMessage_masterSlaveDeterminationReject,
560 eResponseMessage_terminalCapabilitySetAck,
561 eResponseMessage_terminalCapabilitySetReject,
562 eResponseMessage_openLogicalChannelAck,
563 eResponseMessage_openLogicalChannelReject,
564 eResponseMessage_closeLogicalChannelAck,
565 eResponseMessage_requestChannelCloseAck,
566 eResponseMessage_requestChannelCloseReject,
567 eResponseMessage_multiplexEntrySendAck,
568 eResponseMessage_multiplexEntrySendReject,
569 eResponseMessage_requestMultiplexEntryAck,
570 eResponseMessage_requestMultiplexEntryReject,
571 eResponseMessage_requestModeAck,
572 eResponseMessage_requestModeReject,
573 eResponseMessage_roundTripDelayResponse,
574 eResponseMessage_maintenanceLoopAck,
575 eResponseMessage_maintenanceLoopReject,
576 eResponseMessage_communicationModeResponse,
577 eResponseMessage_conferenceResponse,
578 eResponseMessage_multilinkResponse,
579 eResponseMessage_logicalChannelRateAcknowledge,
580 eResponseMessage_logicalChannelRateReject,
581 } choice;
582 union {
583 OpenLogicalChannelAck openLogicalChannelAck;
584 };
585} ResponseMessage;
586
587typedef struct MultimediaSystemControlMessage { /* CHOICE */
588 enum {
589 eMultimediaSystemControlMessage_request,
590 eMultimediaSystemControlMessage_response,
591 eMultimediaSystemControlMessage_command,
592 eMultimediaSystemControlMessage_indication,
593 } choice;
594 union {
595 RequestMessage request;
596 ResponseMessage response;
597 };
598} MultimediaSystemControlMessage;
599
600typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */
601 int count;
602 MultimediaSystemControlMessage item[4];
603} H323_UU_PDU_h245Control;
604
605typedef struct H323_UU_PDU { /* SEQUENCE */
606 enum {
607 eH323_UU_PDU_nonStandardData = (1 << 31),
608 eH323_UU_PDU_h4501SupplementaryService = (1 << 30),
609 eH323_UU_PDU_h245Tunneling = (1 << 29),
610 eH323_UU_PDU_h245Control = (1 << 28),
611 eH323_UU_PDU_nonStandardControl = (1 << 27),
612 eH323_UU_PDU_callLinkage = (1 << 26),
613 eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25),
614 eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24),
615 eH323_UU_PDU_stimulusControl = (1 << 23),
616 eH323_UU_PDU_genericData = (1 << 22),
617 } options;
618 H323_UU_PDU_h323_message_body h323_message_body;
619 H323_UU_PDU_h245Control h245Control;
620} H323_UU_PDU;
621
622typedef struct H323_UserInformation { /* SEQUENCE */
623 enum {
624 eH323_UserInformation_user_data = (1 << 31),
625 } options;
626 H323_UU_PDU h323_uu_pdu;
627} H323_UserInformation;
628
629typedef struct GatekeeperRequest { /* SEQUENCE */
630 enum {
631 eGatekeeperRequest_nonStandardData = (1 << 31),
632 eGatekeeperRequest_gatekeeperIdentifier = (1 << 30),
633 eGatekeeperRequest_callServices = (1 << 29),
634 eGatekeeperRequest_endpointAlias = (1 << 28),
635 eGatekeeperRequest_alternateEndpoints = (1 << 27),
636 eGatekeeperRequest_tokens = (1 << 26),
637 eGatekeeperRequest_cryptoTokens = (1 << 25),
638 eGatekeeperRequest_authenticationCapability = (1 << 24),
639 eGatekeeperRequest_algorithmOIDs = (1 << 23),
640 eGatekeeperRequest_integrity = (1 << 22),
641 eGatekeeperRequest_integrityCheckValue = (1 << 21),
642 eGatekeeperRequest_supportsAltGK = (1 << 20),
643 eGatekeeperRequest_featureSet = (1 << 19),
644 eGatekeeperRequest_genericData = (1 << 18),
645 } options;
646 TransportAddress rasAddress;
647} GatekeeperRequest;
648
649typedef struct GatekeeperConfirm { /* SEQUENCE */
650 enum {
651 eGatekeeperConfirm_nonStandardData = (1 << 31),
652 eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30),
653 eGatekeeperConfirm_alternateGatekeeper = (1 << 29),
654 eGatekeeperConfirm_authenticationMode = (1 << 28),
655 eGatekeeperConfirm_tokens = (1 << 27),
656 eGatekeeperConfirm_cryptoTokens = (1 << 26),
657 eGatekeeperConfirm_algorithmOID = (1 << 25),
658 eGatekeeperConfirm_integrity = (1 << 24),
659 eGatekeeperConfirm_integrityCheckValue = (1 << 23),
660 eGatekeeperConfirm_featureSet = (1 << 22),
661 eGatekeeperConfirm_genericData = (1 << 21),
662 } options;
663 TransportAddress rasAddress;
664} GatekeeperConfirm;
665
666typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */
667 int count;
668 TransportAddress item[10];
669} RegistrationRequest_callSignalAddress;
670
671typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */
672 int count;
673 TransportAddress item[10];
674} RegistrationRequest_rasAddress;
675
676typedef struct RegistrationRequest { /* SEQUENCE */
677 enum {
678 eRegistrationRequest_nonStandardData = (1 << 31),
679 eRegistrationRequest_terminalAlias = (1 << 30),
680 eRegistrationRequest_gatekeeperIdentifier = (1 << 29),
681 eRegistrationRequest_alternateEndpoints = (1 << 28),
682 eRegistrationRequest_timeToLive = (1 << 27),
683 eRegistrationRequest_tokens = (1 << 26),
684 eRegistrationRequest_cryptoTokens = (1 << 25),
685 eRegistrationRequest_integrityCheckValue = (1 << 24),
686 eRegistrationRequest_keepAlive = (1 << 23),
687 eRegistrationRequest_endpointIdentifier = (1 << 22),
688 eRegistrationRequest_willSupplyUUIEs = (1 << 21),
689 eRegistrationRequest_maintainConnection = (1 << 20),
690 eRegistrationRequest_alternateTransportAddresses = (1 << 19),
691 eRegistrationRequest_additiveRegistration = (1 << 18),
692 eRegistrationRequest_terminalAliasPattern = (1 << 17),
693 eRegistrationRequest_supportsAltGK = (1 << 16),
694 eRegistrationRequest_usageReportingCapability = (1 << 15),
695 eRegistrationRequest_multipleCalls = (1 << 14),
696 eRegistrationRequest_supportedH248Packages = (1 << 13),
697 eRegistrationRequest_callCreditCapability = (1 << 12),
698 eRegistrationRequest_capacityReportingCapability = (1 << 11),
699 eRegistrationRequest_capacity = (1 << 10),
700 eRegistrationRequest_featureSet = (1 << 9),
701 eRegistrationRequest_genericData = (1 << 8),
702 } options;
703 RegistrationRequest_callSignalAddress callSignalAddress;
704 RegistrationRequest_rasAddress rasAddress;
705 unsigned timeToLive;
706} RegistrationRequest;
707
708typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */
709 int count;
710 TransportAddress item[10];
711} RegistrationConfirm_callSignalAddress;
712
713typedef struct RegistrationConfirm { /* SEQUENCE */
714 enum {
715 eRegistrationConfirm_nonStandardData = (1 << 31),
716 eRegistrationConfirm_terminalAlias = (1 << 30),
717 eRegistrationConfirm_gatekeeperIdentifier = (1 << 29),
718 eRegistrationConfirm_alternateGatekeeper = (1 << 28),
719 eRegistrationConfirm_timeToLive = (1 << 27),
720 eRegistrationConfirm_tokens = (1 << 26),
721 eRegistrationConfirm_cryptoTokens = (1 << 25),
722 eRegistrationConfirm_integrityCheckValue = (1 << 24),
723 eRegistrationConfirm_willRespondToIRR = (1 << 23),
724 eRegistrationConfirm_preGrantedARQ = (1 << 22),
725 eRegistrationConfirm_maintainConnection = (1 << 21),
726 eRegistrationConfirm_serviceControl = (1 << 20),
727 eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19),
728 eRegistrationConfirm_terminalAliasPattern = (1 << 18),
729 eRegistrationConfirm_supportedPrefixes = (1 << 17),
730 eRegistrationConfirm_usageSpec = (1 << 16),
731 eRegistrationConfirm_featureServerAlias = (1 << 15),
732 eRegistrationConfirm_capacityReportingSpec = (1 << 14),
733 eRegistrationConfirm_featureSet = (1 << 13),
734 eRegistrationConfirm_genericData = (1 << 12),
735 } options;
736 RegistrationConfirm_callSignalAddress callSignalAddress;
737 unsigned timeToLive;
738} RegistrationConfirm;
739
740typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */
741 int count;
742 TransportAddress item[10];
743} UnregistrationRequest_callSignalAddress;
744
745typedef struct UnregistrationRequest { /* SEQUENCE */
746 enum {
747 eUnregistrationRequest_endpointAlias = (1 << 31),
748 eUnregistrationRequest_nonStandardData = (1 << 30),
749 eUnregistrationRequest_endpointIdentifier = (1 << 29),
750 eUnregistrationRequest_alternateEndpoints = (1 << 28),
751 eUnregistrationRequest_gatekeeperIdentifier = (1 << 27),
752 eUnregistrationRequest_tokens = (1 << 26),
753 eUnregistrationRequest_cryptoTokens = (1 << 25),
754 eUnregistrationRequest_integrityCheckValue = (1 << 24),
755 eUnregistrationRequest_reason = (1 << 23),
756 eUnregistrationRequest_endpointAliasPattern = (1 << 22),
757 eUnregistrationRequest_supportedPrefixes = (1 << 21),
758 eUnregistrationRequest_alternateGatekeeper = (1 << 20),
759 eUnregistrationRequest_genericData = (1 << 19),
760 } options;
761 UnregistrationRequest_callSignalAddress callSignalAddress;
762} UnregistrationRequest;
763
764typedef struct AdmissionRequest { /* SEQUENCE */
765 enum {
766 eAdmissionRequest_callModel = (1 << 31),
767 eAdmissionRequest_destinationInfo = (1 << 30),
768 eAdmissionRequest_destCallSignalAddress = (1 << 29),
769 eAdmissionRequest_destExtraCallInfo = (1 << 28),
770 eAdmissionRequest_srcCallSignalAddress = (1 << 27),
771 eAdmissionRequest_nonStandardData = (1 << 26),
772 eAdmissionRequest_callServices = (1 << 25),
773 eAdmissionRequest_canMapAlias = (1 << 24),
774 eAdmissionRequest_callIdentifier = (1 << 23),
775 eAdmissionRequest_srcAlternatives = (1 << 22),
776 eAdmissionRequest_destAlternatives = (1 << 21),
777 eAdmissionRequest_gatekeeperIdentifier = (1 << 20),
778 eAdmissionRequest_tokens = (1 << 19),
779 eAdmissionRequest_cryptoTokens = (1 << 18),
780 eAdmissionRequest_integrityCheckValue = (1 << 17),
781 eAdmissionRequest_transportQOS = (1 << 16),
782 eAdmissionRequest_willSupplyUUIEs = (1 << 15),
783 eAdmissionRequest_callLinkage = (1 << 14),
784 eAdmissionRequest_gatewayDataRate = (1 << 13),
785 eAdmissionRequest_capacity = (1 << 12),
786 eAdmissionRequest_circuitInfo = (1 << 11),
787 eAdmissionRequest_desiredProtocols = (1 << 10),
788 eAdmissionRequest_desiredTunnelledProtocol = (1 << 9),
789 eAdmissionRequest_featureSet = (1 << 8),
790 eAdmissionRequest_genericData = (1 << 7),
791 } options;
792 TransportAddress destCallSignalAddress;
793 TransportAddress srcCallSignalAddress;
794} AdmissionRequest;
795
796typedef struct AdmissionConfirm { /* SEQUENCE */
797 enum {
798 eAdmissionConfirm_irrFrequency = (1 << 31),
799 eAdmissionConfirm_nonStandardData = (1 << 30),
800 eAdmissionConfirm_destinationInfo = (1 << 29),
801 eAdmissionConfirm_destExtraCallInfo = (1 << 28),
802 eAdmissionConfirm_destinationType = (1 << 27),
803 eAdmissionConfirm_remoteExtensionAddress = (1 << 26),
804 eAdmissionConfirm_alternateEndpoints = (1 << 25),
805 eAdmissionConfirm_tokens = (1 << 24),
806 eAdmissionConfirm_cryptoTokens = (1 << 23),
807 eAdmissionConfirm_integrityCheckValue = (1 << 22),
808 eAdmissionConfirm_transportQOS = (1 << 21),
809 eAdmissionConfirm_willRespondToIRR = (1 << 20),
810 eAdmissionConfirm_uuiesRequested = (1 << 19),
811 eAdmissionConfirm_language = (1 << 18),
812 eAdmissionConfirm_alternateTransportAddresses = (1 << 17),
813 eAdmissionConfirm_useSpecifiedTransport = (1 << 16),
814 eAdmissionConfirm_circuitInfo = (1 << 15),
815 eAdmissionConfirm_usageSpec = (1 << 14),
816 eAdmissionConfirm_supportedProtocols = (1 << 13),
817 eAdmissionConfirm_serviceControl = (1 << 12),
818 eAdmissionConfirm_multipleCalls = (1 << 11),
819 eAdmissionConfirm_featureSet = (1 << 10),
820 eAdmissionConfirm_genericData = (1 << 9),
821 } options;
822 TransportAddress destCallSignalAddress;
823} AdmissionConfirm;
824
825typedef struct LocationRequest { /* SEQUENCE */
826 enum {
827 eLocationRequest_endpointIdentifier = (1 << 31),
828 eLocationRequest_nonStandardData = (1 << 30),
829 eLocationRequest_sourceInfo = (1 << 29),
830 eLocationRequest_canMapAlias = (1 << 28),
831 eLocationRequest_gatekeeperIdentifier = (1 << 27),
832 eLocationRequest_tokens = (1 << 26),
833 eLocationRequest_cryptoTokens = (1 << 25),
834 eLocationRequest_integrityCheckValue = (1 << 24),
835 eLocationRequest_desiredProtocols = (1 << 23),
836 eLocationRequest_desiredTunnelledProtocol = (1 << 22),
837 eLocationRequest_featureSet = (1 << 21),
838 eLocationRequest_genericData = (1 << 20),
839 eLocationRequest_hopCount = (1 << 19),
840 eLocationRequest_circuitInfo = (1 << 18),
841 } options;
842 TransportAddress replyAddress;
843} LocationRequest;
844
845typedef struct LocationConfirm { /* SEQUENCE */
846 enum {
847 eLocationConfirm_nonStandardData = (1 << 31),
848 eLocationConfirm_destinationInfo = (1 << 30),
849 eLocationConfirm_destExtraCallInfo = (1 << 29),
850 eLocationConfirm_destinationType = (1 << 28),
851 eLocationConfirm_remoteExtensionAddress = (1 << 27),
852 eLocationConfirm_alternateEndpoints = (1 << 26),
853 eLocationConfirm_tokens = (1 << 25),
854 eLocationConfirm_cryptoTokens = (1 << 24),
855 eLocationConfirm_integrityCheckValue = (1 << 23),
856 eLocationConfirm_alternateTransportAddresses = (1 << 22),
857 eLocationConfirm_supportedProtocols = (1 << 21),
858 eLocationConfirm_multipleCalls = (1 << 20),
859 eLocationConfirm_featureSet = (1 << 19),
860 eLocationConfirm_genericData = (1 << 18),
861 eLocationConfirm_circuitInfo = (1 << 17),
862 eLocationConfirm_serviceControl = (1 << 16),
863 } options;
864 TransportAddress callSignalAddress;
865 TransportAddress rasAddress;
866} LocationConfirm;
867
868typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */
869 int count;
870 TransportAddress item[10];
871} InfoRequestResponse_callSignalAddress;
872
873typedef struct InfoRequestResponse { /* SEQUENCE */
874 enum {
875 eInfoRequestResponse_nonStandardData = (1 << 31),
876 eInfoRequestResponse_endpointAlias = (1 << 30),
877 eInfoRequestResponse_perCallInfo = (1 << 29),
878 eInfoRequestResponse_tokens = (1 << 28),
879 eInfoRequestResponse_cryptoTokens = (1 << 27),
880 eInfoRequestResponse_integrityCheckValue = (1 << 26),
881 eInfoRequestResponse_needResponse = (1 << 25),
882 eInfoRequestResponse_capacity = (1 << 24),
883 eInfoRequestResponse_irrStatus = (1 << 23),
884 eInfoRequestResponse_unsolicited = (1 << 22),
885 eInfoRequestResponse_genericData = (1 << 21),
886 } options;
887 TransportAddress rasAddress;
888 InfoRequestResponse_callSignalAddress callSignalAddress;
889} InfoRequestResponse;
890
891typedef struct RasMessage { /* CHOICE */
892 enum {
893 eRasMessage_gatekeeperRequest,
894 eRasMessage_gatekeeperConfirm,
895 eRasMessage_gatekeeperReject,
896 eRasMessage_registrationRequest,
897 eRasMessage_registrationConfirm,
898 eRasMessage_registrationReject,
899 eRasMessage_unregistrationRequest,
900 eRasMessage_unregistrationConfirm,
901 eRasMessage_unregistrationReject,
902 eRasMessage_admissionRequest,
903 eRasMessage_admissionConfirm,
904 eRasMessage_admissionReject,
905 eRasMessage_bandwidthRequest,
906 eRasMessage_bandwidthConfirm,
907 eRasMessage_bandwidthReject,
908 eRasMessage_disengageRequest,
909 eRasMessage_disengageConfirm,
910 eRasMessage_disengageReject,
911 eRasMessage_locationRequest,
912 eRasMessage_locationConfirm,
913 eRasMessage_locationReject,
914 eRasMessage_infoRequest,
915 eRasMessage_infoRequestResponse,
916 eRasMessage_nonStandardMessage,
917 eRasMessage_unknownMessageResponse,
918 eRasMessage_requestInProgress,
919 eRasMessage_resourcesAvailableIndicate,
920 eRasMessage_resourcesAvailableConfirm,
921 eRasMessage_infoRequestAck,
922 eRasMessage_infoRequestNak,
923 eRasMessage_serviceControlIndication,
924 eRasMessage_serviceControlResponse,
925 } choice;
926 union {
927 GatekeeperRequest gatekeeperRequest;
928 GatekeeperConfirm gatekeeperConfirm;
929 RegistrationRequest registrationRequest;
930 RegistrationConfirm registrationConfirm;
931 UnregistrationRequest unregistrationRequest;
932 AdmissionRequest admissionRequest;
933 AdmissionConfirm admissionConfirm;
934 LocationRequest locationRequest;
935 LocationConfirm locationConfirm;
936 InfoRequestResponse infoRequestResponse;
937 };
938} RasMessage;
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index e0b5926c76f9..9b6e19bae90f 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -4,7 +4,7 @@
4 * (C) 2001 by Jay Schulist <jschlst@samba.org> 4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> 5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
6 * (C) 2003 by Patrick Mchardy <kaber@trash.net> 6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7 * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net> 7 * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8 * 8 *
9 * I've reworked this stuff to use attributes instead of conntrack 9 * I've reworked this stuff to use attributes instead of conntrack
10 * structures. 5.44 am. I need more tea. --pablo 05/07/11. 10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -53,20 +53,18 @@ static char __initdata version[] = "0.90";
53 53
54static inline int 54static inline int
55ctnetlink_dump_tuples_proto(struct sk_buff *skb, 55ctnetlink_dump_tuples_proto(struct sk_buff *skb,
56 const struct ip_conntrack_tuple *tuple) 56 const struct ip_conntrack_tuple *tuple,
57 struct ip_conntrack_protocol *proto)
57{ 58{
58 struct ip_conntrack_protocol *proto;
59 int ret = 0; 59 int ret = 0;
60 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
60 61
61 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); 62 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
62 63
63 /* If no protocol helper is found, this function will return the
64 * generic protocol helper, so proto won't *ever* be NULL */
65 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
66 if (likely(proto->tuple_to_nfattr)) 64 if (likely(proto->tuple_to_nfattr))
67 ret = proto->tuple_to_nfattr(skb, tuple); 65 ret = proto->tuple_to_nfattr(skb, tuple);
68 66
69 ip_conntrack_proto_put(proto); 67 NFA_NEST_END(skb, nest_parms);
70 68
71 return ret; 69 return ret;
72 70
@@ -75,28 +73,41 @@ nfattr_failure:
75} 73}
76 74
77static inline int 75static inline int
78ctnetlink_dump_tuples(struct sk_buff *skb, 76ctnetlink_dump_tuples_ip(struct sk_buff *skb,
79 const struct ip_conntrack_tuple *tuple) 77 const struct ip_conntrack_tuple *tuple)
80{ 78{
81 struct nfattr *nest_parms; 79 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
82 int ret;
83 80
84 nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
85 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip); 81 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
86 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip); 82 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
87 NFA_NEST_END(skb, nest_parms);
88 83
89 nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
90 ret = ctnetlink_dump_tuples_proto(skb, tuple);
91 NFA_NEST_END(skb, nest_parms); 84 NFA_NEST_END(skb, nest_parms);
92 85
93 return ret; 86 return 0;
94 87
95nfattr_failure: 88nfattr_failure:
96 return -1; 89 return -1;
97} 90}
98 91
99static inline int 92static inline int
93ctnetlink_dump_tuples(struct sk_buff *skb,
94 const struct ip_conntrack_tuple *tuple)
95{
96 int ret;
97 struct ip_conntrack_protocol *proto;
98
99 ret = ctnetlink_dump_tuples_ip(skb, tuple);
100 if (unlikely(ret < 0))
101 return ret;
102
103 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
104 ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
105 ip_conntrack_proto_put(proto);
106
107 return ret;
108}
109
110static inline int
100ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct) 111ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
101{ 112{
102 u_int32_t status = htonl((u_int32_t) ct->status); 113 u_int32_t status = htonl((u_int32_t) ct->status);
@@ -327,9 +338,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
327 group = NFNLGRP_CONNTRACK_UPDATE; 338 group = NFNLGRP_CONNTRACK_UPDATE;
328 } else 339 } else
329 return NOTIFY_DONE; 340 return NOTIFY_DONE;
330 341
331 /* FIXME: Check if there are any listeners before, don't hurt performance */ 342 if (!nfnetlink_has_listeners(group))
332 343 return NOTIFY_DONE;
344
333 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 345 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
334 if (!skb) 346 if (!skb)
335 return NOTIFY_DONE; 347 return NOTIFY_DONE;
@@ -1134,6 +1146,33 @@ nfattr_failure:
1134} 1146}
1135 1147
1136static inline int 1148static inline int
1149ctnetlink_exp_dump_mask(struct sk_buff *skb,
1150 const struct ip_conntrack_tuple *tuple,
1151 const struct ip_conntrack_tuple *mask)
1152{
1153 int ret;
1154 struct ip_conntrack_protocol *proto;
1155 struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
1156
1157 ret = ctnetlink_dump_tuples_ip(skb, mask);
1158 if (unlikely(ret < 0))
1159 goto nfattr_failure;
1160
1161 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
1162 ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
1163 ip_conntrack_proto_put(proto);
1164 if (unlikely(ret < 0))
1165 goto nfattr_failure;
1166
1167 NFA_NEST_END(skb, nest_parms);
1168
1169 return 0;
1170
1171nfattr_failure:
1172 return -1;
1173}
1174
1175static inline int
1137ctnetlink_exp_dump_expect(struct sk_buff *skb, 1176ctnetlink_exp_dump_expect(struct sk_buff *skb,
1138 const struct ip_conntrack_expect *exp) 1177 const struct ip_conntrack_expect *exp)
1139{ 1178{
@@ -1143,7 +1182,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1143 1182
1144 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) 1183 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1145 goto nfattr_failure; 1184 goto nfattr_failure;
1146 if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) 1185 if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1147 goto nfattr_failure; 1186 goto nfattr_failure;
1148 if (ctnetlink_exp_dump_tuple(skb, 1187 if (ctnetlink_exp_dump_tuple(skb,
1149 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 1188 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
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 000000000000..a0bc883928c0
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -0,0 +1,605 @@
1/*
2 * H.323 extension for NAT alteration.
3 *
4 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
5 *
6 * This source code is licensed under General Public License version 2.
7 *
8 * Based on the 'brute force' H.323 NAT module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 *
11 * Changes:
12 * 2006-02-01 - initial version 0.1
13 *
14 * 2006-02-20 - version 0.2
15 * 1. Changed source format to follow kernel conventions
16 * 2. Deleted some unnecessary structures
17 * 3. Minor fixes
18 *
19 * 2006-03-10 - version 0.3
20 * 1. Added support for multiple TPKTs in one packet (suggested by
21 * Patrick McHardy)
22 * 2. Added support for non-linear skb (based on Patrick McHardy's patch)
23 * 3. Eliminated unnecessary return code
24 *
25 * 2006-03-15 - version 0.4
26 * 1. Added support for T.120 channels
27 * 2. Added parameter gkrouted_only (suggested by Patrick McHardy)
28 */
29
30#include <linux/module.h>
31#include <linux/netfilter_ipv4.h>
32#include <linux/netfilter.h>
33#include <linux/ip.h>
34#include <linux/tcp.h>
35#include <linux/moduleparam.h>
36#include <net/tcp.h>
37#include <linux/netfilter_ipv4/ip_nat.h>
38#include <linux/netfilter_ipv4/ip_nat_helper.h>
39#include <linux/netfilter_ipv4/ip_nat_rule.h>
40#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
41#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
42#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
43
44#include "ip_conntrack_helper_h323_asn1.h"
45
46#if 0
47#define DEBUGP printk
48#else
49#define DEBUGP(format, args...)
50#endif
51
52extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
53 u_int32_t * ip, u_int16_t * port);
54extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
55 u_int32_t * ip, u_int16_t * port);
56extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
57 struct ip_conntrack_expect *this);
58extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
59 struct ip_conntrack_expect *this);
60extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
61 unsigned char **data, int dataoff,
62 H245_TransportAddress * addr,
63 u_int32_t ip, u_int16_t port);
64extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
65 unsigned char **data, int dataoff,
66 TransportAddress * addr,
67 u_int32_t ip, u_int16_t port);
68extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
69 struct ip_conntrack * ct,
70 enum ip_conntrack_info ctinfo,
71 unsigned char **data,
72 TransportAddress * addr, int count);
73extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
74 struct ip_conntrack * ct,
75 enum ip_conntrack_info ctinfo,
76 unsigned char **data,
77 TransportAddress * addr, int count);
78extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
79 struct ip_conntrack * ct,
80 enum ip_conntrack_info ctinfo,
81 unsigned char **data, int dataoff,
82 H245_TransportAddress * addr,
83 u_int16_t port, u_int16_t rtp_port,
84 struct ip_conntrack_expect * rtp_exp,
85 struct ip_conntrack_expect * rtcp_exp);
86extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
87 enum ip_conntrack_info ctinfo,
88 unsigned char **data, int dataoff,
89 H245_TransportAddress * addr, u_int16_t port,
90 struct ip_conntrack_expect * exp);
91extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
92 enum ip_conntrack_info ctinfo,
93 unsigned char **data, int dataoff,
94 TransportAddress * addr, u_int16_t port,
95 struct ip_conntrack_expect * exp);
96extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
97 enum ip_conntrack_info ctinfo,
98 unsigned char **data, TransportAddress * addr,
99 int idx, u_int16_t port,
100 struct ip_conntrack_expect * exp);
101
102
103/****************************************************************************/
104static int set_addr(struct sk_buff **pskb,
105 unsigned char **data, int dataoff,
106 unsigned int addroff, u_int32_t ip, u_int16_t port)
107{
108 enum ip_conntrack_info ctinfo;
109 struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
110 struct {
111 u_int32_t ip;
112 u_int16_t port;
113 } __attribute__ ((__packed__)) buf;
114 struct tcphdr _tcph, *th;
115
116 buf.ip = ip;
117 buf.port = htons(port);
118 addroff += dataoff;
119
120 if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
121 if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
122 addroff, sizeof(buf),
123 (char *) &buf, sizeof(buf))) {
124 if (net_ratelimit())
125 printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
126 " error\n");
127 return -1;
128 }
129
130 /* Relocate data pointer */
131 th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
132 sizeof(_tcph), &_tcph);
133 if (th == NULL)
134 return -1;
135 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
136 th->doff * 4 + dataoff;
137 } else {
138 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
139 addroff, sizeof(buf),
140 (char *) &buf, sizeof(buf))) {
141 if (net_ratelimit())
142 printk("ip_nat_h323: ip_nat_mangle_udp_packet"
143 " error\n");
144 return -1;
145 }
146 /* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
147 * or pull everything in a linear buffer, so we can safely
148 * use the skb pointers now */
149 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
150 sizeof(struct udphdr);
151 }
152
153 return 0;
154}
155
156/****************************************************************************/
157static int set_h225_addr(struct sk_buff **pskb,
158 unsigned char **data, int dataoff,
159 TransportAddress * addr,
160 u_int32_t ip, u_int16_t port)
161{
162 return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
163}
164
165/****************************************************************************/
166static int set_h245_addr(struct sk_buff **pskb,
167 unsigned char **data, int dataoff,
168 H245_TransportAddress * addr,
169 u_int32_t ip, u_int16_t port)
170{
171 return set_addr(pskb, data, dataoff,
172 addr->unicastAddress.iPAddress.network, ip, port);
173}
174
175/****************************************************************************/
176static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
177 enum ip_conntrack_info ctinfo,
178 unsigned char **data,
179 TransportAddress * addr, int count)
180{
181 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
182 int dir = CTINFO2DIR(ctinfo);
183 int i;
184 u_int32_t ip;
185 u_int16_t port;
186
187 for (i = 0; i < count; i++) {
188 if (get_h225_addr(*data, &addr[i], &ip, &port)) {
189 if (ip == ct->tuplehash[dir].tuple.src.ip &&
190 port == info->sig_port[dir]) {
191 /* GW->GK */
192
193 /* Fix for Gnomemeeting */
194 if (i > 0 &&
195 get_h225_addr(*data, &addr[0],
196 &ip, &port) &&
197 (ntohl(ip) & 0xff000000) == 0x7f000000)
198 i = 0;
199
200 DEBUGP
201 ("ip_nat_ras: set signal address "
202 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
203 NIPQUAD(ip), port,
204 NIPQUAD(ct->tuplehash[!dir].tuple.dst.
205 ip), info->sig_port[!dir]);
206 return set_h225_addr(pskb, data, 0, &addr[i],
207 ct->tuplehash[!dir].
208 tuple.dst.ip,
209 info->sig_port[!dir]);
210 } else if (ip == ct->tuplehash[dir].tuple.dst.ip &&
211 port == info->sig_port[dir]) {
212 /* GK->GW */
213 DEBUGP
214 ("ip_nat_ras: set signal address "
215 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
216 NIPQUAD(ip), port,
217 NIPQUAD(ct->tuplehash[!dir].tuple.src.
218 ip), info->sig_port[!dir]);
219 return set_h225_addr(pskb, data, 0, &addr[i],
220 ct->tuplehash[!dir].
221 tuple.src.ip,
222 info->sig_port[!dir]);
223 }
224 }
225 }
226
227 return 0;
228}
229
230/****************************************************************************/
231static int set_ras_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
232 enum ip_conntrack_info ctinfo,
233 unsigned char **data,
234 TransportAddress * addr, int count)
235{
236 int dir = CTINFO2DIR(ctinfo);
237 int i;
238 u_int32_t ip;
239 u_int16_t port;
240
241 for (i = 0; i < count; i++) {
242 if (get_h225_addr(*data, &addr[i], &ip, &port) &&
243 ip == ct->tuplehash[dir].tuple.src.ip &&
244 port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) {
245 DEBUGP("ip_nat_ras: set rasAddress "
246 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
247 NIPQUAD(ip), port,
248 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
249 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
250 port));
251 return set_h225_addr(pskb, data, 0, &addr[i],
252 ct->tuplehash[!dir].tuple.dst.ip,
253 ntohs(ct->tuplehash[!dir].tuple.
254 dst.u.udp.port));
255 }
256 }
257
258 return 0;
259}
260
261/****************************************************************************/
262static int nat_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
263 enum ip_conntrack_info ctinfo,
264 unsigned char **data, int dataoff,
265 H245_TransportAddress * addr,
266 u_int16_t port, u_int16_t rtp_port,
267 struct ip_conntrack_expect *rtp_exp,
268 struct ip_conntrack_expect *rtcp_exp)
269{
270 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
271 int dir = CTINFO2DIR(ctinfo);
272 int i;
273 u_int16_t nated_port;
274
275 /* Set expectations for NAT */
276 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
277 rtp_exp->expectfn = ip_nat_follow_master;
278 rtp_exp->dir = !dir;
279 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
280 rtcp_exp->expectfn = ip_nat_follow_master;
281 rtcp_exp->dir = !dir;
282
283 /* Lookup existing expects */
284 for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
285 if (info->rtp_port[i][dir] == rtp_port) {
286 /* Expected */
287
288 /* Use allocated ports first. This will refresh
289 * the expects */
290 rtp_exp->tuple.dst.u.udp.port =
291 htons(info->rtp_port[i][dir]);
292 rtcp_exp->tuple.dst.u.udp.port =
293 htons(info->rtp_port[i][dir] + 1);
294 break;
295 } else if (info->rtp_port[i][dir] == 0) {
296 /* Not expected */
297 break;
298 }
299 }
300
301 /* Run out of expectations */
302 if (i >= H323_RTP_CHANNEL_MAX) {
303 if (net_ratelimit())
304 printk("ip_nat_h323: out of expectations\n");
305 return 0;
306 }
307
308 /* Try to get a pair of ports. */
309 for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
310 nated_port != 0; nated_port += 2) {
311 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
312 if (ip_conntrack_expect_related(rtp_exp) == 0) {
313 rtcp_exp->tuple.dst.u.udp.port =
314 htons(nated_port + 1);
315 if (ip_conntrack_expect_related(rtcp_exp) == 0)
316 break;
317 ip_conntrack_unexpect_related(rtp_exp);
318 }
319 }
320
321 if (nated_port == 0) { /* No port available */
322 if (net_ratelimit())
323 printk("ip_nat_h323: out of RTP ports\n");
324 return 0;
325 }
326
327 /* Modify signal */
328 if (set_h245_addr(pskb, data, dataoff, addr,
329 ct->tuplehash[!dir].tuple.dst.ip,
330 (port & 1) ? nated_port + 1 : nated_port) == 0) {
331 /* Save ports */
332 info->rtp_port[i][dir] = rtp_port;
333 info->rtp_port[i][!dir] = nated_port;
334 } else {
335 ip_conntrack_unexpect_related(rtp_exp);
336 ip_conntrack_unexpect_related(rtcp_exp);
337 return -1;
338 }
339
340 /* Success */
341 DEBUGP("ip_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
342 NIPQUAD(rtp_exp->tuple.src.ip),
343 ntohs(rtp_exp->tuple.src.u.udp.port),
344 NIPQUAD(rtp_exp->tuple.dst.ip),
345 ntohs(rtp_exp->tuple.dst.u.udp.port));
346 DEBUGP("ip_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
347 NIPQUAD(rtcp_exp->tuple.src.ip),
348 ntohs(rtcp_exp->tuple.src.u.udp.port),
349 NIPQUAD(rtcp_exp->tuple.dst.ip),
350 ntohs(rtcp_exp->tuple.dst.u.udp.port));
351
352 return 0;
353}
354
355/****************************************************************************/
356static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct,
357 enum ip_conntrack_info ctinfo,
358 unsigned char **data, int dataoff,
359 H245_TransportAddress * addr, u_int16_t port,
360 struct ip_conntrack_expect *exp)
361{
362 int dir = CTINFO2DIR(ctinfo);
363 u_int16_t nated_port = port;
364
365 /* Set expectations for NAT */
366 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
367 exp->expectfn = ip_nat_follow_master;
368 exp->dir = !dir;
369
370 /* Try to get same port: if not, try to change it. */
371 for (; nated_port != 0; nated_port++) {
372 exp->tuple.dst.u.tcp.port = htons(nated_port);
373 if (ip_conntrack_expect_related(exp) == 0)
374 break;
375 }
376
377 if (nated_port == 0) { /* No port available */
378 if (net_ratelimit())
379 printk("ip_nat_h323: out of TCP ports\n");
380 return 0;
381 }
382
383 /* Modify signal */
384 if (set_h245_addr(pskb, data, dataoff, addr,
385 ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) {
386 ip_conntrack_unexpect_related(exp);
387 return -1;
388 }
389
390 DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
391 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
392 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
393
394 return 0;
395}
396
397/****************************************************************************
398 * This conntrack expect function replaces ip_conntrack_h245_expect()
399 * which was set by ip_conntrack_helper_h323.c. It calls both
400 * ip_nat_follow_master() and ip_conntrack_h245_expect()
401 ****************************************************************************/
402static void ip_nat_h245_expect(struct ip_conntrack *new,
403 struct ip_conntrack_expect *this)
404{
405 ip_nat_follow_master(new, this);
406 ip_conntrack_h245_expect(new, this);
407}
408
409/****************************************************************************/
410static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
411 enum ip_conntrack_info ctinfo,
412 unsigned char **data, int dataoff,
413 TransportAddress * addr, u_int16_t port,
414 struct ip_conntrack_expect *exp)
415{
416 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
417 int dir = CTINFO2DIR(ctinfo);
418 u_int16_t nated_port = port;
419
420 /* Set expectations for NAT */
421 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
422 exp->expectfn = ip_nat_h245_expect;
423 exp->dir = !dir;
424
425 /* Check existing expects */
426 if (info->sig_port[dir] == port)
427 nated_port = info->sig_port[!dir];
428
429 /* Try to get same port: if not, try to change it. */
430 for (; nated_port != 0; nated_port++) {
431 exp->tuple.dst.u.tcp.port = htons(nated_port);
432 if (ip_conntrack_expect_related(exp) == 0)
433 break;
434 }
435
436 if (nated_port == 0) { /* No port available */
437 if (net_ratelimit())
438 printk("ip_nat_q931: out of TCP ports\n");
439 return 0;
440 }
441
442 /* Modify signal */
443 if (set_h225_addr(pskb, data, dataoff, addr,
444 ct->tuplehash[!dir].tuple.dst.ip,
445 nated_port) == 0) {
446 /* Save ports */
447 info->sig_port[dir] = port;
448 info->sig_port[!dir] = nated_port;
449 } else {
450 ip_conntrack_unexpect_related(exp);
451 return -1;
452 }
453
454 DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
455 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
456 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
457
458 return 0;
459}
460
461/****************************************************************************
462 * This conntrack expect function replaces ip_conntrack_q931_expect()
463 * which was set by ip_conntrack_helper_h323.c.
464 ****************************************************************************/
465static void ip_nat_q931_expect(struct ip_conntrack *new,
466 struct ip_conntrack_expect *this)
467{
468 struct ip_nat_range range;
469
470 if (this->tuple.src.ip != 0) { /* Only accept calls from GK */
471 ip_nat_follow_master(new, this);
472 goto out;
473 }
474
475 /* This must be a fresh one. */
476 BUG_ON(new->status & IPS_NAT_DONE_MASK);
477
478 /* Change src to where master sends to */
479 range.flags = IP_NAT_RANGE_MAP_IPS;
480 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
481
482 /* hook doesn't matter, but it has to do source manip */
483 ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
484
485 /* For DST manip, map port here to where it's expected. */
486 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
487 range.min = range.max = this->saved_proto;
488 range.min_ip = range.max_ip =
489 new->master->tuplehash[!this->dir].tuple.src.ip;
490
491 /* hook doesn't matter, but it has to do destination manip */
492 ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
493
494 out:
495 ip_conntrack_q931_expect(new, this);
496}
497
498/****************************************************************************/
499static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
500 enum ip_conntrack_info ctinfo,
501 unsigned char **data, TransportAddress * addr, int idx,
502 u_int16_t port, struct ip_conntrack_expect *exp)
503{
504 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
505 int dir = CTINFO2DIR(ctinfo);
506 u_int16_t nated_port = port;
507 u_int32_t ip;
508
509 /* Set expectations for NAT */
510 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
511 exp->expectfn = ip_nat_q931_expect;
512 exp->dir = !dir;
513
514 /* Check existing expects */
515 if (info->sig_port[dir] == port)
516 nated_port = info->sig_port[!dir];
517
518 /* Try to get same port: if not, try to change it. */
519 for (; nated_port != 0; nated_port++) {
520 exp->tuple.dst.u.tcp.port = htons(nated_port);
521 if (ip_conntrack_expect_related(exp) == 0)
522 break;
523 }
524
525 if (nated_port == 0) { /* No port available */
526 if (net_ratelimit())
527 printk("ip_nat_ras: out of TCP ports\n");
528 return 0;
529 }
530
531 /* Modify signal */
532 if (set_h225_addr(pskb, data, 0, &addr[idx],
533 ct->tuplehash[!dir].tuple.dst.ip,
534 nated_port) == 0) {
535 /* Save ports */
536 info->sig_port[dir] = port;
537 info->sig_port[!dir] = nated_port;
538
539 /* Fix for Gnomemeeting */
540 if (idx > 0 &&
541 get_h225_addr(*data, &addr[0], &ip, &port) &&
542 (ntohl(ip) & 0xff000000) == 0x7f000000) {
543 set_h225_addr_hook(pskb, data, 0, &addr[0],
544 ct->tuplehash[!dir].tuple.dst.ip,
545 info->sig_port[!dir]);
546 }
547 } else {
548 ip_conntrack_unexpect_related(exp);
549 return -1;
550 }
551
552 /* Success */
553 DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
554 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
555 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
556
557 return 0;
558}
559
560/****************************************************************************/
561static int __init init(void)
562{
563 BUG_ON(set_h245_addr_hook != NULL);
564 BUG_ON(set_h225_addr_hook != NULL);
565 BUG_ON(set_sig_addr_hook != NULL);
566 BUG_ON(set_ras_addr_hook != NULL);
567 BUG_ON(nat_rtp_rtcp_hook != NULL);
568 BUG_ON(nat_t120_hook != NULL);
569 BUG_ON(nat_h245_hook != NULL);
570 BUG_ON(nat_q931_hook != NULL);
571
572 set_h245_addr_hook = set_h245_addr;
573 set_h225_addr_hook = set_h225_addr;
574 set_sig_addr_hook = set_sig_addr;
575 set_ras_addr_hook = set_ras_addr;
576 nat_rtp_rtcp_hook = nat_rtp_rtcp;
577 nat_t120_hook = nat_t120;
578 nat_h245_hook = nat_h245;
579 nat_q931_hook = nat_q931;
580
581 DEBUGP("ip_nat_h323: init success\n");
582 return 0;
583}
584
585/****************************************************************************/
586static void __exit fini(void)
587{
588 set_h245_addr_hook = NULL;
589 set_h225_addr_hook = NULL;
590 set_sig_addr_hook = NULL;
591 set_ras_addr_hook = NULL;
592 nat_rtp_rtcp_hook = NULL;
593 nat_t120_hook = NULL;
594 nat_h245_hook = NULL;
595 nat_q931_hook = NULL;
596 synchronize_net();
597}
598
599/****************************************************************************/
600module_init(init);
601module_exit(fini);
602
603MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
604MODULE_DESCRIPTION("H.323 NAT helper");
605MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index ac004895781a..b9c016c063b8 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -52,6 +52,8 @@
52 52
53#define IP_NAT_PPTP_VERSION "3.0" 53#define IP_NAT_PPTP_VERSION "3.0"
54 54
55#define REQ_CID(req, off) (*(u_int16_t *)((char *)(req) + (off)))
56
55MODULE_LICENSE("GPL"); 57MODULE_LICENSE("GPL");
56MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 58MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
57MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); 59MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
@@ -198,7 +200,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
198 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass 200 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
199 * down to here */ 201 * down to here */
200 DEBUGP("altering call id from 0x%04x to 0x%04x\n", 202 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
201 ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid)); 203 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
202 204
203 /* mangle packet */ 205 /* mangle packet */
204 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 206 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
@@ -342,7 +344,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
342 344
343 /* mangle packet */ 345 /* mangle packet */
344 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", 346 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
345 ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid)); 347 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
346 348
347 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 349 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
348 pcid_off + sizeof(struct pptp_pkt_hdr) + 350 pcid_off + sizeof(struct pptp_pkt_hdr) +
@@ -353,7 +355,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
353 355
354 if (new_cid) { 356 if (new_cid) {
355 DEBUGP("altering call id from 0x%04x to 0x%04x\n", 357 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
356 ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid)); 358 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_cid));
357 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 359 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
358 cid_off + sizeof(struct pptp_pkt_hdr) + 360 cid_off + sizeof(struct pptp_pkt_hdr) +
359 sizeof(struct PptpControlHeader), 361 sizeof(struct PptpControlHeader),
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 1de86282d232..efba8c4e42e0 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -103,6 +103,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
103 const struct net_device *in, 103 const struct net_device *in,
104 const struct net_device *out, 104 const struct net_device *out,
105 unsigned int hooknum, 105 unsigned int hooknum,
106 const struct ipt_target *target,
106 const void *targinfo, 107 const void *targinfo,
107 void *userinfo) 108 void *userinfo)
108{ 109{
@@ -145,6 +146,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
145 const struct net_device *in, 146 const struct net_device *in,
146 const struct net_device *out, 147 const struct net_device *out,
147 unsigned int hooknum, 148 unsigned int hooknum,
149 const struct ipt_target *target,
148 const void *targinfo, 150 const void *targinfo,
149 void *userinfo) 151 void *userinfo)
150{ 152{
@@ -170,6 +172,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
170 172
171static int ipt_snat_checkentry(const char *tablename, 173static int ipt_snat_checkentry(const char *tablename,
172 const void *entry, 174 const void *entry,
175 const struct ipt_target *target,
173 void *targinfo, 176 void *targinfo,
174 unsigned int targinfosize, 177 unsigned int targinfosize,
175 unsigned int hook_mask) 178 unsigned int hook_mask)
@@ -181,28 +184,12 @@ static int ipt_snat_checkentry(const char *tablename,
181 printk("SNAT: multiple ranges no longer supported\n"); 184 printk("SNAT: multiple ranges no longer supported\n");
182 return 0; 185 return 0;
183 } 186 }
184
185 if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) {
186 DEBUGP("SNAT: Target size %u wrong for %u ranges\n",
187 targinfosize, mr->rangesize);
188 return 0;
189 }
190
191 /* Only allow these for NAT. */
192 if (strcmp(tablename, "nat") != 0) {
193 DEBUGP("SNAT: wrong table %s\n", tablename);
194 return 0;
195 }
196
197 if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
198 DEBUGP("SNAT: hook mask 0x%x bad\n", hook_mask);
199 return 0;
200 }
201 return 1; 187 return 1;
202} 188}
203 189
204static int ipt_dnat_checkentry(const char *tablename, 190static int ipt_dnat_checkentry(const char *tablename,
205 const void *entry, 191 const void *entry,
192 const struct ipt_target *target,
206 void *targinfo, 193 void *targinfo,
207 unsigned int targinfosize, 194 unsigned int targinfosize,
208 unsigned int hook_mask) 195 unsigned int hook_mask)
@@ -214,24 +201,6 @@ static int ipt_dnat_checkentry(const char *tablename,
214 printk("DNAT: multiple ranges no longer supported\n"); 201 printk("DNAT: multiple ranges no longer supported\n");
215 return 0; 202 return 0;
216 } 203 }
217
218 if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) {
219 DEBUGP("DNAT: Target size %u wrong for %u ranges\n",
220 targinfosize, mr->rangesize);
221 return 0;
222 }
223
224 /* Only allow these for NAT. */
225 if (strcmp(tablename, "nat") != 0) {
226 DEBUGP("DNAT: wrong table %s\n", tablename);
227 return 0;
228 }
229
230 if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
231 DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask);
232 return 0;
233 }
234
235 return 1; 204 return 1;
236} 205}
237 206
@@ -299,12 +268,18 @@ int ip_nat_rule_find(struct sk_buff **pskb,
299static struct ipt_target ipt_snat_reg = { 268static struct ipt_target ipt_snat_reg = {
300 .name = "SNAT", 269 .name = "SNAT",
301 .target = ipt_snat_target, 270 .target = ipt_snat_target,
271 .targetsize = sizeof(struct ip_nat_multi_range_compat),
272 .table = "nat",
273 .hooks = 1 << NF_IP_POST_ROUTING,
302 .checkentry = ipt_snat_checkentry, 274 .checkentry = ipt_snat_checkentry,
303}; 275};
304 276
305static struct ipt_target ipt_dnat_reg = { 277static struct ipt_target ipt_dnat_reg = {
306 .name = "DNAT", 278 .name = "DNAT",
307 .target = ipt_dnat_target, 279 .target = ipt_dnat_target,
280 .targetsize = sizeof(struct ip_nat_multi_range_compat),
281 .table = "nat",
282 .hooks = 1 << NF_IP_PRE_ROUTING,
308 .checkentry = ipt_dnat_checkentry, 283 .checkentry = ipt_dnat_checkentry,
309}; 284};
310 285
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 4f95d477805c..f029da2a60ee 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -250,6 +250,7 @@ static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
250 if (!asn1_id_decode(ctx, cls, con, tag)) 250 if (!asn1_id_decode(ctx, cls, con, tag))
251 return 0; 251 return 0;
252 252
253 def = len = 0;
253 if (!asn1_length_decode(ctx, &def, &len)) 254 if (!asn1_length_decode(ctx, &def, &len))
254 return 0; 255 return 0;
255 256
@@ -669,7 +670,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
669 unsigned char *eoc, *end, *p; 670 unsigned char *eoc, *end, *p;
670 unsigned long *lp, *id; 671 unsigned long *lp, *id;
671 unsigned long ul; 672 unsigned long ul;
672 long l; 673 long l;
673 674
674 *obj = NULL; 675 *obj = NULL;
675 id = NULL; 676 id = NULL;
@@ -699,11 +700,13 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
699 return 0; 700 return 0;
700 } 701 }
701 702
703 type = 0;
702 if (!snmp_tag_cls2syntax(tag, cls, &type)) { 704 if (!snmp_tag_cls2syntax(tag, cls, &type)) {
703 kfree(id); 705 kfree(id);
704 return 0; 706 return 0;
705 } 707 }
706 708
709 l = 0;
707 switch (type) { 710 switch (type) {
708 case SNMP_INTEGER: 711 case SNMP_INTEGER:
709 len = sizeof(long); 712 len = sizeof(long);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 08f80e2ea2aa..1655866c55b9 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -35,6 +35,7 @@
35#include <linux/sysctl.h> 35#include <linux/sysctl.h>
36#include <linux/proc_fs.h> 36#include <linux/proc_fs.h>
37#include <linux/security.h> 37#include <linux/security.h>
38#include <linux/mutex.h>
38#include <net/sock.h> 39#include <net/sock.h>
39#include <net/route.h> 40#include <net/route.h>
40 41
@@ -61,7 +62,7 @@ static unsigned int queue_dropped = 0;
61static unsigned int queue_user_dropped = 0; 62static unsigned int queue_user_dropped = 0;
62static struct sock *ipqnl; 63static struct sock *ipqnl;
63static LIST_HEAD(queue_list); 64static LIST_HEAD(queue_list);
64static DECLARE_MUTEX(ipqnl_sem); 65static DEFINE_MUTEX(ipqnl_mutex);
65 66
66static void 67static void
67ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) 68ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
@@ -539,7 +540,7 @@ ipq_rcv_sk(struct sock *sk, int len)
539 struct sk_buff *skb; 540 struct sk_buff *skb;
540 unsigned int qlen; 541 unsigned int qlen;
541 542
542 down(&ipqnl_sem); 543 mutex_lock(&ipqnl_mutex);
543 544
544 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { 545 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
545 skb = skb_dequeue(&sk->sk_receive_queue); 546 skb = skb_dequeue(&sk->sk_receive_queue);
@@ -547,7 +548,7 @@ ipq_rcv_sk(struct sock *sk, int len)
547 kfree_skb(skb); 548 kfree_skb(skb);
548 } 549 }
549 550
550 up(&ipqnl_sem); 551 mutex_unlock(&ipqnl_mutex);
551} 552}
552 553
553static int 554static int
@@ -708,8 +709,8 @@ cleanup_sysctl:
708 709
709cleanup_ipqnl: 710cleanup_ipqnl:
710 sock_release(ipqnl->sk_socket); 711 sock_release(ipqnl->sk_socket);
711 down(&ipqnl_sem); 712 mutex_lock(&ipqnl_mutex);
712 up(&ipqnl_sem); 713 mutex_unlock(&ipqnl_mutex);
713 714
714cleanup_netlink_notifier: 715cleanup_netlink_notifier:
715 netlink_unregister_notifier(&ipq_nl_notifier); 716 netlink_unregister_notifier(&ipq_nl_notifier);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 16f47c675fef..a7b194c4d79d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -25,7 +25,7 @@
25#include <linux/icmp.h> 25#include <linux/icmp.h>
26#include <net/ip.h> 26#include <net/ip.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include <asm/semaphore.h> 28#include <linux/mutex.h>
29#include <linux/proc_fs.h> 29#include <linux/proc_fs.h>
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/cpumask.h> 31#include <linux/cpumask.h>
@@ -179,6 +179,7 @@ ipt_error(struct sk_buff **pskb,
179 const struct net_device *in, 179 const struct net_device *in,
180 const struct net_device *out, 180 const struct net_device *out,
181 unsigned int hooknum, 181 unsigned int hooknum,
182 const struct xt_target *target,
182 const void *targinfo, 183 const void *targinfo,
183 void *userinfo) 184 void *userinfo)
184{ 185{
@@ -197,8 +198,8 @@ int do_match(struct ipt_entry_match *m,
197 int *hotdrop) 198 int *hotdrop)
198{ 199{
199 /* Stop iteration if it doesn't match */ 200 /* Stop iteration if it doesn't match */
200 if (!m->u.kernel.match->match(skb, in, out, m->data, offset, 201 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
201 skb->nh.iph->ihl*4, hotdrop)) 202 offset, skb->nh.iph->ihl*4, hotdrop))
202 return 1; 203 return 1;
203 else 204 else
204 return 0; 205 return 0;
@@ -305,6 +306,7 @@ ipt_do_table(struct sk_buff **pskb,
305 verdict = t->u.kernel.target->target(pskb, 306 verdict = t->u.kernel.target->target(pskb,
306 in, out, 307 in, out,
307 hook, 308 hook,
309 t->u.kernel.target,
308 t->data, 310 t->data,
309 userdata); 311 userdata);
310 312
@@ -464,7 +466,7 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
464 return 1; 466 return 1;
465 467
466 if (m->u.kernel.match->destroy) 468 if (m->u.kernel.match->destroy)
467 m->u.kernel.match->destroy(m->data, 469 m->u.kernel.match->destroy(m->u.kernel.match, m->data,
468 m->u.match_size - sizeof(*m)); 470 m->u.match_size - sizeof(*m));
469 module_put(m->u.kernel.match->me); 471 module_put(m->u.kernel.match->me);
470 return 0; 472 return 0;
@@ -477,21 +479,12 @@ standard_check(const struct ipt_entry_target *t,
477 struct ipt_standard_target *targ = (void *)t; 479 struct ipt_standard_target *targ = (void *)t;
478 480
479 /* Check standard info. */ 481 /* Check standard info. */
480 if (t->u.target_size
481 != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
482 duprintf("standard_check: target size %u != %u\n",
483 t->u.target_size,
484 IPT_ALIGN(sizeof(struct ipt_standard_target)));
485 return 0;
486 }
487
488 if (targ->verdict >= 0 482 if (targ->verdict >= 0
489 && targ->verdict > max_offset - sizeof(struct ipt_entry)) { 483 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
490 duprintf("ipt_standard_check: bad verdict (%i)\n", 484 duprintf("ipt_standard_check: bad verdict (%i)\n",
491 targ->verdict); 485 targ->verdict);
492 return 0; 486 return 0;
493 } 487 }
494
495 if (targ->verdict < -NF_MAX_VERDICT - 1) { 488 if (targ->verdict < -NF_MAX_VERDICT - 1) {
496 duprintf("ipt_standard_check: bad negative verdict (%i)\n", 489 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
497 targ->verdict); 490 targ->verdict);
@@ -508,6 +501,7 @@ check_match(struct ipt_entry_match *m,
508 unsigned int *i) 501 unsigned int *i)
509{ 502{
510 struct ipt_match *match; 503 struct ipt_match *match;
504 int ret;
511 505
512 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, 506 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
513 m->u.user.revision), 507 m->u.user.revision),
@@ -518,18 +512,27 @@ check_match(struct ipt_entry_match *m,
518 } 512 }
519 m->u.kernel.match = match; 513 m->u.kernel.match = match;
520 514
515 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
516 name, hookmask, ip->proto,
517 ip->invflags & IPT_INV_PROTO);
518 if (ret)
519 goto err;
520
521 if (m->u.kernel.match->checkentry 521 if (m->u.kernel.match->checkentry
522 && !m->u.kernel.match->checkentry(name, ip, m->data, 522 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
523 m->u.match_size - sizeof(*m), 523 m->u.match_size - sizeof(*m),
524 hookmask)) { 524 hookmask)) {
525 module_put(m->u.kernel.match->me);
526 duprintf("ip_tables: check failed for `%s'.\n", 525 duprintf("ip_tables: check failed for `%s'.\n",
527 m->u.kernel.match->name); 526 m->u.kernel.match->name);
528 return -EINVAL; 527 ret = -EINVAL;
528 goto err;
529 } 529 }
530 530
531 (*i)++; 531 (*i)++;
532 return 0; 532 return 0;
533err:
534 module_put(m->u.kernel.match->me);
535 return ret;
533} 536}
534 537
535static struct ipt_target ipt_standard_target; 538static struct ipt_target ipt_standard_target;
@@ -565,26 +568,32 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
565 } 568 }
566 t->u.kernel.target = target; 569 t->u.kernel.target = target;
567 570
571 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
572 name, e->comefrom, e->ip.proto,
573 e->ip.invflags & IPT_INV_PROTO);
574 if (ret)
575 goto err;
576
568 if (t->u.kernel.target == &ipt_standard_target) { 577 if (t->u.kernel.target == &ipt_standard_target) {
569 if (!standard_check(t, size)) { 578 if (!standard_check(t, size)) {
570 ret = -EINVAL; 579 ret = -EINVAL;
571 goto cleanup_matches; 580 goto cleanup_matches;
572 } 581 }
573 } else if (t->u.kernel.target->checkentry 582 } else if (t->u.kernel.target->checkentry
574 && !t->u.kernel.target->checkentry(name, e, t->data, 583 && !t->u.kernel.target->checkentry(name, e, target, t->data,
575 t->u.target_size 584 t->u.target_size
576 - sizeof(*t), 585 - sizeof(*t),
577 e->comefrom)) { 586 e->comefrom)) {
578 module_put(t->u.kernel.target->me);
579 duprintf("ip_tables: check failed for `%s'.\n", 587 duprintf("ip_tables: check failed for `%s'.\n",
580 t->u.kernel.target->name); 588 t->u.kernel.target->name);
581 ret = -EINVAL; 589 ret = -EINVAL;
582 goto cleanup_matches; 590 goto err;
583 } 591 }
584 592
585 (*i)++; 593 (*i)++;
586 return 0; 594 return 0;
587 595 err:
596 module_put(t->u.kernel.target->me);
588 cleanup_matches: 597 cleanup_matches:
589 IPT_MATCH_ITERATE(e, cleanup_match, &j); 598 IPT_MATCH_ITERATE(e, cleanup_match, &j);
590 return ret; 599 return ret;
@@ -645,7 +654,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
645 IPT_MATCH_ITERATE(e, cleanup_match, NULL); 654 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
646 t = ipt_get_target(e); 655 t = ipt_get_target(e);
647 if (t->u.kernel.target->destroy) 656 if (t->u.kernel.target->destroy)
648 t->u.kernel.target->destroy(t->data, 657 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
649 t->u.target_size - sizeof(*t)); 658 t->u.target_size - sizeof(*t));
650 module_put(t->u.kernel.target->me); 659 module_put(t->u.kernel.target->me);
651 return 0; 660 return 0;
@@ -1277,6 +1286,7 @@ static int
1277icmp_match(const struct sk_buff *skb, 1286icmp_match(const struct sk_buff *skb,
1278 const struct net_device *in, 1287 const struct net_device *in,
1279 const struct net_device *out, 1288 const struct net_device *out,
1289 const struct xt_match *match,
1280 const void *matchinfo, 1290 const void *matchinfo,
1281 int offset, 1291 int offset,
1282 unsigned int protoff, 1292 unsigned int protoff,
@@ -1310,28 +1320,29 @@ icmp_match(const struct sk_buff *skb,
1310static int 1320static int
1311icmp_checkentry(const char *tablename, 1321icmp_checkentry(const char *tablename,
1312 const void *info, 1322 const void *info,
1323 const struct xt_match *match,
1313 void *matchinfo, 1324 void *matchinfo,
1314 unsigned int matchsize, 1325 unsigned int matchsize,
1315 unsigned int hook_mask) 1326 unsigned int hook_mask)
1316{ 1327{
1317 const struct ipt_ip *ip = info;
1318 const struct ipt_icmp *icmpinfo = matchinfo; 1328 const struct ipt_icmp *icmpinfo = matchinfo;
1319 1329
1320 /* Must specify proto == ICMP, and no unknown invflags */ 1330 /* Must specify no unknown invflags */
1321 return ip->proto == IPPROTO_ICMP 1331 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
1322 && !(ip->invflags & IPT_INV_PROTO)
1323 && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp))
1324 && !(icmpinfo->invflags & ~IPT_ICMP_INV);
1325} 1332}
1326 1333
1327/* The built-in targets: standard (NULL) and error. */ 1334/* The built-in targets: standard (NULL) and error. */
1328static struct ipt_target ipt_standard_target = { 1335static struct ipt_target ipt_standard_target = {
1329 .name = IPT_STANDARD_TARGET, 1336 .name = IPT_STANDARD_TARGET,
1337 .targetsize = sizeof(int),
1338 .family = AF_INET,
1330}; 1339};
1331 1340
1332static struct ipt_target ipt_error_target = { 1341static struct ipt_target ipt_error_target = {
1333 .name = IPT_ERROR_TARGET, 1342 .name = IPT_ERROR_TARGET,
1334 .target = ipt_error, 1343 .target = ipt_error,
1344 .targetsize = IPT_FUNCTION_MAXNAMELEN,
1345 .family = AF_INET,
1335}; 1346};
1336 1347
1337static struct nf_sockopt_ops ipt_sockopts = { 1348static struct nf_sockopt_ops ipt_sockopts = {
@@ -1346,8 +1357,11 @@ static struct nf_sockopt_ops ipt_sockopts = {
1346 1357
1347static struct ipt_match icmp_matchstruct = { 1358static struct ipt_match icmp_matchstruct = {
1348 .name = "icmp", 1359 .name = "icmp",
1349 .match = &icmp_match, 1360 .match = icmp_match,
1350 .checkentry = &icmp_checkentry, 1361 .matchsize = sizeof(struct ipt_icmp),
1362 .proto = IPPROTO_ICMP,
1363 .family = AF_INET,
1364 .checkentry = icmp_checkentry,
1351}; 1365};
1352 1366
1353static int __init init(void) 1367static int __init init(void)
@@ -1357,9 +1371,9 @@ static int __init init(void)
1357 xt_proto_init(AF_INET); 1371 xt_proto_init(AF_INET);
1358 1372
1359 /* Noone else will be downing sem now, so we won't sleep */ 1373 /* Noone else will be downing sem now, so we won't sleep */
1360 xt_register_target(AF_INET, &ipt_standard_target); 1374 xt_register_target(&ipt_standard_target);
1361 xt_register_target(AF_INET, &ipt_error_target); 1375 xt_register_target(&ipt_error_target);
1362 xt_register_match(AF_INET, &icmp_matchstruct); 1376 xt_register_match(&icmp_matchstruct);
1363 1377
1364 /* Register setsockopt */ 1378 /* Register setsockopt */
1365 ret = nf_register_sockopt(&ipt_sockopts); 1379 ret = nf_register_sockopt(&ipt_sockopts);
@@ -1376,9 +1390,9 @@ static void __exit fini(void)
1376{ 1390{
1377 nf_unregister_sockopt(&ipt_sockopts); 1391 nf_unregister_sockopt(&ipt_sockopts);
1378 1392
1379 xt_unregister_match(AF_INET, &icmp_matchstruct); 1393 xt_unregister_match(&icmp_matchstruct);
1380 xt_unregister_target(AF_INET, &ipt_error_target); 1394 xt_unregister_target(&ipt_error_target);
1381 xt_unregister_target(AF_INET, &ipt_standard_target); 1395 xt_unregister_target(&ipt_standard_target);
1382 1396
1383 xt_proto_fini(AF_INET); 1397 xt_proto_fini(AF_INET);
1384} 1398}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index d9bc971f03af..61e11edcd6af 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -311,6 +311,7 @@ target(struct sk_buff **pskb,
311 const struct net_device *in, 311 const struct net_device *in,
312 const struct net_device *out, 312 const struct net_device *out,
313 unsigned int hooknum, 313 unsigned int hooknum,
314 const struct xt_target *target,
314 const void *targinfo, 315 const void *targinfo,
315 void *userinfo) 316 void *userinfo)
316{ 317{
@@ -380,6 +381,7 @@ target(struct sk_buff **pskb,
380static int 381static int
381checkentry(const char *tablename, 382checkentry(const char *tablename,
382 const void *e_void, 383 const void *e_void,
384 const struct xt_target *target,
383 void *targinfo, 385 void *targinfo,
384 unsigned int targinfosize, 386 unsigned int targinfosize,
385 unsigned int hook_mask) 387 unsigned int hook_mask)
@@ -389,13 +391,6 @@ checkentry(const char *tablename,
389 391
390 struct clusterip_config *config; 392 struct clusterip_config *config;
391 393
392 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info))) {
393 printk(KERN_WARNING "CLUSTERIP: targinfosize %u != %Zu\n",
394 targinfosize,
395 IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)));
396 return 0;
397 }
398
399 if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP && 394 if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
400 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT && 395 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
401 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { 396 cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
@@ -465,9 +460,10 @@ checkentry(const char *tablename,
465} 460}
466 461
467/* drop reference count of cluster config when rule is deleted */ 462/* drop reference count of cluster config when rule is deleted */
468static void destroy(void *matchinfo, unsigned int matchinfosize) 463static void destroy(const struct xt_target *target, void *targinfo,
464 unsigned int targinfosize)
469{ 465{
470 struct ipt_clusterip_tgt_info *cipinfo = matchinfo; 466 struct ipt_clusterip_tgt_info *cipinfo = targinfo;
471 467
472 /* if no more entries are referencing the config, remove it 468 /* if no more entries are referencing the config, remove it
473 * from the list and destroy the proc entry */ 469 * from the list and destroy the proc entry */
@@ -476,12 +472,13 @@ static void destroy(void *matchinfo, unsigned int matchinfosize)
476 clusterip_config_put(cipinfo->config); 472 clusterip_config_put(cipinfo->config);
477} 473}
478 474
479static struct ipt_target clusterip_tgt = { 475static struct ipt_target clusterip_tgt = {
480 .name = "CLUSTERIP", 476 .name = "CLUSTERIP",
481 .target = &target, 477 .target = target,
482 .checkentry = &checkentry, 478 .targetsize = sizeof(struct ipt_clusterip_tgt_info),
483 .destroy = &destroy, 479 .checkentry = checkentry,
484 .me = THIS_MODULE 480 .destroy = destroy,
481 .me = THIS_MODULE
485}; 482};
486 483
487 484
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index 898cdf79ce18..cfb0b90e598a 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -29,6 +29,7 @@ target(struct sk_buff **pskb,
29 const struct net_device *in, 29 const struct net_device *in,
30 const struct net_device *out, 30 const struct net_device *out,
31 unsigned int hooknum, 31 unsigned int hooknum,
32 const struct xt_target *target,
32 const void *targinfo, 33 const void *targinfo,
33 void *userinfo) 34 void *userinfo)
34{ 35{
@@ -58,35 +59,25 @@ target(struct sk_buff **pskb,
58static int 59static int
59checkentry(const char *tablename, 60checkentry(const char *tablename,
60 const void *e_void, 61 const void *e_void,
62 const struct xt_target *target,
61 void *targinfo, 63 void *targinfo,
62 unsigned int targinfosize, 64 unsigned int targinfosize,
63 unsigned int hook_mask) 65 unsigned int hook_mask)
64{ 66{
65 const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp; 67 const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp;
66 68
67 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) {
68 printk(KERN_WARNING "DSCP: targinfosize %u != %Zu\n",
69 targinfosize,
70 IPT_ALIGN(sizeof(struct ipt_DSCP_info)));
71 return 0;
72 }
73
74 if (strcmp(tablename, "mangle") != 0) {
75 printk(KERN_WARNING "DSCP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
76 return 0;
77 }
78
79 if ((dscp > IPT_DSCP_MAX)) { 69 if ((dscp > IPT_DSCP_MAX)) {
80 printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); 70 printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
81 return 0; 71 return 0;
82 } 72 }
83
84 return 1; 73 return 1;
85} 74}
86 75
87static struct ipt_target ipt_dscp_reg = { 76static struct ipt_target ipt_dscp_reg = {
88 .name = "DSCP", 77 .name = "DSCP",
89 .target = target, 78 .target = target,
79 .targetsize = sizeof(struct ipt_DSCP_info),
80 .table = "mangle",
90 .checkentry = checkentry, 81 .checkentry = checkentry,
91 .me = THIS_MODULE, 82 .me = THIS_MODULE,
92}; 83};
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 706445426a6d..b9b80f90c84e 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -94,6 +94,7 @@ target(struct sk_buff **pskb,
94 const struct net_device *in, 94 const struct net_device *in,
95 const struct net_device *out, 95 const struct net_device *out,
96 unsigned int hooknum, 96 unsigned int hooknum,
97 const struct xt_target *target,
97 const void *targinfo, 98 const void *targinfo,
98 void *userinfo) 99 void *userinfo)
99{ 100{
@@ -114,6 +115,7 @@ target(struct sk_buff **pskb,
114static int 115static int
115checkentry(const char *tablename, 116checkentry(const char *tablename,
116 const void *e_void, 117 const void *e_void,
118 const struct xt_target *target,
117 void *targinfo, 119 void *targinfo,
118 unsigned int targinfosize, 120 unsigned int targinfosize,
119 unsigned int hook_mask) 121 unsigned int hook_mask)
@@ -121,18 +123,6 @@ checkentry(const char *tablename,
121 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; 123 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
122 const struct ipt_entry *e = e_void; 124 const struct ipt_entry *e = e_void;
123 125
124 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) {
125 printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n",
126 targinfosize,
127 IPT_ALIGN(sizeof(struct ipt_ECN_info)));
128 return 0;
129 }
130
131 if (strcmp(tablename, "mangle") != 0) {
132 printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
133 return 0;
134 }
135
136 if (einfo->operation & IPT_ECN_OP_MASK) { 126 if (einfo->operation & IPT_ECN_OP_MASK) {
137 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", 127 printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
138 einfo->operation); 128 einfo->operation);
@@ -143,20 +133,20 @@ checkentry(const char *tablename,
143 einfo->ip_ect); 133 einfo->ip_ect);
144 return 0; 134 return 0;
145 } 135 }
146
147 if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) 136 if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
148 && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) { 137 && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) {
149 printk(KERN_WARNING "ECN: cannot use TCP operations on a " 138 printk(KERN_WARNING "ECN: cannot use TCP operations on a "
150 "non-tcp rule\n"); 139 "non-tcp rule\n");
151 return 0; 140 return 0;
152 } 141 }
153
154 return 1; 142 return 1;
155} 143}
156 144
157static struct ipt_target ipt_ecn_reg = { 145static struct ipt_target ipt_ecn_reg = {
158 .name = "ECN", 146 .name = "ECN",
159 .target = target, 147 .target = target,
148 .targetsize = sizeof(struct ipt_ECN_info),
149 .table = "mangle",
160 .checkentry = checkentry, 150 .checkentry = checkentry,
161 .me = THIS_MODULE, 151 .me = THIS_MODULE,
162}; 152};
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index cc27545ff97f..750d3221b280 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -415,6 +415,7 @@ ipt_log_target(struct sk_buff **pskb,
415 const struct net_device *in, 415 const struct net_device *in,
416 const struct net_device *out, 416 const struct net_device *out,
417 unsigned int hooknum, 417 unsigned int hooknum,
418 const struct xt_target *target,
418 const void *targinfo, 419 const void *targinfo,
419 void *userinfo) 420 void *userinfo)
420{ 421{
@@ -437,35 +438,29 @@ ipt_log_target(struct sk_buff **pskb,
437 438
438static int ipt_log_checkentry(const char *tablename, 439static int ipt_log_checkentry(const char *tablename,
439 const void *e, 440 const void *e,
441 const struct xt_target *target,
440 void *targinfo, 442 void *targinfo,
441 unsigned int targinfosize, 443 unsigned int targinfosize,
442 unsigned int hook_mask) 444 unsigned int hook_mask)
443{ 445{
444 const struct ipt_log_info *loginfo = targinfo; 446 const struct ipt_log_info *loginfo = targinfo;
445 447
446 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_log_info))) {
447 DEBUGP("LOG: targinfosize %u != %u\n",
448 targinfosize, IPT_ALIGN(sizeof(struct ipt_log_info)));
449 return 0;
450 }
451
452 if (loginfo->level >= 8) { 448 if (loginfo->level >= 8) {
453 DEBUGP("LOG: level %u >= 8\n", loginfo->level); 449 DEBUGP("LOG: level %u >= 8\n", loginfo->level);
454 return 0; 450 return 0;
455 } 451 }
456
457 if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { 452 if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
458 DEBUGP("LOG: prefix term %i\n", 453 DEBUGP("LOG: prefix term %i\n",
459 loginfo->prefix[sizeof(loginfo->prefix)-1]); 454 loginfo->prefix[sizeof(loginfo->prefix)-1]);
460 return 0; 455 return 0;
461 } 456 }
462
463 return 1; 457 return 1;
464} 458}
465 459
466static struct ipt_target ipt_log_reg = { 460static struct ipt_target ipt_log_reg = {
467 .name = "LOG", 461 .name = "LOG",
468 .target = ipt_log_target, 462 .target = ipt_log_target,
463 .targetsize = sizeof(struct ipt_log_info),
469 .checkentry = ipt_log_checkentry, 464 .checkentry = ipt_log_checkentry,
470 .me = THIS_MODULE, 465 .me = THIS_MODULE,
471}; 466};
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 12c56d3343ca..e0c321c3bae5 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -41,25 +41,13 @@ static DEFINE_RWLOCK(masq_lock);
41static int 41static int
42masquerade_check(const char *tablename, 42masquerade_check(const char *tablename,
43 const void *e, 43 const void *e,
44 const struct xt_target *target,
44 void *targinfo, 45 void *targinfo,
45 unsigned int targinfosize, 46 unsigned int targinfosize,
46 unsigned int hook_mask) 47 unsigned int hook_mask)
47{ 48{
48 const struct ip_nat_multi_range_compat *mr = targinfo; 49 const struct ip_nat_multi_range_compat *mr = targinfo;
49 50
50 if (strcmp(tablename, "nat") != 0) {
51 DEBUGP("masquerade_check: bad table `%s'.\n", tablename);
52 return 0;
53 }
54 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
55 DEBUGP("masquerade_check: size %u != %u.\n",
56 targinfosize, sizeof(*mr));
57 return 0;
58 }
59 if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
60 DEBUGP("masquerade_check: bad hooks %x.\n", hook_mask);
61 return 0;
62 }
63 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 51 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
64 DEBUGP("masquerade_check: bad MAP_IPS.\n"); 52 DEBUGP("masquerade_check: bad MAP_IPS.\n");
65 return 0; 53 return 0;
@@ -76,6 +64,7 @@ masquerade_target(struct sk_buff **pskb,
76 const struct net_device *in, 64 const struct net_device *in,
77 const struct net_device *out, 65 const struct net_device *out,
78 unsigned int hooknum, 66 unsigned int hooknum,
67 const struct xt_target *target,
79 const void *targinfo, 68 const void *targinfo,
80 void *userinfo) 69 void *userinfo)
81{ 70{
@@ -179,6 +168,9 @@ static struct notifier_block masq_inet_notifier = {
179static struct ipt_target masquerade = { 168static struct ipt_target masquerade = {
180 .name = "MASQUERADE", 169 .name = "MASQUERADE",
181 .target = masquerade_target, 170 .target = masquerade_target,
171 .targetsize = sizeof(struct ip_nat_multi_range_compat),
172 .table = "nat",
173 .hooks = 1 << NF_IP_POST_ROUTING,
182 .checkentry = masquerade_check, 174 .checkentry = masquerade_check,
183 .me = THIS_MODULE, 175 .me = THIS_MODULE,
184}; 176};
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index b074467fe67b..fba181c2a426 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -32,25 +32,13 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
32static int 32static int
33check(const char *tablename, 33check(const char *tablename,
34 const void *e, 34 const void *e,
35 const struct xt_target *target,
35 void *targinfo, 36 void *targinfo,
36 unsigned int targinfosize, 37 unsigned int targinfosize,
37 unsigned int hook_mask) 38 unsigned int hook_mask)
38{ 39{
39 const struct ip_nat_multi_range_compat *mr = targinfo; 40 const struct ip_nat_multi_range_compat *mr = targinfo;
40 41
41 if (strcmp(tablename, "nat") != 0) {
42 DEBUGP(MODULENAME":check: bad table `%s'.\n", tablename);
43 return 0;
44 }
45 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
46 DEBUGP(MODULENAME":check: size %u.\n", targinfosize);
47 return 0;
48 }
49 if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
50 (1 << NF_IP_LOCAL_OUT))) {
51 DEBUGP(MODULENAME":check: bad hooks %x.\n", hook_mask);
52 return 0;
53 }
54 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { 42 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
55 DEBUGP(MODULENAME":check: bad MAP_IPS.\n"); 43 DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
56 return 0; 44 return 0;
@@ -67,6 +55,7 @@ target(struct sk_buff **pskb,
67 const struct net_device *in, 55 const struct net_device *in,
68 const struct net_device *out, 56 const struct net_device *out,
69 unsigned int hooknum, 57 unsigned int hooknum,
58 const struct xt_target *target,
70 const void *targinfo, 59 const void *targinfo,
71 void *userinfo) 60 void *userinfo)
72{ 61{
@@ -101,6 +90,10 @@ target(struct sk_buff **pskb,
101static struct ipt_target target_module = { 90static struct ipt_target target_module = {
102 .name = MODULENAME, 91 .name = MODULENAME,
103 .target = target, 92 .target = target,
93 .targetsize = sizeof(struct ip_nat_multi_range_compat),
94 .table = "nat",
95 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
96 (1 << NF_IP_LOCAL_OUT),
104 .checkentry = check, 97 .checkentry = check,
105 .me = THIS_MODULE 98 .me = THIS_MODULE
106}; 99};
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 140be51f2f01..be3da7c4b871 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -34,24 +34,13 @@ MODULE_DESCRIPTION("iptables REDIRECT target module");
34static int 34static int
35redirect_check(const char *tablename, 35redirect_check(const char *tablename,
36 const void *e, 36 const void *e,
37 const struct xt_target *target,
37 void *targinfo, 38 void *targinfo,
38 unsigned int targinfosize, 39 unsigned int targinfosize,
39 unsigned int hook_mask) 40 unsigned int hook_mask)
40{ 41{
41 const struct ip_nat_multi_range_compat *mr = targinfo; 42 const struct ip_nat_multi_range_compat *mr = targinfo;
42 43
43 if (strcmp(tablename, "nat") != 0) {
44 DEBUGP("redirect_check: bad table `%s'.\n", table);
45 return 0;
46 }
47 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
48 DEBUGP("redirect_check: size %u.\n", targinfosize);
49 return 0;
50 }
51 if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
52 DEBUGP("redirect_check: bad hooks %x.\n", hook_mask);
53 return 0;
54 }
55 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 44 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
56 DEBUGP("redirect_check: bad MAP_IPS.\n"); 45 DEBUGP("redirect_check: bad MAP_IPS.\n");
57 return 0; 46 return 0;
@@ -68,6 +57,7 @@ redirect_target(struct sk_buff **pskb,
68 const struct net_device *in, 57 const struct net_device *in,
69 const struct net_device *out, 58 const struct net_device *out,
70 unsigned int hooknum, 59 unsigned int hooknum,
60 const struct xt_target *target,
71 const void *targinfo, 61 const void *targinfo,
72 void *userinfo) 62 void *userinfo)
73{ 63{
@@ -115,6 +105,9 @@ redirect_target(struct sk_buff **pskb,
115static struct ipt_target redirect_reg = { 105static struct ipt_target redirect_reg = {
116 .name = "REDIRECT", 106 .name = "REDIRECT",
117 .target = redirect_target, 107 .target = redirect_target,
108 .targetsize = sizeof(struct ip_nat_multi_range_compat),
109 .table = "nat",
110 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
118 .checkentry = redirect_check, 111 .checkentry = redirect_check,
119 .me = THIS_MODULE, 112 .me = THIS_MODULE,
120}; 113};
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 3eb47aae78c5..9d3b3579f27c 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -154,10 +154,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
154 /* This packet will not be the same as the other: clear nf fields */ 154 /* This packet will not be the same as the other: clear nf fields */
155 nf_reset(nskb); 155 nf_reset(nskb);
156 nskb->nfmark = 0; 156 nskb->nfmark = 0;
157#ifdef CONFIG_BRIDGE_NETFILTER
158 nf_bridge_put(nskb->nf_bridge);
159 nskb->nf_bridge = NULL;
160#endif
161 157
162 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); 158 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
163 159
@@ -236,6 +232,7 @@ static unsigned int reject(struct sk_buff **pskb,
236 const struct net_device *in, 232 const struct net_device *in,
237 const struct net_device *out, 233 const struct net_device *out,
238 unsigned int hooknum, 234 unsigned int hooknum,
235 const struct xt_target *target,
239 const void *targinfo, 236 const void *targinfo,
240 void *userinfo) 237 void *userinfo)
241{ 238{
@@ -283,6 +280,7 @@ static unsigned int reject(struct sk_buff **pskb,
283 280
284static int check(const char *tablename, 281static int check(const char *tablename,
285 const void *e_void, 282 const void *e_void,
283 const struct xt_target *target,
286 void *targinfo, 284 void *targinfo,
287 unsigned int targinfosize, 285 unsigned int targinfosize,
288 unsigned int hook_mask) 286 unsigned int hook_mask)
@@ -290,23 +288,6 @@ static int check(const char *tablename,
290 const struct ipt_reject_info *rejinfo = targinfo; 288 const struct ipt_reject_info *rejinfo = targinfo;
291 const struct ipt_entry *e = e_void; 289 const struct ipt_entry *e = e_void;
292 290
293 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
294 DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
295 return 0;
296 }
297
298 /* Only allow these for packet filtering. */
299 if (strcmp(tablename, "filter") != 0) {
300 DEBUGP("REJECT: bad table `%s'.\n", tablename);
301 return 0;
302 }
303 if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
304 | (1 << NF_IP_FORWARD)
305 | (1 << NF_IP_LOCAL_OUT))) != 0) {
306 DEBUGP("REJECT: bad hook mask %X\n", hook_mask);
307 return 0;
308 }
309
310 if (rejinfo->with == IPT_ICMP_ECHOREPLY) { 291 if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
311 printk("REJECT: ECHOREPLY no longer supported.\n"); 292 printk("REJECT: ECHOREPLY no longer supported.\n");
312 return 0; 293 return 0;
@@ -318,13 +299,16 @@ static int check(const char *tablename,
318 return 0; 299 return 0;
319 } 300 }
320 } 301 }
321
322 return 1; 302 return 1;
323} 303}
324 304
325static struct ipt_target ipt_reject_reg = { 305static struct ipt_target ipt_reject_reg = {
326 .name = "REJECT", 306 .name = "REJECT",
327 .target = reject, 307 .target = reject,
308 .targetsize = sizeof(struct ipt_reject_info),
309 .table = "filter",
310 .hooks = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) |
311 (1 << NF_IP_LOCAL_OUT),
328 .checkentry = check, 312 .checkentry = check,
329 .me = THIS_MODULE, 313 .me = THIS_MODULE,
330}; 314};
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index a22de59bba0e..7e2ebc9d945e 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -50,6 +50,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
50static int 50static int
51same_check(const char *tablename, 51same_check(const char *tablename,
52 const void *e, 52 const void *e,
53 const struct xt_target *target,
53 void *targinfo, 54 void *targinfo,
54 unsigned int targinfosize, 55 unsigned int targinfosize,
55 unsigned int hook_mask) 56 unsigned int hook_mask)
@@ -59,18 +60,6 @@ same_check(const char *tablename,
59 60
60 mr->ipnum = 0; 61 mr->ipnum = 0;
61 62
62 if (strcmp(tablename, "nat") != 0) {
63 DEBUGP("same_check: bad table `%s'.\n", tablename);
64 return 0;
65 }
66 if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
67 DEBUGP("same_check: size %u.\n", targinfosize);
68 return 0;
69 }
70 if (hook_mask & ~(1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING)) {
71 DEBUGP("same_check: bad hooks %x.\n", hook_mask);
72 return 0;
73 }
74 if (mr->rangesize < 1) { 63 if (mr->rangesize < 1) {
75 DEBUGP("same_check: need at least one dest range.\n"); 64 DEBUGP("same_check: need at least one dest range.\n");
76 return 0; 65 return 0;
@@ -127,7 +116,7 @@ same_check(const char *tablename,
127} 116}
128 117
129static void 118static void
130same_destroy(void *targinfo, 119same_destroy(const struct xt_target *target, void *targinfo,
131 unsigned int targinfosize) 120 unsigned int targinfosize)
132{ 121{
133 struct ipt_same_info *mr = targinfo; 122 struct ipt_same_info *mr = targinfo;
@@ -143,6 +132,7 @@ same_target(struct sk_buff **pskb,
143 const struct net_device *in, 132 const struct net_device *in,
144 const struct net_device *out, 133 const struct net_device *out,
145 unsigned int hooknum, 134 unsigned int hooknum,
135 const struct xt_target *target,
146 const void *targinfo, 136 const void *targinfo,
147 void *userinfo) 137 void *userinfo)
148{ 138{
@@ -191,6 +181,9 @@ same_target(struct sk_buff **pskb,
191static struct ipt_target same_reg = { 181static struct ipt_target same_reg = {
192 .name = "SAME", 182 .name = "SAME",
193 .target = same_target, 183 .target = same_target,
184 .targetsize = sizeof(struct ipt_same_info),
185 .table = "nat",
186 .hooks = (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING),
194 .checkentry = same_check, 187 .checkentry = same_check,
195 .destroy = same_destroy, 188 .destroy = same_destroy,
196 .me = THIS_MODULE, 189 .me = THIS_MODULE,
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index c122841e182c..c4fc50ec2ddb 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -48,6 +48,7 @@ ipt_tcpmss_target(struct sk_buff **pskb,
48 const struct net_device *in, 48 const struct net_device *in,
49 const struct net_device *out, 49 const struct net_device *out,
50 unsigned int hooknum, 50 unsigned int hooknum,
51 const struct xt_target *target,
51 const void *targinfo, 52 const void *targinfo,
52 void *userinfo) 53 void *userinfo)
53{ 54{
@@ -211,6 +212,7 @@ static inline int find_syn_match(const struct ipt_entry_match *m)
211static int 212static int
212ipt_tcpmss_checkentry(const char *tablename, 213ipt_tcpmss_checkentry(const char *tablename,
213 const void *e_void, 214 const void *e_void,
215 const struct xt_target *target,
214 void *targinfo, 216 void *targinfo,
215 unsigned int targinfosize, 217 unsigned int targinfosize,
216 unsigned int hook_mask) 218 unsigned int hook_mask)
@@ -218,13 +220,6 @@ ipt_tcpmss_checkentry(const char *tablename,
218 const struct ipt_tcpmss_info *tcpmssinfo = targinfo; 220 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
219 const struct ipt_entry *e = e_void; 221 const struct ipt_entry *e = e_void;
220 222
221 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) {
222 DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n",
223 targinfosize, IPT_ALIGN(sizeof(struct ipt_tcpmss_info)));
224 return 0;
225 }
226
227
228 if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && 223 if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) &&
229 ((hook_mask & ~((1 << NF_IP_FORWARD) 224 ((hook_mask & ~((1 << NF_IP_FORWARD)
230 | (1 << NF_IP_LOCAL_OUT) 225 | (1 << NF_IP_LOCAL_OUT)
@@ -233,11 +228,8 @@ ipt_tcpmss_checkentry(const char *tablename,
233 return 0; 228 return 0;
234 } 229 }
235 230
236 if (e->ip.proto == IPPROTO_TCP 231 if (IPT_MATCH_ITERATE(e, find_syn_match))
237 && !(e->ip.invflags & IPT_INV_PROTO)
238 && IPT_MATCH_ITERATE(e, find_syn_match))
239 return 1; 232 return 1;
240
241 printk("TCPMSS: Only works on TCP SYN packets\n"); 233 printk("TCPMSS: Only works on TCP SYN packets\n");
242 return 0; 234 return 0;
243} 235}
@@ -245,6 +237,8 @@ ipt_tcpmss_checkentry(const char *tablename,
245static struct ipt_target ipt_tcpmss_reg = { 237static struct ipt_target ipt_tcpmss_reg = {
246 .name = "TCPMSS", 238 .name = "TCPMSS",
247 .target = ipt_tcpmss_target, 239 .target = ipt_tcpmss_target,
240 .targetsize = sizeof(struct ipt_tcpmss_info),
241 .proto = IPPROTO_TCP,
248 .checkentry = ipt_tcpmss_checkentry, 242 .checkentry = ipt_tcpmss_checkentry,
249 .me = THIS_MODULE, 243 .me = THIS_MODULE,
250}; 244};
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 3a44a56db239..9aa7817657f0 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -25,6 +25,7 @@ target(struct sk_buff **pskb,
25 const struct net_device *in, 25 const struct net_device *in,
26 const struct net_device *out, 26 const struct net_device *out,
27 unsigned int hooknum, 27 unsigned int hooknum,
28 const struct xt_target *target,
28 const void *targinfo, 29 const void *targinfo,
29 void *userinfo) 30 void *userinfo)
30{ 31{
@@ -53,24 +54,13 @@ target(struct sk_buff **pskb,
53static int 54static int
54checkentry(const char *tablename, 55checkentry(const char *tablename,
55 const void *e_void, 56 const void *e_void,
57 const struct xt_target *target,
56 void *targinfo, 58 void *targinfo,
57 unsigned int targinfosize, 59 unsigned int targinfosize,
58 unsigned int hook_mask) 60 unsigned int hook_mask)
59{ 61{
60 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; 62 const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos;
61 63
62 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tos_target_info))) {
63 printk(KERN_WARNING "TOS: targinfosize %u != %Zu\n",
64 targinfosize,
65 IPT_ALIGN(sizeof(struct ipt_tos_target_info)));
66 return 0;
67 }
68
69 if (strcmp(tablename, "mangle") != 0) {
70 printk(KERN_WARNING "TOS: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
71 return 0;
72 }
73
74 if (tos != IPTOS_LOWDELAY 64 if (tos != IPTOS_LOWDELAY
75 && tos != IPTOS_THROUGHPUT 65 && tos != IPTOS_THROUGHPUT
76 && tos != IPTOS_RELIABILITY 66 && tos != IPTOS_RELIABILITY
@@ -79,13 +69,14 @@ checkentry(const char *tablename,
79 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos); 69 printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
80 return 0; 70 return 0;
81 } 71 }
82
83 return 1; 72 return 1;
84} 73}
85 74
86static struct ipt_target ipt_tos_reg = { 75static struct ipt_target ipt_tos_reg = {
87 .name = "TOS", 76 .name = "TOS",
88 .target = target, 77 .target = target,
78 .targetsize = sizeof(struct ipt_tos_target_info),
79 .table = "mangle",
89 .checkentry = checkentry, 80 .checkentry = checkentry,
90 .me = THIS_MODULE, 81 .me = THIS_MODULE,
91}; 82};
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index b769eb231970..5009a003d578 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -20,9 +20,10 @@ MODULE_DESCRIPTION("IP tables TTL modification module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static unsigned int 22static unsigned int
23ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 23ipt_ttl_target(struct sk_buff **pskb,
24 const struct net_device *out, unsigned int hooknum, 24 const struct net_device *in, const struct net_device *out,
25 const void *targinfo, void *userinfo) 25 unsigned int hooknum, const struct xt_target *target,
26 const void *targinfo, void *userinfo)
26{ 27{
27 struct iphdr *iph; 28 struct iphdr *iph;
28 const struct ipt_TTL_info *info = targinfo; 29 const struct ipt_TTL_info *info = targinfo;
@@ -67,40 +68,28 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
67 68
68static int ipt_ttl_checkentry(const char *tablename, 69static int ipt_ttl_checkentry(const char *tablename,
69 const void *e, 70 const void *e,
71 const struct xt_target *target,
70 void *targinfo, 72 void *targinfo,
71 unsigned int targinfosize, 73 unsigned int targinfosize,
72 unsigned int hook_mask) 74 unsigned int hook_mask)
73{ 75{
74 struct ipt_TTL_info *info = targinfo; 76 struct ipt_TTL_info *info = targinfo;
75 77
76 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
77 printk(KERN_WARNING "ipt_TTL: targinfosize %u != %Zu\n",
78 targinfosize,
79 IPT_ALIGN(sizeof(struct ipt_TTL_info)));
80 return 0;
81 }
82
83 if (strcmp(tablename, "mangle")) {
84 printk(KERN_WARNING "ipt_TTL: can only be called from "
85 "\"mangle\" table, not \"%s\"\n", tablename);
86 return 0;
87 }
88
89 if (info->mode > IPT_TTL_MAXMODE) { 78 if (info->mode > IPT_TTL_MAXMODE) {
90 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n", 79 printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
91 info->mode); 80 info->mode);
92 return 0; 81 return 0;
93 } 82 }
94
95 if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) 83 if ((info->mode != IPT_TTL_SET) && (info->ttl == 0))
96 return 0; 84 return 0;
97
98 return 1; 85 return 1;
99} 86}
100 87
101static struct ipt_target ipt_TTL = { 88static struct ipt_target ipt_TTL = {
102 .name = "TTL", 89 .name = "TTL",
103 .target = ipt_ttl_target, 90 .target = ipt_ttl_target,
91 .targetsize = sizeof(struct ipt_TTL_info),
92 .table = "mangle",
104 .checkentry = ipt_ttl_checkentry, 93 .checkentry = ipt_ttl_checkentry,
105 .me = THIS_MODULE, 94 .me = THIS_MODULE,
106}; 95};
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 180a9ea57b69..a82a32ed0e2f 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -303,6 +303,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
303 const struct net_device *in, 303 const struct net_device *in,
304 const struct net_device *out, 304 const struct net_device *out,
305 unsigned int hooknum, 305 unsigned int hooknum,
306 const struct xt_target *target,
306 const void *targinfo, void *userinfo) 307 const void *targinfo, void *userinfo)
307{ 308{
308 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; 309 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
@@ -339,42 +340,37 @@ static void ipt_logfn(unsigned int pf,
339 340
340static int ipt_ulog_checkentry(const char *tablename, 341static int ipt_ulog_checkentry(const char *tablename,
341 const void *e, 342 const void *e,
343 const struct xt_target *target,
342 void *targinfo, 344 void *targinfo,
343 unsigned int targinfosize, 345 unsigned int targinfosize,
344 unsigned int hookmask) 346 unsigned int hookmask)
345{ 347{
346 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; 348 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
347 349
348 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ulog_info))) {
349 DEBUGP("ipt_ULOG: targinfosize %u != 0\n", targinfosize);
350 return 0;
351 }
352
353 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { 350 if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
354 DEBUGP("ipt_ULOG: prefix term %i\n", 351 DEBUGP("ipt_ULOG: prefix term %i\n",
355 loginfo->prefix[sizeof(loginfo->prefix) - 1]); 352 loginfo->prefix[sizeof(loginfo->prefix) - 1]);
356 return 0; 353 return 0;
357 } 354 }
358
359 if (loginfo->qthreshold > ULOG_MAX_QLEN) { 355 if (loginfo->qthreshold > ULOG_MAX_QLEN) {
360 DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n", 356 DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n",
361 loginfo->qthreshold); 357 loginfo->qthreshold);
362 return 0; 358 return 0;
363 } 359 }
364
365 return 1; 360 return 1;
366} 361}
367 362
368static struct ipt_target ipt_ulog_reg = { 363static struct ipt_target ipt_ulog_reg = {
369 .name = "ULOG", 364 .name = "ULOG",
370 .target = ipt_ulog_target, 365 .target = ipt_ulog_target,
366 .targetsize = sizeof(struct ipt_ulog_info),
371 .checkentry = ipt_ulog_checkentry, 367 .checkentry = ipt_ulog_checkentry,
372 .me = THIS_MODULE, 368 .me = THIS_MODULE,
373}; 369};
374 370
375static struct nf_logger ipt_ulog_logger = { 371static struct nf_logger ipt_ulog_logger = {
376 .name = "ipt_ULOG", 372 .name = "ipt_ULOG",
377 .logfn = &ipt_logfn, 373 .logfn = ipt_logfn,
378 .me = THIS_MODULE, 374 .me = THIS_MODULE,
379}; 375};
380 376
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index d6b83a976518..5fdf85d0efcf 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -27,8 +27,9 @@ static inline int match_type(u_int32_t addr, u_int16_t mask)
27 return !!(mask & (1 << inet_addr_type(addr))); 27 return !!(mask & (1 << inet_addr_type(addr)));
28} 28}
29 29
30static int match(const struct sk_buff *skb, const struct net_device *in, 30static int match(const struct sk_buff *skb,
31 const struct net_device *out, const void *matchinfo, 31 const struct net_device *in, const struct net_device *out,
32 const struct xt_match *match, const void *matchinfo,
32 int offset, unsigned int protoff, int *hotdrop) 33 int offset, unsigned int protoff, int *hotdrop)
33{ 34{
34 const struct ipt_addrtype_info *info = matchinfo; 35 const struct ipt_addrtype_info *info = matchinfo;
@@ -43,23 +44,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
43 return ret; 44 return ret;
44} 45}
45 46
46static int checkentry(const char *tablename, const void *ip,
47 void *matchinfo, unsigned int matchsize,
48 unsigned int hook_mask)
49{
50 if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
51 printk(KERN_ERR "ipt_addrtype: invalid size (%u != %Zu)\n",
52 matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
53 return 0;
54 }
55
56 return 1;
57}
58
59static struct ipt_match addrtype_match = { 47static struct ipt_match addrtype_match = {
60 .name = "addrtype", 48 .name = "addrtype",
61 .match = match, 49 .match = match,
62 .checkentry = checkentry, 50 .matchsize = sizeof(struct ipt_addrtype_info),
63 .me = THIS_MODULE 51 .me = THIS_MODULE
64}; 52};
65 53
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 144adfec13cc..35a21fb1f8e0 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -39,6 +39,7 @@ static int
39match(const struct sk_buff *skb, 39match(const struct sk_buff *skb,
40 const struct net_device *in, 40 const struct net_device *in,
41 const struct net_device *out, 41 const struct net_device *out,
42 const struct xt_match *match,
42 const void *matchinfo, 43 const void *matchinfo,
43 int offset, 44 int offset,
44 unsigned int protoff, 45 unsigned int protoff,
@@ -71,37 +72,27 @@ match(const struct sk_buff *skb,
71static int 72static int
72checkentry(const char *tablename, 73checkentry(const char *tablename,
73 const void *ip_void, 74 const void *ip_void,
75 const struct xt_match *match,
74 void *matchinfo, 76 void *matchinfo,
75 unsigned int matchinfosize, 77 unsigned int matchinfosize,
76 unsigned int hook_mask) 78 unsigned int hook_mask)
77{ 79{
78 const struct ipt_ah *ahinfo = matchinfo; 80 const struct ipt_ah *ahinfo = matchinfo;
79 const struct ipt_ip *ip = ip_void;
80 81
81 /* Must specify proto == AH, and no unknown invflags */ 82 /* Must specify no unknown invflags */
82 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) {
83 duprintf("ipt_ah: Protocol %u != %u\n", ip->proto,
84 IPPROTO_AH);
85 return 0;
86 }
87 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_ah))) {
88 duprintf("ipt_ah: matchsize %u != %u\n",
89 matchinfosize, IPT_ALIGN(sizeof(struct ipt_ah)));
90 return 0;
91 }
92 if (ahinfo->invflags & ~IPT_AH_INV_MASK) { 83 if (ahinfo->invflags & ~IPT_AH_INV_MASK) {
93 duprintf("ipt_ah: unknown flags %X\n", 84 duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags);
94 ahinfo->invflags);
95 return 0; 85 return 0;
96 } 86 }
97
98 return 1; 87 return 1;
99} 88}
100 89
101static struct ipt_match ah_match = { 90static struct ipt_match ah_match = {
102 .name = "ah", 91 .name = "ah",
103 .match = &match, 92 .match = match,
104 .checkentry = &checkentry, 93 .matchsize = sizeof(struct ipt_ah),
94 .proto = IPPROTO_AH,
95 .checkentry = checkentry,
105 .me = THIS_MODULE, 96 .me = THIS_MODULE,
106}; 97};
107 98
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 92063b4f8602..11963c385dea 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -19,8 +19,9 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("iptables DSCP matching module"); 19MODULE_DESCRIPTION("iptables DSCP matching module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *in, const struct net_device *out,
24 const struct xt_match *match, const void *matchinfo,
24 int offset, unsigned int protoff, int *hotdrop) 25 int offset, unsigned int protoff, int *hotdrop)
25{ 26{
26 const struct ipt_dscp_info *info = matchinfo; 27 const struct ipt_dscp_info *info = matchinfo;
@@ -31,20 +32,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
31 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; 32 return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert;
32} 33}
33 34
34static int checkentry(const char *tablename, const void *ip,
35 void *matchinfo, unsigned int matchsize,
36 unsigned int hook_mask)
37{
38 if (matchsize != IPT_ALIGN(sizeof(struct ipt_dscp_info)))
39 return 0;
40
41 return 1;
42}
43
44static struct ipt_match dscp_match = { 35static struct ipt_match dscp_match = {
45 .name = "dscp", 36 .name = "dscp",
46 .match = &match, 37 .match = match,
47 .checkentry = &checkentry, 38 .matchsize = sizeof(struct ipt_dscp_info),
48 .me = THIS_MODULE, 39 .me = THIS_MODULE,
49}; 40};
50 41
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index e68b0c7981f0..d7e29f6a38d8 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -65,8 +65,9 @@ static inline int match_tcp(const struct sk_buff *skb,
65 return 1; 65 return 1;
66} 66}
67 67
68static int match(const struct sk_buff *skb, const struct net_device *in, 68static int match(const struct sk_buff *skb,
69 const struct net_device *out, const void *matchinfo, 69 const struct net_device *in, const struct net_device *out,
70 const struct xt_match *match, const void *matchinfo,
70 int offset, unsigned int protoff, int *hotdrop) 71 int offset, unsigned int protoff, int *hotdrop)
71{ 72{
72 const struct ipt_ecn_info *info = matchinfo; 73 const struct ipt_ecn_info *info = matchinfo;
@@ -86,15 +87,13 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
86} 87}
87 88
88static int checkentry(const char *tablename, const void *ip_void, 89static int checkentry(const char *tablename, const void *ip_void,
90 const struct xt_match *match,
89 void *matchinfo, unsigned int matchsize, 91 void *matchinfo, unsigned int matchsize,
90 unsigned int hook_mask) 92 unsigned int hook_mask)
91{ 93{
92 const struct ipt_ecn_info *info = matchinfo; 94 const struct ipt_ecn_info *info = matchinfo;
93 const struct ipt_ip *ip = ip_void; 95 const struct ipt_ip *ip = ip_void;
94 96
95 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info)))
96 return 0;
97
98 if (info->operation & IPT_ECN_OP_MATCH_MASK) 97 if (info->operation & IPT_ECN_OP_MATCH_MASK)
99 return 0; 98 return 0;
100 99
@@ -113,8 +112,9 @@ static int checkentry(const char *tablename, const void *ip_void,
113 112
114static struct ipt_match ecn_match = { 113static struct ipt_match ecn_match = {
115 .name = "ecn", 114 .name = "ecn",
116 .match = &match, 115 .match = match,
117 .checkentry = &checkentry, 116 .matchsize = sizeof(struct ipt_ecn_info),
117 .checkentry = checkentry,
118 .me = THIS_MODULE, 118 .me = THIS_MODULE,
119}; 119};
120 120
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index 9de191a8162d..af0d5ec79cb5 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -40,6 +40,7 @@ static int
40match(const struct sk_buff *skb, 40match(const struct sk_buff *skb,
41 const struct net_device *in, 41 const struct net_device *in,
42 const struct net_device *out, 42 const struct net_device *out,
43 const struct xt_match *match,
43 const void *matchinfo, 44 const void *matchinfo,
44 int offset, 45 int offset,
45 unsigned int protoff, 46 unsigned int protoff,
@@ -72,37 +73,27 @@ match(const struct sk_buff *skb,
72static int 73static int
73checkentry(const char *tablename, 74checkentry(const char *tablename,
74 const void *ip_void, 75 const void *ip_void,
76 const struct xt_match *match,
75 void *matchinfo, 77 void *matchinfo,
76 unsigned int matchinfosize, 78 unsigned int matchinfosize,
77 unsigned int hook_mask) 79 unsigned int hook_mask)
78{ 80{
79 const struct ipt_esp *espinfo = matchinfo; 81 const struct ipt_esp *espinfo = matchinfo;
80 const struct ipt_ip *ip = ip_void;
81 82
82 /* Must specify proto == ESP, and no unknown invflags */ 83 /* Must specify no unknown invflags */
83 if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) {
84 duprintf("ipt_esp: Protocol %u != %u\n", ip->proto,
85 IPPROTO_ESP);
86 return 0;
87 }
88 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_esp))) {
89 duprintf("ipt_esp: matchsize %u != %u\n",
90 matchinfosize, IPT_ALIGN(sizeof(struct ipt_esp)));
91 return 0;
92 }
93 if (espinfo->invflags & ~IPT_ESP_INV_MASK) { 84 if (espinfo->invflags & ~IPT_ESP_INV_MASK) {
94 duprintf("ipt_esp: unknown flags %X\n", 85 duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
95 espinfo->invflags);
96 return 0; 86 return 0;
97 } 87 }
98
99 return 1; 88 return 1;
100} 89}
101 90
102static struct ipt_match esp_match = { 91static struct ipt_match esp_match = {
103 .name = "esp", 92 .name = "esp",
104 .match = &match, 93 .match = match,
105 .checkentry = &checkentry, 94 .matchsize = sizeof(struct ipt_esp),
95 .proto = IPPROTO_ESP,
96 .checkentry = checkentry,
106 .me = THIS_MODULE, 97 .me = THIS_MODULE,
107}; 98};
108 99
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 4fe48c1bd5f3..dc1521c5aa81 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -427,6 +427,7 @@ static int
427hashlimit_match(const struct sk_buff *skb, 427hashlimit_match(const struct sk_buff *skb,
428 const struct net_device *in, 428 const struct net_device *in,
429 const struct net_device *out, 429 const struct net_device *out,
430 const struct xt_match *match,
430 const void *matchinfo, 431 const void *matchinfo,
431 int offset, 432 int offset,
432 unsigned int protoff, 433 unsigned int protoff,
@@ -506,15 +507,13 @@ hashlimit_match(const struct sk_buff *skb,
506static int 507static int
507hashlimit_checkentry(const char *tablename, 508hashlimit_checkentry(const char *tablename,
508 const void *inf, 509 const void *inf,
510 const struct xt_match *match,
509 void *matchinfo, 511 void *matchinfo,
510 unsigned int matchsize, 512 unsigned int matchsize,
511 unsigned int hook_mask) 513 unsigned int hook_mask)
512{ 514{
513 struct ipt_hashlimit_info *r = matchinfo; 515 struct ipt_hashlimit_info *r = matchinfo;
514 516
515 if (matchsize != IPT_ALIGN(sizeof(struct ipt_hashlimit_info)))
516 return 0;
517
518 /* Check for overflow. */ 517 /* Check for overflow. */
519 if (r->cfg.burst == 0 518 if (r->cfg.burst == 0
520 || user2credits(r->cfg.avg * r->cfg.burst) < 519 || user2credits(r->cfg.avg * r->cfg.burst) <
@@ -558,19 +557,21 @@ hashlimit_checkentry(const char *tablename,
558} 557}
559 558
560static void 559static void
561hashlimit_destroy(void *matchinfo, unsigned int matchsize) 560hashlimit_destroy(const struct xt_match *match, void *matchinfo,
561 unsigned int matchsize)
562{ 562{
563 struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *) matchinfo; 563 struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *) matchinfo;
564 564
565 htable_put(r->hinfo); 565 htable_put(r->hinfo);
566} 566}
567 567
568static struct ipt_match ipt_hashlimit = { 568static struct ipt_match ipt_hashlimit = {
569 .name = "hashlimit", 569 .name = "hashlimit",
570 .match = hashlimit_match, 570 .match = hashlimit_match,
571 .checkentry = hashlimit_checkentry, 571 .matchsize = sizeof(struct ipt_hashlimit_info),
572 .destroy = hashlimit_destroy, 572 .checkentry = hashlimit_checkentry,
573 .me = THIS_MODULE 573 .destroy = hashlimit_destroy,
574 .me = THIS_MODULE
574}; 575};
575 576
576/* PROC stuff */ 577/* PROC stuff */
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 13fb16fb7892..ae70112f5e06 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -27,6 +27,7 @@ static int
27match(const struct sk_buff *skb, 27match(const struct sk_buff *skb,
28 const struct net_device *in, 28 const struct net_device *in,
29 const struct net_device *out, 29 const struct net_device *out,
30 const struct xt_match *match,
30 const void *matchinfo, 31 const void *matchinfo,
31 int offset, unsigned int protoff, int *hotdrop) 32 int offset, unsigned int protoff, int *hotdrop)
32{ 33{
@@ -62,27 +63,12 @@ match(const struct sk_buff *skb,
62 return 1; 63 return 1;
63} 64}
64 65
65static int check(const char *tablename, 66static struct ipt_match iprange_match = {
66 const void *inf, 67 .name = "iprange",
67 void *matchinfo, 68 .match = match,
68 unsigned int matchsize, 69 .matchsize = sizeof(struct ipt_iprange_info),
69 unsigned int hook_mask) 70 .destroy = NULL,
70{ 71 .me = THIS_MODULE
71 /* verify size */
72 if (matchsize != IPT_ALIGN(sizeof(struct ipt_iprange_info)))
73 return 0;
74
75 return 1;
76}
77
78static struct ipt_match iprange_match =
79{
80 .list = { NULL, NULL },
81 .name = "iprange",
82 .match = &match,
83 .checkentry = &check,
84 .destroy = NULL,
85 .me = THIS_MODULE
86}; 72};
87 73
88static int __init init(void) 74static int __init init(void)
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index 2d52326553f1..bd07f7c53872 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -95,6 +95,7 @@ static int
95match(const struct sk_buff *skb, 95match(const struct sk_buff *skb,
96 const struct net_device *in, 96 const struct net_device *in,
97 const struct net_device *out, 97 const struct net_device *out,
98 const struct xt_match *match,
98 const void *matchinfo, 99 const void *matchinfo,
99 int offset, 100 int offset,
100 unsigned int protoff, 101 unsigned int protoff,
@@ -127,6 +128,7 @@ static int
127match_v1(const struct sk_buff *skb, 128match_v1(const struct sk_buff *skb,
128 const struct net_device *in, 129 const struct net_device *in,
129 const struct net_device *out, 130 const struct net_device *out,
131 const struct xt_match *match,
130 const void *matchinfo, 132 const void *matchinfo,
131 int offset, 133 int offset,
132 unsigned int protoff, 134 unsigned int protoff,
@@ -153,40 +155,19 @@ match_v1(const struct sk_buff *skb,
153 return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); 155 return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
154} 156}
155 157
156/* Called when user tries to insert an entry of this type. */
157static int
158checkentry(const char *tablename,
159 const void *ip,
160 void *matchinfo,
161 unsigned int matchsize,
162 unsigned int hook_mask)
163{
164 return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport)));
165}
166
167static int
168checkentry_v1(const char *tablename,
169 const void *ip,
170 void *matchinfo,
171 unsigned int matchsize,
172 unsigned int hook_mask)
173{
174 return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1)));
175}
176
177static struct ipt_match multiport_match = { 158static struct ipt_match multiport_match = {
178 .name = "multiport", 159 .name = "multiport",
179 .revision = 0, 160 .revision = 0,
180 .match = &match, 161 .match = match,
181 .checkentry = &checkentry, 162 .matchsize = sizeof(struct ipt_multiport),
182 .me = THIS_MODULE, 163 .me = THIS_MODULE,
183}; 164};
184 165
185static struct ipt_match multiport_match_v1 = { 166static struct ipt_match multiport_match_v1 = {
186 .name = "multiport", 167 .name = "multiport",
187 .revision = 1, 168 .revision = 1,
188 .match = &match_v1, 169 .match = match_v1,
189 .checkentry = &checkentry_v1, 170 .matchsize = sizeof(struct ipt_multiport_v1),
190 .me = THIS_MODULE, 171 .me = THIS_MODULE,
191}; 172};
192 173
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 4843d0c9734f..3900428771f3 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -25,6 +25,7 @@ static int
25match(const struct sk_buff *skb, 25match(const struct sk_buff *skb,
26 const struct net_device *in, 26 const struct net_device *in,
27 const struct net_device *out, 27 const struct net_device *out,
28 const struct xt_match *match,
28 const void *matchinfo, 29 const void *matchinfo,
29 int offset, 30 int offset,
30 unsigned int protoff, 31 unsigned int protoff,
@@ -53,37 +54,27 @@ match(const struct sk_buff *skb,
53static int 54static int
54checkentry(const char *tablename, 55checkentry(const char *tablename,
55 const void *ip, 56 const void *ip,
57 const struct xt_match *match,
56 void *matchinfo, 58 void *matchinfo,
57 unsigned int matchsize, 59 unsigned int matchsize,
58 unsigned int hook_mask) 60 unsigned int hook_mask)
59{ 61{
60 const struct ipt_owner_info *info = matchinfo; 62 const struct ipt_owner_info *info = matchinfo;
61 63
62 if (hook_mask
63 & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
64 printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
65 return 0;
66 }
67
68 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
69 printk("Matchsize %u != %Zu\n", matchsize,
70 IPT_ALIGN(sizeof(struct ipt_owner_info)));
71 return 0;
72 }
73
74 if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) { 64 if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
75 printk("ipt_owner: pid, sid and command matching " 65 printk("ipt_owner: pid, sid and command matching "
76 "not supported anymore\n"); 66 "not supported anymore\n");
77 return 0; 67 return 0;
78 } 68 }
79
80 return 1; 69 return 1;
81} 70}
82 71
83static struct ipt_match owner_match = { 72static struct ipt_match owner_match = {
84 .name = "owner", 73 .name = "owner",
85 .match = &match, 74 .match = match,
86 .checkentry = &checkentry, 75 .matchsize = sizeof(struct ipt_owner_info),
76 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING),
77 .checkentry = checkentry,
87 .me = THIS_MODULE, 78 .me = THIS_MODULE,
88}; 79};
89 80
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c
deleted file mode 100644
index 5a7a265280f9..000000000000
--- a/net/ipv4/netfilter/ipt_policy.c
+++ /dev/null
@@ -1,176 +0,0 @@
1/* IP tables module for matching IPsec policy
2 *
3 * Copyright (c) 2004,2005 Patrick McHardy, <kaber@trash.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/kernel.h>
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/init.h>
15#include <net/xfrm.h>
16
17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv4/ipt_policy.h>
20
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_DESCRIPTION("IPtables IPsec policy matching module");
23MODULE_LICENSE("GPL");
24
25
26static inline int
27match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
28{
29#define MATCH_ADDR(x,y,z) (!e->match.x || \
30 ((e->x.a4.s_addr == (e->y.a4.s_addr & (z))) \
31 ^ e->invert.x))
32#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
33
34 return MATCH_ADDR(saddr, smask, x->props.saddr.a4) &&
35 MATCH_ADDR(daddr, dmask, x->id.daddr.a4) &&
36 MATCH(proto, x->id.proto) &&
37 MATCH(mode, x->props.mode) &&
38 MATCH(spi, x->id.spi) &&
39 MATCH(reqid, x->props.reqid);
40}
41
42static int
43match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
44{
45 const struct ipt_policy_elem *e;
46 struct sec_path *sp = skb->sp;
47 int strict = info->flags & IPT_POLICY_MATCH_STRICT;
48 int i, pos;
49
50 if (sp == NULL)
51 return -1;
52 if (strict && info->len != sp->len)
53 return 0;
54
55 for (i = sp->len - 1; i >= 0; i--) {
56 pos = strict ? i - sp->len + 1 : 0;
57 if (pos >= info->len)
58 return 0;
59 e = &info->pol[pos];
60
61 if (match_xfrm_state(sp->x[i].xvec, e)) {
62 if (!strict)
63 return 1;
64 } else if (strict)
65 return 0;
66 }
67
68 return strict ? 1 : 0;
69}
70
71static int
72match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
73{
74 const struct ipt_policy_elem *e;
75 struct dst_entry *dst = skb->dst;
76 int strict = info->flags & IPT_POLICY_MATCH_STRICT;
77 int i, pos;
78
79 if (dst->xfrm == NULL)
80 return -1;
81
82 for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
83 pos = strict ? i : 0;
84 if (pos >= info->len)
85 return 0;
86 e = &info->pol[pos];
87
88 if (match_xfrm_state(dst->xfrm, e)) {
89 if (!strict)
90 return 1;
91 } else if (strict)
92 return 0;
93 }
94
95 return strict ? i == info->len : 0;
96}
97
98static int match(const struct sk_buff *skb,
99 const struct net_device *in,
100 const struct net_device *out,
101 const void *matchinfo,
102 int offset,
103 unsigned int protoff,
104 int *hotdrop)
105{
106 const struct ipt_policy_info *info = matchinfo;
107 int ret;
108
109 if (info->flags & IPT_POLICY_MATCH_IN)
110 ret = match_policy_in(skb, info);
111 else
112 ret = match_policy_out(skb, info);
113
114 if (ret < 0)
115 ret = info->flags & IPT_POLICY_MATCH_NONE ? 1 : 0;
116 else if (info->flags & IPT_POLICY_MATCH_NONE)
117 ret = 0;
118
119 return ret;
120}
121
122static int checkentry(const char *tablename, const void *ip_void,
123 void *matchinfo, unsigned int matchsize,
124 unsigned int hook_mask)
125{
126 struct ipt_policy_info *info = matchinfo;
127
128 if (matchsize != IPT_ALIGN(sizeof(*info))) {
129 printk(KERN_ERR "ipt_policy: matchsize %u != %zu\n",
130 matchsize, IPT_ALIGN(sizeof(*info)));
131 return 0;
132 }
133 if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))) {
134 printk(KERN_ERR "ipt_policy: neither incoming nor "
135 "outgoing policy selected\n");
136 return 0;
137 }
138 if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
139 && info->flags & IPT_POLICY_MATCH_OUT) {
140 printk(KERN_ERR "ipt_policy: output policy not valid in "
141 "PRE_ROUTING and INPUT\n");
142 return 0;
143 }
144 if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
145 && info->flags & IPT_POLICY_MATCH_IN) {
146 printk(KERN_ERR "ipt_policy: input policy not valid in "
147 "POST_ROUTING and OUTPUT\n");
148 return 0;
149 }
150 if (info->len > IPT_POLICY_MAX_ELEM) {
151 printk(KERN_ERR "ipt_policy: too many policy elements\n");
152 return 0;
153 }
154
155 return 1;
156}
157
158static struct ipt_match policy_match = {
159 .name = "policy",
160 .match = match,
161 .checkentry = checkentry,
162 .me = THIS_MODULE,
163};
164
165static int __init init(void)
166{
167 return ipt_register_match(&policy_match);
168}
169
170static void __exit fini(void)
171{
172 ipt_unregister_match(&policy_match);
173}
174
175module_init(init);
176module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 44611d6d14f5..06792ead1da4 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -102,6 +102,7 @@ static int
102match(const struct sk_buff *skb, 102match(const struct sk_buff *skb,
103 const struct net_device *in, 103 const struct net_device *in,
104 const struct net_device *out, 104 const struct net_device *out,
105 const struct xt_match *match,
105 const void *matchinfo, 106 const void *matchinfo,
106 int offset, 107 int offset,
107 unsigned int protoff, 108 unsigned int protoff,
@@ -318,7 +319,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned
318 skb->nh.iph->daddr = 0; 319 skb->nh.iph->daddr = 0;
319 /* Clear ttl since we have no way of knowing it */ 320 /* Clear ttl since we have no way of knowing it */
320 skb->nh.iph->ttl = 0; 321 skb->nh.iph->ttl = 0;
321 match(skb,NULL,NULL,info,0,0,NULL); 322 match(skb,NULL,NULL,NULL,info,0,0,NULL);
322 323
323 kfree(skb->nh.iph); 324 kfree(skb->nh.iph);
324out_free_skb: 325out_free_skb:
@@ -356,6 +357,7 @@ static int
356match(const struct sk_buff *skb, 357match(const struct sk_buff *skb,
357 const struct net_device *in, 358 const struct net_device *in,
358 const struct net_device *out, 359 const struct net_device *out,
360 const struct xt_match *match,
359 const void *matchinfo, 361 const void *matchinfo,
360 int offset, 362 int offset,
361 unsigned int protoff, 363 unsigned int protoff,
@@ -657,6 +659,7 @@ match(const struct sk_buff *skb,
657static int 659static int
658checkentry(const char *tablename, 660checkentry(const char *tablename,
659 const void *ip, 661 const void *ip,
662 const struct xt_match *match,
660 void *matchinfo, 663 void *matchinfo,
661 unsigned int matchsize, 664 unsigned int matchsize,
662 unsigned int hook_mask) 665 unsigned int hook_mask)
@@ -670,8 +673,6 @@ checkentry(const char *tablename,
670 if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n"); 673 if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
671#endif 674#endif
672 675
673 if (matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return 0;
674
675 /* seconds and hit_count only valid for CHECK/UPDATE */ 676 /* seconds and hit_count only valid for CHECK/UPDATE */
676 if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; } 677 if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
677 if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; } 678 if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
@@ -871,7 +872,7 @@ checkentry(const char *tablename,
871 * up its memory. 872 * up its memory.
872 */ 873 */
873static void 874static void
874destroy(void *matchinfo, unsigned int matchsize) 875destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
875{ 876{
876 const struct ipt_recent_info *info = matchinfo; 877 const struct ipt_recent_info *info = matchinfo;
877 struct recent_ip_tables *curr_table, *last_table; 878 struct recent_ip_tables *curr_table, *last_table;
@@ -951,12 +952,13 @@ destroy(void *matchinfo, unsigned int matchsize)
951/* This is the structure we pass to ipt_register to register our 952/* This is the structure we pass to ipt_register to register our
952 * module with iptables. 953 * module with iptables.
953 */ 954 */
954static struct ipt_match recent_match = { 955static struct ipt_match recent_match = {
955 .name = "recent", 956 .name = "recent",
956 .match = &match, 957 .match = match,
957 .checkentry = &checkentry, 958 .matchsize = sizeof(struct ipt_recent_info),
958 .destroy = &destroy, 959 .checkentry = checkentry,
959 .me = THIS_MODULE 960 .destroy = destroy,
961 .me = THIS_MODULE
960}; 962};
961 963
962/* Kernel module initialization. */ 964/* Kernel module initialization. */
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 9ab765e126f2..e404e92ddd01 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -21,6 +21,7 @@ static int
21match(const struct sk_buff *skb, 21match(const struct sk_buff *skb,
22 const struct net_device *in, 22 const struct net_device *in,
23 const struct net_device *out, 23 const struct net_device *out,
24 const struct xt_match *match,
24 const void *matchinfo, 25 const void *matchinfo,
25 int offset, 26 int offset,
26 unsigned int protoff, 27 unsigned int protoff,
@@ -31,23 +32,10 @@ match(const struct sk_buff *skb,
31 return (skb->nh.iph->tos == info->tos) ^ info->invert; 32 return (skb->nh.iph->tos == info->tos) ^ info->invert;
32} 33}
33 34
34static int
35checkentry(const char *tablename,
36 const void *ip,
37 void *matchinfo,
38 unsigned int matchsize,
39 unsigned int hook_mask)
40{
41 if (matchsize != IPT_ALIGN(sizeof(struct ipt_tos_info)))
42 return 0;
43
44 return 1;
45}
46
47static struct ipt_match tos_match = { 35static struct ipt_match tos_match = {
48 .name = "tos", 36 .name = "tos",
49 .match = &match, 37 .match = match,
50 .checkentry = &checkentry, 38 .matchsize = sizeof(struct ipt_tos_info),
51 .me = THIS_MODULE, 39 .me = THIS_MODULE,
52}; 40};
53 41
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index 82da53f430ab..ae7ce4d8d90e 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -19,8 +19,9 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("IP tables TTL matching module"); 19MODULE_DESCRIPTION("IP tables TTL matching module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21 21
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static int match(const struct sk_buff *skb,
23 const struct net_device *out, const void *matchinfo, 23 const struct net_device *in, const struct net_device *out,
24 const struct xt_match *match, const void *matchinfo,
24 int offset, unsigned int protoff, int *hotdrop) 25 int offset, unsigned int protoff, int *hotdrop)
25{ 26{
26 const struct ipt_ttl_info *info = matchinfo; 27 const struct ipt_ttl_info *info = matchinfo;
@@ -47,20 +48,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
47 return 0; 48 return 0;
48} 49}
49 50
50static int checkentry(const char *tablename, const void *ip,
51 void *matchinfo, unsigned int matchsize,
52 unsigned int hook_mask)
53{
54 if (matchsize != IPT_ALIGN(sizeof(struct ipt_ttl_info)))
55 return 0;
56
57 return 1;
58}
59
60static struct ipt_match ttl_match = { 51static struct ipt_match ttl_match = {
61 .name = "ttl", 52 .name = "ttl",
62 .match = &match, 53 .match = match,
63 .checkentry = &checkentry, 54 .matchsize = sizeof(struct ipt_ttl_info),
64 .me = THIS_MODULE, 55 .me = THIS_MODULE,
65}; 56};
66 57
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 6c8624a54933..c8abc9d859b9 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -141,19 +141,21 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
141{ 141{
142 struct nf_conn *ct; 142 struct nf_conn *ct;
143 enum ip_conntrack_info ctinfo; 143 enum ip_conntrack_info ctinfo;
144 struct nf_conn_help *help;
144 145
145 /* This is where we call the helper: as the packet goes out. */ 146 /* This is where we call the helper: as the packet goes out. */
146 ct = nf_ct_get(*pskb, &ctinfo); 147 ct = nf_ct_get(*pskb, &ctinfo);
147 if (ct && ct->helper) { 148 if (!ct)
148 unsigned int ret; 149 return NF_ACCEPT;
149 ret = ct->helper->help(pskb, 150
150 (*pskb)->nh.raw - (*pskb)->data 151 help = nfct_help(ct);
151 + (*pskb)->nh.iph->ihl*4, 152 if (!help || !help->helper)
152 ct, ctinfo); 153 return NF_ACCEPT;
153 if (ret != NF_ACCEPT) 154
154 return ret; 155 return help->helper->help(pskb,
155 } 156 (*pskb)->nh.raw - (*pskb)->data
156 return NF_ACCEPT; 157 + (*pskb)->nh.iph->ihl*4,
158 ct, ctinfo);
157} 159}
158 160
159static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 161static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -566,6 +568,7 @@ static int init_or_cleanup(int init)
566 return ret; 568 return ret;
567} 569}
568 570
571MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
569MODULE_LICENSE("GPL"); 572MODULE_LICENSE("GPL");
570 573
571static int __init init(void) 574static int __init init(void)
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index f29a12da5109..fc2562415555 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -660,12 +660,9 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o
660out: return ret; 660out: return ret;
661} 661}
662 662
663static int raw_setsockopt(struct sock *sk, int level, int optname, 663static int do_raw_setsockopt(struct sock *sk, int level, int optname,
664 char __user *optval, int optlen) 664 char __user *optval, int optlen)
665{ 665{
666 if (level != SOL_RAW)
667 return ip_setsockopt(sk, level, optname, optval, optlen);
668
669 if (optname == ICMP_FILTER) { 666 if (optname == ICMP_FILTER) {
670 if (inet_sk(sk)->num != IPPROTO_ICMP) 667 if (inet_sk(sk)->num != IPPROTO_ICMP)
671 return -EOPNOTSUPP; 668 return -EOPNOTSUPP;
@@ -675,12 +672,27 @@ static int raw_setsockopt(struct sock *sk, int level, int optname,
675 return -ENOPROTOOPT; 672 return -ENOPROTOOPT;
676} 673}
677 674
678static int raw_getsockopt(struct sock *sk, int level, int optname, 675static int raw_setsockopt(struct sock *sk, int level, int optname,
679 char __user *optval, int __user *optlen) 676 char __user *optval, int optlen)
680{ 677{
681 if (level != SOL_RAW) 678 if (level != SOL_RAW)
682 return ip_getsockopt(sk, level, optname, optval, optlen); 679 return ip_setsockopt(sk, level, optname, optval, optlen);
680 return do_raw_setsockopt(sk, level, optname, optval, optlen);
681}
683 682
683#ifdef CONFIG_COMPAT
684static int compat_raw_setsockopt(struct sock *sk, int level, int optname,
685 char __user *optval, int optlen)
686{
687 if (level != SOL_RAW)
688 return compat_ip_setsockopt(sk, level, optname, optval, optlen);
689 return do_raw_setsockopt(sk, level, optname, optval, optlen);
690}
691#endif
692
693static int do_raw_getsockopt(struct sock *sk, int level, int optname,
694 char __user *optval, int __user *optlen)
695{
684 if (optname == ICMP_FILTER) { 696 if (optname == ICMP_FILTER) {
685 if (inet_sk(sk)->num != IPPROTO_ICMP) 697 if (inet_sk(sk)->num != IPPROTO_ICMP)
686 return -EOPNOTSUPP; 698 return -EOPNOTSUPP;
@@ -690,6 +702,24 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
690 return -ENOPROTOOPT; 702 return -ENOPROTOOPT;
691} 703}
692 704
705static int raw_getsockopt(struct sock *sk, int level, int optname,
706 char __user *optval, int __user *optlen)
707{
708 if (level != SOL_RAW)
709 return ip_getsockopt(sk, level, optname, optval, optlen);
710 return do_raw_getsockopt(sk, level, optname, optval, optlen);
711}
712
713#ifdef CONFIG_COMPAT
714static int compat_raw_getsockopt(struct sock *sk, int level, int optname,
715 char __user *optval, int __user *optlen)
716{
717 if (level != SOL_RAW)
718 return compat_ip_getsockopt(sk, level, optname, optval, optlen);
719 return do_raw_getsockopt(sk, level, optname, optval, optlen);
720}
721#endif
722
693static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) 723static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
694{ 724{
695 switch (cmd) { 725 switch (cmd) {
@@ -719,22 +749,26 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
719} 749}
720 750
721struct proto raw_prot = { 751struct proto raw_prot = {
722 .name = "RAW", 752 .name = "RAW",
723 .owner = THIS_MODULE, 753 .owner = THIS_MODULE,
724 .close = raw_close, 754 .close = raw_close,
725 .connect = ip4_datagram_connect, 755 .connect = ip4_datagram_connect,
726 .disconnect = udp_disconnect, 756 .disconnect = udp_disconnect,
727 .ioctl = raw_ioctl, 757 .ioctl = raw_ioctl,
728 .init = raw_init, 758 .init = raw_init,
729 .setsockopt = raw_setsockopt, 759 .setsockopt = raw_setsockopt,
730 .getsockopt = raw_getsockopt, 760 .getsockopt = raw_getsockopt,
731 .sendmsg = raw_sendmsg, 761 .sendmsg = raw_sendmsg,
732 .recvmsg = raw_recvmsg, 762 .recvmsg = raw_recvmsg,
733 .bind = raw_bind, 763 .bind = raw_bind,
734 .backlog_rcv = raw_rcv_skb, 764 .backlog_rcv = raw_rcv_skb,
735 .hash = raw_v4_hash, 765 .hash = raw_v4_hash,
736 .unhash = raw_v4_unhash, 766 .unhash = raw_v4_unhash,
737 .obj_size = sizeof(struct raw_sock), 767 .obj_size = sizeof(struct raw_sock),
768#ifdef CONFIG_COMPAT
769 .compat_setsockopt = compat_raw_setsockopt,
770 .compat_getsockopt = compat_raw_getsockopt,
771#endif
738}; 772};
739 773
740#ifdef CONFIG_PROC_FS 774#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 16984d4a8a06..6b6c3adfcf00 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -664,7 +664,30 @@ ctl_table ipv4_table[] = {
664 .mode = 0644, 664 .mode = 0644,
665 .proc_handler = &proc_dointvec, 665 .proc_handler = &proc_dointvec,
666 }, 666 },
667 667 {
668 .ctl_name = NET_TCP_MTU_PROBING,
669 .procname = "tcp_mtu_probing",
670 .data = &sysctl_tcp_mtu_probing,
671 .maxlen = sizeof(int),
672 .mode = 0644,
673 .proc_handler = &proc_dointvec,
674 },
675 {
676 .ctl_name = NET_TCP_BASE_MSS,
677 .procname = "tcp_base_mss",
678 .data = &sysctl_tcp_base_mss,
679 .maxlen = sizeof(int),
680 .mode = 0644,
681 .proc_handler = &proc_dointvec,
682 },
683 {
684 .ctl_name = NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS,
685 .procname = "tcp_workaround_signed_windows",
686 .data = &sysctl_tcp_workaround_signed_windows,
687 .maxlen = sizeof(int),
688 .mode = 0644,
689 .proc_handler = &proc_dointvec
690 },
668 { .ctl_name = 0 } 691 { .ctl_name = 0 }
669}; 692};
670 693
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 00aa80e93243..4b0272c92d66 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1687,18 +1687,14 @@ int tcp_disconnect(struct sock *sk, int flags)
1687/* 1687/*
1688 * Socket option code for TCP. 1688 * Socket option code for TCP.
1689 */ 1689 */
1690int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, 1690static int do_tcp_setsockopt(struct sock *sk, int level,
1691 int optlen) 1691 int optname, char __user *optval, int optlen)
1692{ 1692{
1693 struct tcp_sock *tp = tcp_sk(sk); 1693 struct tcp_sock *tp = tcp_sk(sk);
1694 struct inet_connection_sock *icsk = inet_csk(sk); 1694 struct inet_connection_sock *icsk = inet_csk(sk);
1695 int val; 1695 int val;
1696 int err = 0; 1696 int err = 0;
1697 1697
1698 if (level != SOL_TCP)
1699 return icsk->icsk_af_ops->setsockopt(sk, level, optname,
1700 optval, optlen);
1701
1702 /* This is a string value all the others are int's */ 1698 /* This is a string value all the others are int's */
1703 if (optname == TCP_CONGESTION) { 1699 if (optname == TCP_CONGESTION) {
1704 char name[TCP_CA_NAME_MAX]; 1700 char name[TCP_CA_NAME_MAX];
@@ -1871,6 +1867,30 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
1871 return err; 1867 return err;
1872} 1868}
1873 1869
1870int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
1871 int optlen)
1872{
1873 struct inet_connection_sock *icsk = inet_csk(sk);
1874
1875 if (level != SOL_TCP)
1876 return icsk->icsk_af_ops->setsockopt(sk, level, optname,
1877 optval, optlen);
1878 return do_tcp_setsockopt(sk, level, optname, optval, optlen);
1879}
1880
1881#ifdef CONFIG_COMPAT
1882int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
1883 char __user *optval, int optlen)
1884{
1885 if (level != SOL_TCP)
1886 return inet_csk_compat_setsockopt(sk, level, optname,
1887 optval, optlen);
1888 return do_tcp_setsockopt(sk, level, optname, optval, optlen);
1889}
1890
1891EXPORT_SYMBOL(compat_tcp_setsockopt);
1892#endif
1893
1874/* Return information about state of tcp endpoint in API format. */ 1894/* Return information about state of tcp endpoint in API format. */
1875void tcp_get_info(struct sock *sk, struct tcp_info *info) 1895void tcp_get_info(struct sock *sk, struct tcp_info *info)
1876{ 1896{
@@ -1931,17 +1951,13 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
1931 1951
1932EXPORT_SYMBOL_GPL(tcp_get_info); 1952EXPORT_SYMBOL_GPL(tcp_get_info);
1933 1953
1934int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, 1954static int do_tcp_getsockopt(struct sock *sk, int level,
1935 int __user *optlen) 1955 int optname, char __user *optval, int __user *optlen)
1936{ 1956{
1937 struct inet_connection_sock *icsk = inet_csk(sk); 1957 struct inet_connection_sock *icsk = inet_csk(sk);
1938 struct tcp_sock *tp = tcp_sk(sk); 1958 struct tcp_sock *tp = tcp_sk(sk);
1939 int val, len; 1959 int val, len;
1940 1960
1941 if (level != SOL_TCP)
1942 return icsk->icsk_af_ops->getsockopt(sk, level, optname,
1943 optval, optlen);
1944
1945 if (get_user(len, optlen)) 1961 if (get_user(len, optlen))
1946 return -EFAULT; 1962 return -EFAULT;
1947 1963
@@ -2025,6 +2041,29 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
2025 return 0; 2041 return 0;
2026} 2042}
2027 2043
2044int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
2045 int __user *optlen)
2046{
2047 struct inet_connection_sock *icsk = inet_csk(sk);
2048
2049 if (level != SOL_TCP)
2050 return icsk->icsk_af_ops->getsockopt(sk, level, optname,
2051 optval, optlen);
2052 return do_tcp_getsockopt(sk, level, optname, optval, optlen);
2053}
2054
2055#ifdef CONFIG_COMPAT
2056int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
2057 char __user *optval, int __user *optlen)
2058{
2059 if (level != SOL_TCP)
2060 return inet_csk_compat_getsockopt(sk, level, optname,
2061 optval, optlen);
2062 return do_tcp_getsockopt(sk, level, optname, optval, optlen);
2063}
2064
2065EXPORT_SYMBOL(compat_tcp_getsockopt);
2066#endif
2028 2067
2029extern void __skb_cb_too_small_for_tcp(int, int); 2068extern void __skb_cb_too_small_for_tcp(int, int);
2030extern struct tcp_congestion_ops tcp_reno; 2069extern struct tcp_congestion_ops tcp_reno;
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 128de4d7c0b7..1b2ff53f98ed 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -27,12 +27,12 @@ struct htcp {
27 u16 alpha; /* Fixed point arith, << 7 */ 27 u16 alpha; /* Fixed point arith, << 7 */
28 u8 beta; /* Fixed point arith, << 7 */ 28 u8 beta; /* Fixed point arith, << 7 */
29 u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */ 29 u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */
30 u8 ccount; /* Number of RTTs since last congestion event */ 30 u32 last_cong; /* Time since last congestion event end */
31 u8 undo_ccount; 31 u32 undo_last_cong;
32 u16 packetcount; 32 u16 pkts_acked;
33 u32 packetcount;
33 u32 minRTT; 34 u32 minRTT;
34 u32 maxRTT; 35 u32 maxRTT;
35 u32 snd_cwnd_cnt2;
36 36
37 u32 undo_maxRTT; 37 u32 undo_maxRTT;
38 u32 undo_old_maxB; 38 u32 undo_old_maxB;
@@ -45,21 +45,30 @@ struct htcp {
45 u32 lasttime; 45 u32 lasttime;
46}; 46};
47 47
48static inline u32 htcp_cong_time(struct htcp *ca)
49{
50 return jiffies - ca->last_cong;
51}
52
53static inline u32 htcp_ccount(struct htcp *ca)
54{
55 return htcp_cong_time(ca)/ca->minRTT;
56}
57
48static inline void htcp_reset(struct htcp *ca) 58static inline void htcp_reset(struct htcp *ca)
49{ 59{
50 ca->undo_ccount = ca->ccount; 60 ca->undo_last_cong = ca->last_cong;
51 ca->undo_maxRTT = ca->maxRTT; 61 ca->undo_maxRTT = ca->maxRTT;
52 ca->undo_old_maxB = ca->old_maxB; 62 ca->undo_old_maxB = ca->old_maxB;
53 63
54 ca->ccount = 0; 64 ca->last_cong = jiffies;
55 ca->snd_cwnd_cnt2 = 0;
56} 65}
57 66
58static u32 htcp_cwnd_undo(struct sock *sk) 67static u32 htcp_cwnd_undo(struct sock *sk)
59{ 68{
60 const struct tcp_sock *tp = tcp_sk(sk); 69 const struct tcp_sock *tp = tcp_sk(sk);
61 struct htcp *ca = inet_csk_ca(sk); 70 struct htcp *ca = inet_csk_ca(sk);
62 ca->ccount = ca->undo_ccount; 71 ca->last_cong = ca->undo_last_cong;
63 ca->maxRTT = ca->undo_maxRTT; 72 ca->maxRTT = ca->undo_maxRTT;
64 ca->old_maxB = ca->undo_old_maxB; 73 ca->old_maxB = ca->undo_old_maxB;
65 return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta); 74 return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta);
@@ -77,10 +86,10 @@ static inline void measure_rtt(struct sock *sk)
77 ca->minRTT = srtt; 86 ca->minRTT = srtt;
78 87
79 /* max RTT */ 88 /* max RTT */
80 if (icsk->icsk_ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && ca->ccount > 3) { 89 if (icsk->icsk_ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && htcp_ccount(ca) > 3) {
81 if (ca->maxRTT < ca->minRTT) 90 if (ca->maxRTT < ca->minRTT)
82 ca->maxRTT = ca->minRTT; 91 ca->maxRTT = ca->minRTT;
83 if (ca->maxRTT < srtt && srtt <= ca->maxRTT+HZ/50) 92 if (ca->maxRTT < srtt && srtt <= ca->maxRTT+msecs_to_jiffies(20))
84 ca->maxRTT = srtt; 93 ca->maxRTT = srtt;
85 } 94 }
86} 95}
@@ -92,6 +101,12 @@ static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked)
92 struct htcp *ca = inet_csk_ca(sk); 101 struct htcp *ca = inet_csk_ca(sk);
93 u32 now = tcp_time_stamp; 102 u32 now = tcp_time_stamp;
94 103
104 if (icsk->icsk_ca_state == TCP_CA_Open)
105 ca->pkts_acked = pkts_acked;
106
107 if (!use_bandwidth_switch)
108 return;
109
95 /* achieved throughput calculations */ 110 /* achieved throughput calculations */
96 if (icsk->icsk_ca_state != TCP_CA_Open && 111 if (icsk->icsk_ca_state != TCP_CA_Open &&
97 icsk->icsk_ca_state != TCP_CA_Disorder) { 112 icsk->icsk_ca_state != TCP_CA_Disorder) {
@@ -106,7 +121,7 @@ static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked)
106 && now - ca->lasttime >= ca->minRTT 121 && now - ca->lasttime >= ca->minRTT
107 && ca->minRTT > 0) { 122 && ca->minRTT > 0) {
108 __u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime); 123 __u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime);
109 if (ca->ccount <= 3) { 124 if (htcp_ccount(ca) <= 3) {
110 /* just after backoff */ 125 /* just after backoff */
111 ca->minB = ca->maxB = ca->Bi = cur_Bi; 126 ca->minB = ca->maxB = ca->Bi = cur_Bi;
112 } else { 127 } else {
@@ -135,7 +150,7 @@ static inline void htcp_beta_update(struct htcp *ca, u32 minRTT, u32 maxRTT)
135 } 150 }
136 } 151 }
137 152
138 if (ca->modeswitch && minRTT > max(HZ/100, 1) && maxRTT) { 153 if (ca->modeswitch && minRTT > msecs_to_jiffies(10) && maxRTT) {
139 ca->beta = (minRTT<<7)/maxRTT; 154 ca->beta = (minRTT<<7)/maxRTT;
140 if (ca->beta < BETA_MIN) 155 if (ca->beta < BETA_MIN)
141 ca->beta = BETA_MIN; 156 ca->beta = BETA_MIN;
@@ -151,7 +166,7 @@ static inline void htcp_alpha_update(struct htcp *ca)
151{ 166{
152 u32 minRTT = ca->minRTT; 167 u32 minRTT = ca->minRTT;
153 u32 factor = 1; 168 u32 factor = 1;
154 u32 diff = ca->ccount * minRTT; /* time since last backoff */ 169 u32 diff = htcp_cong_time(ca);
155 170
156 if (diff > HZ) { 171 if (diff > HZ) {
157 diff -= HZ; 172 diff -= HZ;
@@ -216,21 +231,18 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
216 231
217 measure_rtt(sk); 232 measure_rtt(sk);
218 233
219 /* keep track of number of round-trip times since last backoff event */
220 if (ca->snd_cwnd_cnt2++ > tp->snd_cwnd) {
221 ca->ccount++;
222 ca->snd_cwnd_cnt2 = 0;
223 htcp_alpha_update(ca);
224 }
225
226 /* In dangerous area, increase slowly. 234 /* In dangerous area, increase slowly.
227 * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd 235 * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd
228 */ 236 */
229 if ((tp->snd_cwnd_cnt++ * ca->alpha)>>7 >= tp->snd_cwnd) { 237 if ((tp->snd_cwnd_cnt * ca->alpha)>>7 >= tp->snd_cwnd) {
230 if (tp->snd_cwnd < tp->snd_cwnd_clamp) 238 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
231 tp->snd_cwnd++; 239 tp->snd_cwnd++;
232 tp->snd_cwnd_cnt = 0; 240 tp->snd_cwnd_cnt = 0;
233 } 241 htcp_alpha_update(ca);
242 } else
243 tp->snd_cwnd_cnt += ca->pkts_acked;
244
245 ca->pkts_acked = 1;
234 } 246 }
235} 247}
236 248
@@ -249,11 +261,19 @@ static void htcp_init(struct sock *sk)
249 memset(ca, 0, sizeof(struct htcp)); 261 memset(ca, 0, sizeof(struct htcp));
250 ca->alpha = ALPHA_BASE; 262 ca->alpha = ALPHA_BASE;
251 ca->beta = BETA_MIN; 263 ca->beta = BETA_MIN;
264 ca->pkts_acked = 1;
265 ca->last_cong = jiffies;
252} 266}
253 267
254static void htcp_state(struct sock *sk, u8 new_state) 268static void htcp_state(struct sock *sk, u8 new_state)
255{ 269{
256 switch (new_state) { 270 switch (new_state) {
271 case TCP_CA_Open:
272 {
273 struct htcp *ca = inet_csk_ca(sk);
274 ca->last_cong = jiffies;
275 }
276 break;
257 case TCP_CA_CWR: 277 case TCP_CA_CWR:
258 case TCP_CA_Recovery: 278 case TCP_CA_Recovery:
259 case TCP_CA_Loss: 279 case TCP_CA_Loss:
@@ -278,8 +298,6 @@ static int __init htcp_register(void)
278{ 298{
279 BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE); 299 BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE);
280 BUILD_BUG_ON(BETA_MIN >= BETA_MAX); 300 BUILD_BUG_ON(BETA_MIN >= BETA_MAX);
281 if (!use_bandwidth_switch)
282 htcp.pkts_acked = NULL;
283 return tcp_register_congestion_control(&htcp); 301 return tcp_register_congestion_control(&htcp);
284} 302}
285 303
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e9a54ae7d690..195d83584558 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1891,6 +1891,34 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
1891 } 1891 }
1892} 1892}
1893 1893
1894static void tcp_mtup_probe_failed(struct sock *sk)
1895{
1896 struct inet_connection_sock *icsk = inet_csk(sk);
1897
1898 icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1;
1899 icsk->icsk_mtup.probe_size = 0;
1900}
1901
1902static void tcp_mtup_probe_success(struct sock *sk, struct sk_buff *skb)
1903{
1904 struct tcp_sock *tp = tcp_sk(sk);
1905 struct inet_connection_sock *icsk = inet_csk(sk);
1906
1907 /* FIXME: breaks with very large cwnd */
1908 tp->prior_ssthresh = tcp_current_ssthresh(sk);
1909 tp->snd_cwnd = tp->snd_cwnd *
1910 tcp_mss_to_mtu(sk, tp->mss_cache) /
1911 icsk->icsk_mtup.probe_size;
1912 tp->snd_cwnd_cnt = 0;
1913 tp->snd_cwnd_stamp = tcp_time_stamp;
1914 tp->rcv_ssthresh = tcp_current_ssthresh(sk);
1915
1916 icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size;
1917 icsk->icsk_mtup.probe_size = 0;
1918 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
1919}
1920
1921
1894/* Process an event, which can update packets-in-flight not trivially. 1922/* Process an event, which can update packets-in-flight not trivially.
1895 * Main goal of this function is to calculate new estimate for left_out, 1923 * Main goal of this function is to calculate new estimate for left_out,
1896 * taking into account both packets sitting in receiver's buffer and 1924 * taking into account both packets sitting in receiver's buffer and
@@ -2023,6 +2051,17 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
2023 return; 2051 return;
2024 } 2052 }
2025 2053
2054 /* MTU probe failure: don't reduce cwnd */
2055 if (icsk->icsk_ca_state < TCP_CA_CWR &&
2056 icsk->icsk_mtup.probe_size &&
2057 tp->snd_una == tp->mtu_probe.probe_seq_start) {
2058 tcp_mtup_probe_failed(sk);
2059 /* Restores the reduction we did in tcp_mtup_probe() */
2060 tp->snd_cwnd++;
2061 tcp_simple_retransmit(sk);
2062 return;
2063 }
2064
2026 /* Otherwise enter Recovery state */ 2065 /* Otherwise enter Recovery state */
2027 2066
2028 if (IsReno(tp)) 2067 if (IsReno(tp))
@@ -2243,6 +2282,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
2243 tp->retrans_stamp = 0; 2282 tp->retrans_stamp = 0;
2244 } 2283 }
2245 2284
2285 /* MTU probing checks */
2286 if (icsk->icsk_mtup.probe_size) {
2287 if (!after(tp->mtu_probe.probe_seq_end, TCP_SKB_CB(skb)->end_seq)) {
2288 tcp_mtup_probe_success(sk, skb);
2289 }
2290 }
2291
2246 if (sacked) { 2292 if (sacked) {
2247 if (sacked & TCPCB_RETRANS) { 2293 if (sacked & TCPCB_RETRANS) {
2248 if(sacked & TCPCB_SACKED_RETRANS) 2294 if(sacked & TCPCB_SACKED_RETRANS)
@@ -4101,6 +4147,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
4101 if (tp->rx_opt.sack_ok && sysctl_tcp_fack) 4147 if (tp->rx_opt.sack_ok && sysctl_tcp_fack)
4102 tp->rx_opt.sack_ok |= 2; 4148 tp->rx_opt.sack_ok |= 2;
4103 4149
4150 tcp_mtup_init(sk);
4104 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 4151 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
4105 tcp_initialize_rcv_mss(sk); 4152 tcp_initialize_rcv_mss(sk);
4106 4153
@@ -4211,6 +4258,7 @@ discard:
4211 if (tp->ecn_flags&TCP_ECN_OK) 4258 if (tp->ecn_flags&TCP_ECN_OK)
4212 sock_set_flag(sk, SOCK_NO_LARGESEND); 4259 sock_set_flag(sk, SOCK_NO_LARGESEND);
4213 4260
4261 tcp_mtup_init(sk);
4214 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); 4262 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
4215 tcp_initialize_rcv_mss(sk); 4263 tcp_initialize_rcv_mss(sk);
4216 4264
@@ -4399,6 +4447,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
4399 */ 4447 */
4400 tp->lsndtime = tcp_time_stamp; 4448 tp->lsndtime = tcp_time_stamp;
4401 4449
4450 tcp_mtup_init(sk);
4402 tcp_initialize_rcv_mss(sk); 4451 tcp_initialize_rcv_mss(sk);
4403 tcp_init_buffer_space(sk); 4452 tcp_init_buffer_space(sk);
4404 tcp_fast_path_on(tp); 4453 tcp_fast_path_on(tp);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 233bdf259965..9e85c0416109 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -900,6 +900,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
900 inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen; 900 inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
901 newinet->id = newtp->write_seq ^ jiffies; 901 newinet->id = newtp->write_seq ^ jiffies;
902 902
903 tcp_mtup_init(newsk);
903 tcp_sync_mss(newsk, dst_mtu(dst)); 904 tcp_sync_mss(newsk, dst_mtu(dst));
904 newtp->advmss = dst_metric(dst, RTAX_ADVMSS); 905 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
905 tcp_initialize_rcv_mss(newsk); 906 tcp_initialize_rcv_mss(newsk);
@@ -1216,17 +1217,21 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
1216} 1217}
1217 1218
1218struct inet_connection_sock_af_ops ipv4_specific = { 1219struct inet_connection_sock_af_ops ipv4_specific = {
1219 .queue_xmit = ip_queue_xmit, 1220 .queue_xmit = ip_queue_xmit,
1220 .send_check = tcp_v4_send_check, 1221 .send_check = tcp_v4_send_check,
1221 .rebuild_header = inet_sk_rebuild_header, 1222 .rebuild_header = inet_sk_rebuild_header,
1222 .conn_request = tcp_v4_conn_request, 1223 .conn_request = tcp_v4_conn_request,
1223 .syn_recv_sock = tcp_v4_syn_recv_sock, 1224 .syn_recv_sock = tcp_v4_syn_recv_sock,
1224 .remember_stamp = tcp_v4_remember_stamp, 1225 .remember_stamp = tcp_v4_remember_stamp,
1225 .net_header_len = sizeof(struct iphdr), 1226 .net_header_len = sizeof(struct iphdr),
1226 .setsockopt = ip_setsockopt, 1227 .setsockopt = ip_setsockopt,
1227 .getsockopt = ip_getsockopt, 1228 .getsockopt = ip_getsockopt,
1228 .addr2sockaddr = inet_csk_addr2sockaddr, 1229 .addr2sockaddr = inet_csk_addr2sockaddr,
1229 .sockaddr_len = sizeof(struct sockaddr_in), 1230 .sockaddr_len = sizeof(struct sockaddr_in),
1231#ifdef CONFIG_COMPAT
1232 .compat_setsockopt = compat_ip_setsockopt,
1233 .compat_getsockopt = compat_ip_getsockopt,
1234#endif
1230}; 1235};
1231 1236
1232/* NOTE: A lot of things set to zero explicitly by call to 1237/* NOTE: A lot of things set to zero explicitly by call to
@@ -1825,23 +1830,16 @@ struct proto tcp_prot = {
1825 .obj_size = sizeof(struct tcp_sock), 1830 .obj_size = sizeof(struct tcp_sock),
1826 .twsk_prot = &tcp_timewait_sock_ops, 1831 .twsk_prot = &tcp_timewait_sock_ops,
1827 .rsk_prot = &tcp_request_sock_ops, 1832 .rsk_prot = &tcp_request_sock_ops,
1833#ifdef CONFIG_COMPAT
1834 .compat_setsockopt = compat_tcp_setsockopt,
1835 .compat_getsockopt = compat_tcp_getsockopt,
1836#endif
1828}; 1837};
1829 1838
1830
1831
1832void __init tcp_v4_init(struct net_proto_family *ops) 1839void __init tcp_v4_init(struct net_proto_family *ops)
1833{ 1840{
1834 int err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket); 1841 if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0)
1835 if (err < 0)
1836 panic("Failed to create the TCP control socket.\n"); 1842 panic("Failed to create the TCP control socket.\n");
1837 tcp_socket->sk->sk_allocation = GFP_ATOMIC;
1838 inet_sk(tcp_socket->sk)->uc_ttl = -1;
1839
1840 /* Unhash it so that IP input processing does not even
1841 * see it, we do not wish this socket to see incoming
1842 * packets.
1843 */
1844 tcp_socket->sk->sk_prot->unhash(tcp_socket->sk);
1845} 1843}
1846 1844
1847EXPORT_SYMBOL(ipv4_specific); 1845EXPORT_SYMBOL(ipv4_specific);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9f498a6c8895..9d79546d384e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -45,12 +45,23 @@
45/* People can turn this off for buggy TCP's found in printers etc. */ 45/* People can turn this off for buggy TCP's found in printers etc. */
46int sysctl_tcp_retrans_collapse = 1; 46int sysctl_tcp_retrans_collapse = 1;
47 47
48/* People can turn this on to work with those rare, broken TCPs that
49 * interpret the window field as a signed quantity.
50 */
51int sysctl_tcp_workaround_signed_windows = 0;
52
48/* This limits the percentage of the congestion window which we 53/* This limits the percentage of the congestion window which we
49 * will allow a single TSO frame to consume. Building TSO frames 54 * will allow a single TSO frame to consume. Building TSO frames
50 * which are too large can cause TCP streams to be bursty. 55 * which are too large can cause TCP streams to be bursty.
51 */ 56 */
52int sysctl_tcp_tso_win_divisor = 3; 57int sysctl_tcp_tso_win_divisor = 3;
53 58
59int sysctl_tcp_mtu_probing = 0;
60int sysctl_tcp_base_mss = 512;
61
62EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
63EXPORT_SYMBOL(sysctl_tcp_base_mss);
64
54static void update_send_head(struct sock *sk, struct tcp_sock *tp, 65static void update_send_head(struct sock *sk, struct tcp_sock *tp,
55 struct sk_buff *skb) 66 struct sk_buff *skb)
56{ 67{
@@ -171,12 +182,18 @@ void tcp_select_initial_window(int __space, __u32 mss,
171 space = (space / mss) * mss; 182 space = (space / mss) * mss;
172 183
173 /* NOTE: offering an initial window larger than 32767 184 /* NOTE: offering an initial window larger than 32767
174 * will break some buggy TCP stacks. We try to be nice. 185 * will break some buggy TCP stacks. If the admin tells us
175 * If we are not window scaling, then this truncates 186 * it is likely we could be speaking with such a buggy stack
176 * our initial window offering to 32k. There should also 187 * we will truncate our initial window offering to 32K-1
177 * be a sysctl option to stop being nice. 188 * unless the remote has sent us a window scaling option,
189 * which we interpret as a sign the remote TCP is not
190 * misinterpreting the window field as a signed quantity.
178 */ 191 */
179 (*rcv_wnd) = min(space, MAX_TCP_WINDOW); 192 if (sysctl_tcp_workaround_signed_windows)
193 (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
194 else
195 (*rcv_wnd) = space;
196
180 (*rcv_wscale) = 0; 197 (*rcv_wscale) = 0;
181 if (wscale_ok) { 198 if (wscale_ok) {
182 /* Set window scaling on max possible window 199 /* Set window scaling on max possible window
@@ -235,7 +252,7 @@ static u16 tcp_select_window(struct sock *sk)
235 /* Make sure we do not exceed the maximum possible 252 /* Make sure we do not exceed the maximum possible
236 * scaled window. 253 * scaled window.
237 */ 254 */
238 if (!tp->rx_opt.rcv_wscale) 255 if (!tp->rx_opt.rcv_wscale && sysctl_tcp_workaround_signed_windows)
239 new_win = min(new_win, MAX_TCP_WINDOW); 256 new_win = min(new_win, MAX_TCP_WINDOW);
240 else 257 else
241 new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale)); 258 new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale));
@@ -681,6 +698,62 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
681 return 0; 698 return 0;
682} 699}
683 700
701/* Not accounting for SACKs here. */
702int tcp_mtu_to_mss(struct sock *sk, int pmtu)
703{
704 struct tcp_sock *tp = tcp_sk(sk);
705 struct inet_connection_sock *icsk = inet_csk(sk);
706 int mss_now;
707
708 /* Calculate base mss without TCP options:
709 It is MMS_S - sizeof(tcphdr) of rfc1122
710 */
711 mss_now = pmtu - icsk->icsk_af_ops->net_header_len - sizeof(struct tcphdr);
712
713 /* Clamp it (mss_clamp does not include tcp options) */
714 if (mss_now > tp->rx_opt.mss_clamp)
715 mss_now = tp->rx_opt.mss_clamp;
716
717 /* Now subtract optional transport overhead */
718 mss_now -= icsk->icsk_ext_hdr_len;
719
720 /* Then reserve room for full set of TCP options and 8 bytes of data */
721 if (mss_now < 48)
722 mss_now = 48;
723
724 /* Now subtract TCP options size, not including SACKs */
725 mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
726
727 return mss_now;
728}
729
730/* Inverse of above */
731int tcp_mss_to_mtu(struct sock *sk, int mss)
732{
733 struct tcp_sock *tp = tcp_sk(sk);
734 struct inet_connection_sock *icsk = inet_csk(sk);
735 int mtu;
736
737 mtu = mss +
738 tp->tcp_header_len +
739 icsk->icsk_ext_hdr_len +
740 icsk->icsk_af_ops->net_header_len;
741
742 return mtu;
743}
744
745void tcp_mtup_init(struct sock *sk)
746{
747 struct tcp_sock *tp = tcp_sk(sk);
748 struct inet_connection_sock *icsk = inet_csk(sk);
749
750 icsk->icsk_mtup.enabled = sysctl_tcp_mtu_probing > 1;
751 icsk->icsk_mtup.search_high = tp->rx_opt.mss_clamp + sizeof(struct tcphdr) +
752 icsk->icsk_af_ops->net_header_len;
753 icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, sysctl_tcp_base_mss);
754 icsk->icsk_mtup.probe_size = 0;
755}
756
684/* This function synchronize snd mss to current pmtu/exthdr set. 757/* This function synchronize snd mss to current pmtu/exthdr set.
685 758
686 tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts 759 tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
@@ -708,25 +781,12 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
708{ 781{
709 struct tcp_sock *tp = tcp_sk(sk); 782 struct tcp_sock *tp = tcp_sk(sk);
710 struct inet_connection_sock *icsk = inet_csk(sk); 783 struct inet_connection_sock *icsk = inet_csk(sk);
711 /* Calculate base mss without TCP options: 784 int mss_now;
712 It is MMS_S - sizeof(tcphdr) of rfc1122
713 */
714 int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -
715 sizeof(struct tcphdr));
716
717 /* Clamp it (mss_clamp does not include tcp options) */
718 if (mss_now > tp->rx_opt.mss_clamp)
719 mss_now = tp->rx_opt.mss_clamp;
720
721 /* Now subtract optional transport overhead */
722 mss_now -= icsk->icsk_ext_hdr_len;
723 785
724 /* Then reserve room for full set of TCP options and 8 bytes of data */ 786 if (icsk->icsk_mtup.search_high > pmtu)
725 if (mss_now < 48) 787 icsk->icsk_mtup.search_high = pmtu;
726 mss_now = 48;
727 788
728 /* Now subtract TCP options size, not including SACKs */ 789 mss_now = tcp_mtu_to_mss(sk, pmtu);
729 mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
730 790
731 /* Bound mss with half of window */ 791 /* Bound mss with half of window */
732 if (tp->max_window && mss_now > (tp->max_window>>1)) 792 if (tp->max_window && mss_now > (tp->max_window>>1))
@@ -734,6 +794,8 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
734 794
735 /* And store cached results */ 795 /* And store cached results */
736 icsk->icsk_pmtu_cookie = pmtu; 796 icsk->icsk_pmtu_cookie = pmtu;
797 if (icsk->icsk_mtup.enabled)
798 mss_now = min(mss_now, tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low));
737 tp->mss_cache = mss_now; 799 tp->mss_cache = mss_now;
738 800
739 return mss_now; 801 return mss_now;
@@ -1063,6 +1125,140 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_
1063 return 1; 1125 return 1;
1064} 1126}
1065 1127
1128/* Create a new MTU probe if we are ready.
1129 * Returns 0 if we should wait to probe (no cwnd available),
1130 * 1 if a probe was sent,
1131 * -1 otherwise */
1132static int tcp_mtu_probe(struct sock *sk)
1133{
1134 struct tcp_sock *tp = tcp_sk(sk);
1135 struct inet_connection_sock *icsk = inet_csk(sk);
1136 struct sk_buff *skb, *nskb, *next;
1137 int len;
1138 int probe_size;
1139 unsigned int pif;
1140 int copy;
1141 int mss_now;
1142
1143 /* Not currently probing/verifying,
1144 * not in recovery,
1145 * have enough cwnd, and
1146 * not SACKing (the variable headers throw things off) */
1147 if (!icsk->icsk_mtup.enabled ||
1148 icsk->icsk_mtup.probe_size ||
1149 inet_csk(sk)->icsk_ca_state != TCP_CA_Open ||
1150 tp->snd_cwnd < 11 ||
1151 tp->rx_opt.eff_sacks)
1152 return -1;
1153
1154 /* Very simple search strategy: just double the MSS. */
1155 mss_now = tcp_current_mss(sk, 0);
1156 probe_size = 2*tp->mss_cache;
1157 if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) {
1158 /* TODO: set timer for probe_converge_event */
1159 return -1;
1160 }
1161
1162 /* Have enough data in the send queue to probe? */
1163 len = 0;
1164 if ((skb = sk->sk_send_head) == NULL)
1165 return -1;
1166 while ((len += skb->len) < probe_size && !tcp_skb_is_last(sk, skb))
1167 skb = skb->next;
1168 if (len < probe_size)
1169 return -1;
1170
1171 /* Receive window check. */
1172 if (after(TCP_SKB_CB(skb)->seq + probe_size, tp->snd_una + tp->snd_wnd)) {
1173 if (tp->snd_wnd < probe_size)
1174 return -1;
1175 else
1176 return 0;
1177 }
1178
1179 /* Do we need to wait to drain cwnd? */
1180 pif = tcp_packets_in_flight(tp);
1181 if (pif + 2 > tp->snd_cwnd) {
1182 /* With no packets in flight, don't stall. */
1183 if (pif == 0)
1184 return -1;
1185 else
1186 return 0;
1187 }
1188
1189 /* We're allowed to probe. Build it now. */
1190 if ((nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC)) == NULL)
1191 return -1;
1192 sk_charge_skb(sk, nskb);
1193
1194 skb = sk->sk_send_head;
1195 __skb_insert(nskb, skb->prev, skb, &sk->sk_write_queue);
1196 sk->sk_send_head = nskb;
1197
1198 TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
1199 TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
1200 TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK;
1201 TCP_SKB_CB(nskb)->sacked = 0;
1202 nskb->csum = 0;
1203 if (skb->ip_summed == CHECKSUM_HW)
1204 nskb->ip_summed = CHECKSUM_HW;
1205
1206 len = 0;
1207 while (len < probe_size) {
1208 next = skb->next;
1209
1210 copy = min_t(int, skb->len, probe_size - len);
1211 if (nskb->ip_summed)
1212 skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
1213 else
1214 nskb->csum = skb_copy_and_csum_bits(skb, 0,
1215 skb_put(nskb, copy), copy, nskb->csum);
1216
1217 if (skb->len <= copy) {
1218 /* We've eaten all the data from this skb.
1219 * Throw it away. */
1220 TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags;
1221 __skb_unlink(skb, &sk->sk_write_queue);
1222 sk_stream_free_skb(sk, skb);
1223 } else {
1224 TCP_SKB_CB(nskb)->flags |= TCP_SKB_CB(skb)->flags &
1225 ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
1226 if (!skb_shinfo(skb)->nr_frags) {
1227 skb_pull(skb, copy);
1228 if (skb->ip_summed != CHECKSUM_HW)
1229 skb->csum = csum_partial(skb->data, skb->len, 0);
1230 } else {
1231 __pskb_trim_head(skb, copy);
1232 tcp_set_skb_tso_segs(sk, skb, mss_now);
1233 }
1234 TCP_SKB_CB(skb)->seq += copy;
1235 }
1236
1237 len += copy;
1238 skb = next;
1239 }
1240 tcp_init_tso_segs(sk, nskb, nskb->len);
1241
1242 /* We're ready to send. If this fails, the probe will
1243 * be resegmented into mss-sized pieces by tcp_write_xmit(). */
1244 TCP_SKB_CB(nskb)->when = tcp_time_stamp;
1245 if (!tcp_transmit_skb(sk, nskb, 1, GFP_ATOMIC)) {
1246 /* Decrement cwnd here because we are sending
1247 * effectively two packets. */
1248 tp->snd_cwnd--;
1249 update_send_head(sk, tp, nskb);
1250
1251 icsk->icsk_mtup.probe_size = tcp_mss_to_mtu(sk, nskb->len);
1252 tp->mtu_probe.probe_seq_start = TCP_SKB_CB(nskb)->seq;
1253 tp->mtu_probe.probe_seq_end = TCP_SKB_CB(nskb)->end_seq;
1254
1255 return 1;
1256 }
1257
1258 return -1;
1259}
1260
1261
1066/* This routine writes packets to the network. It advances the 1262/* This routine writes packets to the network. It advances the
1067 * send_head. This happens as incoming acks open up the remote 1263 * send_head. This happens as incoming acks open up the remote
1068 * window for us. 1264 * window for us.
@@ -1076,6 +1272,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
1076 struct sk_buff *skb; 1272 struct sk_buff *skb;
1077 unsigned int tso_segs, sent_pkts; 1273 unsigned int tso_segs, sent_pkts;
1078 int cwnd_quota; 1274 int cwnd_quota;
1275 int result;
1079 1276
1080 /* If we are closed, the bytes will have to remain here. 1277 /* If we are closed, the bytes will have to remain here.
1081 * In time closedown will finish, we empty the write queue and all 1278 * In time closedown will finish, we empty the write queue and all
@@ -1085,6 +1282,14 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle)
1085 return 0; 1282 return 0;
1086 1283
1087 sent_pkts = 0; 1284 sent_pkts = 0;
1285
1286 /* Do MTU probing. */
1287 if ((result = tcp_mtu_probe(sk)) == 0) {
1288 return 0;
1289 } else if (result > 0) {
1290 sent_pkts = 1;
1291 }
1292
1088 while ((skb = sk->sk_send_head)) { 1293 while ((skb = sk->sk_send_head)) {
1089 unsigned int limit; 1294 unsigned int limit;
1090 1295
@@ -1455,9 +1660,15 @@ void tcp_simple_retransmit(struct sock *sk)
1455int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 1660int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
1456{ 1661{
1457 struct tcp_sock *tp = tcp_sk(sk); 1662 struct tcp_sock *tp = tcp_sk(sk);
1663 struct inet_connection_sock *icsk = inet_csk(sk);
1458 unsigned int cur_mss = tcp_current_mss(sk, 0); 1664 unsigned int cur_mss = tcp_current_mss(sk, 0);
1459 int err; 1665 int err;
1460 1666
1667 /* Inconslusive MTU probe */
1668 if (icsk->icsk_mtup.probe_size) {
1669 icsk->icsk_mtup.probe_size = 0;
1670 }
1671
1461 /* Do not sent more than we queued. 1/4 is reserved for possible 1672 /* Do not sent more than we queued. 1/4 is reserved for possible
1462 * copying overhead: fragmentation, tunneling, mangling etc. 1673 * copying overhead: fragmentation, tunneling, mangling etc.
1463 */ 1674 */
@@ -1883,6 +2094,7 @@ static void tcp_connect_init(struct sock *sk)
1883 if (tp->rx_opt.user_mss) 2094 if (tp->rx_opt.user_mss)
1884 tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; 2095 tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
1885 tp->max_window = 0; 2096 tp->max_window = 0;
2097 tcp_mtup_init(sk);
1886 tcp_sync_mss(sk, dst_mtu(dst)); 2098 tcp_sync_mss(sk, dst_mtu(dst));
1887 2099
1888 if (!tp->window_clamp) 2100 if (!tp->window_clamp)
@@ -2180,3 +2392,4 @@ EXPORT_SYMBOL(tcp_make_synack);
2180EXPORT_SYMBOL(tcp_simple_retransmit); 2392EXPORT_SYMBOL(tcp_simple_retransmit);
2181EXPORT_SYMBOL(tcp_sync_mss); 2393EXPORT_SYMBOL(tcp_sync_mss);
2182EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor); 2394EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor);
2395EXPORT_SYMBOL(tcp_mtup_init);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index e1880959614a..7c1bde3cd6cb 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -119,8 +119,10 @@ static int tcp_orphan_retries(struct sock *sk, int alive)
119/* A write timeout has occurred. Process the after effects. */ 119/* A write timeout has occurred. Process the after effects. */
120static int tcp_write_timeout(struct sock *sk) 120static int tcp_write_timeout(struct sock *sk)
121{ 121{
122 const struct inet_connection_sock *icsk = inet_csk(sk); 122 struct inet_connection_sock *icsk = inet_csk(sk);
123 struct tcp_sock *tp = tcp_sk(sk);
123 int retry_until; 124 int retry_until;
125 int mss;
124 126
125 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { 127 if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
126 if (icsk->icsk_retransmits) 128 if (icsk->icsk_retransmits)
@@ -128,25 +130,19 @@ static int tcp_write_timeout(struct sock *sk)
128 retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; 130 retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
129 } else { 131 } else {
130 if (icsk->icsk_retransmits >= sysctl_tcp_retries1) { 132 if (icsk->icsk_retransmits >= sysctl_tcp_retries1) {
131 /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black 133 /* Black hole detection */
132 hole detection. :-( 134 if (sysctl_tcp_mtu_probing) {
133 135 if (!icsk->icsk_mtup.enabled) {
134 It is place to make it. It is not made. I do not want 136 icsk->icsk_mtup.enabled = 1;
135 to make it. It is disgusting. It does not work in any 137 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
136 case. Let me to cite the same draft, which requires for 138 } else {
137 us to implement this: 139 mss = min(sysctl_tcp_base_mss,
138 140 tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2);
139 "The one security concern raised by this memo is that ICMP black holes 141 mss = max(mss, 68 - tp->tcp_header_len);
140 are often caused by over-zealous security administrators who block 142 icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
141 all ICMP messages. It is vitally important that those who design and 143 tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
142 deploy security systems understand the impact of strict filtering on 144 }
143 upper-layer protocols. The safest web site in the world is worthless 145 }
144 if most TCP implementations cannot transfer data from it. It would
145 be far nicer to have all of the black holes fixed rather than fixing
146 all of the TCP implementations."
147
148 Golden words :-).
149 */
150 146
151 dst_negative_advice(&sk->sk_dst_cache); 147 dst_negative_advice(&sk->sk_dst_cache);
152 } 148 }
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 00840474a449..3f93292b0ad8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1207,16 +1207,13 @@ static int udp_destroy_sock(struct sock *sk)
1207/* 1207/*
1208 * Socket option code for UDP 1208 * Socket option code for UDP
1209 */ 1209 */
1210static int udp_setsockopt(struct sock *sk, int level, int optname, 1210static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1211 char __user *optval, int optlen) 1211 char __user *optval, int optlen)
1212{ 1212{
1213 struct udp_sock *up = udp_sk(sk); 1213 struct udp_sock *up = udp_sk(sk);
1214 int val; 1214 int val;
1215 int err = 0; 1215 int err = 0;
1216 1216
1217 if (level != SOL_UDP)
1218 return ip_setsockopt(sk, level, optname, optval, optlen);
1219
1220 if(optlen<sizeof(int)) 1217 if(optlen<sizeof(int))
1221 return -EINVAL; 1218 return -EINVAL;
1222 1219
@@ -1256,15 +1253,30 @@ static int udp_setsockopt(struct sock *sk, int level, int optname,
1256 return err; 1253 return err;
1257} 1254}
1258 1255
1259static int udp_getsockopt(struct sock *sk, int level, int optname, 1256static int udp_setsockopt(struct sock *sk, int level, int optname,
1257 char __user *optval, int optlen)
1258{
1259 if (level != SOL_UDP)
1260 return ip_setsockopt(sk, level, optname, optval, optlen);
1261 return do_udp_setsockopt(sk, level, optname, optval, optlen);
1262}
1263
1264#ifdef CONFIG_COMPAT
1265static int compat_udp_setsockopt(struct sock *sk, int level, int optname,
1266 char __user *optval, int optlen)
1267{
1268 if (level != SOL_UDP)
1269 return compat_ip_setsockopt(sk, level, optname, optval, optlen);
1270 return do_udp_setsockopt(sk, level, optname, optval, optlen);
1271}
1272#endif
1273
1274static int do_udp_getsockopt(struct sock *sk, int level, int optname,
1260 char __user *optval, int __user *optlen) 1275 char __user *optval, int __user *optlen)
1261{ 1276{
1262 struct udp_sock *up = udp_sk(sk); 1277 struct udp_sock *up = udp_sk(sk);
1263 int val, len; 1278 int val, len;
1264 1279
1265 if (level != SOL_UDP)
1266 return ip_getsockopt(sk, level, optname, optval, optlen);
1267
1268 if(get_user(len,optlen)) 1280 if(get_user(len,optlen))
1269 return -EFAULT; 1281 return -EFAULT;
1270 1282
@@ -1293,6 +1305,23 @@ static int udp_getsockopt(struct sock *sk, int level, int optname,
1293 return 0; 1305 return 0;
1294} 1306}
1295 1307
1308static int udp_getsockopt(struct sock *sk, int level, int optname,
1309 char __user *optval, int __user *optlen)
1310{
1311 if (level != SOL_UDP)
1312 return ip_getsockopt(sk, level, optname, optval, optlen);
1313 return do_udp_getsockopt(sk, level, optname, optval, optlen);
1314}
1315
1316#ifdef CONFIG_COMPAT
1317static int compat_udp_getsockopt(struct sock *sk, int level, int optname,
1318 char __user *optval, int __user *optlen)
1319{
1320 if (level != SOL_UDP)
1321 return compat_ip_getsockopt(sk, level, optname, optval, optlen);
1322 return do_udp_getsockopt(sk, level, optname, optval, optlen);
1323}
1324#endif
1296/** 1325/**
1297 * udp_poll - wait for a UDP event. 1326 * udp_poll - wait for a UDP event.
1298 * @file - file struct 1327 * @file - file struct
@@ -1341,23 +1370,27 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1341} 1370}
1342 1371
1343struct proto udp_prot = { 1372struct proto udp_prot = {
1344 .name = "UDP", 1373 .name = "UDP",
1345 .owner = THIS_MODULE, 1374 .owner = THIS_MODULE,
1346 .close = udp_close, 1375 .close = udp_close,
1347 .connect = ip4_datagram_connect, 1376 .connect = ip4_datagram_connect,
1348 .disconnect = udp_disconnect, 1377 .disconnect = udp_disconnect,
1349 .ioctl = udp_ioctl, 1378 .ioctl = udp_ioctl,
1350 .destroy = udp_destroy_sock, 1379 .destroy = udp_destroy_sock,
1351 .setsockopt = udp_setsockopt, 1380 .setsockopt = udp_setsockopt,
1352 .getsockopt = udp_getsockopt, 1381 .getsockopt = udp_getsockopt,
1353 .sendmsg = udp_sendmsg, 1382 .sendmsg = udp_sendmsg,
1354 .recvmsg = udp_recvmsg, 1383 .recvmsg = udp_recvmsg,
1355 .sendpage = udp_sendpage, 1384 .sendpage = udp_sendpage,
1356 .backlog_rcv = udp_queue_rcv_skb, 1385 .backlog_rcv = udp_queue_rcv_skb,
1357 .hash = udp_v4_hash, 1386 .hash = udp_v4_hash,
1358 .unhash = udp_v4_unhash, 1387 .unhash = udp_v4_unhash,
1359 .get_port = udp_v4_get_port, 1388 .get_port = udp_v4_get_port,
1360 .obj_size = sizeof(struct udp_sock), 1389 .obj_size = sizeof(struct udp_sock),
1390#ifdef CONFIG_COMPAT
1391 .compat_setsockopt = compat_udp_setsockopt,
1392 .compat_getsockopt = compat_udp_getsockopt,
1393#endif
1361}; 1394};
1362 1395
1363/* ------------------------------------------------------------------------ */ 1396/* ------------------------------------------------------------------------ */
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index afbb0d4cc305..b08d56b117f8 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -5,6 +5,7 @@
5 5
6#include <linux/skbuff.h> 6#include <linux/skbuff.h>
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/mutex.h>
8#include <net/xfrm.h> 9#include <net/xfrm.h>
9#include <net/ip.h> 10#include <net/ip.h>
10#include <net/protocol.h> 11#include <net/protocol.h>
@@ -26,19 +27,19 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, s
26} 27}
27 28
28static struct xfrm_tunnel *ipip_handler; 29static struct xfrm_tunnel *ipip_handler;
29static DECLARE_MUTEX(xfrm4_tunnel_sem); 30static DEFINE_MUTEX(xfrm4_tunnel_mutex);
30 31
31int xfrm4_tunnel_register(struct xfrm_tunnel *handler) 32int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
32{ 33{
33 int ret; 34 int ret;
34 35
35 down(&xfrm4_tunnel_sem); 36 mutex_lock(&xfrm4_tunnel_mutex);
36 ret = 0; 37 ret = 0;
37 if (ipip_handler != NULL) 38 if (ipip_handler != NULL)
38 ret = -EINVAL; 39 ret = -EINVAL;
39 if (!ret) 40 if (!ret)
40 ipip_handler = handler; 41 ipip_handler = handler;
41 up(&xfrm4_tunnel_sem); 42 mutex_unlock(&xfrm4_tunnel_mutex);
42 43
43 return ret; 44 return ret;
44} 45}
@@ -49,13 +50,13 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
49{ 50{
50 int ret; 51 int ret;
51 52
52 down(&xfrm4_tunnel_sem); 53 mutex_lock(&xfrm4_tunnel_mutex);
53 ret = 0; 54 ret = 0;
54 if (ipip_handler != handler) 55 if (ipip_handler != handler)
55 ret = -EINVAL; 56 ret = -EINVAL;
56 if (!ret) 57 if (!ret)
57 ipip_handler = NULL; 58 ipip_handler = NULL;
58 up(&xfrm4_tunnel_sem); 59 mutex_unlock(&xfrm4_tunnel_mutex);
59 60
60 synchronize_net(); 61 synchronize_net();
61 62