aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-12-03 01:08:46 -0500
committerDavid S. Miller <davem@davemloft.net>2006-12-03 01:08:46 -0500
commitf587de0e2feb9eb9b94f98d0a7b7437e4d6617b4 (patch)
tree64d29dcacf895c37c4b7520bc8b07f0845baf914
parent16958900578b94585c2ab9a2d20d837b4d5e3ba6 (diff)
[NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port
Add IPv4 and IPv6 capable nf_conntrack port of the H.323 conntrack/NAT helper. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/nf_conntrack_h323.h92
-rw-r--r--include/linux/netfilter/nf_conntrack_h323_asn1.h (renamed from include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h)10
-rw-r--r--include/linux/netfilter/nf_conntrack_h323_types.h (renamed from include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h)12
-rw-r--r--include/linux/netfilter_ipv4/Kbuild2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h2
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h1
-rw-r--r--net/ipv4/netfilter/Kconfig5
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c596
-rw-r--r--net/netfilter/Kconfig19
-rw-r--r--net/netfilter/Makefile3
-rw-r--r--net/netfilter/nf_conntrack_h323_asn1.c (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c)4
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c1856
-rw-r--r--net/netfilter/nf_conntrack_h323_types.c (renamed from net/ipv4/netfilter/ip_conntrack_helper_h323_types.c)7
15 files changed, 2600 insertions, 14 deletions
diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h
new file mode 100644
index 000000000000..08e2f4977c2e
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_h323.h
@@ -0,0 +1,92 @@
1#ifndef _NF_CONNTRACK_H323_H
2#define _NF_CONNTRACK_H323_H
3
4#ifdef __KERNEL__
5
6#include <linux/netfilter/nf_conntrack_h323_asn1.h>
7
8#define RAS_PORT 1719
9#define Q931_PORT 1720
10#define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */
11
12/* This structure exists only once per master */
13struct nf_ct_h323_master {
14
15 /* Original and NATed Q.931 or H.245 signal ports */
16 __be16 sig_port[IP_CT_DIR_MAX];
17
18 /* Original and NATed RTP ports */
19 __be16 rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX];
20
21 union {
22 /* RAS connection timeout */
23 u_int32_t timeout;
24
25 /* Next TPKT length (for separate TPKT header and data) */
26 u_int16_t tpkt_len[IP_CT_DIR_MAX];
27 };
28};
29
30struct nf_conn;
31
32extern int get_h225_addr(struct nf_conn *ct, unsigned char *data,
33 TransportAddress *taddr,
34 union nf_conntrack_address *addr, __be16 *port);
35extern void nf_conntrack_h245_expect(struct nf_conn *new,
36 struct nf_conntrack_expect *this);
37extern void nf_conntrack_q931_expect(struct nf_conn *new,
38 struct nf_conntrack_expect *this);
39extern int (*set_h245_addr_hook) (struct sk_buff **pskb,
40 unsigned char **data, int dataoff,
41 H245_TransportAddress *taddr,
42 union nf_conntrack_address *addr,
43 __be16 port);
44extern int (*set_h225_addr_hook) (struct sk_buff **pskb,
45 unsigned char **data, int dataoff,
46 TransportAddress *taddr,
47 union nf_conntrack_address *addr,
48 __be16 port);
49extern int (*set_sig_addr_hook) (struct sk_buff **pskb,
50 struct nf_conn *ct,
51 enum ip_conntrack_info ctinfo,
52 unsigned char **data,
53 TransportAddress *taddr, int count);
54extern int (*set_ras_addr_hook) (struct sk_buff **pskb,
55 struct nf_conn *ct,
56 enum ip_conntrack_info ctinfo,
57 unsigned char **data,
58 TransportAddress *taddr, int count);
59extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
60 struct nf_conn *ct,
61 enum ip_conntrack_info ctinfo,
62 unsigned char **data, int dataoff,
63 H245_TransportAddress *taddr,
64 __be16 port, __be16 rtp_port,
65 struct nf_conntrack_expect *rtp_exp,
66 struct nf_conntrack_expect *rtcp_exp);
67extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct,
68 enum ip_conntrack_info ctinfo,
69 unsigned char **data, int dataoff,
70 H245_TransportAddress *taddr, __be16 port,
71 struct nf_conntrack_expect *exp);
72extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct,
73 enum ip_conntrack_info ctinfo,
74 unsigned char **data, int dataoff,
75 TransportAddress *taddr, __be16 port,
76 struct nf_conntrack_expect *exp);
77extern int (*nat_callforwarding_hook) (struct sk_buff **pskb,
78 struct nf_conn *ct,
79 enum ip_conntrack_info ctinfo,
80 unsigned char **data, int dataoff,
81 TransportAddress *taddr,
82 __be16 port,
83 struct nf_conntrack_expect *exp);
84extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct,
85 enum ip_conntrack_info ctinfo,
86 unsigned char **data, TransportAddress *taddr,
87 int idx, __be16 port,
88 struct nf_conntrack_expect *exp);
89
90#endif
91
92#endif
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter/nf_conntrack_h323_asn1.h
index c6e9a0b6d30b..8dab5968fc7e 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter/nf_conntrack_h323_asn1.h
@@ -1,6 +1,6 @@
1/**************************************************************************** 1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 2 * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323
3 * conntrack/NAT module. 3 * conntrack/NAT module.
4 * 4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net> 5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
6 * 6 *
@@ -34,13 +34,13 @@
34 * 34 *
35 ****************************************************************************/ 35 ****************************************************************************/
36 36
37#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ 37#ifndef _NF_CONNTRACK_HELPER_H323_ASN1_H_
38#define _IP_CONNTRACK_HELPER_H323_ASN1_H_ 38#define _NF_CONNTRACK_HELPER_H323_ASN1_H_
39 39
40/***************************************************************************** 40/*****************************************************************************
41 * H.323 Types 41 * H.323 Types
42 ****************************************************************************/ 42 ****************************************************************************/
43#include "ip_conntrack_helper_h323_types.h" 43#include "nf_conntrack_h323_types.h"
44 44
45typedef struct { 45typedef struct {
46 enum { 46 enum {
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h b/include/linux/netfilter/nf_conntrack_h323_types.h
index 3d4a773799fc..38d74d5c9700 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
+++ b/include/linux/netfilter/nf_conntrack_h323_types.h
@@ -10,6 +10,11 @@ typedef struct TransportAddress_ipAddress { /* SEQUENCE */
10 unsigned ip; 10 unsigned ip;
11} TransportAddress_ipAddress; 11} TransportAddress_ipAddress;
12 12
13typedef struct TransportAddress_ip6Address { /* SEQUENCE */
14 int options; /* No use */
15 unsigned ip6;
16} TransportAddress_ip6Address;
17
13typedef struct TransportAddress { /* CHOICE */ 18typedef struct TransportAddress { /* CHOICE */
14 enum { 19 enum {
15 eTransportAddress_ipAddress, 20 eTransportAddress_ipAddress,
@@ -22,6 +27,7 @@ typedef struct TransportAddress { /* CHOICE */
22 } choice; 27 } choice;
23 union { 28 union {
24 TransportAddress_ipAddress ipAddress; 29 TransportAddress_ipAddress ipAddress;
30 TransportAddress_ip6Address ip6Address;
25 }; 31 };
26} TransportAddress; 32} TransportAddress;
27 33
@@ -93,6 +99,11 @@ typedef struct UnicastAddress_iPAddress { /* SEQUENCE */
93 unsigned network; 99 unsigned network;
94} UnicastAddress_iPAddress; 100} UnicastAddress_iPAddress;
95 101
102typedef struct UnicastAddress_iP6Address { /* SEQUENCE */
103 int options; /* No use */
104 unsigned network;
105} UnicastAddress_iP6Address;
106
96typedef struct UnicastAddress { /* CHOICE */ 107typedef struct UnicastAddress { /* CHOICE */
97 enum { 108 enum {
98 eUnicastAddress_iPAddress, 109 eUnicastAddress_iPAddress,
@@ -105,6 +116,7 @@ typedef struct UnicastAddress { /* CHOICE */
105 } choice; 116 } choice;
106 union { 117 union {
107 UnicastAddress_iPAddress iPAddress; 118 UnicastAddress_iPAddress iPAddress;
119 UnicastAddress_iP6Address iP6Address;
108 }; 120 };
109} UnicastAddress; 121} UnicastAddress;
110 122
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
index 591c1a809c00..180337801a86 100644
--- a/include/linux/netfilter_ipv4/Kbuild
+++ b/include/linux/netfilter_ipv4/Kbuild
@@ -1,6 +1,4 @@
1header-y += ip_conntrack_helper.h 1header-y += ip_conntrack_helper.h
2header-y += ip_conntrack_helper_h323_asn1.h
3header-y += ip_conntrack_helper_h323_types.h
4header-y += ip_conntrack_protocol.h 2header-y += ip_conntrack_protocol.h
5header-y += ip_conntrack_sctp.h 3header-y += ip_conntrack_sctp.h
6header-y += ip_conntrack_tcp.h 4header-y += ip_conntrack_tcp.h
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 943cc6a4871d..18f769818f4e 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -3,7 +3,7 @@
3 3
4#ifdef __KERNEL__ 4#ifdef __KERNEL__
5 5
6#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> 6#include <linux/netfilter/nf_conntrack_h323_asn1.h>
7 7
8#define RAS_PORT 1719 8#define RAS_PORT 1719
9#define Q931_PORT 1720 9#define Q931_PORT 1720
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 83694cfdfa8f..1646076933b1 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -41,11 +41,13 @@ union nf_conntrack_expect_proto {
41 41
42/* Add protocol helper include file here */ 42/* Add protocol helper include file here */
43#include <linux/netfilter/nf_conntrack_ftp.h> 43#include <linux/netfilter/nf_conntrack_ftp.h>
44#include <linux/netfilter/nf_conntrack_h323.h>
44 45
45/* per conntrack: application helper private data */ 46/* per conntrack: application helper private data */
46union nf_conntrack_help { 47union nf_conntrack_help {
47 /* insert conntrack helper private data (master) here */ 48 /* insert conntrack helper private data (master) here */
48 struct nf_ct_ftp_master ct_ftp_info; 49 struct nf_ct_ftp_master ct_ftp_info;
50 struct nf_ct_h323_master ct_h323_info;
49}; 51};
50 52
51#include <linux/types.h> 53#include <linux/types.h>
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 54a3d038beaa..cef3136e22a3 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -41,6 +41,7 @@ struct nf_conntrack_expect
41 unsigned int flags; 41 unsigned int flags;
42 42
43#ifdef CONFIG_NF_NAT_NEEDED 43#ifdef CONFIG_NF_NAT_NEEDED
44 __be32 saved_ip;
44 /* This is the original per-proto part, used to map the 45 /* This is the original per-proto part, used to map the
45 * expected connection the way the recipient expects. */ 46 * expected connection the way the recipient expects. */
46 union nf_conntrack_man_proto saved_proto; 47 union nf_conntrack_man_proto saved_proto;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 6993ec53dc06..e14156d1122e 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -529,6 +529,11 @@ config IP_NF_NAT_H323
529 default IP_NF_NAT if IP_NF_H323=y 529 default IP_NF_NAT if IP_NF_H323=y
530 default m if IP_NF_H323=m 530 default m if IP_NF_H323=m
531 531
532config NF_NAT_H323
533 tristate
534 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
535 default NF_NAT && NF_CONNTRACK_H323
536
532config IP_NF_NAT_SIP 537config IP_NF_NAT_SIP
533 tristate 538 tristate
534 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n 539 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 8893249bbe98..bdaba4700e3b 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -15,7 +15,7 @@ endif
15ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o 15ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
16ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o 16ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
17 17
18ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o 18ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ../../netfilter/nf_conntrack_h323_asn1.o
19ip_nat_h323-objs := ip_nat_helper_h323.o 19ip_nat_h323-objs := ip_nat_helper_h323.o
20 20
21# connection tracking 21# connection tracking
@@ -52,6 +52,7 @@ obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
52# NAT helpers (nf_conntrack) 52# NAT helpers (nf_conntrack)
53obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o 53obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
54obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 54obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
55obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
55 56
56# generic IP tables 57# generic IP tables
57obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o 58obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
new file mode 100644
index 000000000000..fb9ab0114c23
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -0,0 +1,596 @@
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
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/tcp.h>
15#include <net/tcp.h>
16
17#include <net/netfilter/nf_nat.h>
18#include <net/netfilter/nf_nat_helper.h>
19#include <net/netfilter/nf_nat_rule.h>
20#include <net/netfilter/nf_conntrack_helper.h>
21#include <net/netfilter/nf_conntrack_expect.h>
22#include <linux/netfilter/nf_conntrack_h323.h>
23
24#if 0
25#define DEBUGP printk
26#else
27#define DEBUGP(format, args...)
28#endif
29
30/****************************************************************************/
31static int set_addr(struct sk_buff **pskb,
32 unsigned char **data, int dataoff,
33 unsigned int addroff, __be32 ip, __be16 port)
34{
35 enum ip_conntrack_info ctinfo;
36 struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo);
37 struct {
38 __be32 ip;
39 __be16 port;
40 } __attribute__ ((__packed__)) buf;
41 struct tcphdr _tcph, *th;
42
43 buf.ip = ip;
44 buf.port = port;
45 addroff += dataoff;
46
47 if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
48 if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
49 addroff, sizeof(buf),
50 (char *) &buf, sizeof(buf))) {
51 if (net_ratelimit())
52 printk("nf_nat_h323: nf_nat_mangle_tcp_packet"
53 " error\n");
54 return -1;
55 }
56
57 /* Relocate data pointer */
58 th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
59 sizeof(_tcph), &_tcph);
60 if (th == NULL)
61 return -1;
62 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
63 th->doff * 4 + dataoff;
64 } else {
65 if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
66 addroff, sizeof(buf),
67 (char *) &buf, sizeof(buf))) {
68 if (net_ratelimit())
69 printk("nf_nat_h323: nf_nat_mangle_udp_packet"
70 " error\n");
71 return -1;
72 }
73 /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
74 * or pull everything in a linear buffer, so we can safely
75 * use the skb pointers now */
76 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
77 sizeof(struct udphdr);
78 }
79
80 return 0;
81}
82
83/****************************************************************************/
84static int set_h225_addr(struct sk_buff **pskb,
85 unsigned char **data, int dataoff,
86 TransportAddress *taddr,
87 union nf_conntrack_address *addr, __be16 port)
88{
89 return set_addr(pskb, data, dataoff, taddr->ipAddress.ip,
90 addr->ip, port);
91}
92
93/****************************************************************************/
94static int set_h245_addr(struct sk_buff **pskb,
95 unsigned char **data, int dataoff,
96 H245_TransportAddress *taddr,
97 union nf_conntrack_address *addr, __be16 port)
98{
99 return set_addr(pskb, data, dataoff,
100 taddr->unicastAddress.iPAddress.network,
101 addr->ip, port);
102}
103
104/****************************************************************************/
105static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
106 enum ip_conntrack_info ctinfo,
107 unsigned char **data,
108 TransportAddress *taddr, int count)
109{
110 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
111 int dir = CTINFO2DIR(ctinfo);
112 int i;
113 __be16 port;
114 union nf_conntrack_address addr;
115
116 for (i = 0; i < count; i++) {
117 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
118 if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
119 port == info->sig_port[dir]) {
120 /* GW->GK */
121
122 /* Fix for Gnomemeeting */
123 if (i > 0 &&
124 get_h225_addr(ct, *data, &taddr[0],
125 &addr, &port) &&
126 (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
127 i = 0;
128
129 DEBUGP
130 ("nf_nat_ras: set signal address "
131 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
132 NIPQUAD(ip), port,
133 NIPQUAD(ct->tuplehash[!dir].tuple.dst.
134 ip), info->sig_port[!dir]);
135 return set_h225_addr(pskb, data, 0, &taddr[i],
136 &ct->tuplehash[!dir].
137 tuple.dst.u3,
138 info->sig_port[!dir]);
139 } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
140 port == info->sig_port[dir]) {
141 /* GK->GW */
142 DEBUGP
143 ("nf_nat_ras: set signal address "
144 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
145 NIPQUAD(ip), port,
146 NIPQUAD(ct->tuplehash[!dir].tuple.src.
147 ip), info->sig_port[!dir]);
148 return set_h225_addr(pskb, data, 0, &taddr[i],
149 &ct->tuplehash[!dir].
150 tuple.src.u3,
151 info->sig_port[!dir]);
152 }
153 }
154 }
155
156 return 0;
157}
158
159/****************************************************************************/
160static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
161 enum ip_conntrack_info ctinfo,
162 unsigned char **data,
163 TransportAddress *taddr, int count)
164{
165 int dir = CTINFO2DIR(ctinfo);
166 int i;
167 __be16 port;
168 union nf_conntrack_address addr;
169
170 for (i = 0; i < count; i++) {
171 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
172 addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
173 port == ct->tuplehash[dir].tuple.src.u.udp.port) {
174 DEBUGP("nf_nat_ras: set rasAddress "
175 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
176 NIPQUAD(ip), ntohs(port),
177 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
178 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
179 port));
180 return set_h225_addr(pskb, data, 0, &taddr[i],
181 &ct->tuplehash[!dir].tuple.dst.u3,
182 ct->tuplehash[!dir].tuple.
183 dst.u.udp.port);
184 }
185 }
186
187 return 0;
188}
189
190/****************************************************************************/
191static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
192 enum ip_conntrack_info ctinfo,
193 unsigned char **data, int dataoff,
194 H245_TransportAddress *taddr,
195 __be16 port, __be16 rtp_port,
196 struct nf_conntrack_expect *rtp_exp,
197 struct nf_conntrack_expect *rtcp_exp)
198{
199 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
200 int dir = CTINFO2DIR(ctinfo);
201 int i;
202 u_int16_t nated_port;
203
204 /* Set expectations for NAT */
205 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
206 rtp_exp->expectfn = nf_nat_follow_master;
207 rtp_exp->dir = !dir;
208 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
209 rtcp_exp->expectfn = nf_nat_follow_master;
210 rtcp_exp->dir = !dir;
211
212 /* Lookup existing expects */
213 for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
214 if (info->rtp_port[i][dir] == rtp_port) {
215 /* Expected */
216
217 /* Use allocated ports first. This will refresh
218 * the expects */
219 rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
220 rtcp_exp->tuple.dst.u.udp.port =
221 htons(ntohs(info->rtp_port[i][dir]) + 1);
222 break;
223 } else if (info->rtp_port[i][dir] == 0) {
224 /* Not expected */
225 break;
226 }
227 }
228
229 /* Run out of expectations */
230 if (i >= H323_RTP_CHANNEL_MAX) {
231 if (net_ratelimit())
232 printk("nf_nat_h323: out of expectations\n");
233 return 0;
234 }
235
236 /* Try to get a pair of ports. */
237 for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
238 nated_port != 0; nated_port += 2) {
239 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
240 if (nf_conntrack_expect_related(rtp_exp) == 0) {
241 rtcp_exp->tuple.dst.u.udp.port =
242 htons(nated_port + 1);
243 if (nf_conntrack_expect_related(rtcp_exp) == 0)
244 break;
245 nf_conntrack_unexpect_related(rtp_exp);
246 }
247 }
248
249 if (nated_port == 0) { /* No port available */
250 if (net_ratelimit())
251 printk("nf_nat_h323: out of RTP ports\n");
252 return 0;
253 }
254
255 /* Modify signal */
256 if (set_h245_addr(pskb, data, dataoff, taddr,
257 &ct->tuplehash[!dir].tuple.dst.u3,
258 htons((port & htons(1)) ? nated_port + 1 :
259 nated_port)) == 0) {
260 /* Save ports */
261 info->rtp_port[i][dir] = rtp_port;
262 info->rtp_port[i][!dir] = htons(nated_port);
263 } else {
264 nf_conntrack_unexpect_related(rtp_exp);
265 nf_conntrack_unexpect_related(rtcp_exp);
266 return -1;
267 }
268
269 /* Success */
270 DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
271 NIPQUAD(rtp_exp->tuple.src.ip),
272 ntohs(rtp_exp->tuple.src.u.udp.port),
273 NIPQUAD(rtp_exp->tuple.dst.ip),
274 ntohs(rtp_exp->tuple.dst.u.udp.port));
275 DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
276 NIPQUAD(rtcp_exp->tuple.src.ip),
277 ntohs(rtcp_exp->tuple.src.u.udp.port),
278 NIPQUAD(rtcp_exp->tuple.dst.ip),
279 ntohs(rtcp_exp->tuple.dst.u.udp.port));
280
281 return 0;
282}
283
284/****************************************************************************/
285static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
286 enum ip_conntrack_info ctinfo,
287 unsigned char **data, int dataoff,
288 H245_TransportAddress *taddr, __be16 port,
289 struct nf_conntrack_expect *exp)
290{
291 int dir = CTINFO2DIR(ctinfo);
292 u_int16_t nated_port = ntohs(port);
293
294 /* Set expectations for NAT */
295 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
296 exp->expectfn = nf_nat_follow_master;
297 exp->dir = !dir;
298
299 /* Try to get same port: if not, try to change it. */
300 for (; nated_port != 0; nated_port++) {
301 exp->tuple.dst.u.tcp.port = htons(nated_port);
302 if (nf_conntrack_expect_related(exp) == 0)
303 break;
304 }
305
306 if (nated_port == 0) { /* No port available */
307 if (net_ratelimit())
308 printk("nf_nat_h323: out of TCP ports\n");
309 return 0;
310 }
311
312 /* Modify signal */
313 if (set_h245_addr(pskb, data, dataoff, taddr,
314 &ct->tuplehash[!dir].tuple.dst.u3,
315 htons(nated_port)) < 0) {
316 nf_conntrack_unexpect_related(exp);
317 return -1;
318 }
319
320 DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
321 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
322 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
323
324 return 0;
325}
326
327/****************************************************************************/
328static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
329 enum ip_conntrack_info ctinfo,
330 unsigned char **data, int dataoff,
331 TransportAddress *taddr, __be16 port,
332 struct nf_conntrack_expect *exp)
333{
334 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
335 int dir = CTINFO2DIR(ctinfo);
336 u_int16_t nated_port = ntohs(port);
337
338 /* Set expectations for NAT */
339 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
340 exp->expectfn = nf_nat_follow_master;
341 exp->dir = !dir;
342
343 /* Check existing expects */
344 if (info->sig_port[dir] == port)
345 nated_port = ntohs(info->sig_port[!dir]);
346
347 /* Try to get same port: if not, try to change it. */
348 for (; nated_port != 0; nated_port++) {
349 exp->tuple.dst.u.tcp.port = htons(nated_port);
350 if (nf_conntrack_expect_related(exp) == 0)
351 break;
352 }
353
354 if (nated_port == 0) { /* No port available */
355 if (net_ratelimit())
356 printk("nf_nat_q931: out of TCP ports\n");
357 return 0;
358 }
359
360 /* Modify signal */
361 if (set_h225_addr(pskb, data, dataoff, taddr,
362 &ct->tuplehash[!dir].tuple.dst.u3,
363 htons(nated_port)) == 0) {
364 /* Save ports */
365 info->sig_port[dir] = port;
366 info->sig_port[!dir] = htons(nated_port);
367 } else {
368 nf_conntrack_unexpect_related(exp);
369 return -1;
370 }
371
372 DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
373 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
374 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
375
376 return 0;
377}
378
379/****************************************************************************
380 * This conntrack expect function replaces nf_conntrack_q931_expect()
381 * which was set by nf_conntrack_h323.c.
382 ****************************************************************************/
383static void ip_nat_q931_expect(struct nf_conn *new,
384 struct nf_conntrack_expect *this)
385{
386 struct ip_nat_range range;
387
388 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
389 nf_nat_follow_master(new, this);
390 return;
391 }
392
393 /* This must be a fresh one. */
394 BUG_ON(new->status & IPS_NAT_DONE_MASK);
395
396 /* Change src to where master sends to */
397 range.flags = IP_NAT_RANGE_MAP_IPS;
398 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
399
400 /* hook doesn't matter, but it has to do source manip */
401 nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
402
403 /* For DST manip, map port here to where it's expected. */
404 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
405 range.min = range.max = this->saved_proto;
406 range.min_ip = range.max_ip =
407 new->master->tuplehash[!this->dir].tuple.src.u3.ip;
408
409 /* hook doesn't matter, but it has to do destination manip */
410 nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
411}
412
413/****************************************************************************/
414static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
415 enum ip_conntrack_info ctinfo,
416 unsigned char **data, TransportAddress *taddr, int idx,
417 __be16 port, struct nf_conntrack_expect *exp)
418{
419 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
420 int dir = CTINFO2DIR(ctinfo);
421 u_int16_t nated_port = ntohs(port);
422 union nf_conntrack_address addr;
423
424 /* Set expectations for NAT */
425 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
426 exp->expectfn = ip_nat_q931_expect;
427 exp->dir = !dir;
428
429 /* Check existing expects */
430 if (info->sig_port[dir] == port)
431 nated_port = ntohs(info->sig_port[!dir]);
432
433 /* Try to get same port: if not, try to change it. */
434 for (; nated_port != 0; nated_port++) {
435 exp->tuple.dst.u.tcp.port = htons(nated_port);
436 if (nf_conntrack_expect_related(exp) == 0)
437 break;
438 }
439
440 if (nated_port == 0) { /* No port available */
441 if (net_ratelimit())
442 printk("nf_nat_ras: out of TCP ports\n");
443 return 0;
444 }
445
446 /* Modify signal */
447 if (set_h225_addr(pskb, data, 0, &taddr[idx],
448 &ct->tuplehash[!dir].tuple.dst.u3,
449 htons(nated_port)) == 0) {
450 /* Save ports */
451 info->sig_port[dir] = port;
452 info->sig_port[!dir] = htons(nated_port);
453
454 /* Fix for Gnomemeeting */
455 if (idx > 0 &&
456 get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
457 (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
458 set_h225_addr_hook(pskb, data, 0, &taddr[0],
459 &ct->tuplehash[!dir].tuple.dst.u3,
460 info->sig_port[!dir]);
461 }
462 } else {
463 nf_conntrack_unexpect_related(exp);
464 return -1;
465 }
466
467 /* Success */
468 DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
469 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
470 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
471
472 return 0;
473}
474
475/****************************************************************************/
476static void ip_nat_callforwarding_expect(struct nf_conn *new,
477 struct nf_conntrack_expect *this)
478{
479 struct nf_nat_range range;
480
481 /* This must be a fresh one. */
482 BUG_ON(new->status & IPS_NAT_DONE_MASK);
483
484 /* Change src to where master sends to */
485 range.flags = IP_NAT_RANGE_MAP_IPS;
486 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
487
488 /* hook doesn't matter, but it has to do source manip */
489 nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
490
491 /* For DST manip, map port here to where it's expected. */
492 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
493 range.min = range.max = this->saved_proto;
494 range.min_ip = range.max_ip = this->saved_ip;
495
496 /* hook doesn't matter, but it has to do destination manip */
497 nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
498}
499
500/****************************************************************************/
501static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
502 enum ip_conntrack_info ctinfo,
503 unsigned char **data, int dataoff,
504 TransportAddress *taddr, __be16 port,
505 struct nf_conntrack_expect *exp)
506{
507 int dir = CTINFO2DIR(ctinfo);
508 u_int16_t nated_port;
509
510 /* Set expectations for NAT */
511 exp->saved_ip = exp->tuple.dst.u3.ip;
512 exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
513 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
514 exp->expectfn = ip_nat_callforwarding_expect;
515 exp->dir = !dir;
516
517 /* Try to get same port: if not, try to change it. */
518 for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
519 exp->tuple.dst.u.tcp.port = htons(nated_port);
520 if (nf_conntrack_expect_related(exp) == 0)
521 break;
522 }
523
524 if (nated_port == 0) { /* No port available */
525 if (net_ratelimit())
526 printk("nf_nat_q931: out of TCP ports\n");
527 return 0;
528 }
529
530 /* Modify signal */
531 if (!set_h225_addr(pskb, data, dataoff, taddr,
532 &ct->tuplehash[!dir].tuple.dst.u3,
533 htons(nated_port)) == 0) {
534 nf_conntrack_unexpect_related(exp);
535 return -1;
536 }
537
538 /* Success */
539 DEBUGP("nf_nat_q931: expect Call Forwarding "
540 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
541 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
542 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
543
544 return 0;
545}
546
547/****************************************************************************/
548static int __init init(void)
549{
550 BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
551 BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
552 BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
553 BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
554 BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
555 BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
556 BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
557 BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
558 BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
559
560 rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
561 rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
562 rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
563 rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
564 rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
565 rcu_assign_pointer(nat_t120_hook, nat_t120);
566 rcu_assign_pointer(nat_h245_hook, nat_h245);
567 rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
568 rcu_assign_pointer(nat_q931_hook, nat_q931);
569
570 DEBUGP("nf_nat_h323: init success\n");
571 return 0;
572}
573
574/****************************************************************************/
575static void __exit fini(void)
576{
577 rcu_assign_pointer(set_h245_addr_hook, NULL);
578 rcu_assign_pointer(set_h225_addr_hook, NULL);
579 rcu_assign_pointer(set_sig_addr_hook, NULL);
580 rcu_assign_pointer(set_ras_addr_hook, NULL);
581 rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
582 rcu_assign_pointer(nat_t120_hook, NULL);
583 rcu_assign_pointer(nat_h245_hook, NULL);
584 rcu_assign_pointer(nat_callforwarding_hook, NULL);
585 rcu_assign_pointer(nat_q931_hook, NULL);
586 synchronize_rcu();
587}
588
589/****************************************************************************/
590module_init(init);
591module_exit(fini);
592
593MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
594MODULE_DESCRIPTION("H.323 NAT helper");
595MODULE_LICENSE("GPL");
596MODULE_ALIAS("ip_nat_h323");
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f85fd43b344b..d8f3451c95b6 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -160,6 +160,25 @@ config NF_CONNTRACK_FTP
160 160
161 To compile it as a module, choose M here. If unsure, say N. 161 To compile it as a module, choose M here. If unsure, say N.
162 162
163config NF_CONNTRACK_H323
164 tristate "H.323 protocol support (EXPERIMENTAL)"
165 depends on EXPERIMENTAL && NF_CONNTRACK
166 help
167 H.323 is a VoIP signalling protocol from ITU-T. As one of the most
168 important VoIP protocols, it is widely used by voice hardware and
169 software including voice gateways, IP phones, Netmeeting, OpenPhone,
170 Gnomemeeting, etc.
171
172 With this module you can support H.323 on a connection tracking/NAT
173 firewall.
174
175 This module supports RAS, Fast Start, H.245 Tunnelling, Call
176 Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
177 whiteboard, file transfer, etc. For more information, please
178 visit http://nath323.sourceforge.net/.
179
180 To compile it as a module, choose M here. If unsure, say N.
181
163config NF_CT_NETLINK 182config NF_CT_NETLINK
164 tristate 'Connection tracking netlink interface (EXPERIMENTAL)' 183 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
165 depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK 184 depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a5ee93817427..69b554576b6b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -20,8 +20,11 @@ obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
20obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 20obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
21 21
22# connection tracking helpers 22# connection tracking helpers
23nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o
24
23obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o 25obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
24obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o 26obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
27obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o
25 28
26# generic X tables 29# generic X tables
27obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o 30obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index 26dfecadb335..f6fad713d484 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -15,7 +15,7 @@
15#else 15#else
16#include <stdio.h> 16#include <stdio.h>
17#endif 17#endif
18#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> 18#include <linux/netfilter/nf_conntrack_h323_asn1.h>
19 19
20/* Trace Flag */ 20/* Trace Flag */
21#ifndef H323_TRACE 21#ifndef H323_TRACE
@@ -144,7 +144,7 @@ static decoder_t Decoders[] = {
144/**************************************************************************** 144/****************************************************************************
145 * H.323 Types 145 * H.323 Types
146 ****************************************************************************/ 146 ****************************************************************************/
147#include "ip_conntrack_helper_h323_types.c" 147#include "nf_conntrack_h323_types.c"
148 148
149/**************************************************************************** 149/****************************************************************************
150 * Functions 150 * Functions
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
new file mode 100644
index 000000000000..6d8568959f82
--- /dev/null
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -0,0 +1,1856 @@
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
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/ctype.h>
17#include <linux/inet.h>
18#include <linux/in.h>
19#include <linux/ip.h>
20#include <linux/udp.h>
21#include <linux/tcp.h>
22#include <linux/skbuff.h>
23#include <net/route.h>
24#include <net/ip6_route.h>
25
26#include <net/netfilter/nf_conntrack.h>
27#include <net/netfilter/nf_conntrack_core.h>
28#include <net/netfilter/nf_conntrack_tuple.h>
29#include <net/netfilter/nf_conntrack_expect.h>
30#include <net/netfilter/nf_conntrack_ecache.h>
31#include <net/netfilter/nf_conntrack_helper.h>
32#include <linux/netfilter/nf_conntrack_h323.h>
33
34#if 0
35#define DEBUGP printk
36#else
37#define DEBUGP(format, args...)
38#endif
39
40/* Parameters */
41static unsigned int default_rrq_ttl __read_mostly = 300;
42module_param(default_rrq_ttl, uint, 0600);
43MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
44
45static int gkrouted_only __read_mostly = 1;
46module_param(gkrouted_only, int, 0600);
47MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
48
49static int callforward_filter __read_mostly = 1;
50module_param(callforward_filter, bool, 0600);
51MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
52 "if both endpoints are on different sides "
53 "(determined by routing information)");
54
55/* Hooks for NAT */
56int (*set_h245_addr_hook) (struct sk_buff **pskb,
57 unsigned char **data, int dataoff,
58 H245_TransportAddress *taddr,
59 union nf_conntrack_address *addr, __be16 port)
60 __read_mostly;
61int (*set_h225_addr_hook) (struct sk_buff **pskb,
62 unsigned char **data, int dataoff,
63 TransportAddress *taddr,
64 union nf_conntrack_address *addr, __be16 port)
65 __read_mostly;
66int (*set_sig_addr_hook) (struct sk_buff **pskb,
67 struct nf_conn *ct,
68 enum ip_conntrack_info ctinfo,
69 unsigned char **data,
70 TransportAddress *taddr, int count) __read_mostly;
71int (*set_ras_addr_hook) (struct sk_buff **pskb,
72 struct nf_conn *ct,
73 enum ip_conntrack_info ctinfo,
74 unsigned char **data,
75 TransportAddress *taddr, int count) __read_mostly;
76int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb,
77 struct nf_conn *ct,
78 enum ip_conntrack_info ctinfo,
79 unsigned char **data, int dataoff,
80 H245_TransportAddress *taddr,
81 __be16 port, __be16 rtp_port,
82 struct nf_conntrack_expect *rtp_exp,
83 struct nf_conntrack_expect *rtcp_exp) __read_mostly;
84int (*nat_t120_hook) (struct sk_buff **pskb,
85 struct nf_conn *ct,
86 enum ip_conntrack_info ctinfo,
87 unsigned char **data, int dataoff,
88 H245_TransportAddress *taddr, __be16 port,
89 struct nf_conntrack_expect *exp) __read_mostly;
90int (*nat_h245_hook) (struct sk_buff **pskb,
91 struct nf_conn *ct,
92 enum ip_conntrack_info ctinfo,
93 unsigned char **data, int dataoff,
94 TransportAddress *taddr, __be16 port,
95 struct nf_conntrack_expect *exp) __read_mostly;
96int (*nat_callforwarding_hook) (struct sk_buff **pskb,
97 struct nf_conn *ct,
98 enum ip_conntrack_info ctinfo,
99 unsigned char **data, int dataoff,
100 TransportAddress *taddr, __be16 port,
101 struct nf_conntrack_expect *exp) __read_mostly;
102int (*nat_q931_hook) (struct sk_buff **pskb,
103 struct nf_conn *ct,
104 enum ip_conntrack_info ctinfo,
105 unsigned char **data, TransportAddress *taddr, int idx,
106 __be16 port, struct nf_conntrack_expect *exp)
107 __read_mostly;
108
109static DEFINE_SPINLOCK(nf_h323_lock);
110static char *h323_buffer;
111
112static struct nf_conntrack_helper nf_conntrack_helper_h245;
113static struct nf_conntrack_helper nf_conntrack_helper_q931[];
114static struct nf_conntrack_helper nf_conntrack_helper_ras[];
115
116/****************************************************************************/
117static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
118 struct nf_conn *ct, enum ip_conntrack_info ctinfo,
119 unsigned char **data, int *datalen, int *dataoff)
120{
121 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
122 int dir = CTINFO2DIR(ctinfo);
123 struct tcphdr _tcph, *th;
124 int tcpdatalen;
125 int tcpdataoff;
126 unsigned char *tpkt;
127 int tpktlen;
128 int tpktoff;
129
130 /* Get TCP header */
131 th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph);
132 if (th == NULL)
133 return 0;
134
135 /* Get TCP data offset */
136 tcpdataoff = protoff + th->doff * 4;
137
138 /* Get TCP data length */
139 tcpdatalen = (*pskb)->len - tcpdataoff;
140 if (tcpdatalen <= 0) /* No TCP data */
141 goto clear_out;
142
143 if (*data == NULL) { /* first TPKT */
144 /* Get first TPKT pointer */
145 tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
146 h323_buffer);
147 BUG_ON(tpkt == NULL);
148
149 /* Validate TPKT identifier */
150 if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
151 /* Netmeeting sends TPKT header and data separately */
152 if (info->tpkt_len[dir] > 0) {
153 DEBUGP("nf_ct_h323: previous packet "
154 "indicated separate TPKT data of %hu "
155 "bytes\n", info->tpkt_len[dir]);
156 if (info->tpkt_len[dir] <= tcpdatalen) {
157 /* Yes, there was a TPKT header
158 * received */
159 *data = tpkt;
160 *datalen = info->tpkt_len[dir];
161 *dataoff = 0;
162 goto out;
163 }
164
165 /* Fragmented TPKT */
166 if (net_ratelimit())
167 printk("nf_ct_h323: "
168 "fragmented TPKT\n");
169 goto clear_out;
170 }
171
172 /* It is not even a TPKT */
173 return 0;
174 }
175 tpktoff = 0;
176 } else { /* Next TPKT */
177 tpktoff = *dataoff + *datalen;
178 tcpdatalen -= tpktoff;
179 if (tcpdatalen <= 4) /* No more TPKT */
180 goto clear_out;
181 tpkt = *data + *datalen;
182
183 /* Validate TPKT identifier */
184 if (tpkt[0] != 0x03 || tpkt[1] != 0)
185 goto clear_out;
186 }
187
188 /* Validate TPKT length */
189 tpktlen = tpkt[2] * 256 + tpkt[3];
190 if (tpktlen < 4)
191 goto clear_out;
192 if (tpktlen > tcpdatalen) {
193 if (tcpdatalen == 4) { /* Separate TPKT header */
194 /* Netmeeting sends TPKT header and data separately */
195 DEBUGP("nf_ct_h323: separate TPKT header indicates "
196 "there will be TPKT data of %hu bytes\n",
197 tpktlen - 4);
198 info->tpkt_len[dir] = tpktlen - 4;
199 return 0;
200 }
201
202 if (net_ratelimit())
203 printk("nf_ct_h323: incomplete TPKT (fragmented?)\n");
204 goto clear_out;
205 }
206
207 /* This is the encapsulated data */
208 *data = tpkt + 4;
209 *datalen = tpktlen - 4;
210 *dataoff = tpktoff + 4;
211
212 out:
213 /* Clear TPKT length */
214 info->tpkt_len[dir] = 0;
215 return 1;
216
217 clear_out:
218 info->tpkt_len[dir] = 0;
219 return 0;
220}
221
222/****************************************************************************/
223static int get_h245_addr(struct nf_conn *ct, unsigned char *data,
224 H245_TransportAddress *taddr,
225 union nf_conntrack_address *addr, __be16 *port)
226{
227 unsigned char *p;
228 int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
229 int len;
230
231 if (taddr->choice != eH245_TransportAddress_unicastAddress)
232 return 0;
233
234 switch (taddr->unicastAddress.choice) {
235 case eUnicastAddress_iPAddress:
236 if (family != AF_INET)
237 return 0;
238 p = data + taddr->unicastAddress.iPAddress.network;
239 len = 4;
240 break;
241 case eUnicastAddress_iP6Address:
242 if (family != AF_INET6)
243 return 0;
244 p = data + taddr->unicastAddress.iP6Address.network;
245 len = 16;
246 break;
247 default:
248 return 0;
249 }
250
251 memcpy(addr, p, len);
252 memset((void *)addr + len, 0, sizeof(*addr) - len);
253 memcpy(port, p + len, sizeof(__be16));
254
255 return 1;
256}
257
258/****************************************************************************/
259static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
260 enum ip_conntrack_info ctinfo,
261 unsigned char **data, int dataoff,
262 H245_TransportAddress *taddr)
263{
264 int dir = CTINFO2DIR(ctinfo);
265 int ret = 0;
266 __be16 port;
267 __be16 rtp_port, rtcp_port;
268 union nf_conntrack_address addr;
269 struct nf_conntrack_expect *rtp_exp;
270 struct nf_conntrack_expect *rtcp_exp;
271 typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
272
273 /* Read RTP or RTCP address */
274 if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
275 memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
276 port == 0)
277 return 0;
278
279 /* RTP port is even */
280 port &= htons(~1);
281 rtp_port = port;
282 rtcp_port = htons(ntohs(port) + 1);
283
284 /* Create expect for RTP */
285 if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL)
286 return -1;
287 nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
288 &ct->tuplehash[!dir].tuple.src.u3,
289 &ct->tuplehash[!dir].tuple.dst.u3,
290 IPPROTO_UDP, NULL, &rtp_port);
291
292 /* Create expect for RTCP */
293 if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) {
294 nf_conntrack_expect_put(rtp_exp);
295 return -1;
296 }
297 nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
298 &ct->tuplehash[!dir].tuple.src.u3,
299 &ct->tuplehash[!dir].tuple.dst.u3,
300 IPPROTO_UDP, NULL, &rtcp_port);
301
302 if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
303 &ct->tuplehash[!dir].tuple.dst.u3,
304 sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
305 (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
306 ct->status & IPS_NAT_MASK) {
307 /* NAT needed */
308 ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
309 taddr, port, rtp_port, rtp_exp, rtcp_exp);
310 } else { /* Conntrack only */
311 if (nf_conntrack_expect_related(rtp_exp) == 0) {
312 if (nf_conntrack_expect_related(rtcp_exp) == 0) {
313 DEBUGP("nf_ct_h323: expect RTP ");
314 NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
315 DEBUGP("nf_ct_h323: expect RTCP ");
316 NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
317 } else {
318 nf_conntrack_unexpect_related(rtp_exp);
319 ret = -1;
320 }
321 } else
322 ret = -1;
323 }
324
325 nf_conntrack_expect_put(rtp_exp);
326 nf_conntrack_expect_put(rtcp_exp);
327
328 return ret;
329}
330
331/****************************************************************************/
332static int expect_t120(struct sk_buff **pskb,
333 struct nf_conn *ct,
334 enum ip_conntrack_info ctinfo,
335 unsigned char **data, int dataoff,
336 H245_TransportAddress *taddr)
337{
338 int dir = CTINFO2DIR(ctinfo);
339 int ret = 0;
340 __be16 port;
341 union nf_conntrack_address addr;
342 struct nf_conntrack_expect *exp;
343 typeof(nat_t120_hook) nat_t120;
344
345 /* Read T.120 address */
346 if (!get_h245_addr(ct, *data, taddr, &addr, &port) ||
347 memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
348 port == 0)
349 return 0;
350
351 /* Create expect for T.120 connections */
352 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
353 return -1;
354 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
355 &ct->tuplehash[!dir].tuple.src.u3,
356 &ct->tuplehash[!dir].tuple.dst.u3,
357 IPPROTO_TCP, NULL, &port);
358 exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */
359
360 if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
361 &ct->tuplehash[!dir].tuple.dst.u3,
362 sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
363 (nat_t120 = rcu_dereference(nat_t120_hook)) &&
364 ct->status & IPS_NAT_MASK) {
365 /* NAT needed */
366 ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr,
367 port, exp);
368 } else { /* Conntrack only */
369 if (nf_conntrack_expect_related(exp) == 0) {
370 DEBUGP("nf_ct_h323: expect T.120 ");
371 NF_CT_DUMP_TUPLE(&exp->tuple);
372 } else
373 ret = -1;
374 }
375
376 nf_conntrack_expect_put(exp);
377
378 return ret;
379}
380
381/****************************************************************************/
382static int process_h245_channel(struct sk_buff **pskb,
383 struct nf_conn *ct,
384 enum ip_conntrack_info ctinfo,
385 unsigned char **data, int dataoff,
386 H2250LogicalChannelParameters *channel)
387{
388 int ret;
389
390 if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
391 /* RTP */
392 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
393 &channel->mediaChannel);
394 if (ret < 0)
395 return -1;
396 }
397
398 if (channel->
399 options & eH2250LogicalChannelParameters_mediaControlChannel) {
400 /* RTCP */
401 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
402 &channel->mediaControlChannel);
403 if (ret < 0)
404 return -1;
405 }
406
407 return 0;
408}
409
410/****************************************************************************/
411static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
412 enum ip_conntrack_info ctinfo,
413 unsigned char **data, int dataoff,
414 OpenLogicalChannel *olc)
415{
416 int ret;
417
418 DEBUGP("nf_ct_h323: OpenLogicalChannel\n");
419
420 if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
421 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
422 {
423 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
424 &olc->
425 forwardLogicalChannelParameters.
426 multiplexParameters.
427 h2250LogicalChannelParameters);
428 if (ret < 0)
429 return -1;
430 }
431
432 if ((olc->options &
433 eOpenLogicalChannel_reverseLogicalChannelParameters) &&
434 (olc->reverseLogicalChannelParameters.options &
435 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
436 && (olc->reverseLogicalChannelParameters.multiplexParameters.
437 choice ==
438 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
439 {
440 ret =
441 process_h245_channel(pskb, ct, ctinfo, data, dataoff,
442 &olc->
443 reverseLogicalChannelParameters.
444 multiplexParameters.
445 h2250LogicalChannelParameters);
446 if (ret < 0)
447 return -1;
448 }
449
450 if ((olc->options & eOpenLogicalChannel_separateStack) &&
451 olc->forwardLogicalChannelParameters.dataType.choice ==
452 eDataType_data &&
453 olc->forwardLogicalChannelParameters.dataType.data.application.
454 choice == eDataApplicationCapability_application_t120 &&
455 olc->forwardLogicalChannelParameters.dataType.data.application.
456 t120.choice == eDataProtocolCapability_separateLANStack &&
457 olc->separateStack.networkAddress.choice ==
458 eNetworkAccessParameters_networkAddress_localAreaAddress) {
459 ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
460 &olc->separateStack.networkAddress.
461 localAreaAddress);
462 if (ret < 0)
463 return -1;
464 }
465
466 return 0;
467}
468
469/****************************************************************************/
470static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
471 enum ip_conntrack_info ctinfo,
472 unsigned char **data, int dataoff,
473 OpenLogicalChannelAck *olca)
474{
475 H2250LogicalChannelAckParameters *ack;
476 int ret;
477
478 DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n");
479
480 if ((olca->options &
481 eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
482 (olca->reverseLogicalChannelParameters.options &
483 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
484 && (olca->reverseLogicalChannelParameters.multiplexParameters.
485 choice ==
486 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
487 {
488 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
489 &olca->
490 reverseLogicalChannelParameters.
491 multiplexParameters.
492 h2250LogicalChannelParameters);
493 if (ret < 0)
494 return -1;
495 }
496
497 if ((olca->options &
498 eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
499 (olca->forwardMultiplexAckParameters.choice ==
500 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
501 {
502 ack = &olca->forwardMultiplexAckParameters.
503 h2250LogicalChannelAckParameters;
504 if (ack->options &
505 eH2250LogicalChannelAckParameters_mediaChannel) {
506 /* RTP */
507 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
508 &ack->mediaChannel);
509 if (ret < 0)
510 return -1;
511 }
512
513 if (ack->options &
514 eH2250LogicalChannelAckParameters_mediaControlChannel) {
515 /* RTCP */
516 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
517 &ack->mediaControlChannel);
518 if (ret < 0)
519 return -1;
520 }
521 }
522
523 return 0;
524}
525
526/****************************************************************************/
527static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
528 enum ip_conntrack_info ctinfo,
529 unsigned char **data, int dataoff,
530 MultimediaSystemControlMessage *mscm)
531{
532 switch (mscm->choice) {
533 case eMultimediaSystemControlMessage_request:
534 if (mscm->request.choice ==
535 eRequestMessage_openLogicalChannel) {
536 return process_olc(pskb, ct, ctinfo, data, dataoff,
537 &mscm->request.openLogicalChannel);
538 }
539 DEBUGP("nf_ct_h323: H.245 Request %d\n",
540 mscm->request.choice);
541 break;
542 case eMultimediaSystemControlMessage_response:
543 if (mscm->response.choice ==
544 eResponseMessage_openLogicalChannelAck) {
545 return process_olca(pskb, ct, ctinfo, data, dataoff,
546 &mscm->response.
547 openLogicalChannelAck);
548 }
549 DEBUGP("nf_ct_h323: H.245 Response %d\n",
550 mscm->response.choice);
551 break;
552 default:
553 DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice);
554 break;
555 }
556
557 return 0;
558}
559
560/****************************************************************************/
561static int h245_help(struct sk_buff **pskb, unsigned int protoff,
562 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
563{
564 static MultimediaSystemControlMessage mscm;
565 unsigned char *data = NULL;
566 int datalen;
567 int dataoff;
568 int ret;
569
570 /* Until there's been traffic both ways, don't look in packets. */
571 if (ctinfo != IP_CT_ESTABLISHED &&
572 ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
573 return NF_ACCEPT;
574 }
575 DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len);
576
577 spin_lock_bh(&nf_h323_lock);
578
579 /* Process each TPKT */
580 while (get_tpkt_data(pskb, protoff, ct, ctinfo,
581 &data, &datalen, &dataoff)) {
582 DEBUGP("nf_ct_h245: TPKT len=%d ", datalen);
583 NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
584
585 /* Decode H.245 signal */
586 ret = DecodeMultimediaSystemControlMessage(data, datalen,
587 &mscm);
588 if (ret < 0) {
589 if (net_ratelimit())
590 printk("nf_ct_h245: decoding error: %s\n",
591 ret == H323_ERROR_BOUND ?
592 "out of bound" : "out of range");
593 /* We don't drop when decoding error */
594 break;
595 }
596
597 /* Process H.245 signal */
598 if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
599 goto drop;
600 }
601
602 spin_unlock_bh(&nf_h323_lock);
603 return NF_ACCEPT;
604
605 drop:
606 spin_unlock_bh(&nf_h323_lock);
607 if (net_ratelimit())
608 printk("nf_ct_h245: packet dropped\n");
609 return NF_DROP;
610}
611
612/****************************************************************************/
613static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
614 .name = "H.245",
615 .me = THIS_MODULE,
616 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
617 .timeout = 240,
618 .tuple.dst.protonum = IPPROTO_UDP,
619 .mask.src.u.udp.port = __constant_htons(0xFFFF),
620 .mask.dst.protonum = 0xFF,
621 .help = h245_help
622};
623
624/****************************************************************************/
625int get_h225_addr(struct nf_conn *ct, unsigned char *data,
626 TransportAddress *taddr,
627 union nf_conntrack_address *addr, __be16 *port)
628{
629 unsigned char *p;
630 int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
631 int len;
632
633 switch (taddr->choice) {
634 case eTransportAddress_ipAddress:
635 if (family != AF_INET)
636 return 0;
637 p = data + taddr->ipAddress.ip;
638 len = 4;
639 break;
640 case eTransportAddress_ip6Address:
641 if (family != AF_INET6)
642 return 0;
643 p = data + taddr->ip6Address.ip6;
644 len = 16;
645 break;
646 default:
647 return 0;
648 }
649
650 memcpy(addr, p, len);
651 memset((void *)addr + len, 0, sizeof(*addr) - len);
652 memcpy(port, p + len, sizeof(__be16));
653
654 return 1;
655}
656
657/****************************************************************************/
658static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct,
659 enum ip_conntrack_info ctinfo,
660 unsigned char **data, int dataoff,
661 TransportAddress *taddr)
662{
663 int dir = CTINFO2DIR(ctinfo);
664 int ret = 0;
665 __be16 port;
666 union nf_conntrack_address addr;
667 struct nf_conntrack_expect *exp;
668 typeof(nat_h245_hook) nat_h245;
669
670 /* Read h245Address */
671 if (!get_h225_addr(ct, *data, taddr, &addr, &port) ||
672 memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) ||
673 port == 0)
674 return 0;
675
676 /* Create expect for h245 connection */
677 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
678 return -1;
679 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
680 &ct->tuplehash[!dir].tuple.src.u3,
681 &ct->tuplehash[!dir].tuple.dst.u3,
682 IPPROTO_TCP, NULL, &port);
683 exp->helper = &nf_conntrack_helper_h245;
684
685 if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
686 &ct->tuplehash[!dir].tuple.dst.u3,
687 sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
688 (nat_h245 = rcu_dereference(nat_h245_hook)) &&
689 ct->status & IPS_NAT_MASK) {
690 /* NAT needed */
691 ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr,
692 port, exp);
693 } else { /* Conntrack only */
694 if (nf_conntrack_expect_related(exp) == 0) {
695 DEBUGP("nf_ct_q931: expect H.245 ");
696 NF_CT_DUMP_TUPLE(&exp->tuple);
697 } else
698 ret = -1;
699 }
700
701 nf_conntrack_expect_put(exp);
702
703 return ret;
704}
705
706/* If the calling party is on the same side of the forward-to party,
707 * we don't need to track the second call */
708static int callforward_do_filter(union nf_conntrack_address *src,
709 union nf_conntrack_address *dst,
710 int family)
711{
712 struct flowi fl1, fl2;
713 int ret = 0;
714
715 memset(&fl1, 0, sizeof(fl1));
716 memset(&fl2, 0, sizeof(fl2));
717
718 switch (family) {
719 case AF_INET: {
720 struct rtable *rt1, *rt2;
721
722 fl1.fl4_dst = src->ip;
723 fl2.fl4_dst = dst->ip;
724 if (ip_route_output_key(&rt1, &fl1) == 0) {
725 if (ip_route_output_key(&rt2, &fl2) == 0) {
726 if (rt1->rt_gateway == rt2->rt_gateway &&
727 rt1->u.dst.dev == rt2->u.dst.dev)
728 ret = 1;
729 dst_release(&rt2->u.dst);
730 }
731 dst_release(&rt1->u.dst);
732 }
733 break;
734 }
735#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
736 case AF_INET6: {
737 struct rt6_info *rt1, *rt2;
738
739 memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst));
740 memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst));
741 rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1);
742 if (rt1) {
743 rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2);
744 if (rt2) {
745 if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
746 sizeof(rt1->rt6i_gateway)) &&
747 rt1->u.dst.dev == rt2->u.dst.dev)
748 ret = 1;
749 dst_release(&rt2->u.dst);
750 }
751 dst_release(&rt1->u.dst);
752 }
753 break;
754 }
755#endif
756 }
757 return ret;
758
759}
760
761/****************************************************************************/
762static int expect_callforwarding(struct sk_buff **pskb,
763 struct nf_conn *ct,
764 enum ip_conntrack_info ctinfo,
765 unsigned char **data, int dataoff,
766 TransportAddress *taddr)
767{
768 int dir = CTINFO2DIR(ctinfo);
769 int ret = 0;
770 __be16 port;
771 union nf_conntrack_address addr;
772 struct nf_conntrack_expect *exp;
773 typeof(nat_callforwarding_hook) nat_callforwarding;
774
775 /* Read alternativeAddress */
776 if (!get_h225_addr(ct, *data, taddr, &addr, &port) || port == 0)
777 return 0;
778
779 /* If the calling party is on the same side of the forward-to party,
780 * we don't need to track the second call */
781 if (callforward_filter &&
782 callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
783 ct->tuplehash[!dir].tuple.src.l3num)) {
784 DEBUGP("nf_ct_q931: Call Forwarding not tracked\n");
785 return 0;
786 }
787
788 /* Create expect for the second call leg */
789 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
790 return -1;
791 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
792 &ct->tuplehash[!dir].tuple.src.u3, &addr,
793 IPPROTO_TCP, NULL, &port);
794 exp->helper = nf_conntrack_helper_q931;
795
796 if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
797 &ct->tuplehash[!dir].tuple.dst.u3,
798 sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
799 (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
800 ct->status & IPS_NAT_MASK) {
801 /* Need NAT */
802 ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
803 taddr, port, exp);
804 } else { /* Conntrack only */
805 if (nf_conntrack_expect_related(exp) == 0) {
806 DEBUGP("nf_ct_q931: expect Call Forwarding ");
807 NF_CT_DUMP_TUPLE(&exp->tuple);
808 } else
809 ret = -1;
810 }
811
812 nf_conntrack_expect_put(exp);
813
814 return ret;
815}
816
817/****************************************************************************/
818static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
819 enum ip_conntrack_info ctinfo,
820 unsigned char **data, int dataoff,
821 Setup_UUIE *setup)
822{
823 int dir = CTINFO2DIR(ctinfo);
824 int ret;
825 int i;
826 __be16 port;
827 union nf_conntrack_address addr;
828 typeof(set_h225_addr_hook) set_h225_addr;
829
830 DEBUGP("nf_ct_q931: Setup\n");
831
832 if (setup->options & eSetup_UUIE_h245Address) {
833 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
834 &setup->h245Address);
835 if (ret < 0)
836 return -1;
837 }
838
839 set_h225_addr = rcu_dereference(set_h225_addr_hook);
840 if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
841 (set_h225_addr) && ct->status && IPS_NAT_MASK &&
842 get_h225_addr(ct, *data, &setup->destCallSignalAddress,
843 &addr, &port) &&
844 memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
845 DEBUGP("nf_ct_q931: set destCallSignalAddress "
846 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
847 NIP6(*(struct in6_addr *)&addr), ntohs(port),
848 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
849 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
850 ret = set_h225_addr(pskb, data, dataoff,
851 &setup->destCallSignalAddress,
852 &ct->tuplehash[!dir].tuple.src.u3,
853 ct->tuplehash[!dir].tuple.src.u.tcp.port);
854 if (ret < 0)
855 return -1;
856 }
857
858 if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
859 (set_h225_addr) && ct->status & IPS_NAT_MASK &&
860 get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
861 &addr, &port) &&
862 memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
863 DEBUGP("nf_ct_q931: set sourceCallSignalAddress "
864 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
865 NIP6(*(struct in6_addr *)&addr), ntohs(port),
866 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
867 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
868 ret = set_h225_addr(pskb, data, dataoff,
869 &setup->sourceCallSignalAddress,
870 &ct->tuplehash[!dir].tuple.dst.u3,
871 ct->tuplehash[!dir].tuple.dst.u.tcp.port);
872 if (ret < 0)
873 return -1;
874 }
875
876 if (setup->options & eSetup_UUIE_fastStart) {
877 for (i = 0; i < setup->fastStart.count; i++) {
878 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
879 &setup->fastStart.item[i]);
880 if (ret < 0)
881 return -1;
882 }
883 }
884
885 return 0;
886}
887
888/****************************************************************************/
889static int process_callproceeding(struct sk_buff **pskb,
890 struct nf_conn *ct,
891 enum ip_conntrack_info ctinfo,
892 unsigned char **data, int dataoff,
893 CallProceeding_UUIE *callproc)
894{
895 int ret;
896 int i;
897
898 DEBUGP("nf_ct_q931: CallProceeding\n");
899
900 if (callproc->options & eCallProceeding_UUIE_h245Address) {
901 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
902 &callproc->h245Address);
903 if (ret < 0)
904 return -1;
905 }
906
907 if (callproc->options & eCallProceeding_UUIE_fastStart) {
908 for (i = 0; i < callproc->fastStart.count; i++) {
909 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
910 &callproc->fastStart.item[i]);
911 if (ret < 0)
912 return -1;
913 }
914 }
915
916 return 0;
917}
918
919/****************************************************************************/
920static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
921 enum ip_conntrack_info ctinfo,
922 unsigned char **data, int dataoff,
923 Connect_UUIE *connect)
924{
925 int ret;
926 int i;
927
928 DEBUGP("nf_ct_q931: Connect\n");
929
930 if (connect->options & eConnect_UUIE_h245Address) {
931 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
932 &connect->h245Address);
933 if (ret < 0)
934 return -1;
935 }
936
937 if (connect->options & eConnect_UUIE_fastStart) {
938 for (i = 0; i < connect->fastStart.count; i++) {
939 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
940 &connect->fastStart.item[i]);
941 if (ret < 0)
942 return -1;
943 }
944 }
945
946 return 0;
947}
948
949/****************************************************************************/
950static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
951 enum ip_conntrack_info ctinfo,
952 unsigned char **data, int dataoff,
953 Alerting_UUIE *alert)
954{
955 int ret;
956 int i;
957
958 DEBUGP("nf_ct_q931: Alerting\n");
959
960 if (alert->options & eAlerting_UUIE_h245Address) {
961 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
962 &alert->h245Address);
963 if (ret < 0)
964 return -1;
965 }
966
967 if (alert->options & eAlerting_UUIE_fastStart) {
968 for (i = 0; i < alert->fastStart.count; i++) {
969 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
970 &alert->fastStart.item[i]);
971 if (ret < 0)
972 return -1;
973 }
974 }
975
976 return 0;
977}
978
979/****************************************************************************/
980static int process_information(struct sk_buff **pskb,
981 struct nf_conn *ct,
982 enum ip_conntrack_info ctinfo,
983 unsigned char **data, int dataoff,
984 Information_UUIE *info)
985{
986 int ret;
987 int i;
988
989 DEBUGP("nf_ct_q931: Information\n");
990
991 if (info->options & eInformation_UUIE_fastStart) {
992 for (i = 0; i < info->fastStart.count; i++) {
993 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
994 &info->fastStart.item[i]);
995 if (ret < 0)
996 return -1;
997 }
998 }
999
1000 return 0;
1001}
1002
1003/****************************************************************************/
1004static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
1005 enum ip_conntrack_info ctinfo,
1006 unsigned char **data, int dataoff,
1007 Facility_UUIE *facility)
1008{
1009 int ret;
1010 int i;
1011
1012 DEBUGP("nf_ct_q931: Facility\n");
1013
1014 if (facility->reason.choice == eFacilityReason_callForwarded) {
1015 if (facility->options & eFacility_UUIE_alternativeAddress)
1016 return expect_callforwarding(pskb, ct, ctinfo, data,
1017 dataoff,
1018 &facility->
1019 alternativeAddress);
1020 return 0;
1021 }
1022
1023 if (facility->options & eFacility_UUIE_h245Address) {
1024 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
1025 &facility->h245Address);
1026 if (ret < 0)
1027 return -1;
1028 }
1029
1030 if (facility->options & eFacility_UUIE_fastStart) {
1031 for (i = 0; i < facility->fastStart.count; i++) {
1032 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
1033 &facility->fastStart.item[i]);
1034 if (ret < 0)
1035 return -1;
1036 }
1037 }
1038
1039 return 0;
1040}
1041
1042/****************************************************************************/
1043static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
1044 enum ip_conntrack_info ctinfo,
1045 unsigned char **data, int dataoff,
1046 Progress_UUIE *progress)
1047{
1048 int ret;
1049 int i;
1050
1051 DEBUGP("nf_ct_q931: Progress\n");
1052
1053 if (progress->options & eProgress_UUIE_h245Address) {
1054 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
1055 &progress->h245Address);
1056 if (ret < 0)
1057 return -1;
1058 }
1059
1060 if (progress->options & eProgress_UUIE_fastStart) {
1061 for (i = 0; i < progress->fastStart.count; i++) {
1062 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
1063 &progress->fastStart.item[i]);
1064 if (ret < 0)
1065 return -1;
1066 }
1067 }
1068
1069 return 0;
1070}
1071
1072/****************************************************************************/
1073static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
1074 enum ip_conntrack_info ctinfo,
1075 unsigned char **data, int dataoff, Q931 *q931)
1076{
1077 H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
1078 int i;
1079 int ret = 0;
1080
1081 switch (pdu->h323_message_body.choice) {
1082 case eH323_UU_PDU_h323_message_body_setup:
1083 ret = process_setup(pskb, ct, ctinfo, data, dataoff,
1084 &pdu->h323_message_body.setup);
1085 break;
1086 case eH323_UU_PDU_h323_message_body_callProceeding:
1087 ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
1088 &pdu->h323_message_body.
1089 callProceeding);
1090 break;
1091 case eH323_UU_PDU_h323_message_body_connect:
1092 ret = process_connect(pskb, ct, ctinfo, data, dataoff,
1093 &pdu->h323_message_body.connect);
1094 break;
1095 case eH323_UU_PDU_h323_message_body_alerting:
1096 ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
1097 &pdu->h323_message_body.alerting);
1098 break;
1099 case eH323_UU_PDU_h323_message_body_information:
1100 ret = process_information(pskb, ct, ctinfo, data, dataoff,
1101 &pdu->h323_message_body.
1102 information);
1103 break;
1104 case eH323_UU_PDU_h323_message_body_facility:
1105 ret = process_facility(pskb, ct, ctinfo, data, dataoff,
1106 &pdu->h323_message_body.facility);
1107 break;
1108 case eH323_UU_PDU_h323_message_body_progress:
1109 ret = process_progress(pskb, ct, ctinfo, data, dataoff,
1110 &pdu->h323_message_body.progress);
1111 break;
1112 default:
1113 DEBUGP("nf_ct_q931: Q.931 signal %d\n",
1114 pdu->h323_message_body.choice);
1115 break;
1116 }
1117
1118 if (ret < 0)
1119 return -1;
1120
1121 if (pdu->options & eH323_UU_PDU_h245Control) {
1122 for (i = 0; i < pdu->h245Control.count; i++) {
1123 ret = process_h245(pskb, ct, ctinfo, data, dataoff,
1124 &pdu->h245Control.item[i]);
1125 if (ret < 0)
1126 return -1;
1127 }
1128 }
1129
1130 return 0;
1131}
1132
1133/****************************************************************************/
1134static int q931_help(struct sk_buff **pskb, unsigned int protoff,
1135 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1136{
1137 static Q931 q931;
1138 unsigned char *data = NULL;
1139 int datalen;
1140 int dataoff;
1141 int ret;
1142
1143 /* Until there's been traffic both ways, don't look in packets. */
1144 if (ctinfo != IP_CT_ESTABLISHED &&
1145 ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1146 return NF_ACCEPT;
1147 }
1148 DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len);
1149
1150 spin_lock_bh(&nf_h323_lock);
1151
1152 /* Process each TPKT */
1153 while (get_tpkt_data(pskb, protoff, ct, ctinfo,
1154 &data, &datalen, &dataoff)) {
1155 DEBUGP("nf_ct_q931: TPKT len=%d ", datalen);
1156 NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
1157
1158 /* Decode Q.931 signal */
1159 ret = DecodeQ931(data, datalen, &q931);
1160 if (ret < 0) {
1161 if (net_ratelimit())
1162 printk("nf_ct_q931: decoding error: %s\n",
1163 ret == H323_ERROR_BOUND ?
1164 "out of bound" : "out of range");
1165 /* We don't drop when decoding error */
1166 break;
1167 }
1168
1169 /* Process Q.931 signal */
1170 if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
1171 goto drop;
1172 }
1173
1174 spin_unlock_bh(&nf_h323_lock);
1175 return NF_ACCEPT;
1176
1177 drop:
1178 spin_unlock_bh(&nf_h323_lock);
1179 if (net_ratelimit())
1180 printk("nf_ct_q931: packet dropped\n");
1181 return NF_DROP;
1182}
1183
1184/****************************************************************************/
1185static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
1186 {
1187 .name = "Q.931",
1188 .me = THIS_MODULE,
1189 /* T.120 and H.245 */
1190 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
1191 .timeout = 240,
1192 .tuple.src.l3num = AF_INET,
1193 .tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
1194 .tuple.dst.protonum = IPPROTO_TCP,
1195 .mask.src.l3num = 0xFFFF,
1196 .mask.src.u.tcp.port = __constant_htons(0xFFFF),
1197 .mask.dst.protonum = 0xFF,
1198 .help = q931_help
1199 },
1200 {
1201 .name = "Q.931",
1202 .me = THIS_MODULE,
1203 /* T.120 and H.245 */
1204 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4,
1205 .timeout = 240,
1206 .tuple.src.l3num = AF_INET6,
1207 .tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
1208 .tuple.dst.protonum = IPPROTO_TCP,
1209 .mask.src.l3num = 0xFFFF,
1210 .mask.src.u.tcp.port = __constant_htons(0xFFFF),
1211 .mask.dst.protonum = 0xFF,
1212 .help = q931_help
1213 },
1214};
1215
1216/****************************************************************************/
1217static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff,
1218 int *datalen)
1219{
1220 struct udphdr _uh, *uh;
1221 int dataoff;
1222
1223 uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh);
1224 if (uh == NULL)
1225 return NULL;
1226 dataoff = protoff + sizeof(_uh);
1227 if (dataoff >= (*pskb)->len)
1228 return NULL;
1229 *datalen = (*pskb)->len - dataoff;
1230 return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
1231}
1232
1233/****************************************************************************/
1234static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
1235 union nf_conntrack_address *addr,
1236 __be16 port)
1237{
1238 struct nf_conntrack_expect *exp;
1239 struct nf_conntrack_tuple tuple;
1240
1241 memset(&tuple.src.u3, 0, sizeof(tuple.src.u3));
1242 tuple.src.u.tcp.port = 0;
1243 memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3));
1244 tuple.dst.u.tcp.port = port;
1245 tuple.dst.protonum = IPPROTO_TCP;
1246
1247 exp = __nf_conntrack_expect_find(&tuple);
1248 if (exp && exp->master == ct)
1249 return exp;
1250 return NULL;
1251}
1252
1253/****************************************************************************/
1254static int set_expect_timeout(struct nf_conntrack_expect *exp,
1255 unsigned timeout)
1256{
1257 if (!exp || !del_timer(&exp->timeout))
1258 return 0;
1259
1260 exp->timeout.expires = jiffies + timeout * HZ;
1261 add_timer(&exp->timeout);
1262
1263 return 1;
1264}
1265
1266/****************************************************************************/
1267static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
1268 enum ip_conntrack_info ctinfo,
1269 unsigned char **data,
1270 TransportAddress *taddr, int count)
1271{
1272 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
1273 int dir = CTINFO2DIR(ctinfo);
1274 int ret = 0;
1275 int i;
1276 __be16 port;
1277 union nf_conntrack_address addr;
1278 struct nf_conntrack_expect *exp;
1279 typeof(nat_q931_hook) nat_q931;
1280
1281 /* Look for the first related address */
1282 for (i = 0; i < count; i++) {
1283 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
1284 memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3,
1285 sizeof(addr)) == 0 && port != 0)
1286 break;
1287 }
1288
1289 if (i >= count) /* Not found */
1290 return 0;
1291
1292 /* Create expect for Q.931 */
1293 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
1294 return -1;
1295 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
1296 gkrouted_only ? /* only accept calls from GK? */
1297 &ct->tuplehash[!dir].tuple.src.u3 :
1298 NULL,
1299 &ct->tuplehash[!dir].tuple.dst.u3,
1300 IPPROTO_TCP, NULL, &port);
1301 exp->helper = nf_conntrack_helper_q931;
1302 exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
1303
1304 nat_q931 = rcu_dereference(nat_q931_hook);
1305 if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */
1306 ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp);
1307 } else { /* Conntrack only */
1308 if (nf_conntrack_expect_related(exp) == 0) {
1309 DEBUGP("nf_ct_ras: expect Q.931 ");
1310 NF_CT_DUMP_TUPLE(&exp->tuple);
1311
1312 /* Save port for looking up expect in processing RCF */
1313 info->sig_port[dir] = port;
1314 } else
1315 ret = -1;
1316 }
1317
1318 nf_conntrack_expect_put(exp);
1319
1320 return ret;
1321}
1322
1323/****************************************************************************/
1324static int process_grq(struct sk_buff **pskb, struct nf_conn *ct,
1325 enum ip_conntrack_info ctinfo,
1326 unsigned char **data, GatekeeperRequest *grq)
1327{
1328 typeof(set_ras_addr_hook) set_ras_addr;
1329
1330 DEBUGP("nf_ct_ras: GRQ\n");
1331
1332 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1333 if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */
1334 return set_ras_addr(pskb, ct, ctinfo, data,
1335 &grq->rasAddress, 1);
1336 return 0;
1337}
1338
1339/****************************************************************************/
1340static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct,
1341 enum ip_conntrack_info ctinfo,
1342 unsigned char **data, GatekeeperConfirm *gcf)
1343{
1344 int dir = CTINFO2DIR(ctinfo);
1345 int ret = 0;
1346 __be16 port;
1347 union nf_conntrack_address addr;
1348 struct nf_conntrack_expect *exp;
1349
1350 DEBUGP("nf_ct_ras: GCF\n");
1351
1352 if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
1353 return 0;
1354
1355 /* Registration port is the same as discovery port */
1356 if (!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
1357 port == ct->tuplehash[dir].tuple.src.u.udp.port)
1358 return 0;
1359
1360 /* Avoid RAS expectation loops. A GCF is never expected. */
1361 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
1362 return 0;
1363
1364 /* Need new expect */
1365 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
1366 return -1;
1367 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
1368 &ct->tuplehash[!dir].tuple.src.u3, &addr,
1369 IPPROTO_UDP, NULL, &port);
1370 exp->helper = nf_conntrack_helper_ras;
1371
1372 if (nf_conntrack_expect_related(exp) == 0) {
1373 DEBUGP("nf_ct_ras: expect RAS ");
1374 NF_CT_DUMP_TUPLE(&exp->tuple);
1375 } else
1376 ret = -1;
1377
1378 nf_conntrack_expect_put(exp);
1379
1380 return ret;
1381}
1382
1383/****************************************************************************/
1384static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
1385 enum ip_conntrack_info ctinfo,
1386 unsigned char **data, RegistrationRequest *rrq)
1387{
1388 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
1389 int ret;
1390 typeof(set_ras_addr_hook) set_ras_addr;
1391
1392 DEBUGP("nf_ct_ras: RRQ\n");
1393
1394 ret = expect_q931(pskb, ct, ctinfo, data,
1395 rrq->callSignalAddress.item,
1396 rrq->callSignalAddress.count);
1397 if (ret < 0)
1398 return -1;
1399
1400 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1401 if (set_ras_addr && ct->status & IPS_NAT_MASK) {
1402 ret = set_ras_addr(pskb, ct, ctinfo, data,
1403 rrq->rasAddress.item,
1404 rrq->rasAddress.count);
1405 if (ret < 0)
1406 return -1;
1407 }
1408
1409 if (rrq->options & eRegistrationRequest_timeToLive) {
1410 DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
1411 info->timeout = rrq->timeToLive;
1412 } else
1413 info->timeout = default_rrq_ttl;
1414
1415 return 0;
1416}
1417
1418/****************************************************************************/
1419static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
1420 enum ip_conntrack_info ctinfo,
1421 unsigned char **data, RegistrationConfirm *rcf)
1422{
1423 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
1424 int dir = CTINFO2DIR(ctinfo);
1425 int ret;
1426 struct nf_conntrack_expect *exp;
1427 typeof(set_sig_addr_hook) set_sig_addr;
1428
1429 DEBUGP("nf_ct_ras: RCF\n");
1430
1431 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1432 if (set_sig_addr && ct->status & IPS_NAT_MASK) {
1433 ret = set_sig_addr(pskb, ct, ctinfo, data,
1434 rcf->callSignalAddress.item,
1435 rcf->callSignalAddress.count);
1436 if (ret < 0)
1437 return -1;
1438 }
1439
1440 if (rcf->options & eRegistrationConfirm_timeToLive) {
1441 DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
1442 info->timeout = rcf->timeToLive;
1443 }
1444
1445 if (info->timeout > 0) {
1446 DEBUGP
1447 ("nf_ct_ras: set RAS connection timeout to %u seconds\n",
1448 info->timeout);
1449 nf_ct_refresh(ct, *pskb, info->timeout * HZ);
1450
1451 /* Set expect timeout */
1452 read_lock_bh(&nf_conntrack_lock);
1453 exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
1454 info->sig_port[!dir]);
1455 if (exp) {
1456 DEBUGP("nf_ct_ras: set Q.931 expect "
1457 "timeout to %u seconds for",
1458 info->timeout);
1459 NF_CT_DUMP_TUPLE(&exp->tuple);
1460 set_expect_timeout(exp, info->timeout);
1461 }
1462 read_unlock_bh(&nf_conntrack_lock);
1463 }
1464
1465 return 0;
1466}
1467
1468/****************************************************************************/
1469static int process_urq(struct sk_buff **pskb, struct nf_conn *ct,
1470 enum ip_conntrack_info ctinfo,
1471 unsigned char **data, UnregistrationRequest *urq)
1472{
1473 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
1474 int dir = CTINFO2DIR(ctinfo);
1475 int ret;
1476 typeof(set_sig_addr_hook) set_sig_addr;
1477
1478 DEBUGP("nf_ct_ras: URQ\n");
1479
1480 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1481 if (set_sig_addr && ct->status & IPS_NAT_MASK) {
1482 ret = set_sig_addr(pskb, ct, ctinfo, data,
1483 urq->callSignalAddress.item,
1484 urq->callSignalAddress.count);
1485 if (ret < 0)
1486 return -1;
1487 }
1488
1489 /* Clear old expect */
1490 nf_ct_remove_expectations(ct);
1491 info->sig_port[dir] = 0;
1492 info->sig_port[!dir] = 0;
1493
1494 /* Give it 30 seconds for UCF or URJ */
1495 nf_ct_refresh(ct, *pskb, 30 * HZ);
1496
1497 return 0;
1498}
1499
1500/****************************************************************************/
1501static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
1502 enum ip_conntrack_info ctinfo,
1503 unsigned char **data, AdmissionRequest *arq)
1504{
1505 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
1506 int dir = CTINFO2DIR(ctinfo);
1507 __be16 port;
1508 union nf_conntrack_address addr;
1509 typeof(set_h225_addr_hook) set_h225_addr;
1510
1511 DEBUGP("nf_ct_ras: ARQ\n");
1512
1513 set_h225_addr = rcu_dereference(set_h225_addr_hook);
1514 if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
1515 get_h225_addr(ct, *data, &arq->destCallSignalAddress,
1516 &addr, &port) &&
1517 !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
1518 port == info->sig_port[dir] &&
1519 set_h225_addr && ct->status & IPS_NAT_MASK) {
1520 /* Answering ARQ */
1521 return set_h225_addr(pskb, data, 0,
1522 &arq->destCallSignalAddress,
1523 &ct->tuplehash[!dir].tuple.dst.u3,
1524 info->sig_port[!dir]);
1525 }
1526
1527 if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
1528 get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
1529 &addr, &port) &&
1530 !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
1531 set_h225_addr && ct->status & IPS_NAT_MASK) {
1532 /* Calling ARQ */
1533 return set_h225_addr(pskb, data, 0,
1534 &arq->srcCallSignalAddress,
1535 &ct->tuplehash[!dir].tuple.dst.u3,
1536 port);
1537 }
1538
1539 return 0;
1540}
1541
1542/****************************************************************************/
1543static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
1544 enum ip_conntrack_info ctinfo,
1545 unsigned char **data, AdmissionConfirm *acf)
1546{
1547 int dir = CTINFO2DIR(ctinfo);
1548 int ret = 0;
1549 __be16 port;
1550 union nf_conntrack_address addr;
1551 struct nf_conntrack_expect *exp;
1552 typeof(set_sig_addr_hook) set_sig_addr;
1553
1554 DEBUGP("nf_ct_ras: ACF\n");
1555
1556 if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
1557 &addr, &port))
1558 return 0;
1559
1560 if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) {
1561 /* Answering ACF */
1562 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1563 if (set_sig_addr && ct->status & IPS_NAT_MASK)
1564 return set_sig_addr(pskb, ct, ctinfo, data,
1565 &acf->destCallSignalAddress, 1);
1566 return 0;
1567 }
1568
1569 /* Need new expect */
1570 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
1571 return -1;
1572 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
1573 &ct->tuplehash[!dir].tuple.src.u3, &addr,
1574 IPPROTO_TCP, NULL, &port);
1575 exp->flags = NF_CT_EXPECT_PERMANENT;
1576 exp->helper = nf_conntrack_helper_q931;
1577
1578 if (nf_conntrack_expect_related(exp) == 0) {
1579 DEBUGP("nf_ct_ras: expect Q.931 ");
1580 NF_CT_DUMP_TUPLE(&exp->tuple);
1581 } else
1582 ret = -1;
1583
1584 nf_conntrack_expect_put(exp);
1585
1586 return ret;
1587}
1588
1589/****************************************************************************/
1590static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct,
1591 enum ip_conntrack_info ctinfo,
1592 unsigned char **data, LocationRequest *lrq)
1593{
1594 typeof(set_ras_addr_hook) set_ras_addr;
1595
1596 DEBUGP("nf_ct_ras: LRQ\n");
1597
1598 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1599 if (set_ras_addr && ct->status & IPS_NAT_MASK)
1600 return set_ras_addr(pskb, ct, ctinfo, data,
1601 &lrq->replyAddress, 1);
1602 return 0;
1603}
1604
1605/****************************************************************************/
1606static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct,
1607 enum ip_conntrack_info ctinfo,
1608 unsigned char **data, LocationConfirm *lcf)
1609{
1610 int dir = CTINFO2DIR(ctinfo);
1611 int ret = 0;
1612 __be16 port;
1613 union nf_conntrack_address addr;
1614 struct nf_conntrack_expect *exp;
1615
1616 DEBUGP("nf_ct_ras: LCF\n");
1617
1618 if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
1619 &addr, &port))
1620 return 0;
1621
1622 /* Need new expect for call signal */
1623 if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
1624 return -1;
1625 nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
1626 &ct->tuplehash[!dir].tuple.src.u3, &addr,
1627 IPPROTO_TCP, NULL, &port);
1628 exp->flags = NF_CT_EXPECT_PERMANENT;
1629 exp->helper = nf_conntrack_helper_q931;
1630
1631 if (nf_conntrack_expect_related(exp) == 0) {
1632 DEBUGP("nf_ct_ras: expect Q.931 ");
1633 NF_CT_DUMP_TUPLE(&exp->tuple);
1634 } else
1635 ret = -1;
1636
1637 nf_conntrack_expect_put(exp);
1638
1639 /* Ignore rasAddress */
1640
1641 return ret;
1642}
1643
1644/****************************************************************************/
1645static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
1646 enum ip_conntrack_info ctinfo,
1647 unsigned char **data, InfoRequestResponse *irr)
1648{
1649 int ret;
1650 typeof(set_ras_addr_hook) set_ras_addr;
1651 typeof(set_sig_addr_hook) set_sig_addr;
1652
1653 DEBUGP("nf_ct_ras: IRR\n");
1654
1655 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1656 if (set_ras_addr && ct->status & IPS_NAT_MASK) {
1657 ret = set_ras_addr(pskb, ct, ctinfo, data,
1658 &irr->rasAddress, 1);
1659 if (ret < 0)
1660 return -1;
1661 }
1662
1663 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1664 if (set_sig_addr && ct->status & IPS_NAT_MASK) {
1665 ret = set_sig_addr(pskb, ct, ctinfo, data,
1666 irr->callSignalAddress.item,
1667 irr->callSignalAddress.count);
1668 if (ret < 0)
1669 return -1;
1670 }
1671
1672 return 0;
1673}
1674
1675/****************************************************************************/
1676static int process_ras(struct sk_buff **pskb, struct nf_conn *ct,
1677 enum ip_conntrack_info ctinfo,
1678 unsigned char **data, RasMessage *ras)
1679{
1680 switch (ras->choice) {
1681 case eRasMessage_gatekeeperRequest:
1682 return process_grq(pskb, ct, ctinfo, data,
1683 &ras->gatekeeperRequest);
1684 case eRasMessage_gatekeeperConfirm:
1685 return process_gcf(pskb, ct, ctinfo, data,
1686 &ras->gatekeeperConfirm);
1687 case eRasMessage_registrationRequest:
1688 return process_rrq(pskb, ct, ctinfo, data,
1689 &ras->registrationRequest);
1690 case eRasMessage_registrationConfirm:
1691 return process_rcf(pskb, ct, ctinfo, data,
1692 &ras->registrationConfirm);
1693 case eRasMessage_unregistrationRequest:
1694 return process_urq(pskb, ct, ctinfo, data,
1695 &ras->unregistrationRequest);
1696 case eRasMessage_admissionRequest:
1697 return process_arq(pskb, ct, ctinfo, data,
1698 &ras->admissionRequest);
1699 case eRasMessage_admissionConfirm:
1700 return process_acf(pskb, ct, ctinfo, data,
1701 &ras->admissionConfirm);
1702 case eRasMessage_locationRequest:
1703 return process_lrq(pskb, ct, ctinfo, data,
1704 &ras->locationRequest);
1705 case eRasMessage_locationConfirm:
1706 return process_lcf(pskb, ct, ctinfo, data,
1707 &ras->locationConfirm);
1708 case eRasMessage_infoRequestResponse:
1709 return process_irr(pskb, ct, ctinfo, data,
1710 &ras->infoRequestResponse);
1711 default:
1712 DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice);
1713 break;
1714 }
1715
1716 return 0;
1717}
1718
1719/****************************************************************************/
1720static int ras_help(struct sk_buff **pskb, unsigned int protoff,
1721 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1722{
1723 static RasMessage ras;
1724 unsigned char *data;
1725 int datalen = 0;
1726 int ret;
1727
1728 DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len);
1729
1730 spin_lock_bh(&nf_h323_lock);
1731
1732 /* Get UDP data */
1733 data = get_udp_data(pskb, protoff, &datalen);
1734 if (data == NULL)
1735 goto accept;
1736 DEBUGP("nf_ct_ras: RAS message len=%d ", datalen);
1737 NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
1738
1739 /* Decode RAS message */
1740 ret = DecodeRasMessage(data, datalen, &ras);
1741 if (ret < 0) {
1742 if (net_ratelimit())
1743 printk("nf_ct_ras: decoding error: %s\n",
1744 ret == H323_ERROR_BOUND ?
1745 "out of bound" : "out of range");
1746 goto accept;
1747 }
1748
1749 /* Process RAS message */
1750 if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
1751 goto drop;
1752
1753 accept:
1754 spin_unlock_bh(&nf_h323_lock);
1755 return NF_ACCEPT;
1756
1757 drop:
1758 spin_unlock_bh(&nf_h323_lock);
1759 if (net_ratelimit())
1760 printk("nf_ct_ras: packet dropped\n");
1761 return NF_DROP;
1762}
1763
1764/****************************************************************************/
1765static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
1766 {
1767 .name = "RAS",
1768 .me = THIS_MODULE,
1769 .max_expected = 32,
1770 .timeout = 240,
1771 .tuple.src.l3num = AF_INET,
1772 .tuple.src.u.udp.port = __constant_htons(RAS_PORT),
1773 .tuple.dst.protonum = IPPROTO_UDP,
1774 .mask.src.l3num = 0xFFFF,
1775 .mask.src.u.udp.port = __constant_htons(0xFFFF),
1776 .mask.dst.protonum = 0xFF,
1777 .help = ras_help,
1778 },
1779 {
1780 .name = "RAS",
1781 .me = THIS_MODULE,
1782 .max_expected = 32,
1783 .timeout = 240,
1784 .tuple.src.l3num = AF_INET6,
1785 .tuple.src.u.udp.port = __constant_htons(RAS_PORT),
1786 .tuple.dst.protonum = IPPROTO_UDP,
1787 .mask.src.l3num = 0xFFFF,
1788 .mask.src.u.udp.port = __constant_htons(0xFFFF),
1789 .mask.dst.protonum = 0xFF,
1790 .help = ras_help,
1791 },
1792};
1793
1794/****************************************************************************/
1795static void __exit nf_conntrack_h323_fini(void)
1796{
1797 nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[1]);
1798 nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
1799 nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
1800 nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
1801 kfree(h323_buffer);
1802 DEBUGP("nf_ct_h323: fini\n");
1803}
1804
1805/****************************************************************************/
1806static int __init nf_conntrack_h323_init(void)
1807{
1808 int ret;
1809
1810 h323_buffer = kmalloc(65536, GFP_KERNEL);
1811 if (!h323_buffer)
1812 return -ENOMEM;
1813 ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]);
1814 if (ret < 0)
1815 goto err1;
1816 ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]);
1817 if (ret < 0)
1818 goto err2;
1819 ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]);
1820 if (ret < 0)
1821 goto err3;
1822 ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
1823 if (ret < 0)
1824 goto err4;
1825 DEBUGP("nf_ct_h323: init success\n");
1826 return 0;
1827
1828err4:
1829 nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]);
1830err3:
1831 nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
1832err2:
1833 nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
1834err1:
1835 return ret;
1836}
1837
1838/****************************************************************************/
1839module_init(nf_conntrack_h323_init);
1840module_exit(nf_conntrack_h323_fini);
1841
1842EXPORT_SYMBOL_GPL(get_h225_addr);
1843EXPORT_SYMBOL_GPL(set_h245_addr_hook);
1844EXPORT_SYMBOL_GPL(set_h225_addr_hook);
1845EXPORT_SYMBOL_GPL(set_sig_addr_hook);
1846EXPORT_SYMBOL_GPL(set_ras_addr_hook);
1847EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
1848EXPORT_SYMBOL_GPL(nat_t120_hook);
1849EXPORT_SYMBOL_GPL(nat_h245_hook);
1850EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
1851EXPORT_SYMBOL_GPL(nat_q931_hook);
1852
1853MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
1854MODULE_DESCRIPTION("H.323 connection tracking helper");
1855MODULE_LICENSE("GPL");
1856MODULE_ALIAS("ip_conntrack_h323");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/netfilter/nf_conntrack_h323_types.c
index 4b359618bedd..4c6f8b3b1208 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
+++ b/net/netfilter/nf_conntrack_h323_types.c
@@ -36,7 +36,8 @@ static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */
36}; 36};
37 37
38static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ 38static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */
39 {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, 39 {FNAME("ip") OCTSTR, FIXD, 16, 0, DECODE,
40 offsetof(TransportAddress_ip6Address, ip6), NULL},
40 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, 41 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
41}; 42};
42 43
@@ -65,8 +66,8 @@ static field_t _TransportAddress[] = { /* CHOICE */
65 _TransportAddress_ipSourceRoute}, 66 _TransportAddress_ipSourceRoute},
66 {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0, 67 {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
67 _TransportAddress_ipxAddress}, 68 _TransportAddress_ipxAddress},
68 {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, 69 {FNAME("ip6Address") SEQ, 0, 2, 2, DECODE | EXT,
69 _TransportAddress_ip6Address}, 70 offsetof(TransportAddress, ip6Address), _TransportAddress_ip6Address},
70 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, 71 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
71 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, 72 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
72 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, 73 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,