aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-03-14 19:37:25 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:25:34 -0400
commit587aa64163bb14f70098f450abab9410787fce9d (patch)
tree399c00a969d9a8c7af13675583c5417282d18974
parentce18afe57bf53477f133208856dd2b7e6b5db5e3 (diff)
[NETFILTER]: Remove IPv4 only connection tracking/NAT
Remove the obsolete IPv4 only connection tracking/NAT as scheduled in feature-removal-schedule. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/feature-removal-schedule.txt9
-rw-r--r--include/linux/netfilter_ipv4/Kbuild14
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h402
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_amanda.h11
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_core.h61
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_ftp.h44
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_h323.h89
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper.h46
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_icmp.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_irc.h32
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_pptp.h326
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h114
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_protocol.h98
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_sctp.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_sip.h40
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tcp.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tftp.h20
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tuple.h146
-rw-r--r--include/linux/netfilter_ipv4/ip_nat.h79
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_core.h18
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_helper.h33
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_pptp.h11
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_protocol.h74
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_rule.h28
-rw-r--r--include/linux/netfilter_ipv4/ipt_SAME.h2
-rw-r--r--include/net/netfilter/nf_conntrack.h5
-rw-r--r--include/net/netfilter/nf_conntrack_compat.h145
-rw-r--r--include/net/netfilter/nf_nat_rule.h10
-rw-r--r--net/ipv4/netfilter/Kconfig267
-rw-r--r--net/ipv4/netfilter/Makefile45
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c229
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c1549
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c520
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c1840
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c684
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c314
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c143
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c1577
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_generic.c74
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c328
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c315
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c659
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c1163
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c148
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c520
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c962
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c161
-rw-r--r--net/ipv4/netfilter/ip_nat_amanda.c85
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c633
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c180
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c436
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c611
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c350
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c122
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c174
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_icmp.c87
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c154
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c144
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_unknown.c55
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c314
-rw-r--r--net/ipv4/netfilter/ip_nat_sip.c282
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c1333
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c387
-rw-r--r--net/ipv4/netfilter/ip_nat_tftp.c70
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c18
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c57
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c22
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c24
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c25
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c2
-rw-r--r--net/netfilter/Kconfig63
-rw-r--r--net/netfilter/xt_CONNMARK.c32
-rw-r--r--net/netfilter/xt_CONNSECMARK.c18
-rw-r--r--net/netfilter/xt_NOTRACK.c4
-rw-r--r--net/netfilter/xt_connbytes.c10
-rw-r--r--net/netfilter/xt_connmark.c17
-rw-r--r--net/netfilter/xt_conntrack.c110
-rw-r--r--net/netfilter/xt_helper.c57
-rw-r--r--net/netfilter/xt_state.c4
80 files changed, 122 insertions, 19135 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 19b4c96b2a49..9817b60e70a3 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -211,15 +211,6 @@ Who: Adrian Bunk <bunk@stusta.de>
211 211
212--------------------------- 212---------------------------
213 213
214What: IPv4 only connection tracking/NAT/helpers
215When: 2.6.22
216Why: The new layer 3 independant connection tracking replaces the old
217 IPv4 only version. After some stabilization of the new code the
218 old one will be removed.
219Who: Patrick McHardy <kaber@trash.net>
220
221---------------------------
222
223What: ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver 214What: ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
224When: December 2006 215When: December 2006
225Why: Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are 216Why: Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
index 180337801a86..7185792b900f 100644
--- a/include/linux/netfilter_ipv4/Kbuild
+++ b/include/linux/netfilter_ipv4/Kbuild
@@ -1,9 +1,3 @@
1header-y += ip_conntrack_helper.h
2header-y += ip_conntrack_protocol.h
3header-y += ip_conntrack_sctp.h
4header-y += ip_conntrack_tcp.h
5header-y += ip_conntrack_tftp.h
6header-y += ip_nat_pptp.h
7header-y += ipt_addrtype.h 1header-y += ipt_addrtype.h
8header-y += ipt_ah.h 2header-y += ipt_ah.h
9header-y += ipt_CLASSIFY.h 3header-y += ipt_CLASSIFY.h
@@ -49,13 +43,5 @@ header-y += ipt_ttl.h
49header-y += ipt_TTL.h 43header-y += ipt_TTL.h
50header-y += ipt_ULOG.h 44header-y += ipt_ULOG.h
51 45
52unifdef-y += ip_conntrack.h
53unifdef-y += ip_conntrack_h323.h
54unifdef-y += ip_conntrack_irc.h
55unifdef-y += ip_conntrack_pptp.h
56unifdef-y += ip_conntrack_proto_gre.h
57unifdef-y += ip_conntrack_tuple.h
58unifdef-y += ip_nat.h
59unifdef-y += ip_nat_rule.h
60unifdef-y += ip_queue.h 46unifdef-y += ip_queue.h
61unifdef-y += ip_tables.h 47unifdef-y += ip_tables.h
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
deleted file mode 100644
index da9274e6bf12..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ /dev/null
@@ -1,402 +0,0 @@
1#ifndef _IP_CONNTRACK_H
2#define _IP_CONNTRACK_H
3
4#include <linux/netfilter/nf_conntrack_common.h>
5
6#ifdef __KERNEL__
7#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
8#include <linux/bitops.h>
9#include <linux/compiler.h>
10#include <asm/atomic.h>
11
12#include <linux/timer.h>
13#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
14#include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
15#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
16#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
17
18/* per conntrack: protocol private data */
19union ip_conntrack_proto {
20 /* insert conntrack proto private data here */
21 struct ip_ct_gre gre;
22 struct ip_ct_sctp sctp;
23 struct ip_ct_tcp tcp;
24 struct ip_ct_icmp icmp;
25};
26
27union ip_conntrack_expect_proto {
28 /* insert expect proto private data here */
29};
30
31/* Add protocol helper include file here */
32#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
33#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
34#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
35#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
36#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
37
38/* per conntrack: application helper private data */
39union ip_conntrack_help {
40 /* insert conntrack helper private data (master) here */
41 struct ip_ct_h323_master ct_h323_info;
42 struct ip_ct_pptp_master ct_pptp_info;
43 struct ip_ct_ftp_master ct_ftp_info;
44 struct ip_ct_irc_master ct_irc_info;
45};
46
47#ifdef CONFIG_IP_NF_NAT_NEEDED
48#include <linux/netfilter_ipv4/ip_nat.h>
49#include <linux/netfilter_ipv4/ip_nat_pptp.h>
50
51/* per conntrack: nat application helper private data */
52union ip_conntrack_nat_help {
53 /* insert nat helper private data here */
54 struct ip_nat_pptp nat_pptp_info;
55};
56#endif
57
58#include <linux/types.h>
59#include <linux/skbuff.h>
60
61#ifdef CONFIG_NETFILTER_DEBUG
62#define IP_NF_ASSERT(x) \
63do { \
64 if (!(x)) \
65 /* Wooah! I'm tripping my conntrack in a frenzy of \
66 netplay... */ \
67 printk("NF_IP_ASSERT: %s:%i(%s)\n", \
68 __FILE__, __LINE__, __FUNCTION__); \
69} while(0)
70#else
71#define IP_NF_ASSERT(x)
72#endif
73
74struct ip_conntrack_helper;
75
76struct ip_conntrack
77{
78 /* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
79 plus 1 for any connection(s) we are `master' for */
80 struct nf_conntrack ct_general;
81
82 /* Have we seen traffic both ways yet? (bitset) */
83 unsigned long status;
84
85 /* Timer function; drops refcnt when it goes off. */
86 struct timer_list timeout;
87
88#ifdef CONFIG_IP_NF_CT_ACCT
89 /* Accounting Information (same cache line as other written members) */
90 struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
91#endif
92 /* If we were expected by an expectation, this will be it */
93 struct ip_conntrack *master;
94
95 /* Current number of expected connections */
96 unsigned int expecting;
97
98 /* Unique ID that identifies this conntrack*/
99 unsigned int id;
100
101 /* Helper, if any. */
102 struct ip_conntrack_helper *helper;
103
104 /* Storage reserved for other modules: */
105 union ip_conntrack_proto proto;
106
107 union ip_conntrack_help help;
108
109#ifdef CONFIG_IP_NF_NAT_NEEDED
110 struct {
111 struct ip_nat_info info;
112 union ip_conntrack_nat_help help;
113#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
114 defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
115 int masq_index;
116#endif
117 } nat;
118#endif /* CONFIG_IP_NF_NAT_NEEDED */
119
120#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
121 u_int32_t mark;
122#endif
123
124#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
125 u_int32_t secmark;
126#endif
127
128 /* Traversed often, so hopefully in different cacheline to top */
129 /* These are my tuples; original and reply */
130 struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
131};
132
133struct ip_conntrack_expect
134{
135 /* Internal linked list (global expectation list) */
136 struct list_head list;
137
138 /* We expect this tuple, with the following mask */
139 struct ip_conntrack_tuple tuple, mask;
140
141 /* Function to call after setup and insertion */
142 void (*expectfn)(struct ip_conntrack *new,
143 struct ip_conntrack_expect *this);
144
145 /* The conntrack of the master connection */
146 struct ip_conntrack *master;
147
148 /* Timer function; deletes the expectation. */
149 struct timer_list timeout;
150
151 /* Usage count. */
152 atomic_t use;
153
154 /* Unique ID */
155 unsigned int id;
156
157 /* Flags */
158 unsigned int flags;
159
160#ifdef CONFIG_IP_NF_NAT_NEEDED
161 __be32 saved_ip;
162 /* This is the original per-proto part, used to map the
163 * expected connection the way the recipient expects. */
164 union ip_conntrack_manip_proto saved_proto;
165 /* Direction relative to the master connection. */
166 enum ip_conntrack_dir dir;
167#endif
168};
169
170#define IP_CT_EXPECT_PERMANENT 0x1
171
172static inline struct ip_conntrack *
173tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash)
174{
175 return container_of(hash, struct ip_conntrack,
176 tuplehash[hash->tuple.dst.dir]);
177}
178
179/* get master conntrack via master expectation */
180#define master_ct(conntr) (conntr->master)
181
182/* Alter reply tuple (maybe alter helper). */
183extern void
184ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
185 const struct ip_conntrack_tuple *newreply);
186
187/* Is this tuple taken? (ignoring any belonging to the given
188 conntrack). */
189extern int
190ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
191 const struct ip_conntrack *ignored_conntrack);
192
193/* Return conntrack_info and tuple hash for given skb. */
194static inline struct ip_conntrack *
195ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
196{
197 *ctinfo = skb->nfctinfo;
198 return (struct ip_conntrack *)skb->nfct;
199}
200
201/* decrement reference count on a conntrack */
202static inline void
203ip_conntrack_put(struct ip_conntrack *ct)
204{
205 IP_NF_ASSERT(ct);
206 nf_conntrack_put(&ct->ct_general);
207}
208
209extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
210 const struct ip_conntrack_tuple *orig);
211
212extern void __ip_ct_refresh_acct(struct ip_conntrack *ct,
213 enum ip_conntrack_info ctinfo,
214 const struct sk_buff *skb,
215 unsigned long extra_jiffies,
216 int do_acct);
217
218/* Refresh conntrack for this many jiffies and do accounting */
219static inline void ip_ct_refresh_acct(struct ip_conntrack *ct,
220 enum ip_conntrack_info ctinfo,
221 const struct sk_buff *skb,
222 unsigned long extra_jiffies)
223{
224 __ip_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
225}
226
227/* Refresh conntrack for this many jiffies */
228static inline void ip_ct_refresh(struct ip_conntrack *ct,
229 const struct sk_buff *skb,
230 unsigned long extra_jiffies)
231{
232 __ip_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
233}
234
235/* These are for NAT. Icky. */
236/* Update TCP window tracking data when NAT mangles the packet */
237extern void ip_conntrack_tcp_update(struct sk_buff *skb,
238 struct ip_conntrack *conntrack,
239 enum ip_conntrack_dir dir);
240
241/* Call me when a conntrack is destroyed. */
242extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
243
244/* Fake conntrack entry for untracked connections */
245extern struct ip_conntrack ip_conntrack_untracked;
246
247/* Returns new sk_buff, or NULL */
248struct sk_buff *
249ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
250
251/* Iterate over all conntracks: if iter returns true, it's deleted. */
252extern void
253ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *data),
254 void *data);
255
256extern struct ip_conntrack_helper *
257__ip_conntrack_helper_find_byname(const char *);
258extern struct ip_conntrack_helper *
259ip_conntrack_helper_find_get(const struct ip_conntrack_tuple *tuple);
260extern void ip_conntrack_helper_put(struct ip_conntrack_helper *helper);
261
262extern struct ip_conntrack_protocol *
263__ip_conntrack_proto_find(u_int8_t protocol);
264extern struct ip_conntrack_protocol *
265ip_conntrack_proto_find_get(u_int8_t protocol);
266extern void ip_conntrack_proto_put(struct ip_conntrack_protocol *proto);
267
268extern void ip_ct_remove_expectations(struct ip_conntrack *ct);
269
270extern struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *,
271 struct ip_conntrack_tuple *);
272
273extern void ip_conntrack_free(struct ip_conntrack *ct);
274
275extern void ip_conntrack_hash_insert(struct ip_conntrack *ct);
276
277extern struct ip_conntrack_expect *
278__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
279
280extern struct ip_conntrack_expect *
281ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
282
283extern struct ip_conntrack_tuple_hash *
284__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
285 const struct ip_conntrack *ignored_conntrack);
286
287extern void ip_conntrack_flush(void);
288
289/* It's confirmed if it is, or has been in the hash table. */
290static inline int is_confirmed(struct ip_conntrack *ct)
291{
292 return test_bit(IPS_CONFIRMED_BIT, &ct->status);
293}
294
295static inline int is_dying(struct ip_conntrack *ct)
296{
297 return test_bit(IPS_DYING_BIT, &ct->status);
298}
299
300extern unsigned int ip_conntrack_htable_size;
301extern int ip_conntrack_checksum;
302
303#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
304#define CONNTRACK_STAT_INC_ATOMIC(count) \
305do { \
306 local_bh_disable(); \
307 __get_cpu_var(ip_conntrack_stat).count++; \
308 local_bh_enable(); \
309} while (0)
310
311#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
312#include <linux/notifier.h>
313#include <linux/interrupt.h>
314
315struct ip_conntrack_ecache {
316 struct ip_conntrack *ct;
317 unsigned int events;
318};
319DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
320
321#define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x)
322
323extern struct atomic_notifier_head ip_conntrack_chain;
324extern struct atomic_notifier_head ip_conntrack_expect_chain;
325
326static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
327{
328 return atomic_notifier_chain_register(&ip_conntrack_chain, nb);
329}
330
331static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
332{
333 return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb);
334}
335
336static inline int
337ip_conntrack_expect_register_notifier(struct notifier_block *nb)
338{
339 return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb);
340}
341
342static inline int
343ip_conntrack_expect_unregister_notifier(struct notifier_block *nb)
344{
345 return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain,
346 nb);
347}
348
349extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
350extern void __ip_ct_event_cache_init(struct ip_conntrack *ct);
351
352static inline void
353ip_conntrack_event_cache(enum ip_conntrack_events event,
354 const struct sk_buff *skb)
355{
356 struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct;
357 struct ip_conntrack_ecache *ecache;
358
359 local_bh_disable();
360 ecache = &__get_cpu_var(ip_conntrack_ecache);
361 if (ct != ecache->ct)
362 __ip_ct_event_cache_init(ct);
363 ecache->events |= event;
364 local_bh_enable();
365}
366
367static inline void ip_conntrack_event(enum ip_conntrack_events event,
368 struct ip_conntrack *ct)
369{
370 if (is_confirmed(ct) && !is_dying(ct))
371 atomic_notifier_call_chain(&ip_conntrack_chain, event, ct);
372}
373
374static inline void
375ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
376 struct ip_conntrack_expect *exp)
377{
378 atomic_notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
379}
380#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
381static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
382 const struct sk_buff *skb) {}
383static inline void ip_conntrack_event(enum ip_conntrack_events event,
384 struct ip_conntrack *ct) {}
385static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {}
386static inline void
387ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
388 struct ip_conntrack_expect *exp) {}
389#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
390
391#ifdef CONFIG_IP_NF_NAT_NEEDED
392static inline int ip_nat_initialized(struct ip_conntrack *conntrack,
393 enum ip_nat_manip_type manip)
394{
395 if (manip == IP_NAT_MANIP_SRC)
396 return test_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status);
397 return test_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status);
398}
399#endif /* CONFIG_IP_NF_NAT_NEEDED */
400
401#endif /* __KERNEL__ */
402#endif /* _IP_CONNTRACK_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_amanda.h b/include/linux/netfilter_ipv4/ip_conntrack_amanda.h
deleted file mode 100644
index de3e41f51aec..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_amanda.h
+++ /dev/null
@@ -1,11 +0,0 @@
1#ifndef _IP_CONNTRACK_AMANDA_H
2#define _IP_CONNTRACK_AMANDA_H
3/* AMANDA tracking. */
4
5struct ip_conntrack_expect;
6extern unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
7 enum ip_conntrack_info ctinfo,
8 unsigned int matchoff,
9 unsigned int matchlen,
10 struct ip_conntrack_expect *exp);
11#endif /* _IP_CONNTRACK_AMANDA_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
deleted file mode 100644
index e3a6df07aa4b..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h
+++ /dev/null
@@ -1,61 +0,0 @@
1#ifndef _IP_CONNTRACK_CORE_H
2#define _IP_CONNTRACK_CORE_H
3#include <linux/netfilter.h>
4
5#define MAX_IP_CT_PROTO 256
6extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
7
8/* This header is used to share core functionality between the
9 standalone connection tracking module, and the compatibility layer's use
10 of connection tracking. */
11extern unsigned int ip_conntrack_in(unsigned int hooknum,
12 struct sk_buff **pskb,
13 const struct net_device *in,
14 const struct net_device *out,
15 int (*okfn)(struct sk_buff *));
16
17extern int ip_conntrack_init(void);
18extern void ip_conntrack_cleanup(void);
19
20struct ip_conntrack_protocol;
21
22extern int
23ip_ct_get_tuple(const struct iphdr *iph,
24 const struct sk_buff *skb,
25 unsigned int dataoff,
26 struct ip_conntrack_tuple *tuple,
27 const struct ip_conntrack_protocol *protocol);
28
29extern int
30ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
31 const struct ip_conntrack_tuple *orig,
32 const struct ip_conntrack_protocol *protocol);
33
34/* Find a connection corresponding to a tuple. */
35struct ip_conntrack_tuple_hash *
36ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
37 const struct ip_conntrack *ignored_conntrack);
38
39extern int __ip_conntrack_confirm(struct sk_buff **pskb);
40
41/* Confirm a connection: returns NF_DROP if packet must be dropped. */
42static inline int ip_conntrack_confirm(struct sk_buff **pskb)
43{
44 struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct;
45 int ret = NF_ACCEPT;
46
47 if (ct) {
48 if (!is_confirmed(ct) && !is_dying(ct))
49 ret = __ip_conntrack_confirm(pskb);
50 ip_ct_deliver_cached_events(ct);
51 }
52 return ret;
53}
54
55extern void ip_ct_unlink_expect(struct ip_conntrack_expect *exp);
56
57extern struct list_head *ip_conntrack_hash;
58extern struct list_head ip_conntrack_expect_list;
59extern rwlock_t ip_conntrack_lock;
60#endif /* _IP_CONNTRACK_CORE_H */
61
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
deleted file mode 100644
index 2129fc3972ac..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
+++ /dev/null
@@ -1,44 +0,0 @@
1#ifndef _IP_CONNTRACK_FTP_H
2#define _IP_CONNTRACK_FTP_H
3/* FTP tracking. */
4
5/* This enum is exposed to userspace */
6enum ip_ct_ftp_type
7{
8 /* PORT command from client */
9 IP_CT_FTP_PORT,
10 /* PASV response from server */
11 IP_CT_FTP_PASV,
12 /* EPRT command from client */
13 IP_CT_FTP_EPRT,
14 /* EPSV response from server */
15 IP_CT_FTP_EPSV,
16};
17
18#ifdef __KERNEL__
19
20#define FTP_PORT 21
21
22#define NUM_SEQ_TO_REMEMBER 2
23/* This structure exists only once per master */
24struct ip_ct_ftp_master {
25 /* Valid seq positions for cmd matching after newline */
26 u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
27 /* 0 means seq_match_aft_nl not set */
28 int seq_aft_nl_num[IP_CT_DIR_MAX];
29};
30
31struct ip_conntrack_expect;
32
33/* For NAT to hook in when we find a packet which describes what other
34 * connection we should expect. */
35extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
36 enum ip_conntrack_info ctinfo,
37 enum ip_ct_ftp_type type,
38 unsigned int matchoff,
39 unsigned int matchlen,
40 struct ip_conntrack_expect *exp,
41 u32 *seq);
42#endif /* __KERNEL__ */
43
44#endif /* _IP_CONNTRACK_FTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
deleted file mode 100644
index 18f769818f4e..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ /dev/null
@@ -1,89 +0,0 @@
1#ifndef _IP_CONNTRACK_H323_H
2#define _IP_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 ip_ct_h323_master {
14
15 /* Original and NATed Q.931 or H.245 signal ports */
16 u_int16_t sig_port[IP_CT_DIR_MAX];
17
18 /* Original and NATed RTP ports */
19 u_int16_t 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 ip_conntrack_expect;
31
32extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
33 __be32 * ip, u_int16_t * port);
34extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
35 struct ip_conntrack_expect *this);
36extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
37 struct ip_conntrack_expect *this);
38extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
39 unsigned char **data, int dataoff,
40 H245_TransportAddress * addr,
41 __be32 ip, u_int16_t port);
42extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
43 unsigned char **data, int dataoff,
44 TransportAddress * addr,
45 __be32 ip, u_int16_t port);
46extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
47 struct ip_conntrack * ct,
48 enum ip_conntrack_info ctinfo,
49 unsigned char **data,
50 TransportAddress * addr, int count);
51extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
52 struct ip_conntrack * ct,
53 enum ip_conntrack_info ctinfo,
54 unsigned char **data,
55 TransportAddress * addr, int count);
56extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
57 struct ip_conntrack * ct,
58 enum ip_conntrack_info ctinfo,
59 unsigned char **data, int dataoff,
60 H245_TransportAddress * addr,
61 u_int16_t port, u_int16_t rtp_port,
62 struct ip_conntrack_expect * rtp_exp,
63 struct ip_conntrack_expect * rtcp_exp);
64extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
65 enum ip_conntrack_info ctinfo,
66 unsigned char **data, int dataoff,
67 H245_TransportAddress * addr, u_int16_t port,
68 struct ip_conntrack_expect * exp);
69extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
70 enum ip_conntrack_info ctinfo,
71 unsigned char **data, int dataoff,
72 TransportAddress * addr, u_int16_t port,
73 struct ip_conntrack_expect * exp);
74extern int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
75 struct ip_conntrack * ct,
76 enum ip_conntrack_info ctinfo,
77 unsigned char **data, int dataoff,
78 TransportAddress * addr,
79 u_int16_t port,
80 struct ip_conntrack_expect * exp);
81extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
82 enum ip_conntrack_info ctinfo,
83 unsigned char **data, TransportAddress * addr,
84 int idx, u_int16_t port,
85 struct ip_conntrack_expect * exp);
86
87#endif
88
89#endif
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper.h b/include/linux/netfilter_ipv4/ip_conntrack_helper.h
deleted file mode 100644
index 77fe868d36ff..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper.h
+++ /dev/null
@@ -1,46 +0,0 @@
1/* IP connection tracking helpers. */
2#ifndef _IP_CONNTRACK_HELPER_H
3#define _IP_CONNTRACK_HELPER_H
4#include <linux/netfilter_ipv4/ip_conntrack.h>
5
6struct module;
7
8struct ip_conntrack_helper
9{
10 struct list_head list; /* Internal use. */
11
12 const char *name; /* name of the module */
13 struct module *me; /* pointer to self */
14 unsigned int max_expected; /* Maximum number of concurrent
15 * expected connections */
16 unsigned int timeout; /* timeout for expecteds */
17
18 /* Mask of things we will help (compared against server response) */
19 struct ip_conntrack_tuple tuple;
20 struct ip_conntrack_tuple mask;
21
22 /* Function to call when data passes; return verdict, or -1 to
23 invalidate. */
24 int (*help)(struct sk_buff **pskb,
25 struct ip_conntrack *ct,
26 enum ip_conntrack_info conntrackinfo);
27
28 void (*destroy)(struct ip_conntrack *ct);
29
30 int (*to_nfattr)(struct sk_buff *skb, const struct ip_conntrack *ct);
31};
32
33extern int ip_conntrack_helper_register(struct ip_conntrack_helper *);
34extern void ip_conntrack_helper_unregister(struct ip_conntrack_helper *);
35
36/* Allocate space for an expectation: this is mandatory before calling
37 ip_conntrack_expect_related. You will have to call put afterwards. */
38extern struct ip_conntrack_expect *
39ip_conntrack_expect_alloc(struct ip_conntrack *master);
40extern void ip_conntrack_expect_put(struct ip_conntrack_expect *exp);
41
42/* Add an expected connection: can have more than one per connection */
43extern int ip_conntrack_expect_related(struct ip_conntrack_expect *exp);
44extern void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp);
45
46#endif /*_IP_CONNTRACK_HELPER_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_icmp.h b/include/linux/netfilter_ipv4/ip_conntrack_icmp.h
deleted file mode 100644
index eed5ee3e4744..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_icmp.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _IP_CONNTRACK_ICMP_H
2#define _IP_CONNTRACK_ICMP_H
3
4#include <net/netfilter/ipv4/nf_conntrack_icmp.h>
5
6#endif /* _IP_CONNTRACK_ICMP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_irc.h b/include/linux/netfilter_ipv4/ip_conntrack_irc.h
deleted file mode 100644
index 16601e0d5626..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_irc.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/* IRC extension for IP connection tracking.
2 * (C) 2000 by Harald Welte <laforge@gnumonks.org>
3 * based on RR's ip_conntrack_ftp.h
4 *
5 * ip_conntrack_irc.h,v 1.6 2000/11/07 18:26:42 laforge Exp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 *
13 */
14#ifndef _IP_CONNTRACK_IRC_H
15#define _IP_CONNTRACK_IRC_H
16
17/* This structure exists only once per master */
18struct ip_ct_irc_master {
19};
20
21#ifdef __KERNEL__
22extern unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
23 enum ip_conntrack_info ctinfo,
24 unsigned int matchoff,
25 unsigned int matchlen,
26 struct ip_conntrack_expect *exp);
27
28#define IRC_PORT 6667
29
30#endif /* __KERNEL__ */
31
32#endif /* _IP_CONNTRACK_IRC_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
deleted file mode 100644
index 2644b1faddd6..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
+++ /dev/null
@@ -1,326 +0,0 @@
1/* PPTP constants and structs */
2#ifndef _CONNTRACK_PPTP_H
3#define _CONNTRACK_PPTP_H
4
5/* state of the control session */
6enum pptp_ctrlsess_state {
7 PPTP_SESSION_NONE, /* no session present */
8 PPTP_SESSION_ERROR, /* some session error */
9 PPTP_SESSION_STOPREQ, /* stop_sess request seen */
10 PPTP_SESSION_REQUESTED, /* start_sess request seen */
11 PPTP_SESSION_CONFIRMED, /* session established */
12};
13
14/* state of the call inside the control session */
15enum pptp_ctrlcall_state {
16 PPTP_CALL_NONE,
17 PPTP_CALL_ERROR,
18 PPTP_CALL_OUT_REQ,
19 PPTP_CALL_OUT_CONF,
20 PPTP_CALL_IN_REQ,
21 PPTP_CALL_IN_REP,
22 PPTP_CALL_IN_CONF,
23 PPTP_CALL_CLEAR_REQ,
24};
25
26
27/* conntrack private data */
28struct ip_ct_pptp_master {
29 enum pptp_ctrlsess_state sstate; /* session state */
30
31 /* everything below is going to be per-expectation in newnat,
32 * since there could be more than one call within one session */
33 enum pptp_ctrlcall_state cstate; /* call state */
34 __be16 pac_call_id; /* call id of PAC, host byte order */
35 __be16 pns_call_id; /* call id of PNS, host byte order */
36
37 /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
38 * and therefore imposes a fixed limit on the number of maps */
39 struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
40};
41
42/* conntrack_expect private member */
43struct ip_ct_pptp_expect {
44 enum pptp_ctrlcall_state cstate; /* call state */
45 __be16 pac_call_id; /* call id of PAC */
46 __be16 pns_call_id; /* call id of PNS */
47};
48
49
50#ifdef __KERNEL__
51
52#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
53
54#define PPTP_CONTROL_PORT 1723
55
56#define PPTP_PACKET_CONTROL 1
57#define PPTP_PACKET_MGMT 2
58
59#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
60
61struct pptp_pkt_hdr {
62 __u16 packetLength;
63 __be16 packetType;
64 __be32 magicCookie;
65};
66
67/* PptpControlMessageType values */
68#define PPTP_START_SESSION_REQUEST 1
69#define PPTP_START_SESSION_REPLY 2
70#define PPTP_STOP_SESSION_REQUEST 3
71#define PPTP_STOP_SESSION_REPLY 4
72#define PPTP_ECHO_REQUEST 5
73#define PPTP_ECHO_REPLY 6
74#define PPTP_OUT_CALL_REQUEST 7
75#define PPTP_OUT_CALL_REPLY 8
76#define PPTP_IN_CALL_REQUEST 9
77#define PPTP_IN_CALL_REPLY 10
78#define PPTP_IN_CALL_CONNECT 11
79#define PPTP_CALL_CLEAR_REQUEST 12
80#define PPTP_CALL_DISCONNECT_NOTIFY 13
81#define PPTP_WAN_ERROR_NOTIFY 14
82#define PPTP_SET_LINK_INFO 15
83
84#define PPTP_MSG_MAX 15
85
86/* PptpGeneralError values */
87#define PPTP_ERROR_CODE_NONE 0
88#define PPTP_NOT_CONNECTED 1
89#define PPTP_BAD_FORMAT 2
90#define PPTP_BAD_VALUE 3
91#define PPTP_NO_RESOURCE 4
92#define PPTP_BAD_CALLID 5
93#define PPTP_REMOVE_DEVICE_ERROR 6
94
95struct PptpControlHeader {
96 __be16 messageType;
97 __u16 reserved;
98};
99
100/* FramingCapability Bitmap Values */
101#define PPTP_FRAME_CAP_ASYNC 0x1
102#define PPTP_FRAME_CAP_SYNC 0x2
103
104/* BearerCapability Bitmap Values */
105#define PPTP_BEARER_CAP_ANALOG 0x1
106#define PPTP_BEARER_CAP_DIGITAL 0x2
107
108struct PptpStartSessionRequest {
109 __be16 protocolVersion;
110 __u16 reserved1;
111 __be32 framingCapability;
112 __be32 bearerCapability;
113 __be16 maxChannels;
114 __be16 firmwareRevision;
115 __u8 hostName[64];
116 __u8 vendorString[64];
117};
118
119/* PptpStartSessionResultCode Values */
120#define PPTP_START_OK 1
121#define PPTP_START_GENERAL_ERROR 2
122#define PPTP_START_ALREADY_CONNECTED 3
123#define PPTP_START_NOT_AUTHORIZED 4
124#define PPTP_START_UNKNOWN_PROTOCOL 5
125
126struct PptpStartSessionReply {
127 __be16 protocolVersion;
128 __u8 resultCode;
129 __u8 generalErrorCode;
130 __be32 framingCapability;
131 __be32 bearerCapability;
132 __be16 maxChannels;
133 __be16 firmwareRevision;
134 __u8 hostName[64];
135 __u8 vendorString[64];
136};
137
138/* PptpStopReasons */
139#define PPTP_STOP_NONE 1
140#define PPTP_STOP_PROTOCOL 2
141#define PPTP_STOP_LOCAL_SHUTDOWN 3
142
143struct PptpStopSessionRequest {
144 __u8 reason;
145 __u8 reserved1;
146 __u16 reserved2;
147};
148
149/* PptpStopSessionResultCode */
150#define PPTP_STOP_OK 1
151#define PPTP_STOP_GENERAL_ERROR 2
152
153struct PptpStopSessionReply {
154 __u8 resultCode;
155 __u8 generalErrorCode;
156 __u16 reserved1;
157};
158
159struct PptpEchoRequest {
160 __be32 identNumber;
161};
162
163/* PptpEchoReplyResultCode */
164#define PPTP_ECHO_OK 1
165#define PPTP_ECHO_GENERAL_ERROR 2
166
167struct PptpEchoReply {
168 __be32 identNumber;
169 __u8 resultCode;
170 __u8 generalErrorCode;
171 __u16 reserved;
172};
173
174/* PptpFramingType */
175#define PPTP_ASYNC_FRAMING 1
176#define PPTP_SYNC_FRAMING 2
177#define PPTP_DONT_CARE_FRAMING 3
178
179/* PptpCallBearerType */
180#define PPTP_ANALOG_TYPE 1
181#define PPTP_DIGITAL_TYPE 2
182#define PPTP_DONT_CARE_BEARER_TYPE 3
183
184struct PptpOutCallRequest {
185 __be16 callID;
186 __be16 callSerialNumber;
187 __be32 minBPS;
188 __be32 maxBPS;
189 __be32 bearerType;
190 __be32 framingType;
191 __be16 packetWindow;
192 __be16 packetProcDelay;
193 __be16 phoneNumberLength;
194 __u16 reserved1;
195 __u8 phoneNumber[64];
196 __u8 subAddress[64];
197};
198
199/* PptpCallResultCode */
200#define PPTP_OUTCALL_CONNECT 1
201#define PPTP_OUTCALL_GENERAL_ERROR 2
202#define PPTP_OUTCALL_NO_CARRIER 3
203#define PPTP_OUTCALL_BUSY 4
204#define PPTP_OUTCALL_NO_DIAL_TONE 5
205#define PPTP_OUTCALL_TIMEOUT 6
206#define PPTP_OUTCALL_DONT_ACCEPT 7
207
208struct PptpOutCallReply {
209 __be16 callID;
210 __be16 peersCallID;
211 __u8 resultCode;
212 __u8 generalErrorCode;
213 __be16 causeCode;
214 __be32 connectSpeed;
215 __be16 packetWindow;
216 __be16 packetProcDelay;
217 __be32 physChannelID;
218};
219
220struct PptpInCallRequest {
221 __be16 callID;
222 __be16 callSerialNumber;
223 __be32 callBearerType;
224 __be32 physChannelID;
225 __be16 dialedNumberLength;
226 __be16 dialingNumberLength;
227 __u8 dialedNumber[64];
228 __u8 dialingNumber[64];
229 __u8 subAddress[64];
230};
231
232/* PptpInCallResultCode */
233#define PPTP_INCALL_ACCEPT 1
234#define PPTP_INCALL_GENERAL_ERROR 2
235#define PPTP_INCALL_DONT_ACCEPT 3
236
237struct PptpInCallReply {
238 __be16 callID;
239 __be16 peersCallID;
240 __u8 resultCode;
241 __u8 generalErrorCode;
242 __be16 packetWindow;
243 __be16 packetProcDelay;
244 __u16 reserved;
245};
246
247struct PptpInCallConnected {
248 __be16 peersCallID;
249 __u16 reserved;
250 __be32 connectSpeed;
251 __be16 packetWindow;
252 __be16 packetProcDelay;
253 __be32 callFramingType;
254};
255
256struct PptpClearCallRequest {
257 __be16 callID;
258 __u16 reserved;
259};
260
261struct PptpCallDisconnectNotify {
262 __be16 callID;
263 __u8 resultCode;
264 __u8 generalErrorCode;
265 __be16 causeCode;
266 __u16 reserved;
267 __u8 callStatistics[128];
268};
269
270struct PptpWanErrorNotify {
271 __be16 peersCallID;
272 __u16 reserved;
273 __be32 crcErrors;
274 __be32 framingErrors;
275 __be32 hardwareOverRuns;
276 __be32 bufferOverRuns;
277 __be32 timeoutErrors;
278 __be32 alignmentErrors;
279};
280
281struct PptpSetLinkInfo {
282 __be16 peersCallID;
283 __u16 reserved;
284 __be32 sendAccm;
285 __be32 recvAccm;
286};
287
288union pptp_ctrl_union {
289 struct PptpStartSessionRequest sreq;
290 struct PptpStartSessionReply srep;
291 struct PptpStopSessionRequest streq;
292 struct PptpStopSessionReply strep;
293 struct PptpOutCallRequest ocreq;
294 struct PptpOutCallReply ocack;
295 struct PptpInCallRequest icreq;
296 struct PptpInCallReply icack;
297 struct PptpInCallConnected iccon;
298 struct PptpClearCallRequest clrreq;
299 struct PptpCallDisconnectNotify disc;
300 struct PptpWanErrorNotify wanerr;
301 struct PptpSetLinkInfo setlink;
302};
303
304extern int
305(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
306 struct ip_conntrack *ct,
307 enum ip_conntrack_info ctinfo,
308 struct PptpControlHeader *ctlh,
309 union pptp_ctrl_union *pptpReq);
310
311extern int
312(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
313 struct ip_conntrack *ct,
314 enum ip_conntrack_info ctinfo,
315 struct PptpControlHeader *ctlh,
316 union pptp_ctrl_union *pptpReq);
317
318extern void
319(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig,
320 struct ip_conntrack_expect *exp_reply);
321
322extern void
323(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
324 struct ip_conntrack_expect *exp);
325#endif /* __KERNEL__ */
326#endif /* _CONNTRACK_PPTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
deleted file mode 100644
index e371e0fc1672..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
+++ /dev/null
@@ -1,114 +0,0 @@
1#ifndef _CONNTRACK_PROTO_GRE_H
2#define _CONNTRACK_PROTO_GRE_H
3#include <asm/byteorder.h>
4
5/* GRE PROTOCOL HEADER */
6
7/* GRE Version field */
8#define GRE_VERSION_1701 0x0
9#define GRE_VERSION_PPTP 0x1
10
11/* GRE Protocol field */
12#define GRE_PROTOCOL_PPTP 0x880B
13
14/* GRE Flags */
15#define GRE_FLAG_C 0x80
16#define GRE_FLAG_R 0x40
17#define GRE_FLAG_K 0x20
18#define GRE_FLAG_S 0x10
19#define GRE_FLAG_A 0x80
20
21#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
22#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
23#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
24#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
25#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
26
27/* GRE is a mess: Four different standards */
28struct gre_hdr {
29#if defined(__LITTLE_ENDIAN_BITFIELD)
30 __u16 rec:3,
31 srr:1,
32 seq:1,
33 key:1,
34 routing:1,
35 csum:1,
36 version:3,
37 reserved:4,
38 ack:1;
39#elif defined(__BIG_ENDIAN_BITFIELD)
40 __u16 csum:1,
41 routing:1,
42 key:1,
43 seq:1,
44 srr:1,
45 rec:3,
46 ack:1,
47 reserved:4,
48 version:3;
49#else
50#error "Adjust your <asm/byteorder.h> defines"
51#endif
52 __be16 protocol;
53};
54
55/* modified GRE header for PPTP */
56struct gre_hdr_pptp {
57 __u8 flags; /* bitfield */
58 __u8 version; /* should be GRE_VERSION_PPTP */
59 __be16 protocol; /* should be GRE_PROTOCOL_PPTP */
60 __be16 payload_len; /* size of ppp payload, not inc. gre header */
61 __be16 call_id; /* peer's call_id for this session */
62 __be32 seq; /* sequence number. Present if S==1 */
63 __be32 ack; /* seq number of highest packet recieved by */
64 /* sender in this session */
65};
66
67
68/* this is part of ip_conntrack */
69struct ip_ct_gre {
70 unsigned int stream_timeout;
71 unsigned int timeout;
72};
73
74#ifdef __KERNEL__
75struct ip_conntrack_expect;
76struct ip_conntrack;
77
78/* structure for original <-> reply keymap */
79struct ip_ct_gre_keymap {
80 struct list_head list;
81
82 struct ip_conntrack_tuple tuple;
83};
84
85/* add new tuple->key_reply pair to keymap */
86int ip_ct_gre_keymap_add(struct ip_conntrack *ct,
87 struct ip_conntrack_tuple *t,
88 int reply);
89
90/* delete keymap entries */
91void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct);
92
93
94/* get pointer to gre key, if present */
95static inline __be32 *gre_key(struct gre_hdr *greh)
96{
97 if (!greh->key)
98 return NULL;
99 if (greh->csum || greh->routing)
100 return (__be32 *) (greh+sizeof(*greh)+4);
101 return (__be32 *) (greh+sizeof(*greh));
102}
103
104/* get pointer ot gre csum, if present */
105static inline __sum16 *gre_csum(struct gre_hdr *greh)
106{
107 if (!greh->csum)
108 return NULL;
109 return (__sum16 *) (greh+sizeof(*greh));
110}
111
112#endif /* __KERNEL__ */
113
114#endif /* _CONNTRACK_PROTO_GRE_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
deleted file mode 100644
index 2c76b879e3dc..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
+++ /dev/null
@@ -1,98 +0,0 @@
1/* Header for use in defining a given protocol for connection tracking. */
2#ifndef _IP_CONNTRACK_PROTOCOL_H
3#define _IP_CONNTRACK_PROTOCOL_H
4#include <linux/netfilter_ipv4/ip_conntrack.h>
5#include <linux/netfilter/nfnetlink_conntrack.h>
6
7struct seq_file;
8
9struct ip_conntrack_protocol
10{
11 /* Protocol number. */
12 u_int8_t proto;
13
14 /* Protocol name */
15 const char *name;
16
17 /* Try to fill in the third arg: dataoff is offset past IP
18 hdr. Return true if possible. */
19 int (*pkt_to_tuple)(const struct sk_buff *skb,
20 unsigned int dataoff,
21 struct ip_conntrack_tuple *tuple);
22
23 /* Invert the per-proto part of the tuple: ie. turn xmit into reply.
24 * Some packets can't be inverted: return 0 in that case.
25 */
26 int (*invert_tuple)(struct ip_conntrack_tuple *inverse,
27 const struct ip_conntrack_tuple *orig);
28
29 /* Print out the per-protocol part of the tuple. Return like seq_* */
30 int (*print_tuple)(struct seq_file *,
31 const struct ip_conntrack_tuple *);
32
33 /* Print out the private part of the conntrack. */
34 int (*print_conntrack)(struct seq_file *, const struct ip_conntrack *);
35
36 /* Returns verdict for packet, or -1 for invalid. */
37 int (*packet)(struct ip_conntrack *conntrack,
38 const struct sk_buff *skb,
39 enum ip_conntrack_info ctinfo);
40
41 /* Called when a new connection for this protocol found;
42 * returns TRUE if it's OK. If so, packet() called next. */
43 int (*new)(struct ip_conntrack *conntrack, const struct sk_buff *skb);
44
45 /* Called when a conntrack entry is destroyed */
46 void (*destroy)(struct ip_conntrack *conntrack);
47
48 int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
49 unsigned int hooknum);
50
51 /* convert protoinfo to nfnetink attributes */
52 int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
53 const struct ip_conntrack *ct);
54
55 /* convert nfnetlink attributes to protoinfo */
56 int (*from_nfattr)(struct nfattr *tb[], struct ip_conntrack *ct);
57
58 int (*tuple_to_nfattr)(struct sk_buff *skb,
59 const struct ip_conntrack_tuple *t);
60 int (*nfattr_to_tuple)(struct nfattr *tb[],
61 struct ip_conntrack_tuple *t);
62
63 /* Module (if any) which this is connected to. */
64 struct module *me;
65};
66
67/* Protocol registration. */
68extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
69extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
70/* Existing built-in protocols */
71extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
72extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
73extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
74extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
75extern int ip_conntrack_protocol_tcp_init(void);
76
77/* Log invalid packets */
78extern unsigned int ip_ct_log_invalid;
79
80extern int ip_ct_port_tuple_to_nfattr(struct sk_buff *,
81 const struct ip_conntrack_tuple *);
82extern int ip_ct_port_nfattr_to_tuple(struct nfattr *tb[],
83 struct ip_conntrack_tuple *);
84
85#ifdef CONFIG_SYSCTL
86#ifdef DEBUG_INVALID_PACKETS
87#define LOG_INVALID(proto) \
88 (ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
89#else
90#define LOG_INVALID(proto) \
91 ((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
92 && net_ratelimit())
93#endif
94#else
95#define LOG_INVALID(proto) 0
96#endif /* CONFIG_SYSCTL */
97
98#endif /*_IP_CONNTRACK_PROTOCOL_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sctp.h b/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
deleted file mode 100644
index 4099a041a32a..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _IP_CONNTRACK_SCTP_H
2#define _IP_CONNTRACK_SCTP_H
3
4#include <linux/netfilter/nf_conntrack_sctp.h>
5
6#endif /* _IP_CONNTRACK_SCTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
deleted file mode 100644
index bef6c646defa..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_sip.h
+++ /dev/null
@@ -1,40 +0,0 @@
1#ifndef __IP_CONNTRACK_SIP_H__
2#define __IP_CONNTRACK_SIP_H__
3#ifdef __KERNEL__
4
5#define SIP_PORT 5060
6#define SIP_TIMEOUT 3600
7
8enum sip_header_pos {
9 POS_REG_REQ_URI,
10 POS_REQ_URI,
11 POS_FROM,
12 POS_TO,
13 POS_VIA,
14 POS_CONTACT,
15 POS_CONTENT,
16 POS_MEDIA,
17 POS_OWNER,
18 POS_CONNECTION,
19 POS_SDP_HEADER,
20};
21
22extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
23 enum ip_conntrack_info ctinfo,
24 struct ip_conntrack *ct,
25 const char **dptr);
26extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
27 enum ip_conntrack_info ctinfo,
28 struct ip_conntrack_expect *exp,
29 const char *dptr);
30
31extern int ct_sip_get_info(const char *dptr, size_t dlen,
32 unsigned int *matchoff,
33 unsigned int *matchlen,
34 enum sip_header_pos pos);
35extern int ct_sip_lnlen(const char *line, const char *limit);
36extern const char *ct_sip_search(const char *needle, const char *haystack,
37 size_t needle_len, size_t haystack_len,
38 int case_sensitive);
39#endif /* __KERNEL__ */
40#endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
deleted file mode 100644
index 876b8fb17e68..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef _IP_CONNTRACK_TCP_H
2#define _IP_CONNTRACK_TCP_H
3
4#include <linux/netfilter/nf_conntrack_tcp.h>
5
6#endif /* _IP_CONNTRACK_TCP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tftp.h b/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
deleted file mode 100644
index a404fc0abf0e..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
+++ /dev/null
@@ -1,20 +0,0 @@
1#ifndef _IP_CT_TFTP
2#define _IP_CT_TFTP
3
4#define TFTP_PORT 69
5
6struct tftphdr {
7 __be16 opcode;
8};
9
10#define TFTP_OPCODE_READ 1
11#define TFTP_OPCODE_WRITE 2
12#define TFTP_OPCODE_DATA 3
13#define TFTP_OPCODE_ACK 4
14#define TFTP_OPCODE_ERROR 5
15
16extern unsigned int (*ip_nat_tftp_hook)(struct sk_buff **pskb,
17 enum ip_conntrack_info ctinfo,
18 struct ip_conntrack_expect *exp);
19
20#endif /* _IP_CT_TFTP */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
deleted file mode 100644
index c228bde74c33..000000000000
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ /dev/null
@@ -1,146 +0,0 @@
1#ifndef _IP_CONNTRACK_TUPLE_H
2#define _IP_CONNTRACK_TUPLE_H
3
4#include <linux/types.h>
5#include <linux/netfilter/nf_conntrack_tuple_common.h>
6
7/* A `tuple' is a structure containing the information to uniquely
8 identify a connection. ie. if two packets have the same tuple, they
9 are in the same connection; if not, they are not.
10
11 We divide the structure along "manipulatable" and
12 "non-manipulatable" lines, for the benefit of the NAT code.
13*/
14
15/* The protocol-specific manipulable parts of the tuple: always in
16 network order! */
17union ip_conntrack_manip_proto
18{
19 /* Add other protocols here. */
20 u_int16_t all;
21
22 struct {
23 __be16 port;
24 } tcp;
25 struct {
26 __be16 port;
27 } udp;
28 struct {
29 __be16 id;
30 } icmp;
31 struct {
32 __be16 port;
33 } sctp;
34 struct {
35 __be16 key; /* key is 32bit, pptp only uses 16 */
36 } gre;
37};
38
39/* The manipulable part of the tuple. */
40struct ip_conntrack_manip
41{
42 __be32 ip;
43 union ip_conntrack_manip_proto u;
44};
45
46/* This contains the information to distinguish a connection. */
47struct ip_conntrack_tuple
48{
49 struct ip_conntrack_manip src;
50
51 /* These are the parts of the tuple which are fixed. */
52 struct {
53 __be32 ip;
54 union {
55 /* Add other protocols here. */
56 u_int16_t all;
57
58 struct {
59 __be16 port;
60 } tcp;
61 struct {
62 __be16 port;
63 } udp;
64 struct {
65 u_int8_t type, code;
66 } icmp;
67 struct {
68 __be16 port;
69 } sctp;
70 struct {
71 __be16 key; /* key is 32bit,
72 * pptp only uses 16 */
73 } gre;
74 } u;
75
76 /* The protocol. */
77 u_int8_t protonum;
78
79 /* The direction (for tuplehash) */
80 u_int8_t dir;
81 } dst;
82};
83
84/* This is optimized opposed to a memset of the whole structure. Everything we
85 * really care about is the source/destination unions */
86#define IP_CT_TUPLE_U_BLANK(tuple) \
87 do { \
88 (tuple)->src.u.all = 0; \
89 (tuple)->dst.u.all = 0; \
90 } while (0)
91
92#ifdef __KERNEL__
93
94#define DUMP_TUPLE(tp) \
95DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
96 (tp), (tp)->dst.protonum, \
97 NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \
98 NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
99
100/* If we're the first tuple, it's the original dir. */
101#define DIRECTION(h) ((enum ip_conntrack_dir)(h)->tuple.dst.dir)
102
103/* Connections have two entries in the hash table: one for each way */
104struct ip_conntrack_tuple_hash
105{
106 struct list_head list;
107
108 struct ip_conntrack_tuple tuple;
109};
110
111#endif /* __KERNEL__ */
112
113static inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1,
114 const struct ip_conntrack_tuple *t2)
115{
116 return t1->src.ip == t2->src.ip
117 && t1->src.u.all == t2->src.u.all;
118}
119
120static inline int ip_ct_tuple_dst_equal(const struct ip_conntrack_tuple *t1,
121 const struct ip_conntrack_tuple *t2)
122{
123 return t1->dst.ip == t2->dst.ip
124 && t1->dst.u.all == t2->dst.u.all
125 && t1->dst.protonum == t2->dst.protonum;
126}
127
128static inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1,
129 const struct ip_conntrack_tuple *t2)
130{
131 return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2);
132}
133
134static inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t,
135 const struct ip_conntrack_tuple *tuple,
136 const struct ip_conntrack_tuple *mask)
137{
138 return !(((t->src.ip ^ tuple->src.ip) & mask->src.ip)
139 || ((t->dst.ip ^ tuple->dst.ip) & mask->dst.ip)
140 || ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all)
141 || ((t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all)
142 || ((t->dst.protonum ^ tuple->dst.protonum)
143 & mask->dst.protonum));
144}
145
146#endif /* _IP_CONNTRACK_TUPLE_H */
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
deleted file mode 100644
index bbca89aab813..000000000000
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ /dev/null
@@ -1,79 +0,0 @@
1#ifndef _IP_NAT_H
2#define _IP_NAT_H
3#include <linux/netfilter_ipv4.h>
4#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5
6#define IP_NAT_MAPPING_TYPE_MAX_NAMELEN 16
7
8enum ip_nat_manip_type
9{
10 IP_NAT_MANIP_SRC,
11 IP_NAT_MANIP_DST
12};
13
14/* SRC manip occurs POST_ROUTING or LOCAL_IN */
15#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN)
16
17#define IP_NAT_RANGE_MAP_IPS 1
18#define IP_NAT_RANGE_PROTO_SPECIFIED 2
19#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */
20
21/* NAT sequence number modifications */
22struct ip_nat_seq {
23 /* position of the last TCP sequence number
24 * modification (if any) */
25 u_int32_t correction_pos;
26 /* sequence number offset before and after last modification */
27 int16_t offset_before, offset_after;
28};
29
30/* Single range specification. */
31struct ip_nat_range
32{
33 /* Set to OR of flags above. */
34 unsigned int flags;
35
36 /* Inclusive: network order. */
37 __be32 min_ip, max_ip;
38
39 /* Inclusive: network order */
40 union ip_conntrack_manip_proto min, max;
41};
42
43/* For backwards compat: don't use in modern code. */
44struct ip_nat_multi_range_compat
45{
46 unsigned int rangesize; /* Must be 1. */
47
48 /* hangs off end. */
49 struct ip_nat_range range[1];
50};
51
52#ifdef __KERNEL__
53#include <linux/list.h>
54
55/* Protects NAT hash tables, and NAT-private part of conntracks. */
56extern rwlock_t ip_nat_lock;
57
58/* The structure embedded in the conntrack structure. */
59struct ip_nat_info
60{
61 struct list_head bysource;
62 struct ip_nat_seq seq[IP_CT_DIR_MAX];
63};
64
65struct ip_conntrack;
66
67/* Set up the info structure to map into this range. */
68extern unsigned int ip_nat_setup_info(struct ip_conntrack *conntrack,
69 const struct ip_nat_range *range,
70 unsigned int hooknum);
71
72/* Is this tuple already taken? (not by us)*/
73extern int ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
74 const struct ip_conntrack *ignored_conntrack);
75
76#else /* !__KERNEL__: iptables wants this to compile. */
77#define ip_nat_multi_range ip_nat_multi_range_compat
78#endif /*__KERNEL__*/
79#endif
diff --git a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h
deleted file mode 100644
index 60566f9fd7b3..000000000000
--- a/include/linux/netfilter_ipv4/ip_nat_core.h
+++ /dev/null
@@ -1,18 +0,0 @@
1#ifndef _IP_NAT_CORE_H
2#define _IP_NAT_CORE_H
3#include <linux/list.h>
4#include <linux/netfilter_ipv4/ip_conntrack.h>
5
6/* This header used to share core functionality between the standalone
7 NAT module, and the compatibility layer's use of NAT for masquerading. */
8
9extern unsigned int ip_nat_packet(struct ip_conntrack *ct,
10 enum ip_conntrack_info conntrackinfo,
11 unsigned int hooknum,
12 struct sk_buff **pskb);
13
14extern int ip_nat_icmp_reply_translation(struct ip_conntrack *ct,
15 enum ip_conntrack_info ctinfo,
16 unsigned int hooknum,
17 struct sk_buff **pskb);
18#endif /* _IP_NAT_CORE_H */
diff --git a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h
deleted file mode 100644
index bf9cb105c885..000000000000
--- a/include/linux/netfilter_ipv4/ip_nat_helper.h
+++ /dev/null
@@ -1,33 +0,0 @@
1#ifndef _IP_NAT_HELPER_H
2#define _IP_NAT_HELPER_H
3/* NAT protocol helper routines. */
4
5#include <linux/netfilter_ipv4/ip_conntrack.h>
6#include <linux/module.h>
7
8struct sk_buff;
9
10/* These return true or false. */
11extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
12 struct ip_conntrack *ct,
13 enum ip_conntrack_info ctinfo,
14 unsigned int match_offset,
15 unsigned int match_len,
16 const char *rep_buffer,
17 unsigned int rep_len);
18extern int ip_nat_mangle_udp_packet(struct sk_buff **skb,
19 struct ip_conntrack *ct,
20 enum ip_conntrack_info ctinfo,
21 unsigned int match_offset,
22 unsigned int match_len,
23 const char *rep_buffer,
24 unsigned int rep_len);
25extern int ip_nat_seq_adjust(struct sk_buff **pskb,
26 struct ip_conntrack *ct,
27 enum ip_conntrack_info ctinfo);
28
29/* Setup NAT on this expected conntrack so it follows master, but goes
30 * to port ct->master->saved_proto. */
31extern void ip_nat_follow_master(struct ip_conntrack *ct,
32 struct ip_conntrack_expect *this);
33#endif
diff --git a/include/linux/netfilter_ipv4/ip_nat_pptp.h b/include/linux/netfilter_ipv4/ip_nat_pptp.h
deleted file mode 100644
index 36668bf0f373..000000000000
--- a/include/linux/netfilter_ipv4/ip_nat_pptp.h
+++ /dev/null
@@ -1,11 +0,0 @@
1/* PPTP constants and structs */
2#ifndef _NAT_PPTP_H
3#define _NAT_PPTP_H
4
5/* conntrack private data */
6struct ip_nat_pptp {
7 __be16 pns_call_id; /* NAT'ed PNS call id */
8 __be16 pac_call_id; /* NAT'ed PAC call id */
9};
10
11#endif /* _NAT_PPTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
deleted file mode 100644
index 612a43614e7b..000000000000
--- a/include/linux/netfilter_ipv4/ip_nat_protocol.h
+++ /dev/null
@@ -1,74 +0,0 @@
1/* Header for use in defining a given protocol. */
2#ifndef _IP_NAT_PROTOCOL_H
3#define _IP_NAT_PROTOCOL_H
4#include <linux/init.h>
5#include <linux/list.h>
6
7#include <linux/netfilter_ipv4/ip_nat.h>
8#include <linux/netfilter/nfnetlink_conntrack.h>
9
10struct iphdr;
11struct ip_nat_range;
12
13struct ip_nat_protocol
14{
15 /* Protocol name */
16 const char *name;
17
18 /* Protocol number. */
19 unsigned int protonum;
20
21 struct module *me;
22
23 /* Translate a packet to the target according to manip type.
24 Return true if succeeded. */
25 int (*manip_pkt)(struct sk_buff **pskb,
26 unsigned int iphdroff,
27 const struct ip_conntrack_tuple *tuple,
28 enum ip_nat_manip_type maniptype);
29
30 /* Is the manipable part of the tuple between min and max incl? */
31 int (*in_range)(const struct ip_conntrack_tuple *tuple,
32 enum ip_nat_manip_type maniptype,
33 const union ip_conntrack_manip_proto *min,
34 const union ip_conntrack_manip_proto *max);
35
36 /* Alter the per-proto part of the tuple (depending on
37 maniptype), to give a unique tuple in the given range if
38 possible; return false if not. Per-protocol part of tuple
39 is initialized to the incoming packet. */
40 int (*unique_tuple)(struct ip_conntrack_tuple *tuple,
41 const struct ip_nat_range *range,
42 enum ip_nat_manip_type maniptype,
43 const struct ip_conntrack *conntrack);
44
45 int (*range_to_nfattr)(struct sk_buff *skb,
46 const struct ip_nat_range *range);
47
48 int (*nfattr_to_range)(struct nfattr *tb[],
49 struct ip_nat_range *range);
50};
51
52/* Protocol registration. */
53extern int ip_nat_protocol_register(struct ip_nat_protocol *proto);
54extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto);
55
56extern struct ip_nat_protocol *ip_nat_proto_find_get(u_int8_t protocol);
57extern void ip_nat_proto_put(struct ip_nat_protocol *proto);
58
59/* Built-in protocols. */
60extern struct ip_nat_protocol ip_nat_protocol_tcp;
61extern struct ip_nat_protocol ip_nat_protocol_udp;
62extern struct ip_nat_protocol ip_nat_protocol_icmp;
63extern struct ip_nat_protocol ip_nat_unknown_protocol;
64
65extern int init_protocols(void) __init;
66extern void cleanup_protocols(void);
67extern struct ip_nat_protocol *find_nat_proto(u_int16_t protonum);
68
69extern int ip_nat_port_range_to_nfattr(struct sk_buff *skb,
70 const struct ip_nat_range *range);
71extern int ip_nat_port_nfattr_to_range(struct nfattr *tb[],
72 struct ip_nat_range *range);
73
74#endif /*_IP_NAT_PROTO_H*/
diff --git a/include/linux/netfilter_ipv4/ip_nat_rule.h b/include/linux/netfilter_ipv4/ip_nat_rule.h
deleted file mode 100644
index 73b9552e6a89..000000000000
--- a/include/linux/netfilter_ipv4/ip_nat_rule.h
+++ /dev/null
@@ -1,28 +0,0 @@
1#ifndef _IP_NAT_RULE_H
2#define _IP_NAT_RULE_H
3#include <linux/netfilter_ipv4/ip_conntrack.h>
4#include <linux/netfilter_ipv4/ip_tables.h>
5#include <linux/netfilter_ipv4/ip_nat.h>
6
7#ifdef __KERNEL__
8
9extern int ip_nat_rule_init(void) __init;
10extern void ip_nat_rule_cleanup(void);
11extern int ip_nat_rule_find(struct sk_buff **pskb,
12 unsigned int hooknum,
13 const struct net_device *in,
14 const struct net_device *out,
15 struct ip_conntrack *ct,
16 struct ip_nat_info *info);
17
18extern unsigned int
19alloc_null_binding(struct ip_conntrack *conntrack,
20 struct ip_nat_info *info,
21 unsigned int hooknum);
22
23extern unsigned int
24alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
25 struct ip_nat_info *info,
26 unsigned int hooknum);
27#endif
28#endif /* _IP_NAT_RULE_H */
diff --git a/include/linux/netfilter_ipv4/ipt_SAME.h b/include/linux/netfilter_ipv4/ipt_SAME.h
index cc4c0b2269af..be6e682a85ec 100644
--- a/include/linux/netfilter_ipv4/ipt_SAME.h
+++ b/include/linux/netfilter_ipv4/ipt_SAME.h
@@ -13,7 +13,7 @@ struct ipt_same_info
13 u_int32_t *iparray; 13 u_int32_t *iparray;
14 14
15 /* hangs off end. */ 15 /* hangs off end. */
16 struct ip_nat_range range[IPT_SAME_MAX_RANGE]; 16 struct nf_nat_range range[IPT_SAME_MAX_RANGE];
17}; 17};
18 18
19#endif /*_IPT_SAME_H*/ 19#endif /*_IPT_SAME_H*/
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 0e690e34c00b..1c6b8bd09b9a 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -250,6 +250,11 @@ static inline int nf_ct_is_dying(struct nf_conn *ct)
250 return test_bit(IPS_DYING_BIT, &ct->status); 250 return test_bit(IPS_DYING_BIT, &ct->status);
251} 251}
252 252
253static inline int nf_ct_is_untracked(const struct sk_buff *skb)
254{
255 return (skb->nfct == &nf_conntrack_untracked.ct_general);
256}
257
253extern unsigned int nf_conntrack_htable_size; 258extern unsigned int nf_conntrack_htable_size;
254extern int nf_conntrack_checksum; 259extern int nf_conntrack_checksum;
255extern atomic_t nf_conntrack_count; 260extern atomic_t nf_conntrack_count;
diff --git a/include/net/netfilter/nf_conntrack_compat.h b/include/net/netfilter/nf_conntrack_compat.h
deleted file mode 100644
index 6f84c1f7fcd4..000000000000
--- a/include/net/netfilter/nf_conntrack_compat.h
+++ /dev/null
@@ -1,145 +0,0 @@
1#ifndef _NF_CONNTRACK_COMPAT_H
2#define _NF_CONNTRACK_COMPAT_H
3
4#ifdef __KERNEL__
5
6#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
7
8#include <linux/netfilter_ipv4/ip_conntrack.h>
9#include <linux/socket.h>
10
11#ifdef CONFIG_IP_NF_CONNTRACK_MARK
12static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
13 u_int32_t *ctinfo)
14{
15 struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
16
17 if (ct)
18 return &ct->mark;
19 else
20 return NULL;
21}
22#endif /* CONFIG_IP_NF_CONNTRACK_MARK */
23
24#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
25static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
26 u_int32_t *ctinfo)
27{
28 struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
29
30 if (ct)
31 return &ct->secmark;
32 else
33 return NULL;
34}
35#endif /* CONFIG_IP_NF_CONNTRACK_SECMARK */
36
37#ifdef CONFIG_IP_NF_CT_ACCT
38static inline struct ip_conntrack_counter *
39nf_ct_get_counters(const struct sk_buff *skb)
40{
41 enum ip_conntrack_info ctinfo;
42 struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo);
43
44 if (ct)
45 return ct->counters;
46 else
47 return NULL;
48}
49#endif /* CONFIG_IP_NF_CT_ACCT */
50
51static inline int nf_ct_is_untracked(const struct sk_buff *skb)
52{
53 return (skb->nfct == &ip_conntrack_untracked.ct_general);
54}
55
56static inline void nf_ct_untrack(struct sk_buff *skb)
57{
58 skb->nfct = &ip_conntrack_untracked.ct_general;
59}
60
61static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
62 enum ip_conntrack_info *ctinfo)
63{
64 struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
65 return (ct != NULL);
66}
67
68static inline int nf_ct_l3proto_try_module_get(unsigned short l3proto)
69{
70 need_conntrack();
71 return l3proto == PF_INET ? 0 : -1;
72}
73
74static inline void nf_ct_l3proto_module_put(unsigned short l3proto)
75{
76}
77
78#else /* CONFIG_IP_NF_CONNTRACK */
79
80#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
81#include <net/netfilter/nf_conntrack.h>
82
83#ifdef CONFIG_NF_CONNTRACK_MARK
84
85static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
86 u_int32_t *ctinfo)
87{
88 struct nf_conn *ct = nf_ct_get(skb, ctinfo);
89
90 if (ct)
91 return &ct->mark;
92 else
93 return NULL;
94}
95#endif /* CONFIG_NF_CONNTRACK_MARK */
96
97#ifdef CONFIG_NF_CONNTRACK_SECMARK
98static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
99 u_int32_t *ctinfo)
100{
101 struct nf_conn *ct = nf_ct_get(skb, ctinfo);
102
103 if (ct)
104 return &ct->secmark;
105 else
106 return NULL;
107}
108#endif /* CONFIG_NF_CONNTRACK_MARK */
109
110#ifdef CONFIG_NF_CT_ACCT
111static inline struct ip_conntrack_counter *
112nf_ct_get_counters(const struct sk_buff *skb)
113{
114 enum ip_conntrack_info ctinfo;
115 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
116
117 if (ct)
118 return ct->counters;
119 else
120 return NULL;
121}
122#endif /* CONFIG_NF_CT_ACCT */
123
124static inline int nf_ct_is_untracked(const struct sk_buff *skb)
125{
126 return (skb->nfct == &nf_conntrack_untracked.ct_general);
127}
128
129static inline void nf_ct_untrack(struct sk_buff *skb)
130{
131 skb->nfct = &nf_conntrack_untracked.ct_general;
132}
133
134static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
135 enum ip_conntrack_info *ctinfo)
136{
137 struct nf_conn *ct = nf_ct_get(skb, ctinfo);
138 return (ct != NULL);
139}
140
141#endif /* CONFIG_IP_NF_CONNTRACK */
142
143#endif /* __KERNEL__ */
144
145#endif /* _NF_CONNTRACK_COMPAT_H */
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
index f191c672bcc6..e76565459ad9 100644
--- a/include/net/netfilter/nf_nat_rule.h
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -4,16 +4,6 @@
4#include <net/netfilter/nf_nat.h> 4#include <net/netfilter/nf_nat.h>
5#include <linux/netfilter_ipv4/ip_tables.h> 5#include <linux/netfilter_ipv4/ip_tables.h>
6 6
7/* Compatibility definitions for ipt_FOO modules */
8#define ip_nat_range nf_nat_range
9#define ip_conntrack_tuple nf_conntrack_tuple
10#define ip_conntrack_get nf_ct_get
11#define ip_conntrack nf_conn
12#define ip_nat_setup_info nf_nat_setup_info
13#define ip_nat_multi_range_compat nf_nat_multi_range_compat
14#define ip_ct_iterate_cleanup nf_ct_iterate_cleanup
15#define IP_NF_ASSERT NF_CT_ASSERT
16
17extern int nf_nat_rule_init(void) __init; 7extern int nf_nat_rule_init(void) __init;
18extern void nf_nat_rule_cleanup(void); 8extern void nf_nat_rule_cleanup(void);
19extern int nf_nat_rule_find(struct sk_buff **pskb, 9extern int nf_nat_rule_find(struct sk_buff **pskb,
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 601808c796ec..46509fae9fd8 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -30,188 +30,6 @@ config NF_CONNTRACK_PROC_COMPAT
30 30
31 If unsure, say Y. 31 If unsure, say Y.
32 32
33# connection tracking, helpers and protocols
34config IP_NF_CT_ACCT
35 bool "Connection tracking flow accounting"
36 depends on IP_NF_CONNTRACK
37 help
38 If this option is enabled, the connection tracking code will
39 keep per-flow packet and byte counters.
40
41 Those counters can be used for flow-based accounting or the
42 `connbytes' match.
43
44 If unsure, say `N'.
45
46config IP_NF_CONNTRACK_MARK
47 bool 'Connection mark tracking support'
48 depends on IP_NF_CONNTRACK
49 help
50 This option enables support for connection marks, used by the
51 `CONNMARK' target and `connmark' match. Similar to the mark value
52 of packets, but this mark value is kept in the conntrack session
53 instead of the individual packets.
54
55config IP_NF_CONNTRACK_SECMARK
56 bool 'Connection tracking security mark support'
57 depends on IP_NF_CONNTRACK && NETWORK_SECMARK
58 help
59 This option enables security markings to be applied to
60 connections. Typically they are copied to connections from
61 packets using the CONNSECMARK target and copied back from
62 connections to packets with the same target, with the packets
63 being originally labeled via SECMARK.
64
65 If unsure, say 'N'.
66
67config IP_NF_CONNTRACK_EVENTS
68 bool "Connection tracking events (EXPERIMENTAL)"
69 depends on EXPERIMENTAL && IP_NF_CONNTRACK
70 help
71 If this option is enabled, the connection tracking code will
72 provide a notifier chain that can be used by other kernel code
73 to get notified about changes in the connection tracking state.
74
75 IF unsure, say `N'.
76
77config IP_NF_CONNTRACK_NETLINK
78 tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
79 depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
80 depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
81 depends on IP_NF_NAT=n || IP_NF_NAT
82 help
83 This option enables support for a netlink-based userspace interface
84
85
86config IP_NF_CT_PROTO_SCTP
87 tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
88 depends on IP_NF_CONNTRACK && EXPERIMENTAL
89 help
90 With this option enabled, the connection tracking code will
91 be able to do state tracking on SCTP connections.
92
93 If you want to compile it as a module, say M here and read
94 <file:Documentation/modules.txt>. If unsure, say `N'.
95
96config IP_NF_FTP
97 tristate "FTP protocol support"
98 depends on IP_NF_CONNTRACK
99 help
100 Tracking FTP connections is problematic: special helpers are
101 required for tracking them, and doing masquerading and other forms
102 of Network Address Translation on them.
103
104 To compile it as a module, choose M here. If unsure, say Y.
105
106config IP_NF_IRC
107 tristate "IRC protocol support"
108 depends on IP_NF_CONNTRACK
109 ---help---
110 There is a commonly-used extension to IRC called
111 Direct Client-to-Client Protocol (DCC). This enables users to send
112 files to each other, and also chat to each other without the need
113 of a server. DCC Sending is used anywhere you send files over IRC,
114 and DCC Chat is most commonly used by Eggdrop bots. If you are
115 using NAT, this extension will enable you to send files and initiate
116 chats. Note that you do NOT need this extension to get files or
117 have others initiate chats, or everything else in IRC.
118
119 To compile it as a module, choose M here. If unsure, say Y.
120
121config IP_NF_NETBIOS_NS
122 tristate "NetBIOS name service protocol support (EXPERIMENTAL)"
123 depends on IP_NF_CONNTRACK && EXPERIMENTAL
124 help
125 NetBIOS name service requests are sent as broadcast messages from an
126 unprivileged port and responded to with unicast messages to the
127 same port. This make them hard to firewall properly because connection
128 tracking doesn't deal with broadcasts. This helper tracks locally
129 originating NetBIOS name service requests and the corresponding
130 responses. It relies on correct IP address configuration, specifically
131 netmask and broadcast address. When properly configured, the output
132 of "ip address show" should look similar to this:
133
134 $ ip -4 address show eth0
135 4: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
136 inet 172.16.2.252/24 brd 172.16.2.255 scope global eth0
137
138 To compile it as a module, choose M here. If unsure, say N.
139
140config IP_NF_TFTP
141 tristate "TFTP protocol support"
142 depends on IP_NF_CONNTRACK
143 help
144 TFTP connection tracking helper, this is required depending
145 on how restrictive your ruleset is.
146 If you are using a tftp client behind -j SNAT or -j MASQUERADING
147 you will need this.
148
149 To compile it as a module, choose M here. If unsure, say Y.
150
151config IP_NF_AMANDA
152 tristate "Amanda backup protocol support"
153 depends on IP_NF_CONNTRACK
154 select TEXTSEARCH
155 select TEXTSEARCH_KMP
156 help
157 If you are running the Amanda backup package <http://www.amanda.org/>
158 on this machine or machines that will be MASQUERADED through this
159 machine, then you may want to enable this feature. This allows the
160 connection tracking and natting code to allow the sub-channels that
161 Amanda requires for communication of the backup data, messages and
162 index.
163
164 To compile it as a module, choose M here. If unsure, say Y.
165
166config IP_NF_PPTP
167 tristate 'PPTP protocol support'
168 depends on IP_NF_CONNTRACK
169 help
170 This module adds support for PPTP (Point to Point Tunnelling
171 Protocol, RFC2637) connection tracking and NAT.
172
173 If you are running PPTP sessions over a stateful firewall or NAT
174 box, you may want to enable this feature.
175
176 Please note that not all PPTP modes of operation are supported yet.
177 For more info, read top of the file
178 net/ipv4/netfilter/ip_conntrack_pptp.c
179
180 If you want to compile it as a module, say M here and read
181 Documentation/modules.txt. If unsure, say `N'.
182
183config IP_NF_H323
184 tristate 'H.323 protocol support (EXPERIMENTAL)'
185 depends on IP_NF_CONNTRACK && EXPERIMENTAL
186 help
187 H.323 is a VoIP signalling protocol from ITU-T. As one of the most
188 important VoIP protocols, it is widely used by voice hardware and
189 software including voice gateways, IP phones, Netmeeting, OpenPhone,
190 Gnomemeeting, etc.
191
192 With this module you can support H.323 on a connection tracking/NAT
193 firewall.
194
195 This module supports RAS, Fast Start, H.245 Tunnelling, Call
196 Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
197 whiteboard, file transfer, etc. For more information, please
198 visit http://nath323.sourceforge.net/.
199
200 If you want to compile it as a module, say 'M' here and read
201 Documentation/modules.txt. If unsure, say 'N'.
202
203config IP_NF_SIP
204 tristate "SIP protocol support (EXPERIMENTAL)"
205 depends on IP_NF_CONNTRACK && EXPERIMENTAL
206 help
207 SIP is an application-layer control protocol that can establish,
208 modify, and terminate multimedia sessions (conferences) such as
209 Internet telephony calls. With the ip_conntrack_sip and
210 the ip_nat_sip modules you can support the protocol on a connection
211 tracking/NATing firewall.
212
213 To compile it as a module, choose M here. If unsure, say Y.
214
215config IP_NF_QUEUE 33config IP_NF_QUEUE
216 tristate "IP Userspace queueing via NETLINK (OBSOLETE)" 34 tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
217 help 35 help
@@ -361,17 +179,6 @@ config IP_NF_TARGET_ULOG
361 179
362 To compile it as a module, choose M here. If unsure, say N. 180 To compile it as a module, choose M here. If unsure, say N.
363 181
364# NAT + specific targets: ip_conntrack
365config IP_NF_NAT
366 tristate "Full NAT"
367 depends on IP_NF_IPTABLES && IP_NF_CONNTRACK
368 help
369 The Full NAT option allows masquerading, port forwarding and other
370 forms of full Network Address Port Translation. It is controlled by
371 the `nat' table in iptables: see the man page for iptables(8).
372
373 To compile it as a module, choose M here. If unsure, say N.
374
375# NAT + specific targets: nf_conntrack 182# NAT + specific targets: nf_conntrack
376config NF_NAT 183config NF_NAT
377 tristate "Full NAT" 184 tristate "Full NAT"
@@ -383,11 +190,6 @@ config NF_NAT
383 190
384 To compile it as a module, choose M here. If unsure, say N. 191 To compile it as a module, choose M here. If unsure, say N.
385 192
386config IP_NF_NAT_NEEDED
387 bool
388 depends on IP_NF_NAT
389 default y
390
391config NF_NAT_NEEDED 193config NF_NAT_NEEDED
392 bool 194 bool
393 depends on NF_NAT 195 depends on NF_NAT
@@ -395,7 +197,7 @@ config NF_NAT_NEEDED
395 197
396config IP_NF_TARGET_MASQUERADE 198config IP_NF_TARGET_MASQUERADE
397 tristate "MASQUERADE target support" 199 tristate "MASQUERADE target support"
398 depends on (NF_NAT || IP_NF_NAT) 200 depends on NF_NAT
399 help 201 help
400 Masquerading is a special case of NAT: all outgoing connections are 202 Masquerading is a special case of NAT: all outgoing connections are
401 changed to seem to come from a particular interface's address, and 203 changed to seem to come from a particular interface's address, and
@@ -407,7 +209,7 @@ config IP_NF_TARGET_MASQUERADE
407 209
408config IP_NF_TARGET_REDIRECT 210config IP_NF_TARGET_REDIRECT
409 tristate "REDIRECT target support" 211 tristate "REDIRECT target support"
410 depends on (NF_NAT || IP_NF_NAT) 212 depends on NF_NAT
411 help 213 help
412 REDIRECT is a special case of NAT: all incoming connections are 214 REDIRECT is a special case of NAT: all incoming connections are
413 mapped onto the incoming interface's address, causing the packets to 215 mapped onto the incoming interface's address, causing the packets to
@@ -418,7 +220,7 @@ config IP_NF_TARGET_REDIRECT
418 220
419config IP_NF_TARGET_NETMAP 221config IP_NF_TARGET_NETMAP
420 tristate "NETMAP target support" 222 tristate "NETMAP target support"
421 depends on (NF_NAT || IP_NF_NAT) 223 depends on NF_NAT
422 help 224 help
423 NETMAP is an implementation of static 1:1 NAT mapping of network 225 NETMAP is an implementation of static 1:1 NAT mapping of network
424 addresses. It maps the network address part, while keeping the host 226 addresses. It maps the network address part, while keeping the host
@@ -429,28 +231,13 @@ config IP_NF_TARGET_NETMAP
429 231
430config IP_NF_TARGET_SAME 232config IP_NF_TARGET_SAME
431 tristate "SAME target support" 233 tristate "SAME target support"
432 depends on (NF_NAT || IP_NF_NAT) 234 depends on NF_NAT
433 help 235 help
434 This option adds a `SAME' target, which works like the standard SNAT 236 This option adds a `SAME' target, which works like the standard SNAT
435 target, but attempts to give clients the same IP for all connections. 237 target, but attempts to give clients the same IP for all connections.
436 238
437 To compile it as a module, choose M here. If unsure, say N. 239 To compile it as a module, choose M here. If unsure, say N.
438 240
439config IP_NF_NAT_SNMP_BASIC
440 tristate "Basic SNMP-ALG support (EXPERIMENTAL)"
441 depends on EXPERIMENTAL && IP_NF_NAT
442 ---help---
443
444 This module implements an Application Layer Gateway (ALG) for
445 SNMP payloads. In conjunction with NAT, it allows a network
446 management system to access multiple private networks with
447 conflicting addresses. It works by modifying IP addresses
448 inside SNMP payloads to match IP-layer NAT mapping.
449
450 This is the "basic" form of SNMP-ALG, as described in RFC 2962
451
452 To compile it as a module, choose M here. If unsure, say N.
453
454config NF_NAT_SNMP_BASIC 241config NF_NAT_SNMP_BASIC
455 tristate "Basic SNMP-ALG support (EXPERIMENTAL)" 242 tristate "Basic SNMP-ALG support (EXPERIMENTAL)"
456 depends on EXPERIMENTAL && NF_NAT 243 depends on EXPERIMENTAL && NF_NAT
@@ -477,78 +264,37 @@ config NF_NAT_PROTO_GRE
477 tristate 264 tristate
478 depends on NF_NAT && NF_CT_PROTO_GRE 265 depends on NF_NAT && NF_CT_PROTO_GRE
479 266
480config IP_NF_NAT_FTP
481 tristate
482 depends on IP_NF_IPTABLES && IP_NF_CONNTRACK && IP_NF_NAT
483 default IP_NF_NAT && IP_NF_FTP
484
485config NF_NAT_FTP 267config NF_NAT_FTP
486 tristate 268 tristate
487 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 269 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
488 default NF_NAT && NF_CONNTRACK_FTP 270 default NF_NAT && NF_CONNTRACK_FTP
489 271
490config IP_NF_NAT_IRC
491 tristate
492 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
493 default IP_NF_NAT if IP_NF_IRC=y
494 default m if IP_NF_IRC=m
495
496config NF_NAT_IRC 272config NF_NAT_IRC
497 tristate 273 tristate
498 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 274 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
499 default NF_NAT && NF_CONNTRACK_IRC 275 default NF_NAT && NF_CONNTRACK_IRC
500 276
501config IP_NF_NAT_TFTP
502 tristate
503 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
504 default IP_NF_NAT if IP_NF_TFTP=y
505 default m if IP_NF_TFTP=m
506
507config NF_NAT_TFTP 277config NF_NAT_TFTP
508 tristate 278 tristate
509 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 279 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
510 default NF_NAT && NF_CONNTRACK_TFTP 280 default NF_NAT && NF_CONNTRACK_TFTP
511 281
512config IP_NF_NAT_AMANDA
513 tristate
514 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
515 default IP_NF_NAT if IP_NF_AMANDA=y
516 default m if IP_NF_AMANDA=m
517
518config NF_NAT_AMANDA 282config NF_NAT_AMANDA
519 tristate 283 tristate
520 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 284 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
521 default NF_NAT && NF_CONNTRACK_AMANDA 285 default NF_NAT && NF_CONNTRACK_AMANDA
522 286
523config IP_NF_NAT_PPTP
524 tristate
525 depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
526 default IP_NF_NAT if IP_NF_PPTP=y
527 default m if IP_NF_PPTP=m
528
529config NF_NAT_PPTP 287config NF_NAT_PPTP
530 tristate 288 tristate
531 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 289 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
532 default NF_NAT && NF_CONNTRACK_PPTP 290 default NF_NAT && NF_CONNTRACK_PPTP
533 select NF_NAT_PROTO_GRE 291 select NF_NAT_PROTO_GRE
534 292
535config IP_NF_NAT_H323
536 tristate
537 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
538 default IP_NF_NAT if IP_NF_H323=y
539 default m if IP_NF_H323=m
540
541config NF_NAT_H323 293config NF_NAT_H323
542 tristate 294 tristate
543 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 295 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
544 default NF_NAT && NF_CONNTRACK_H323 296 default NF_NAT && NF_CONNTRACK_H323
545 297
546config IP_NF_NAT_SIP
547 tristate
548 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
549 default IP_NF_NAT if IP_NF_SIP=y
550 default m if IP_NF_SIP=m
551
552config NF_NAT_SIP 298config NF_NAT_SIP
553 tristate 299 tristate
554 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 300 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
@@ -606,9 +352,8 @@ config IP_NF_TARGET_TTL
606config IP_NF_TARGET_CLUSTERIP 352config IP_NF_TARGET_CLUSTERIP
607 tristate "CLUSTERIP target support (EXPERIMENTAL)" 353 tristate "CLUSTERIP target support (EXPERIMENTAL)"
608 depends on IP_NF_MANGLE && EXPERIMENTAL 354 depends on IP_NF_MANGLE && EXPERIMENTAL
609 depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 355 depends on NF_CONNTRACK_IPV4
610 select IP_NF_CONNTRACK_MARK if IP_NF_CONNTRACK 356 select NF_CONNTRACK_MARK
611 select NF_CONNTRACK_MARK if NF_CONNTRACK_IPV4
612 help 357 help
613 The CLUSTERIP target allows you to build load-balancing clusters of 358 The CLUSTERIP target allows you to build load-balancing clusters of
614 network servers without having a dedicated load-balancing 359 network servers without having a dedicated load-balancing
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 6625ec68180c..409d273f6f82 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -2,8 +2,6 @@
2# Makefile for the netfilter modules on top of IPv4. 2# Makefile for the netfilter modules on top of IPv4.
3# 3#
4 4
5# objects for the standalone - connection tracking / NAT
6ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
7# objects for l3 independent conntrack 5# objects for l3 independent conntrack
8nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o 6nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
9ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y) 7ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
@@ -12,53 +10,14 @@ nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
12endif 10endif
13endif 11endif
14 12
15ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o 13nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
16nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
17ifneq ($(CONFIG_NF_NAT),)
18iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o 14iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o
19else
20iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
21endif
22
23ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
24ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
25
26ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ../../netfilter/nf_conntrack_h323_asn1.o
27ip_nat_h323-objs := ip_nat_helper_h323.o
28 15
29# connection tracking 16# connection tracking
30obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
31obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o 17obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
32 18
33obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
34obj-$(CONFIG_NF_NAT) += nf_nat.o 19obj-$(CONFIG_NF_NAT) += nf_nat.o
35 20
36# conntrack netlink interface
37obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
38
39
40# SCTP protocol connection tracking
41obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
42
43# connection tracking helpers
44obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
45obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
46obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
47obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
48obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
49obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
50obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
51obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
52
53# NAT helpers (ip_conntrack)
54obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
55obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
56obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
57obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
58obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
59obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
60obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
61
62# NAT helpers (nf_conntrack) 21# NAT helpers (nf_conntrack)
63obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o 22obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
64obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 23obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
@@ -78,7 +37,6 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
78# the three instances of ip_tables 37# the three instances of ip_tables
79obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o 38obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
80obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o 39obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
81obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
82obj-$(CONFIG_NF_NAT) += iptable_nat.o 40obj-$(CONFIG_NF_NAT) += iptable_nat.o
83obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o 41obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
84 42
@@ -100,7 +58,6 @@ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
100obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 58obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
101obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 59obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
102obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o 60obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
103obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
104obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 61obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
105obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 62obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
106obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 63obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
deleted file mode 100644
index c40762c67d0e..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ /dev/null
@@ -1,229 +0,0 @@
1/* Amanda extension for IP connection tracking, Version 0.2
2 * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
3 * based on HW's ip_conntrack_irc.c as well as other modules
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 * Module load syntax:
11 * insmod ip_conntrack_amanda.o [master_timeout=n]
12 *
13 * Where master_timeout is the timeout (in seconds) of the master
14 * connection (port 10080). This defaults to 5 minutes but if
15 * your clients take longer than 5 minutes to do their work
16 * before getting back to the Amanda server, you can increase
17 * this value.
18 *
19 */
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/textsearch.h>
24#include <linux/skbuff.h>
25#include <linux/in.h>
26#include <linux/ip.h>
27#include <linux/udp.h>
28
29#include <linux/netfilter.h>
30#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
31#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
32
33static unsigned int master_timeout = 300;
34static char *ts_algo = "kmp";
35
36MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
37MODULE_DESCRIPTION("Amanda connection tracking module");
38MODULE_LICENSE("GPL");
39module_param(master_timeout, uint, 0600);
40MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
41module_param(ts_algo, charp, 0400);
42MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
43
44unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
45 enum ip_conntrack_info ctinfo,
46 unsigned int matchoff,
47 unsigned int matchlen,
48 struct ip_conntrack_expect *exp);
49EXPORT_SYMBOL_GPL(ip_nat_amanda_hook);
50
51enum amanda_strings {
52 SEARCH_CONNECT,
53 SEARCH_NEWLINE,
54 SEARCH_DATA,
55 SEARCH_MESG,
56 SEARCH_INDEX,
57};
58
59static struct {
60 char *string;
61 size_t len;
62 struct ts_config *ts;
63} search[] = {
64 [SEARCH_CONNECT] = {
65 .string = "CONNECT ",
66 .len = 8,
67 },
68 [SEARCH_NEWLINE] = {
69 .string = "\n",
70 .len = 1,
71 },
72 [SEARCH_DATA] = {
73 .string = "DATA ",
74 .len = 5,
75 },
76 [SEARCH_MESG] = {
77 .string = "MESG ",
78 .len = 5,
79 },
80 [SEARCH_INDEX] = {
81 .string = "INDEX ",
82 .len = 6,
83 },
84};
85
86static int help(struct sk_buff **pskb,
87 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
88{
89 struct ts_state ts;
90 struct ip_conntrack_expect *exp;
91 unsigned int dataoff, start, stop, off, i;
92 char pbuf[sizeof("65535")], *tmp;
93 u_int16_t port, len;
94 int ret = NF_ACCEPT;
95 typeof(ip_nat_amanda_hook) ip_nat_amanda;
96
97 /* Only look at packets from the Amanda server */
98 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
99 return NF_ACCEPT;
100
101 /* increase the UDP timeout of the master connection as replies from
102 * Amanda clients to the server can be quite delayed */
103 ip_ct_refresh(ct, *pskb, master_timeout * HZ);
104
105 /* No data? */
106 dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
107 if (dataoff >= (*pskb)->len) {
108 if (net_ratelimit())
109 printk("amanda_help: skblen = %u\n", (*pskb)->len);
110 return NF_ACCEPT;
111 }
112
113 memset(&ts, 0, sizeof(ts));
114 start = skb_find_text(*pskb, dataoff, (*pskb)->len,
115 search[SEARCH_CONNECT].ts, &ts);
116 if (start == UINT_MAX)
117 goto out;
118 start += dataoff + search[SEARCH_CONNECT].len;
119
120 memset(&ts, 0, sizeof(ts));
121 stop = skb_find_text(*pskb, start, (*pskb)->len,
122 search[SEARCH_NEWLINE].ts, &ts);
123 if (stop == UINT_MAX)
124 goto out;
125 stop += start;
126
127 for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
128 memset(&ts, 0, sizeof(ts));
129 off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
130 if (off == UINT_MAX)
131 continue;
132 off += start + search[i].len;
133
134 len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
135 if (skb_copy_bits(*pskb, off, pbuf, len))
136 break;
137 pbuf[len] = '\0';
138
139 port = simple_strtoul(pbuf, &tmp, 10);
140 len = tmp - pbuf;
141 if (port == 0 || len > 5)
142 break;
143
144 exp = ip_conntrack_expect_alloc(ct);
145 if (exp == NULL) {
146 ret = NF_DROP;
147 goto out;
148 }
149
150 exp->expectfn = NULL;
151 exp->flags = 0;
152
153 exp->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
154 exp->tuple.src.u.tcp.port = 0;
155 exp->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
156 exp->tuple.dst.protonum = IPPROTO_TCP;
157 exp->tuple.dst.u.tcp.port = htons(port);
158
159 exp->mask.src.ip = htonl(0xFFFFFFFF);
160 exp->mask.src.u.tcp.port = 0;
161 exp->mask.dst.ip = htonl(0xFFFFFFFF);
162 exp->mask.dst.protonum = 0xFF;
163 exp->mask.dst.u.tcp.port = htons(0xFFFF);
164
165 /* RCU read locked by nf_hook_slow */
166 ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook);
167 if (ip_nat_amanda)
168 ret = ip_nat_amanda(pskb, ctinfo, off - dataoff,
169 len, exp);
170 else if (ip_conntrack_expect_related(exp) != 0)
171 ret = NF_DROP;
172 ip_conntrack_expect_put(exp);
173 }
174
175out:
176 return ret;
177}
178
179static struct ip_conntrack_helper amanda_helper = {
180 .max_expected = 3,
181 .timeout = 180,
182 .me = THIS_MODULE,
183 .help = help,
184 .name = "amanda",
185
186 .tuple = { .src = { .u = { .udp = {.port = __constant_htons(10080) } } },
187 .dst = { .protonum = IPPROTO_UDP },
188 },
189 .mask = { .src = { .u = { 0xFFFF } },
190 .dst = { .protonum = 0xFF },
191 },
192};
193
194static void __exit ip_conntrack_amanda_fini(void)
195{
196 int i;
197
198 ip_conntrack_helper_unregister(&amanda_helper);
199 for (i = 0; i < ARRAY_SIZE(search); i++)
200 textsearch_destroy(search[i].ts);
201}
202
203static int __init ip_conntrack_amanda_init(void)
204{
205 int ret, i;
206
207 ret = -ENOMEM;
208 for (i = 0; i < ARRAY_SIZE(search); i++) {
209 search[i].ts = textsearch_prepare(ts_algo, search[i].string,
210 search[i].len,
211 GFP_KERNEL, TS_AUTOLOAD);
212 if (search[i].ts == NULL)
213 goto err;
214 }
215 ret = ip_conntrack_helper_register(&amanda_helper);
216 if (ret < 0)
217 goto err;
218 return 0;
219
220err:
221 for (; i >= 0; i--) {
222 if (search[i].ts)
223 textsearch_destroy(search[i].ts);
224 }
225 return ret;
226}
227
228module_init(ip_conntrack_amanda_init);
229module_exit(ip_conntrack_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
deleted file mode 100644
index 986c0c81294f..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ /dev/null
@@ -1,1549 +0,0 @@
1/* Connection state tracking for netfilter. This is separated from,
2 but required by, the NAT layer; it can also be used by an iptables
3 extension. */
4
5/* (C) 1999-2001 Paul `Rusty' Russell
6 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
13 * - new API and handling of conntrack/nat helpers
14 * - now capable of multiple expectations for one master
15 * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
16 * - add usage/reference counts to ip_conntrack_expect
17 * - export ip_conntrack[_expect]_{find_get,put} functions
18 * */
19
20#include <linux/types.h>
21#include <linux/icmp.h>
22#include <linux/ip.h>
23#include <linux/netfilter.h>
24#include <linux/netfilter_ipv4.h>
25#include <linux/module.h>
26#include <linux/skbuff.h>
27#include <linux/proc_fs.h>
28#include <linux/vmalloc.h>
29#include <net/checksum.h>
30#include <net/ip.h>
31#include <linux/stddef.h>
32#include <linux/sysctl.h>
33#include <linux/slab.h>
34#include <linux/random.h>
35#include <linux/jhash.h>
36#include <linux/err.h>
37#include <linux/percpu.h>
38#include <linux/moduleparam.h>
39#include <linux/notifier.h>
40
41/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
42 registrations, conntrack timers*/
43#include <linux/netfilter_ipv4/ip_conntrack.h>
44#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
45#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
46#include <linux/netfilter_ipv4/ip_conntrack_core.h>
47
48#define IP_CONNTRACK_VERSION "2.4"
49
50#if 0
51#define DEBUGP printk
52#else
53#define DEBUGP(format, args...)
54#endif
55
56DEFINE_RWLOCK(ip_conntrack_lock);
57
58/* ip_conntrack_standalone needs this */
59atomic_t ip_conntrack_count = ATOMIC_INIT(0);
60
61void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
62LIST_HEAD(ip_conntrack_expect_list);
63struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO] __read_mostly;
64static LIST_HEAD(helpers);
65unsigned int ip_conntrack_htable_size __read_mostly = 0;
66int ip_conntrack_max __read_mostly;
67struct list_head *ip_conntrack_hash __read_mostly;
68static struct kmem_cache *ip_conntrack_cachep __read_mostly;
69static struct kmem_cache *ip_conntrack_expect_cachep __read_mostly;
70struct ip_conntrack ip_conntrack_untracked;
71unsigned int ip_ct_log_invalid __read_mostly;
72static LIST_HEAD(unconfirmed);
73static int ip_conntrack_vmalloc __read_mostly;
74
75static unsigned int ip_conntrack_next_id;
76static unsigned int ip_conntrack_expect_next_id;
77#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
78ATOMIC_NOTIFIER_HEAD(ip_conntrack_chain);
79ATOMIC_NOTIFIER_HEAD(ip_conntrack_expect_chain);
80
81DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
82
83/* deliver cached events and clear cache entry - must be called with locally
84 * disabled softirqs */
85static inline void
86__ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache)
87{
88 DEBUGP("ecache: delivering events for %p\n", ecache->ct);
89 if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events)
90 atomic_notifier_call_chain(&ip_conntrack_chain, ecache->events,
91 ecache->ct);
92 ecache->events = 0;
93 ip_conntrack_put(ecache->ct);
94 ecache->ct = NULL;
95}
96
97/* Deliver all cached events for a particular conntrack. This is called
98 * by code prior to async packet handling or freeing the skb */
99void ip_ct_deliver_cached_events(const struct ip_conntrack *ct)
100{
101 struct ip_conntrack_ecache *ecache;
102
103 local_bh_disable();
104 ecache = &__get_cpu_var(ip_conntrack_ecache);
105 if (ecache->ct == ct)
106 __ip_ct_deliver_cached_events(ecache);
107 local_bh_enable();
108}
109
110void __ip_ct_event_cache_init(struct ip_conntrack *ct)
111{
112 struct ip_conntrack_ecache *ecache;
113
114 /* take care of delivering potentially old events */
115 ecache = &__get_cpu_var(ip_conntrack_ecache);
116 BUG_ON(ecache->ct == ct);
117 if (ecache->ct)
118 __ip_ct_deliver_cached_events(ecache);
119 /* initialize for this conntrack/packet */
120 ecache->ct = ct;
121 nf_conntrack_get(&ct->ct_general);
122}
123
124/* flush the event cache - touches other CPU's data and must not be called while
125 * packets are still passing through the code */
126static void ip_ct_event_cache_flush(void)
127{
128 struct ip_conntrack_ecache *ecache;
129 int cpu;
130
131 for_each_possible_cpu(cpu) {
132 ecache = &per_cpu(ip_conntrack_ecache, cpu);
133 if (ecache->ct)
134 ip_conntrack_put(ecache->ct);
135 }
136}
137#else
138static inline void ip_ct_event_cache_flush(void) {}
139#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
140
141DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
142
143static int ip_conntrack_hash_rnd_initted;
144static unsigned int ip_conntrack_hash_rnd;
145
146static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
147 unsigned int size, unsigned int rnd)
148{
149 return (jhash_3words((__force u32)tuple->src.ip,
150 ((__force u32)tuple->dst.ip ^ tuple->dst.protonum),
151 (tuple->src.u.all | (tuple->dst.u.all << 16)),
152 rnd) % size);
153}
154
155static u_int32_t
156hash_conntrack(const struct ip_conntrack_tuple *tuple)
157{
158 return __hash_conntrack(tuple, ip_conntrack_htable_size,
159 ip_conntrack_hash_rnd);
160}
161
162int
163ip_ct_get_tuple(const struct iphdr *iph,
164 const struct sk_buff *skb,
165 unsigned int dataoff,
166 struct ip_conntrack_tuple *tuple,
167 const struct ip_conntrack_protocol *protocol)
168{
169 /* Never happen */
170 if (iph->frag_off & htons(IP_OFFSET)) {
171 printk("ip_conntrack_core: Frag of proto %u.\n",
172 iph->protocol);
173 return 0;
174 }
175
176 tuple->src.ip = iph->saddr;
177 tuple->dst.ip = iph->daddr;
178 tuple->dst.protonum = iph->protocol;
179 tuple->dst.dir = IP_CT_DIR_ORIGINAL;
180
181 return protocol->pkt_to_tuple(skb, dataoff, tuple);
182}
183
184int
185ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
186 const struct ip_conntrack_tuple *orig,
187 const struct ip_conntrack_protocol *protocol)
188{
189 inverse->src.ip = orig->dst.ip;
190 inverse->dst.ip = orig->src.ip;
191 inverse->dst.protonum = orig->dst.protonum;
192 inverse->dst.dir = !orig->dst.dir;
193
194 return protocol->invert_tuple(inverse, orig);
195}
196
197
198/* ip_conntrack_expect helper functions */
199void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
200{
201 IP_NF_ASSERT(!timer_pending(&exp->timeout));
202 list_del(&exp->list);
203 CONNTRACK_STAT_INC(expect_delete);
204 exp->master->expecting--;
205 ip_conntrack_expect_put(exp);
206}
207
208static void expectation_timed_out(unsigned long ul_expect)
209{
210 struct ip_conntrack_expect *exp = (void *)ul_expect;
211
212 write_lock_bh(&ip_conntrack_lock);
213 ip_ct_unlink_expect(exp);
214 write_unlock_bh(&ip_conntrack_lock);
215 ip_conntrack_expect_put(exp);
216}
217
218struct ip_conntrack_expect *
219__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
220{
221 struct ip_conntrack_expect *i;
222
223 list_for_each_entry(i, &ip_conntrack_expect_list, list) {
224 if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
225 return i;
226 }
227 return NULL;
228}
229
230/* Just find a expectation corresponding to a tuple. */
231struct ip_conntrack_expect *
232ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
233{
234 struct ip_conntrack_expect *i;
235
236 read_lock_bh(&ip_conntrack_lock);
237 i = __ip_conntrack_expect_find(tuple);
238 if (i)
239 atomic_inc(&i->use);
240 read_unlock_bh(&ip_conntrack_lock);
241
242 return i;
243}
244
245/* If an expectation for this connection is found, it gets delete from
246 * global list then returned. */
247static struct ip_conntrack_expect *
248find_expectation(const struct ip_conntrack_tuple *tuple)
249{
250 struct ip_conntrack_expect *i;
251
252 list_for_each_entry(i, &ip_conntrack_expect_list, list) {
253 /* If master is not in hash table yet (ie. packet hasn't left
254 this machine yet), how can other end know about expected?
255 Hence these are not the droids you are looking for (if
256 master ct never got confirmed, we'd hold a reference to it
257 and weird things would happen to future packets). */
258 if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)
259 && is_confirmed(i->master)) {
260 if (i->flags & IP_CT_EXPECT_PERMANENT) {
261 atomic_inc(&i->use);
262 return i;
263 } else if (del_timer(&i->timeout)) {
264 ip_ct_unlink_expect(i);
265 return i;
266 }
267 }
268 }
269 return NULL;
270}
271
272/* delete all expectations for this conntrack */
273void ip_ct_remove_expectations(struct ip_conntrack *ct)
274{
275 struct ip_conntrack_expect *i, *tmp;
276
277 /* Optimization: most connection never expect any others. */
278 if (ct->expecting == 0)
279 return;
280
281 list_for_each_entry_safe(i, tmp, &ip_conntrack_expect_list, list) {
282 if (i->master == ct && del_timer(&i->timeout)) {
283 ip_ct_unlink_expect(i);
284 ip_conntrack_expect_put(i);
285 }
286 }
287}
288
289static void
290clean_from_lists(struct ip_conntrack *ct)
291{
292 DEBUGP("clean_from_lists(%p)\n", ct);
293 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
294 list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
295
296 /* Destroy all pending expectations */
297 ip_ct_remove_expectations(ct);
298}
299
300static void
301destroy_conntrack(struct nf_conntrack *nfct)
302{
303 struct ip_conntrack *ct = (struct ip_conntrack *)nfct;
304 struct ip_conntrack_protocol *proto;
305 struct ip_conntrack_helper *helper;
306 typeof(ip_conntrack_destroyed) destroyed;
307
308 DEBUGP("destroy_conntrack(%p)\n", ct);
309 IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
310 IP_NF_ASSERT(!timer_pending(&ct->timeout));
311
312 ip_conntrack_event(IPCT_DESTROY, ct);
313 set_bit(IPS_DYING_BIT, &ct->status);
314
315 helper = ct->helper;
316 if (helper && helper->destroy)
317 helper->destroy(ct);
318
319 /* To make sure we don't get any weird locking issues here:
320 * destroy_conntrack() MUST NOT be called with a write lock
321 * to ip_conntrack_lock!!! -HW */
322 rcu_read_lock();
323 proto = __ip_conntrack_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
324 if (proto && proto->destroy)
325 proto->destroy(ct);
326
327 destroyed = rcu_dereference(ip_conntrack_destroyed);
328 if (destroyed)
329 destroyed(ct);
330
331 rcu_read_unlock();
332
333 write_lock_bh(&ip_conntrack_lock);
334 /* Expectations will have been removed in clean_from_lists,
335 * except TFTP can create an expectation on the first packet,
336 * before connection is in the list, so we need to clean here,
337 * too. */
338 ip_ct_remove_expectations(ct);
339
340 /* We overload first tuple to link into unconfirmed list. */
341 if (!is_confirmed(ct)) {
342 BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list));
343 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
344 }
345
346 CONNTRACK_STAT_INC(delete);
347 write_unlock_bh(&ip_conntrack_lock);
348
349 if (ct->master)
350 ip_conntrack_put(ct->master);
351
352 DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
353 ip_conntrack_free(ct);
354}
355
356static void death_by_timeout(unsigned long ul_conntrack)
357{
358 struct ip_conntrack *ct = (void *)ul_conntrack;
359
360 write_lock_bh(&ip_conntrack_lock);
361 /* Inside lock so preempt is disabled on module removal path.
362 * Otherwise we can get spurious warnings. */
363 CONNTRACK_STAT_INC(delete_list);
364 clean_from_lists(ct);
365 write_unlock_bh(&ip_conntrack_lock);
366 ip_conntrack_put(ct);
367}
368
369struct ip_conntrack_tuple_hash *
370__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
371 const struct ip_conntrack *ignored_conntrack)
372{
373 struct ip_conntrack_tuple_hash *h;
374 unsigned int hash = hash_conntrack(tuple);
375
376 list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
377 if (tuplehash_to_ctrack(h) != ignored_conntrack &&
378 ip_ct_tuple_equal(tuple, &h->tuple)) {
379 CONNTRACK_STAT_INC(found);
380 return h;
381 }
382 CONNTRACK_STAT_INC(searched);
383 }
384
385 return NULL;
386}
387
388/* Find a connection corresponding to a tuple. */
389struct ip_conntrack_tuple_hash *
390ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
391 const struct ip_conntrack *ignored_conntrack)
392{
393 struct ip_conntrack_tuple_hash *h;
394
395 read_lock_bh(&ip_conntrack_lock);
396 h = __ip_conntrack_find(tuple, ignored_conntrack);
397 if (h)
398 atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
399 read_unlock_bh(&ip_conntrack_lock);
400
401 return h;
402}
403
404static void __ip_conntrack_hash_insert(struct ip_conntrack *ct,
405 unsigned int hash,
406 unsigned int repl_hash)
407{
408 ct->id = ++ip_conntrack_next_id;
409 list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
410 &ip_conntrack_hash[hash]);
411 list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
412 &ip_conntrack_hash[repl_hash]);
413}
414
415void ip_conntrack_hash_insert(struct ip_conntrack *ct)
416{
417 unsigned int hash, repl_hash;
418
419 hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
420 repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
421
422 write_lock_bh(&ip_conntrack_lock);
423 __ip_conntrack_hash_insert(ct, hash, repl_hash);
424 write_unlock_bh(&ip_conntrack_lock);
425}
426
427/* Confirm a connection given skb; places it in hash table */
428int
429__ip_conntrack_confirm(struct sk_buff **pskb)
430{
431 unsigned int hash, repl_hash;
432 struct ip_conntrack_tuple_hash *h;
433 struct ip_conntrack *ct;
434 enum ip_conntrack_info ctinfo;
435
436 ct = ip_conntrack_get(*pskb, &ctinfo);
437
438 /* ipt_REJECT uses ip_conntrack_attach to attach related
439 ICMP/TCP RST packets in other direction. Actual packet
440 which created connection will be IP_CT_NEW or for an
441 expected connection, IP_CT_RELATED. */
442 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
443 return NF_ACCEPT;
444
445 hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
446 repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
447
448 /* We're not in hash table, and we refuse to set up related
449 connections for unconfirmed conns. But packet copies and
450 REJECT will give spurious warnings here. */
451 /* IP_NF_ASSERT(atomic_read(&ct->ct_general.use) == 1); */
452
453 /* No external references means noone else could have
454 confirmed us. */
455 IP_NF_ASSERT(!is_confirmed(ct));
456 DEBUGP("Confirming conntrack %p\n", ct);
457
458 write_lock_bh(&ip_conntrack_lock);
459
460 /* See if there's one in the list already, including reverse:
461 NAT could have grabbed it without realizing, since we're
462 not in the hash. If there is, we lost race. */
463 list_for_each_entry(h, &ip_conntrack_hash[hash], list)
464 if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
465 &h->tuple))
466 goto out;
467 list_for_each_entry(h, &ip_conntrack_hash[repl_hash], list)
468 if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
469 &h->tuple))
470 goto out;
471
472 /* Remove from unconfirmed list */
473 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
474
475 __ip_conntrack_hash_insert(ct, hash, repl_hash);
476 /* Timer relative to confirmation time, not original
477 setting time, otherwise we'd get timer wrap in
478 weird delay cases. */
479 ct->timeout.expires += jiffies;
480 add_timer(&ct->timeout);
481 atomic_inc(&ct->ct_general.use);
482 set_bit(IPS_CONFIRMED_BIT, &ct->status);
483 CONNTRACK_STAT_INC(insert);
484 write_unlock_bh(&ip_conntrack_lock);
485 if (ct->helper)
486 ip_conntrack_event_cache(IPCT_HELPER, *pskb);
487#ifdef CONFIG_IP_NF_NAT_NEEDED
488 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
489 test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
490 ip_conntrack_event_cache(IPCT_NATINFO, *pskb);
491#endif
492 ip_conntrack_event_cache(master_ct(ct) ?
493 IPCT_RELATED : IPCT_NEW, *pskb);
494
495 return NF_ACCEPT;
496
497out:
498 CONNTRACK_STAT_INC(insert_failed);
499 write_unlock_bh(&ip_conntrack_lock);
500 return NF_DROP;
501}
502
503/* Returns true if a connection correspondings to the tuple (required
504 for NAT). */
505int
506ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
507 const struct ip_conntrack *ignored_conntrack)
508{
509 struct ip_conntrack_tuple_hash *h;
510
511 read_lock_bh(&ip_conntrack_lock);
512 h = __ip_conntrack_find(tuple, ignored_conntrack);
513 read_unlock_bh(&ip_conntrack_lock);
514
515 return h != NULL;
516}
517
518/* There's a small race here where we may free a just-assured
519 connection. Too bad: we're in trouble anyway. */
520static int early_drop(struct list_head *chain)
521{
522 /* Traverse backwards: gives us oldest, which is roughly LRU */
523 struct ip_conntrack_tuple_hash *h;
524 struct ip_conntrack *ct = NULL, *tmp;
525 int dropped = 0;
526
527 read_lock_bh(&ip_conntrack_lock);
528 list_for_each_entry_reverse(h, chain, list) {
529 tmp = tuplehash_to_ctrack(h);
530 if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
531 ct = tmp;
532 atomic_inc(&ct->ct_general.use);
533 break;
534 }
535 }
536 read_unlock_bh(&ip_conntrack_lock);
537
538 if (!ct)
539 return dropped;
540
541 if (del_timer(&ct->timeout)) {
542 death_by_timeout((unsigned long)ct);
543 dropped = 1;
544 CONNTRACK_STAT_INC_ATOMIC(early_drop);
545 }
546 ip_conntrack_put(ct);
547 return dropped;
548}
549
550static struct ip_conntrack_helper *
551__ip_conntrack_helper_find( const struct ip_conntrack_tuple *tuple)
552{
553 struct ip_conntrack_helper *h;
554
555 list_for_each_entry(h, &helpers, list) {
556 if (ip_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
557 return h;
558 }
559 return NULL;
560}
561
562struct ip_conntrack_helper *
563ip_conntrack_helper_find_get( const struct ip_conntrack_tuple *tuple)
564{
565 struct ip_conntrack_helper *helper;
566
567 /* need ip_conntrack_lock to assure that helper exists until
568 * try_module_get() is called */
569 read_lock_bh(&ip_conntrack_lock);
570
571 helper = __ip_conntrack_helper_find(tuple);
572 if (helper) {
573 /* need to increase module usage count to assure helper will
574 * not go away while the caller is e.g. busy putting a
575 * conntrack in the hash that uses the helper */
576 if (!try_module_get(helper->me))
577 helper = NULL;
578 }
579
580 read_unlock_bh(&ip_conntrack_lock);
581
582 return helper;
583}
584
585void ip_conntrack_helper_put(struct ip_conntrack_helper *helper)
586{
587 module_put(helper->me);
588}
589
590struct ip_conntrack_protocol *
591__ip_conntrack_proto_find(u_int8_t protocol)
592{
593 return ip_ct_protos[protocol];
594}
595
596/* this is guaranteed to always return a valid protocol helper, since
597 * it falls back to generic_protocol */
598struct ip_conntrack_protocol *
599ip_conntrack_proto_find_get(u_int8_t protocol)
600{
601 struct ip_conntrack_protocol *p;
602
603 rcu_read_lock();
604 p = __ip_conntrack_proto_find(protocol);
605 if (p) {
606 if (!try_module_get(p->me))
607 p = &ip_conntrack_generic_protocol;
608 }
609 rcu_read_unlock();
610
611 return p;
612}
613
614void ip_conntrack_proto_put(struct ip_conntrack_protocol *p)
615{
616 module_put(p->me);
617}
618
619struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *orig,
620 struct ip_conntrack_tuple *repl)
621{
622 struct ip_conntrack *conntrack;
623
624 if (!ip_conntrack_hash_rnd_initted) {
625 get_random_bytes(&ip_conntrack_hash_rnd, 4);
626 ip_conntrack_hash_rnd_initted = 1;
627 }
628
629 /* We don't want any race condition at early drop stage */
630 atomic_inc(&ip_conntrack_count);
631
632 if (ip_conntrack_max
633 && atomic_read(&ip_conntrack_count) > ip_conntrack_max) {
634 unsigned int hash = hash_conntrack(orig);
635 /* Try dropping from this hash chain. */
636 if (!early_drop(&ip_conntrack_hash[hash])) {
637 atomic_dec(&ip_conntrack_count);
638 if (net_ratelimit())
639 printk(KERN_WARNING
640 "ip_conntrack: table full, dropping"
641 " packet.\n");
642 return ERR_PTR(-ENOMEM);
643 }
644 }
645
646 conntrack = kmem_cache_zalloc(ip_conntrack_cachep, GFP_ATOMIC);
647 if (!conntrack) {
648 DEBUGP("Can't allocate conntrack.\n");
649 atomic_dec(&ip_conntrack_count);
650 return ERR_PTR(-ENOMEM);
651 }
652
653 atomic_set(&conntrack->ct_general.use, 1);
654 conntrack->ct_general.destroy = destroy_conntrack;
655 conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
656 conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
657 /* Don't set timer yet: wait for confirmation */
658 init_timer(&conntrack->timeout);
659 conntrack->timeout.data = (unsigned long)conntrack;
660 conntrack->timeout.function = death_by_timeout;
661
662 return conntrack;
663}
664
665void
666ip_conntrack_free(struct ip_conntrack *conntrack)
667{
668 atomic_dec(&ip_conntrack_count);
669 kmem_cache_free(ip_conntrack_cachep, conntrack);
670}
671
672/* Allocate a new conntrack: we return -ENOMEM if classification
673 * failed due to stress. Otherwise it really is unclassifiable */
674static struct ip_conntrack_tuple_hash *
675init_conntrack(struct ip_conntrack_tuple *tuple,
676 struct ip_conntrack_protocol *protocol,
677 struct sk_buff *skb)
678{
679 struct ip_conntrack *conntrack;
680 struct ip_conntrack_tuple repl_tuple;
681 struct ip_conntrack_expect *exp;
682
683 if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
684 DEBUGP("Can't invert tuple.\n");
685 return NULL;
686 }
687
688 conntrack = ip_conntrack_alloc(tuple, &repl_tuple);
689 if (conntrack == NULL || IS_ERR(conntrack))
690 return (struct ip_conntrack_tuple_hash *)conntrack;
691
692 if (!protocol->new(conntrack, skb)) {
693 ip_conntrack_free(conntrack);
694 return NULL;
695 }
696
697 write_lock_bh(&ip_conntrack_lock);
698 exp = find_expectation(tuple);
699
700 if (exp) {
701 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
702 conntrack, exp);
703 /* Welcome, Mr. Bond. We've been expecting you... */
704 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
705 conntrack->master = exp->master;
706#ifdef CONFIG_IP_NF_CONNTRACK_MARK
707 conntrack->mark = exp->master->mark;
708#endif
709#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
710 defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
711 /* this is ugly, but there is no other place where to put it */
712 conntrack->nat.masq_index = exp->master->nat.masq_index;
713#endif
714#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
715 conntrack->secmark = exp->master->secmark;
716#endif
717 nf_conntrack_get(&conntrack->master->ct_general);
718 CONNTRACK_STAT_INC(expect_new);
719 } else {
720 conntrack->helper = __ip_conntrack_helper_find(&repl_tuple);
721
722 CONNTRACK_STAT_INC(new);
723 }
724
725 /* Overload tuple linked list to put us in unconfirmed list. */
726 list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
727
728 write_unlock_bh(&ip_conntrack_lock);
729
730 if (exp) {
731 if (exp->expectfn)
732 exp->expectfn(conntrack, exp);
733 ip_conntrack_expect_put(exp);
734 }
735
736 return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
737}
738
739/* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
740static inline struct ip_conntrack *
741resolve_normal_ct(struct sk_buff *skb,
742 struct ip_conntrack_protocol *proto,
743 int *set_reply,
744 unsigned int hooknum,
745 enum ip_conntrack_info *ctinfo)
746{
747 struct ip_conntrack_tuple tuple;
748 struct ip_conntrack_tuple_hash *h;
749 struct ip_conntrack *ct;
750
751 IP_NF_ASSERT((ip_hdr(skb)->frag_off & htons(IP_OFFSET)) == 0);
752
753 if (!ip_ct_get_tuple(ip_hdr(skb), skb, ip_hdrlen(skb), &tuple,proto))
754 return NULL;
755
756 /* look for tuple match */
757 h = ip_conntrack_find_get(&tuple, NULL);
758 if (!h) {
759 h = init_conntrack(&tuple, proto, skb);
760 if (!h)
761 return NULL;
762 if (IS_ERR(h))
763 return (void *)h;
764 }
765 ct = tuplehash_to_ctrack(h);
766
767 /* It exists; we have (non-exclusive) reference. */
768 if (DIRECTION(h) == IP_CT_DIR_REPLY) {
769 *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;
770 /* Please set reply bit if this packet OK */
771 *set_reply = 1;
772 } else {
773 /* Once we've had two way comms, always ESTABLISHED. */
774 if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
775 DEBUGP("ip_conntrack_in: normal packet for %p\n",
776 ct);
777 *ctinfo = IP_CT_ESTABLISHED;
778 } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
779 DEBUGP("ip_conntrack_in: related packet for %p\n",
780 ct);
781 *ctinfo = IP_CT_RELATED;
782 } else {
783 DEBUGP("ip_conntrack_in: new packet for %p\n",
784 ct);
785 *ctinfo = IP_CT_NEW;
786 }
787 *set_reply = 0;
788 }
789 skb->nfct = &ct->ct_general;
790 skb->nfctinfo = *ctinfo;
791 return ct;
792}
793
794/* Netfilter hook itself. */
795unsigned int ip_conntrack_in(unsigned int hooknum,
796 struct sk_buff **pskb,
797 const struct net_device *in,
798 const struct net_device *out,
799 int (*okfn)(struct sk_buff *))
800{
801 struct ip_conntrack *ct;
802 enum ip_conntrack_info ctinfo;
803 struct ip_conntrack_protocol *proto;
804 int set_reply = 0;
805 int ret;
806
807 /* Previously seen (loopback or untracked)? Ignore. */
808 if ((*pskb)->nfct) {
809 CONNTRACK_STAT_INC_ATOMIC(ignore);
810 return NF_ACCEPT;
811 }
812
813 /* Never happen */
814 if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) {
815 if (net_ratelimit()) {
816 printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
817 ip_hdr(*pskb)->protocol, hooknum);
818 }
819 return NF_DROP;
820 }
821
822/* Doesn't cover locally-generated broadcast, so not worth it. */
823#if 0
824 /* Ignore broadcast: no `connection'. */
825 if ((*pskb)->pkt_type == PACKET_BROADCAST) {
826 printk("Broadcast packet!\n");
827 return NF_ACCEPT;
828 } else if ((ip_hdr(*pskb)->daddr & htonl(0x000000FF))
829 == htonl(0x000000FF)) {
830 printk("Should bcast: %u.%u.%u.%u->%u.%u.%u.%u (sk=%p, ptype=%u)\n",
831 NIPQUAD(ip_hdr(*pskb)->saddr),
832 NIPQUAD(ip_hdr(*pskb)->daddr),
833 (*pskb)->sk, (*pskb)->pkt_type);
834 }
835#endif
836
837 /* rcu_read_lock()ed by nf_hook_slow */
838 proto = __ip_conntrack_proto_find(ip_hdr(*pskb)->protocol);
839
840 /* It may be an special packet, error, unclean...
841 * inverse of the return code tells to the netfilter
842 * core what to do with the packet. */
843 if (proto->error != NULL
844 && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0) {
845 CONNTRACK_STAT_INC_ATOMIC(error);
846 CONNTRACK_STAT_INC_ATOMIC(invalid);
847 return -ret;
848 }
849
850 if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) {
851 /* Not valid part of a connection */
852 CONNTRACK_STAT_INC_ATOMIC(invalid);
853 return NF_ACCEPT;
854 }
855
856 if (IS_ERR(ct)) {
857 /* Too stressed to deal. */
858 CONNTRACK_STAT_INC_ATOMIC(drop);
859 return NF_DROP;
860 }
861
862 IP_NF_ASSERT((*pskb)->nfct);
863
864 ret = proto->packet(ct, *pskb, ctinfo);
865 if (ret < 0) {
866 /* Invalid: inverse of the return code tells
867 * the netfilter core what to do*/
868 nf_conntrack_put((*pskb)->nfct);
869 (*pskb)->nfct = NULL;
870 CONNTRACK_STAT_INC_ATOMIC(invalid);
871 return -ret;
872 }
873
874 if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
875 ip_conntrack_event_cache(IPCT_STATUS, *pskb);
876
877 return ret;
878}
879
880int invert_tuplepr(struct ip_conntrack_tuple *inverse,
881 const struct ip_conntrack_tuple *orig)
882{
883 struct ip_conntrack_protocol *proto;
884 int ret;
885
886 rcu_read_lock();
887 proto = __ip_conntrack_proto_find(orig->dst.protonum);
888 ret = ip_ct_invert_tuple(inverse, orig, proto);
889 rcu_read_unlock();
890
891 return ret;
892}
893
894/* Would two expected things clash? */
895static inline int expect_clash(const struct ip_conntrack_expect *a,
896 const struct ip_conntrack_expect *b)
897{
898 /* Part covered by intersection of masks must be unequal,
899 otherwise they clash */
900 struct ip_conntrack_tuple intersect_mask
901 = { { a->mask.src.ip & b->mask.src.ip,
902 { a->mask.src.u.all & b->mask.src.u.all } },
903 { a->mask.dst.ip & b->mask.dst.ip,
904 { a->mask.dst.u.all & b->mask.dst.u.all },
905 a->mask.dst.protonum & b->mask.dst.protonum } };
906
907 return ip_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
908}
909
910static inline int expect_matches(const struct ip_conntrack_expect *a,
911 const struct ip_conntrack_expect *b)
912{
913 return a->master == b->master
914 && ip_ct_tuple_equal(&a->tuple, &b->tuple)
915 && ip_ct_tuple_equal(&a->mask, &b->mask);
916}
917
918/* Generally a bad idea to call this: could have matched already. */
919void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
920{
921 struct ip_conntrack_expect *i;
922
923 write_lock_bh(&ip_conntrack_lock);
924 /* choose the the oldest expectation to evict */
925 list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
926 if (expect_matches(i, exp) && del_timer(&i->timeout)) {
927 ip_ct_unlink_expect(i);
928 write_unlock_bh(&ip_conntrack_lock);
929 ip_conntrack_expect_put(i);
930 return;
931 }
932 }
933 write_unlock_bh(&ip_conntrack_lock);
934}
935
936/* We don't increase the master conntrack refcount for non-fulfilled
937 * conntracks. During the conntrack destruction, the expectations are
938 * always killed before the conntrack itself */
939struct ip_conntrack_expect *ip_conntrack_expect_alloc(struct ip_conntrack *me)
940{
941 struct ip_conntrack_expect *new;
942
943 new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
944 if (!new) {
945 DEBUGP("expect_related: OOM allocating expect\n");
946 return NULL;
947 }
948 new->master = me;
949 atomic_set(&new->use, 1);
950 return new;
951}
952
953void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
954{
955 if (atomic_dec_and_test(&exp->use))
956 kmem_cache_free(ip_conntrack_expect_cachep, exp);
957}
958
959static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp)
960{
961 atomic_inc(&exp->use);
962 exp->master->expecting++;
963 list_add(&exp->list, &ip_conntrack_expect_list);
964
965 init_timer(&exp->timeout);
966 exp->timeout.data = (unsigned long)exp;
967 exp->timeout.function = expectation_timed_out;
968 exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ;
969 add_timer(&exp->timeout);
970
971 exp->id = ++ip_conntrack_expect_next_id;
972 atomic_inc(&exp->use);
973 CONNTRACK_STAT_INC(expect_create);
974}
975
976/* Race with expectations being used means we could have none to find; OK. */
977static void evict_oldest_expect(struct ip_conntrack *master)
978{
979 struct ip_conntrack_expect *i;
980
981 list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
982 if (i->master == master) {
983 if (del_timer(&i->timeout)) {
984 ip_ct_unlink_expect(i);
985 ip_conntrack_expect_put(i);
986 }
987 break;
988 }
989 }
990}
991
992static inline int refresh_timer(struct ip_conntrack_expect *i)
993{
994 if (!del_timer(&i->timeout))
995 return 0;
996
997 i->timeout.expires = jiffies + i->master->helper->timeout*HZ;
998 add_timer(&i->timeout);
999 return 1;
1000}
1001
1002int ip_conntrack_expect_related(struct ip_conntrack_expect *expect)
1003{
1004 struct ip_conntrack_expect *i;
1005 int ret;
1006
1007 DEBUGP("ip_conntrack_expect_related %p\n", related_to);
1008 DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
1009 DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
1010
1011 write_lock_bh(&ip_conntrack_lock);
1012 list_for_each_entry(i, &ip_conntrack_expect_list, list) {
1013 if (expect_matches(i, expect)) {
1014 /* Refresh timer: if it's dying, ignore.. */
1015 if (refresh_timer(i)) {
1016 ret = 0;
1017 goto out;
1018 }
1019 } else if (expect_clash(i, expect)) {
1020 ret = -EBUSY;
1021 goto out;
1022 }
1023 }
1024
1025 /* Will be over limit? */
1026 if (expect->master->helper->max_expected &&
1027 expect->master->expecting >= expect->master->helper->max_expected)
1028 evict_oldest_expect(expect->master);
1029
1030 ip_conntrack_expect_insert(expect);
1031 ip_conntrack_expect_event(IPEXP_NEW, expect);
1032 ret = 0;
1033out:
1034 write_unlock_bh(&ip_conntrack_lock);
1035 return ret;
1036}
1037
1038/* Alter reply tuple (maybe alter helper). This is for NAT, and is
1039 implicitly racy: see __ip_conntrack_confirm */
1040void ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
1041 const struct ip_conntrack_tuple *newreply)
1042{
1043 write_lock_bh(&ip_conntrack_lock);
1044 /* Should be unconfirmed, so not in hash table yet */
1045 IP_NF_ASSERT(!is_confirmed(conntrack));
1046
1047 DEBUGP("Altering reply tuple of %p to ", conntrack);
1048 DUMP_TUPLE(newreply);
1049
1050 conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
1051 if (!conntrack->master && conntrack->expecting == 0)
1052 conntrack->helper = __ip_conntrack_helper_find(newreply);
1053 write_unlock_bh(&ip_conntrack_lock);
1054}
1055
1056int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
1057{
1058 BUG_ON(me->timeout == 0);
1059 write_lock_bh(&ip_conntrack_lock);
1060 list_add(&me->list, &helpers);
1061 write_unlock_bh(&ip_conntrack_lock);
1062
1063 return 0;
1064}
1065
1066struct ip_conntrack_helper *
1067__ip_conntrack_helper_find_byname(const char *name)
1068{
1069 struct ip_conntrack_helper *h;
1070
1071 list_for_each_entry(h, &helpers, list) {
1072 if (!strcmp(h->name, name))
1073 return h;
1074 }
1075
1076 return NULL;
1077}
1078
1079static inline void unhelp(struct ip_conntrack_tuple_hash *i,
1080 const struct ip_conntrack_helper *me)
1081{
1082 if (tuplehash_to_ctrack(i)->helper == me) {
1083 ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i));
1084 tuplehash_to_ctrack(i)->helper = NULL;
1085 }
1086}
1087
1088void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1089{
1090 unsigned int i;
1091 struct ip_conntrack_tuple_hash *h;
1092 struct ip_conntrack_expect *exp, *tmp;
1093
1094 /* Need write lock here, to delete helper. */
1095 write_lock_bh(&ip_conntrack_lock);
1096 list_del(&me->list);
1097
1098 /* Get rid of expectations */
1099 list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
1100 if (exp->master->helper == me && del_timer(&exp->timeout)) {
1101 ip_ct_unlink_expect(exp);
1102 ip_conntrack_expect_put(exp);
1103 }
1104 }
1105 /* Get rid of expecteds, set helpers to NULL. */
1106 list_for_each_entry(h, &unconfirmed, list)
1107 unhelp(h, me);
1108 for (i = 0; i < ip_conntrack_htable_size; i++) {
1109 list_for_each_entry(h, &ip_conntrack_hash[i], list)
1110 unhelp(h, me);
1111 }
1112 write_unlock_bh(&ip_conntrack_lock);
1113
1114 /* Someone could be still looking at the helper in a bh. */
1115 synchronize_net();
1116}
1117
1118/* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
1119void __ip_ct_refresh_acct(struct ip_conntrack *ct,
1120 enum ip_conntrack_info ctinfo,
1121 const struct sk_buff *skb,
1122 unsigned long extra_jiffies,
1123 int do_acct)
1124{
1125 int event = 0;
1126
1127 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1128 IP_NF_ASSERT(skb);
1129
1130 write_lock_bh(&ip_conntrack_lock);
1131
1132 /* Only update if this is not a fixed timeout */
1133 if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
1134 write_unlock_bh(&ip_conntrack_lock);
1135 return;
1136 }
1137
1138 /* If not in hash table, timer will not be active yet */
1139 if (!is_confirmed(ct)) {
1140 ct->timeout.expires = extra_jiffies;
1141 event = IPCT_REFRESH;
1142 } else {
1143 /* Need del_timer for race avoidance (may already be dying). */
1144 if (del_timer(&ct->timeout)) {
1145 ct->timeout.expires = jiffies + extra_jiffies;
1146 add_timer(&ct->timeout);
1147 event = IPCT_REFRESH;
1148 }
1149 }
1150
1151#ifdef CONFIG_IP_NF_CT_ACCT
1152 if (do_acct) {
1153 ct->counters[CTINFO2DIR(ctinfo)].packets++;
1154 ct->counters[CTINFO2DIR(ctinfo)].bytes +=
1155 ntohs(ip_hdr(skb)->tot_len);
1156 if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
1157 || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
1158 event |= IPCT_COUNTER_FILLING;
1159 }
1160#endif
1161
1162 write_unlock_bh(&ip_conntrack_lock);
1163
1164 /* must be unlocked when calling event cache */
1165 if (event)
1166 ip_conntrack_event_cache(event, skb);
1167}
1168
1169#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
1170 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
1171/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
1172 * in ip_conntrack_core, since we don't want the protocols to autoload
1173 * or depend on ctnetlink */
1174int ip_ct_port_tuple_to_nfattr(struct sk_buff *skb,
1175 const struct ip_conntrack_tuple *tuple)
1176{
1177 NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(__be16),
1178 &tuple->src.u.tcp.port);
1179 NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(__be16),
1180 &tuple->dst.u.tcp.port);
1181 return 0;
1182
1183nfattr_failure:
1184 return -1;
1185}
1186
1187int ip_ct_port_nfattr_to_tuple(struct nfattr *tb[],
1188 struct ip_conntrack_tuple *t)
1189{
1190 if (!tb[CTA_PROTO_SRC_PORT-1] || !tb[CTA_PROTO_DST_PORT-1])
1191 return -EINVAL;
1192
1193 t->src.u.tcp.port =
1194 *(__be16 *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
1195 t->dst.u.tcp.port =
1196 *(__be16 *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
1197
1198 return 0;
1199}
1200#endif
1201
1202/* Returns new sk_buff, or NULL */
1203struct sk_buff *
1204ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
1205{
1206 skb_orphan(skb);
1207
1208 local_bh_disable();
1209 skb = ip_defrag(skb, user);
1210 local_bh_enable();
1211
1212 if (skb)
1213 ip_send_check(ip_hdr(skb));
1214 return skb;
1215}
1216
1217/* Used by ipt_REJECT. */
1218static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
1219{
1220 struct ip_conntrack *ct;
1221 enum ip_conntrack_info ctinfo;
1222
1223 /* This ICMP is in reverse direction to the packet which caused it */
1224 ct = ip_conntrack_get(skb, &ctinfo);
1225
1226 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
1227 ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY;
1228 else
1229 ctinfo = IP_CT_RELATED;
1230
1231 /* Attach to new skbuff, and increment count */
1232 nskb->nfct = &ct->ct_general;
1233 nskb->nfctinfo = ctinfo;
1234 nf_conntrack_get(nskb->nfct);
1235}
1236
1237/* Bring out ya dead! */
1238static struct ip_conntrack *
1239get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data),
1240 void *data, unsigned int *bucket)
1241{
1242 struct ip_conntrack_tuple_hash *h;
1243 struct ip_conntrack *ct;
1244
1245 write_lock_bh(&ip_conntrack_lock);
1246 for (; *bucket < ip_conntrack_htable_size; (*bucket)++) {
1247 list_for_each_entry(h, &ip_conntrack_hash[*bucket], list) {
1248 ct = tuplehash_to_ctrack(h);
1249 if (iter(ct, data))
1250 goto found;
1251 }
1252 }
1253 list_for_each_entry(h, &unconfirmed, list) {
1254 ct = tuplehash_to_ctrack(h);
1255 if (iter(ct, data))
1256 set_bit(IPS_DYING_BIT, &ct->status);
1257 }
1258 write_unlock_bh(&ip_conntrack_lock);
1259 return NULL;
1260
1261found:
1262 atomic_inc(&ct->ct_general.use);
1263 write_unlock_bh(&ip_conntrack_lock);
1264 return ct;
1265}
1266
1267void
1268ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *), void *data)
1269{
1270 struct ip_conntrack *ct;
1271 unsigned int bucket = 0;
1272
1273 while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) {
1274 /* Time to push up daises... */
1275 if (del_timer(&ct->timeout))
1276 death_by_timeout((unsigned long)ct);
1277 /* ... else the timer will get him soon. */
1278
1279 ip_conntrack_put(ct);
1280 }
1281}
1282
1283/* Fast function for those who don't want to parse /proc (and I don't
1284 blame them). */
1285/* Reversing the socket's dst/src point of view gives us the reply
1286 mapping. */
1287static int
1288getorigdst(struct sock *sk, int optval, void __user *user, int *len)
1289{
1290 struct inet_sock *inet = inet_sk(sk);
1291 struct ip_conntrack_tuple_hash *h;
1292 struct ip_conntrack_tuple tuple;
1293
1294 IP_CT_TUPLE_U_BLANK(&tuple);
1295 tuple.src.ip = inet->rcv_saddr;
1296 tuple.src.u.tcp.port = inet->sport;
1297 tuple.dst.ip = inet->daddr;
1298 tuple.dst.u.tcp.port = inet->dport;
1299 tuple.dst.protonum = IPPROTO_TCP;
1300
1301 /* We only do TCP at the moment: is there a better way? */
1302 if (strcmp(sk->sk_prot->name, "TCP")) {
1303 DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
1304 return -ENOPROTOOPT;
1305 }
1306
1307 if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
1308 DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
1309 *len, sizeof(struct sockaddr_in));
1310 return -EINVAL;
1311 }
1312
1313 h = ip_conntrack_find_get(&tuple, NULL);
1314 if (h) {
1315 struct sockaddr_in sin;
1316 struct ip_conntrack *ct = tuplehash_to_ctrack(h);
1317
1318 sin.sin_family = AF_INET;
1319 sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL]
1320 .tuple.dst.u.tcp.port;
1321 sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
1322 .tuple.dst.ip;
1323 memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
1324
1325 DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
1326 NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
1327 ip_conntrack_put(ct);
1328 if (copy_to_user(user, &sin, sizeof(sin)) != 0)
1329 return -EFAULT;
1330 else
1331 return 0;
1332 }
1333 DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
1334 NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
1335 NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
1336 return -ENOENT;
1337}
1338
1339static struct nf_sockopt_ops so_getorigdst = {
1340 .pf = PF_INET,
1341 .get_optmin = SO_ORIGINAL_DST,
1342 .get_optmax = SO_ORIGINAL_DST+1,
1343 .get = &getorigdst,
1344};
1345
1346static int kill_all(struct ip_conntrack *i, void *data)
1347{
1348 return 1;
1349}
1350
1351void ip_conntrack_flush(void)
1352{
1353 ip_ct_iterate_cleanup(kill_all, NULL);
1354}
1355
1356static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size)
1357{
1358 if (vmalloced)
1359 vfree(hash);
1360 else
1361 free_pages((unsigned long)hash,
1362 get_order(sizeof(struct list_head) * size));
1363}
1364
1365/* Mishearing the voices in his head, our hero wonders how he's
1366 supposed to kill the mall. */
1367void ip_conntrack_cleanup(void)
1368{
1369 rcu_assign_pointer(ip_ct_attach, NULL);
1370
1371 /* This makes sure all current packets have passed through
1372 netfilter framework. Roll on, two-stage module
1373 delete... */
1374 synchronize_net();
1375
1376 ip_ct_event_cache_flush();
1377 i_see_dead_people:
1378 ip_conntrack_flush();
1379 if (atomic_read(&ip_conntrack_count) != 0) {
1380 schedule();
1381 goto i_see_dead_people;
1382 }
1383 /* wait until all references to ip_conntrack_untracked are dropped */
1384 while (atomic_read(&ip_conntrack_untracked.ct_general.use) > 1)
1385 schedule();
1386
1387 kmem_cache_destroy(ip_conntrack_cachep);
1388 kmem_cache_destroy(ip_conntrack_expect_cachep);
1389 free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
1390 ip_conntrack_htable_size);
1391 nf_unregister_sockopt(&so_getorigdst);
1392}
1393
1394static struct list_head *alloc_hashtable(int size, int *vmalloced)
1395{
1396 struct list_head *hash;
1397 unsigned int i;
1398
1399 *vmalloced = 0;
1400 hash = (void*)__get_free_pages(GFP_KERNEL,
1401 get_order(sizeof(struct list_head)
1402 * size));
1403 if (!hash) {
1404 *vmalloced = 1;
1405 printk(KERN_WARNING"ip_conntrack: falling back to vmalloc.\n");
1406 hash = vmalloc(sizeof(struct list_head) * size);
1407 }
1408
1409 if (hash)
1410 for (i = 0; i < size; i++)
1411 INIT_LIST_HEAD(&hash[i]);
1412
1413 return hash;
1414}
1415
1416static int set_hashsize(const char *val, struct kernel_param *kp)
1417{
1418 int i, bucket, hashsize, vmalloced;
1419 int old_vmalloced, old_size;
1420 int rnd;
1421 struct list_head *hash, *old_hash;
1422 struct ip_conntrack_tuple_hash *h;
1423
1424 /* On boot, we can set this without any fancy locking. */
1425 if (!ip_conntrack_htable_size)
1426 return param_set_int(val, kp);
1427
1428 hashsize = simple_strtol(val, NULL, 0);
1429 if (!hashsize)
1430 return -EINVAL;
1431
1432 hash = alloc_hashtable(hashsize, &vmalloced);
1433 if (!hash)
1434 return -ENOMEM;
1435
1436 /* We have to rehash for the new table anyway, so we also can
1437 * use a new random seed */
1438 get_random_bytes(&rnd, 4);
1439
1440 write_lock_bh(&ip_conntrack_lock);
1441 for (i = 0; i < ip_conntrack_htable_size; i++) {
1442 while (!list_empty(&ip_conntrack_hash[i])) {
1443 h = list_entry(ip_conntrack_hash[i].next,
1444 struct ip_conntrack_tuple_hash, list);
1445 list_del(&h->list);
1446 bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
1447 list_add_tail(&h->list, &hash[bucket]);
1448 }
1449 }
1450 old_size = ip_conntrack_htable_size;
1451 old_vmalloced = ip_conntrack_vmalloc;
1452 old_hash = ip_conntrack_hash;
1453
1454 ip_conntrack_htable_size = hashsize;
1455 ip_conntrack_vmalloc = vmalloced;
1456 ip_conntrack_hash = hash;
1457 ip_conntrack_hash_rnd = rnd;
1458 write_unlock_bh(&ip_conntrack_lock);
1459
1460 free_conntrack_hash(old_hash, old_vmalloced, old_size);
1461 return 0;
1462}
1463
1464module_param_call(hashsize, set_hashsize, param_get_uint,
1465 &ip_conntrack_htable_size, 0600);
1466
1467int __init ip_conntrack_init(void)
1468{
1469 unsigned int i;
1470 int ret;
1471
1472 /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB
1473 * machine has 256 buckets. >= 1GB machines have 8192 buckets. */
1474 if (!ip_conntrack_htable_size) {
1475 ip_conntrack_htable_size
1476 = (((num_physpages << PAGE_SHIFT) / 16384)
1477 / sizeof(struct list_head));
1478 if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
1479 ip_conntrack_htable_size = 8192;
1480 if (ip_conntrack_htable_size < 16)
1481 ip_conntrack_htable_size = 16;
1482 }
1483 ip_conntrack_max = 8 * ip_conntrack_htable_size;
1484
1485 printk("ip_conntrack version %s (%u buckets, %d max)"
1486 " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
1487 ip_conntrack_htable_size, ip_conntrack_max,
1488 sizeof(struct ip_conntrack));
1489
1490 ret = nf_register_sockopt(&so_getorigdst);
1491 if (ret != 0) {
1492 printk(KERN_ERR "Unable to register netfilter socket option\n");
1493 return ret;
1494 }
1495
1496 ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
1497 &ip_conntrack_vmalloc);
1498 if (!ip_conntrack_hash) {
1499 printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
1500 goto err_unreg_sockopt;
1501 }
1502
1503 ip_conntrack_cachep = kmem_cache_create("ip_conntrack",
1504 sizeof(struct ip_conntrack), 0,
1505 0, NULL, NULL);
1506 if (!ip_conntrack_cachep) {
1507 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
1508 goto err_free_hash;
1509 }
1510
1511 ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
1512 sizeof(struct ip_conntrack_expect),
1513 0, 0, NULL, NULL);
1514 if (!ip_conntrack_expect_cachep) {
1515 printk(KERN_ERR "Unable to create ip_expect slab cache\n");
1516 goto err_free_conntrack_slab;
1517 }
1518
1519 /* Don't NEED lock here, but good form anyway. */
1520 write_lock_bh(&ip_conntrack_lock);
1521 for (i = 0; i < MAX_IP_CT_PROTO; i++)
1522 rcu_assign_pointer(ip_ct_protos[i], &ip_conntrack_generic_protocol);
1523 /* Sew in builtin protocols. */
1524 rcu_assign_pointer(ip_ct_protos[IPPROTO_TCP], &ip_conntrack_protocol_tcp);
1525 rcu_assign_pointer(ip_ct_protos[IPPROTO_UDP], &ip_conntrack_protocol_udp);
1526 rcu_assign_pointer(ip_ct_protos[IPPROTO_ICMP], &ip_conntrack_protocol_icmp);
1527 write_unlock_bh(&ip_conntrack_lock);
1528
1529 /* For use by ipt_REJECT */
1530 rcu_assign_pointer(ip_ct_attach, ip_conntrack_attach);
1531
1532 /* Set up fake conntrack:
1533 - to never be deleted, not in any hashes */
1534 atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
1535 /* - and look it like as a confirmed connection */
1536 set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
1537
1538 return ret;
1539
1540err_free_conntrack_slab:
1541 kmem_cache_destroy(ip_conntrack_cachep);
1542err_free_hash:
1543 free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
1544 ip_conntrack_htable_size);
1545err_unreg_sockopt:
1546 nf_unregister_sockopt(&so_getorigdst);
1547
1548 return -ENOMEM;
1549}
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
deleted file mode 100644
index 92389987e789..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ /dev/null
@@ -1,520 +0,0 @@
1/* FTP extension for IP connection tracking. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/netfilter.h>
13#include <linux/ip.h>
14#include <linux/ctype.h>
15#include <net/checksum.h>
16#include <net/tcp.h>
17
18#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
19#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
20#include <linux/moduleparam.h>
21
22MODULE_LICENSE("GPL");
23MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
24MODULE_DESCRIPTION("ftp connection tracking helper");
25
26/* This is slow, but it's simple. --RR */
27static char *ftp_buffer;
28static DEFINE_SPINLOCK(ip_ftp_lock);
29
30#define MAX_PORTS 8
31static unsigned short ports[MAX_PORTS];
32static int ports_c;
33module_param_array(ports, ushort, &ports_c, 0400);
34
35static int loose;
36module_param(loose, bool, 0600);
37
38unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
39 enum ip_conntrack_info ctinfo,
40 enum ip_ct_ftp_type type,
41 unsigned int matchoff,
42 unsigned int matchlen,
43 struct ip_conntrack_expect *exp,
44 u32 *seq);
45EXPORT_SYMBOL_GPL(ip_nat_ftp_hook);
46
47#if 0
48#define DEBUGP printk
49#else
50#define DEBUGP(format, args...)
51#endif
52
53static int try_rfc959(const char *, size_t, u_int32_t [], char);
54static int try_eprt(const char *, size_t, u_int32_t [], char);
55static int try_epsv_response(const char *, size_t, u_int32_t [], char);
56
57static const struct ftp_search {
58 const char *pattern;
59 size_t plen;
60 char skip;
61 char term;
62 enum ip_ct_ftp_type ftptype;
63 int (*getnum)(const char *, size_t, u_int32_t[], char);
64} search[IP_CT_DIR_MAX][2] = {
65 [IP_CT_DIR_ORIGINAL] = {
66 {
67 .pattern = "PORT",
68 .plen = sizeof("PORT") - 1,
69 .skip = ' ',
70 .term = '\r',
71 .ftptype = IP_CT_FTP_PORT,
72 .getnum = try_rfc959,
73 },
74 {
75 .pattern = "EPRT",
76 .plen = sizeof("EPRT") - 1,
77 .skip = ' ',
78 .term = '\r',
79 .ftptype = IP_CT_FTP_EPRT,
80 .getnum = try_eprt,
81 },
82 },
83 [IP_CT_DIR_REPLY] = {
84 {
85 .pattern = "227 ",
86 .plen = sizeof("227 ") - 1,
87 .skip = '(',
88 .term = ')',
89 .ftptype = IP_CT_FTP_PASV,
90 .getnum = try_rfc959,
91 },
92 {
93 .pattern = "229 ",
94 .plen = sizeof("229 ") - 1,
95 .skip = '(',
96 .term = ')',
97 .ftptype = IP_CT_FTP_EPSV,
98 .getnum = try_epsv_response,
99 },
100 },
101};
102
103static int try_number(const char *data, size_t dlen, u_int32_t array[],
104 int array_size, char sep, char term)
105{
106 u_int32_t i, len;
107
108 memset(array, 0, sizeof(array[0])*array_size);
109
110 /* Keep data pointing at next char. */
111 for (i = 0, len = 0; len < dlen && i < array_size; len++, data++) {
112 if (*data >= '0' && *data <= '9') {
113 array[i] = array[i]*10 + *data - '0';
114 }
115 else if (*data == sep)
116 i++;
117 else {
118 /* Unexpected character; true if it's the
119 terminator and we're finished. */
120 if (*data == term && i == array_size - 1)
121 return len;
122
123 DEBUGP("Char %u (got %u nums) `%u' unexpected\n",
124 len, i, *data);
125 return 0;
126 }
127 }
128 DEBUGP("Failed to fill %u numbers separated by %c\n", array_size, sep);
129
130 return 0;
131}
132
133/* Returns 0, or length of numbers: 192,168,1,1,5,6 */
134static int try_rfc959(const char *data, size_t dlen, u_int32_t array[6],
135 char term)
136{
137 return try_number(data, dlen, array, 6, ',', term);
138}
139
140/* Grab port: number up to delimiter */
141static int get_port(const char *data, int start, size_t dlen, char delim,
142 u_int32_t array[2])
143{
144 u_int16_t port = 0;
145 int i;
146
147 for (i = start; i < dlen; i++) {
148 /* Finished? */
149 if (data[i] == delim) {
150 if (port == 0)
151 break;
152 array[0] = port >> 8;
153 array[1] = port;
154 return i + 1;
155 }
156 else if (data[i] >= '0' && data[i] <= '9')
157 port = port*10 + data[i] - '0';
158 else /* Some other crap */
159 break;
160 }
161 return 0;
162}
163
164/* Returns 0, or length of numbers: |1|132.235.1.2|6275| */
165static int try_eprt(const char *data, size_t dlen, u_int32_t array[6],
166 char term)
167{
168 char delim;
169 int length;
170
171 /* First character is delimiter, then "1" for IPv4, then
172 delimiter again. */
173 if (dlen <= 3) return 0;
174 delim = data[0];
175 if (isdigit(delim) || delim < 33 || delim > 126
176 || data[1] != '1' || data[2] != delim)
177 return 0;
178
179 DEBUGP("EPRT: Got |1|!\n");
180 /* Now we have IP address. */
181 length = try_number(data + 3, dlen - 3, array, 4, '.', delim);
182 if (length == 0)
183 return 0;
184
185 DEBUGP("EPRT: Got IP address!\n");
186 /* Start offset includes initial "|1|", and trailing delimiter */
187 return get_port(data, 3 + length + 1, dlen, delim, array+4);
188}
189
190/* Returns 0, or length of numbers: |||6446| */
191static int try_epsv_response(const char *data, size_t dlen, u_int32_t array[6],
192 char term)
193{
194 char delim;
195
196 /* Three delimiters. */
197 if (dlen <= 3) return 0;
198 delim = data[0];
199 if (isdigit(delim) || delim < 33 || delim > 126
200 || data[1] != delim || data[2] != delim)
201 return 0;
202
203 return get_port(data, 3, dlen, delim, array+4);
204}
205
206/* Return 1 for match, 0 for accept, -1 for partial. */
207static int find_pattern(const char *data, size_t dlen,
208 const char *pattern, size_t plen,
209 char skip, char term,
210 unsigned int *numoff,
211 unsigned int *numlen,
212 u_int32_t array[6],
213 int (*getnum)(const char *, size_t, u_int32_t[], char))
214{
215 size_t i;
216
217 DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen);
218 if (dlen == 0)
219 return 0;
220
221 if (dlen <= plen) {
222 /* Short packet: try for partial? */
223 if (strnicmp(data, pattern, dlen) == 0)
224 return -1;
225 else return 0;
226 }
227
228 if (strnicmp(data, pattern, plen) != 0) {
229#if 0
230 size_t i;
231
232 DEBUGP("ftp: string mismatch\n");
233 for (i = 0; i < plen; i++) {
234 DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
235 i, data[i], data[i],
236 pattern[i], pattern[i]);
237 }
238#endif
239 return 0;
240 }
241
242 DEBUGP("Pattern matches!\n");
243 /* Now we've found the constant string, try to skip
244 to the 'skip' character */
245 for (i = plen; data[i] != skip; i++)
246 if (i == dlen - 1) return -1;
247
248 /* Skip over the last character */
249 i++;
250
251 DEBUGP("Skipped up to `%c'!\n", skip);
252
253 *numoff = i;
254 *numlen = getnum(data + i, dlen - i, array, term);
255 if (!*numlen)
256 return -1;
257
258 DEBUGP("Match succeeded!\n");
259 return 1;
260}
261
262/* Look up to see if we're just after a \n. */
263static int find_nl_seq(u32 seq, const struct ip_ct_ftp_master *info, int dir)
264{
265 unsigned int i;
266
267 for (i = 0; i < info->seq_aft_nl_num[dir]; i++)
268 if (info->seq_aft_nl[dir][i] == seq)
269 return 1;
270 return 0;
271}
272
273/* We don't update if it's older than what we have. */
274static void update_nl_seq(u32 nl_seq, struct ip_ct_ftp_master *info, int dir,
275 struct sk_buff *skb)
276{
277 unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
278
279 /* Look for oldest: if we find exact match, we're done. */
280 for (i = 0; i < info->seq_aft_nl_num[dir]; i++) {
281 if (info->seq_aft_nl[dir][i] == nl_seq)
282 return;
283
284 if (oldest == info->seq_aft_nl_num[dir]
285 || before(info->seq_aft_nl[dir][i], oldest))
286 oldest = i;
287 }
288
289 if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
290 info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
291 ip_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
292 } else if (oldest != NUM_SEQ_TO_REMEMBER) {
293 info->seq_aft_nl[dir][oldest] = nl_seq;
294 ip_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
295 }
296}
297
298static int help(struct sk_buff **pskb,
299 struct ip_conntrack *ct,
300 enum ip_conntrack_info ctinfo)
301{
302 unsigned int dataoff, datalen;
303 struct tcphdr _tcph, *th;
304 char *fb_ptr;
305 int ret;
306 u32 seq, array[6] = { 0 };
307 int dir = CTINFO2DIR(ctinfo);
308 unsigned int matchlen, matchoff;
309 struct ip_ct_ftp_master *ct_ftp_info = &ct->help.ct_ftp_info;
310 struct ip_conntrack_expect *exp;
311 unsigned int i;
312 int found = 0, ends_in_nl;
313 typeof(ip_nat_ftp_hook) ip_nat_ftp;
314
315 /* Until there's been traffic both ways, don't look in packets. */
316 if (ctinfo != IP_CT_ESTABLISHED
317 && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
318 DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo);
319 return NF_ACCEPT;
320 }
321
322 th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
323 sizeof(_tcph), &_tcph);
324 if (th == NULL)
325 return NF_ACCEPT;
326
327 dataoff = ip_hdrlen(*pskb) + th->doff * 4;
328 /* No data? */
329 if (dataoff >= (*pskb)->len) {
330 DEBUGP("ftp: pskblen = %u\n", (*pskb)->len);
331 return NF_ACCEPT;
332 }
333 datalen = (*pskb)->len - dataoff;
334
335 spin_lock_bh(&ip_ftp_lock);
336 fb_ptr = skb_header_pointer(*pskb, dataoff,
337 (*pskb)->len - dataoff, ftp_buffer);
338 BUG_ON(fb_ptr == NULL);
339
340 ends_in_nl = (fb_ptr[datalen - 1] == '\n');
341 seq = ntohl(th->seq) + datalen;
342
343 /* Look up to see if we're just after a \n. */
344 if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
345 /* Now if this ends in \n, update ftp info. */
346 DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n",
347 ct_ftp_info->seq_aft_nl[0][dir]
348 old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl);
349 ret = NF_ACCEPT;
350 goto out_update_nl;
351 }
352
353 /* Initialize IP array to expected address (it's not mentioned
354 in EPSV responses) */
355 array[0] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 24) & 0xFF;
356 array[1] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 16) & 0xFF;
357 array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
358 array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF;
359
360 for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
361 found = find_pattern(fb_ptr, (*pskb)->len - dataoff,
362 search[dir][i].pattern,
363 search[dir][i].plen,
364 search[dir][i].skip,
365 search[dir][i].term,
366 &matchoff, &matchlen,
367 array,
368 search[dir][i].getnum);
369 if (found) break;
370 }
371 if (found == -1) {
372 /* We don't usually drop packets. After all, this is
373 connection tracking, not packet filtering.
374 However, it is necessary for accurate tracking in
375 this case. */
376 if (net_ratelimit())
377 printk("conntrack_ftp: partial %s %u+%u\n",
378 search[dir][i].pattern,
379 ntohl(th->seq), datalen);
380 ret = NF_DROP;
381 goto out;
382 } else if (found == 0) { /* No match */
383 ret = NF_ACCEPT;
384 goto out_update_nl;
385 }
386
387 DEBUGP("conntrack_ftp: match `%s' (%u bytes at %u)\n",
388 fb_ptr + matchoff, matchlen, ntohl(th->seq) + matchoff);
389
390 /* Allocate expectation which will be inserted */
391 exp = ip_conntrack_expect_alloc(ct);
392 if (exp == NULL) {
393 ret = NF_DROP;
394 goto out;
395 }
396
397 /* We refer to the reverse direction ("!dir") tuples here,
398 * because we're expecting something in the other direction.
399 * Doesn't matter unless NAT is happening. */
400 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
401
402 if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
403 != ct->tuplehash[dir].tuple.src.ip) {
404 /* Enrico Scholz's passive FTP to partially RNAT'd ftp
405 server: it really wants us to connect to a
406 different IP address. Simply don't record it for
407 NAT. */
408 DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n",
409 array[0], array[1], array[2], array[3],
410 NIPQUAD(ct->tuplehash[dir].tuple.src.ip));
411
412 /* Thanks to Cristiano Lincoln Mattos
413 <lincoln@cesar.org.br> for reporting this potential
414 problem (DMZ machines opening holes to internal
415 networks, or the packet filter itself). */
416 if (!loose) {
417 ret = NF_ACCEPT;
418 goto out_put_expect;
419 }
420 exp->tuple.dst.ip = htonl((array[0] << 24) | (array[1] << 16)
421 | (array[2] << 8) | array[3]);
422 }
423
424 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
425 exp->tuple.dst.u.tcp.port = htons(array[4] << 8 | array[5]);
426 exp->tuple.src.u.tcp.port = 0; /* Don't care. */
427 exp->tuple.dst.protonum = IPPROTO_TCP;
428 exp->mask = ((struct ip_conntrack_tuple)
429 { { htonl(0xFFFFFFFF), { 0 } },
430 { htonl(0xFFFFFFFF), { .tcp = { htons(0xFFFF) } }, 0xFF }});
431
432 exp->expectfn = NULL;
433 exp->flags = 0;
434
435 /* Now, NAT might want to mangle the packet, and register the
436 * (possibly changed) expectation itself. */
437 ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook);
438 if (ip_nat_ftp)
439 ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
440 matchoff, matchlen, exp, &seq);
441 else {
442 /* Can't expect this? Best to drop packet now. */
443 if (ip_conntrack_expect_related(exp) != 0)
444 ret = NF_DROP;
445 else
446 ret = NF_ACCEPT;
447 }
448
449out_put_expect:
450 ip_conntrack_expect_put(exp);
451
452out_update_nl:
453 /* Now if this ends in \n, update ftp info. Seq may have been
454 * adjusted by NAT code. */
455 if (ends_in_nl)
456 update_nl_seq(seq, ct_ftp_info,dir, *pskb);
457 out:
458 spin_unlock_bh(&ip_ftp_lock);
459 return ret;
460}
461
462static struct ip_conntrack_helper ftp[MAX_PORTS];
463static char ftp_names[MAX_PORTS][sizeof("ftp-65535")];
464
465/* Not __exit: called from init() */
466static void ip_conntrack_ftp_fini(void)
467{
468 int i;
469 for (i = 0; i < ports_c; i++) {
470 DEBUGP("ip_ct_ftp: unregistering helper for port %d\n",
471 ports[i]);
472 ip_conntrack_helper_unregister(&ftp[i]);
473 }
474
475 kfree(ftp_buffer);
476}
477
478static int __init ip_conntrack_ftp_init(void)
479{
480 int i, ret;
481 char *tmpname;
482
483 ftp_buffer = kmalloc(65536, GFP_KERNEL);
484 if (!ftp_buffer)
485 return -ENOMEM;
486
487 if (ports_c == 0)
488 ports[ports_c++] = FTP_PORT;
489
490 for (i = 0; i < ports_c; i++) {
491 ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
492 ftp[i].tuple.dst.protonum = IPPROTO_TCP;
493 ftp[i].mask.src.u.tcp.port = htons(0xFFFF);
494 ftp[i].mask.dst.protonum = 0xFF;
495 ftp[i].max_expected = 1;
496 ftp[i].timeout = 5 * 60; /* 5 minutes */
497 ftp[i].me = THIS_MODULE;
498 ftp[i].help = help;
499
500 tmpname = &ftp_names[i][0];
501 if (ports[i] == FTP_PORT)
502 sprintf(tmpname, "ftp");
503 else
504 sprintf(tmpname, "ftp-%d", ports[i]);
505 ftp[i].name = tmpname;
506
507 DEBUGP("ip_ct_ftp: registering helper for port %d\n",
508 ports[i]);
509 ret = ip_conntrack_helper_register(&ftp[i]);
510
511 if (ret) {
512 ip_conntrack_ftp_fini();
513 return ret;
514 }
515 }
516 return 0;
517}
518
519module_init(ip_conntrack_ftp_init);
520module_exit(ip_conntrack_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
deleted file mode 100644
index cecb6e0c8ed0..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ /dev/null
@@ -1,1840 +0,0 @@
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/netfilter.h>
16#include <linux/ip.h>
17#include <net/tcp.h>
18#include <linux/netfilter_ipv4/ip_conntrack.h>
19#include <linux/netfilter_ipv4/ip_conntrack_core.h>
20#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
21#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
22#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
23#include <linux/moduleparam.h>
24#include <linux/ctype.h>
25#include <linux/inet.h>
26
27#if 0
28#define DEBUGP printk
29#else
30#define DEBUGP(format, args...)
31#endif
32
33/* Parameters */
34static unsigned int default_rrq_ttl = 300;
35module_param(default_rrq_ttl, uint, 0600);
36MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
37
38static int gkrouted_only = 1;
39module_param(gkrouted_only, int, 0600);
40MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
41
42static int callforward_filter = 1;
43module_param(callforward_filter, bool, 0600);
44MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
45 "if both endpoints are on different sides "
46 "(determined by routing information)");
47
48/* Hooks for NAT */
49int (*set_h245_addr_hook) (struct sk_buff ** pskb,
50 unsigned char **data, int dataoff,
51 H245_TransportAddress * addr,
52 __be32 ip, u_int16_t port);
53int (*set_h225_addr_hook) (struct sk_buff ** pskb,
54 unsigned char **data, int dataoff,
55 TransportAddress * addr,
56 __be32 ip, u_int16_t port);
57int (*set_sig_addr_hook) (struct sk_buff ** pskb,
58 struct ip_conntrack * ct,
59 enum ip_conntrack_info ctinfo,
60 unsigned char **data,
61 TransportAddress * addr, int count);
62int (*set_ras_addr_hook) (struct sk_buff ** pskb,
63 struct ip_conntrack * ct,
64 enum ip_conntrack_info ctinfo,
65 unsigned char **data,
66 TransportAddress * addr, int count);
67int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
68 struct ip_conntrack * ct,
69 enum ip_conntrack_info ctinfo,
70 unsigned char **data, int dataoff,
71 H245_TransportAddress * addr,
72 u_int16_t port, u_int16_t rtp_port,
73 struct ip_conntrack_expect * rtp_exp,
74 struct ip_conntrack_expect * rtcp_exp);
75int (*nat_t120_hook) (struct sk_buff ** pskb,
76 struct ip_conntrack * ct,
77 enum ip_conntrack_info ctinfo,
78 unsigned char **data, int dataoff,
79 H245_TransportAddress * addr, u_int16_t port,
80 struct ip_conntrack_expect * exp);
81int (*nat_h245_hook) (struct sk_buff ** pskb,
82 struct ip_conntrack * ct,
83 enum ip_conntrack_info ctinfo,
84 unsigned char **data, int dataoff,
85 TransportAddress * addr, u_int16_t port,
86 struct ip_conntrack_expect * exp);
87int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
88 struct ip_conntrack * ct,
89 enum ip_conntrack_info ctinfo,
90 unsigned char **data, int dataoff,
91 TransportAddress * addr, u_int16_t port,
92 struct ip_conntrack_expect * exp);
93int (*nat_q931_hook) (struct sk_buff ** pskb,
94 struct ip_conntrack * ct,
95 enum ip_conntrack_info ctinfo,
96 unsigned char **data, TransportAddress * addr, int idx,
97 u_int16_t port, struct ip_conntrack_expect * exp);
98
99
100static DEFINE_SPINLOCK(ip_h323_lock);
101static char *h323_buffer;
102
103/****************************************************************************/
104static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
105 enum ip_conntrack_info ctinfo,
106 unsigned char **data, int *datalen, int *dataoff)
107{
108 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
109 int dir = CTINFO2DIR(ctinfo);
110 struct tcphdr _tcph, *th;
111 int tcpdatalen;
112 int tcpdataoff;
113 unsigned char *tpkt;
114 int tpktlen;
115 int tpktoff;
116
117 /* Get TCP header */
118 th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
119 sizeof(_tcph), &_tcph);
120 if (th == NULL)
121 return 0;
122
123 /* Get TCP data offset */
124 tcpdataoff = ip_hdrlen(*pskb) + th->doff * 4;
125
126 /* Get TCP data length */
127 tcpdatalen = (*pskb)->len - tcpdataoff;
128 if (tcpdatalen <= 0) /* No TCP data */
129 goto clear_out;
130
131 if (*data == NULL) { /* first TPKT */
132 /* Get first TPKT pointer */
133 tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen,
134 h323_buffer);
135 BUG_ON(tpkt == NULL);
136
137 /* Validate TPKT identifier */
138 if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
139 /* Netmeeting sends TPKT header and data separately */
140 if (info->tpkt_len[dir] > 0) {
141 DEBUGP("ip_ct_h323: previous packet "
142 "indicated separate TPKT data of %hu "
143 "bytes\n", info->tpkt_len[dir]);
144 if (info->tpkt_len[dir] <= tcpdatalen) {
145 /* Yes, there was a TPKT header
146 * received */
147 *data = tpkt;
148 *datalen = info->tpkt_len[dir];
149 *dataoff = 0;
150 goto out;
151 }
152
153 /* Fragmented TPKT */
154 if (net_ratelimit())
155 printk("ip_ct_h323: "
156 "fragmented TPKT\n");
157 goto clear_out;
158 }
159
160 /* It is not even a TPKT */
161 return 0;
162 }
163 tpktoff = 0;
164 } else { /* Next TPKT */
165 tpktoff = *dataoff + *datalen;
166 tcpdatalen -= tpktoff;
167 if (tcpdatalen <= 4) /* No more TPKT */
168 goto clear_out;
169 tpkt = *data + *datalen;
170
171 /* Validate TPKT identifier */
172 if (tpkt[0] != 0x03 || tpkt[1] != 0)
173 goto clear_out;
174 }
175
176 /* Validate TPKT length */
177 tpktlen = tpkt[2] * 256 + tpkt[3];
178 if (tpktlen < 4)
179 goto clear_out;
180 if (tpktlen > tcpdatalen) {
181 if (tcpdatalen == 4) { /* Separate TPKT header */
182 /* Netmeeting sends TPKT header and data separately */
183 DEBUGP("ip_ct_h323: separate TPKT header indicates "
184 "there will be TPKT data of %hu bytes\n",
185 tpktlen - 4);
186 info->tpkt_len[dir] = tpktlen - 4;
187 return 0;
188 }
189
190 if (net_ratelimit())
191 printk("ip_ct_h323: incomplete TPKT (fragmented?)\n");
192 goto clear_out;
193 }
194
195 /* This is the encapsulated data */
196 *data = tpkt + 4;
197 *datalen = tpktlen - 4;
198 *dataoff = tpktoff + 4;
199
200 out:
201 /* Clear TPKT length */
202 info->tpkt_len[dir] = 0;
203 return 1;
204
205 clear_out:
206 info->tpkt_len[dir] = 0;
207 return 0;
208}
209
210/****************************************************************************/
211static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
212 __be32 * ip, u_int16_t * port)
213{
214 unsigned char *p;
215
216 if (addr->choice != eH245_TransportAddress_unicastAddress ||
217 addr->unicastAddress.choice != eUnicastAddress_iPAddress)
218 return 0;
219
220 p = data + addr->unicastAddress.iPAddress.network;
221 *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
222 *port = (p[4] << 8) | (p[5]);
223
224 return 1;
225}
226
227/****************************************************************************/
228static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
229 enum ip_conntrack_info ctinfo,
230 unsigned char **data, int dataoff,
231 H245_TransportAddress * addr)
232{
233 int dir = CTINFO2DIR(ctinfo);
234 int ret = 0;
235 __be32 ip;
236 u_int16_t port;
237 u_int16_t rtp_port;
238 struct ip_conntrack_expect *rtp_exp;
239 struct ip_conntrack_expect *rtcp_exp;
240 typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
241
242 /* Read RTP or RTCP address */
243 if (!get_h245_addr(*data, addr, &ip, &port) ||
244 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
245 return 0;
246
247 /* RTP port is even */
248 rtp_port = port & (~1);
249
250 /* Create expect for RTP */
251 if ((rtp_exp = ip_conntrack_expect_alloc(ct)) == NULL)
252 return -1;
253 rtp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
254 rtp_exp->tuple.src.u.udp.port = 0;
255 rtp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
256 rtp_exp->tuple.dst.u.udp.port = htons(rtp_port);
257 rtp_exp->tuple.dst.protonum = IPPROTO_UDP;
258 rtp_exp->mask.src.ip = htonl(0xFFFFFFFF);
259 rtp_exp->mask.src.u.udp.port = 0;
260 rtp_exp->mask.dst.ip = htonl(0xFFFFFFFF);
261 rtp_exp->mask.dst.u.udp.port = htons(0xFFFF);
262 rtp_exp->mask.dst.protonum = 0xFF;
263 rtp_exp->flags = 0;
264
265 /* Create expect for RTCP */
266 if ((rtcp_exp = ip_conntrack_expect_alloc(ct)) == NULL) {
267 ip_conntrack_expect_put(rtp_exp);
268 return -1;
269 }
270 rtcp_exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
271 rtcp_exp->tuple.src.u.udp.port = 0;
272 rtcp_exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
273 rtcp_exp->tuple.dst.u.udp.port = htons(rtp_port + 1);
274 rtcp_exp->tuple.dst.protonum = IPPROTO_UDP;
275 rtcp_exp->mask.src.ip = htonl(0xFFFFFFFF);
276 rtcp_exp->mask.src.u.udp.port = 0;
277 rtcp_exp->mask.dst.ip = htonl(0xFFFFFFFF);
278 rtcp_exp->mask.dst.u.udp.port = htons(0xFFFF);
279 rtcp_exp->mask.dst.protonum = 0xFF;
280 rtcp_exp->flags = 0;
281
282 if (ct->tuplehash[dir].tuple.src.ip !=
283 ct->tuplehash[!dir].tuple.dst.ip &&
284 (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) {
285 /* NAT needed */
286 ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
287 addr, port, rtp_port, rtp_exp, rtcp_exp);
288 } else { /* Conntrack only */
289 rtp_exp->expectfn = NULL;
290 rtcp_exp->expectfn = NULL;
291
292 if (ip_conntrack_expect_related(rtp_exp) == 0) {
293 if (ip_conntrack_expect_related(rtcp_exp) == 0) {
294 DEBUGP("ip_ct_h323: expect RTP "
295 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
296 NIPQUAD(rtp_exp->tuple.src.ip),
297 ntohs(rtp_exp->tuple.src.u.udp.port),
298 NIPQUAD(rtp_exp->tuple.dst.ip),
299 ntohs(rtp_exp->tuple.dst.u.udp.port));
300 DEBUGP("ip_ct_h323: expect RTCP "
301 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
302 NIPQUAD(rtcp_exp->tuple.src.ip),
303 ntohs(rtcp_exp->tuple.src.u.udp.port),
304 NIPQUAD(rtcp_exp->tuple.dst.ip),
305 ntohs(rtcp_exp->tuple.dst.u.udp.port));
306 } else {
307 ip_conntrack_unexpect_related(rtp_exp);
308 ret = -1;
309 }
310 } else
311 ret = -1;
312 }
313
314 ip_conntrack_expect_put(rtp_exp);
315 ip_conntrack_expect_put(rtcp_exp);
316
317 return ret;
318}
319
320/****************************************************************************/
321static int expect_t120(struct sk_buff **pskb,
322 struct ip_conntrack *ct,
323 enum ip_conntrack_info ctinfo,
324 unsigned char **data, int dataoff,
325 H245_TransportAddress * addr)
326{
327 int dir = CTINFO2DIR(ctinfo);
328 int ret = 0;
329 __be32 ip;
330 u_int16_t port;
331 struct ip_conntrack_expect *exp = NULL;
332 typeof(nat_t120_hook) nat_t120;
333
334 /* Read T.120 address */
335 if (!get_h245_addr(*data, addr, &ip, &port) ||
336 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
337 return 0;
338
339 /* Create expect for T.120 connections */
340 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
341 return -1;
342 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
343 exp->tuple.src.u.tcp.port = 0;
344 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
345 exp->tuple.dst.u.tcp.port = htons(port);
346 exp->tuple.dst.protonum = IPPROTO_TCP;
347 exp->mask.src.ip = htonl(0xFFFFFFFF);
348 exp->mask.src.u.tcp.port = 0;
349 exp->mask.dst.ip = htonl(0xFFFFFFFF);
350 exp->mask.dst.u.tcp.port = htons(0xFFFF);
351 exp->mask.dst.protonum = 0xFF;
352 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */
353
354 if (ct->tuplehash[dir].tuple.src.ip !=
355 ct->tuplehash[!dir].tuple.dst.ip &&
356 (nat_t120 = rcu_dereference(nat_t120_hook))) {
357 /* NAT needed */
358 ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr,
359 port, exp);
360 } else { /* Conntrack only */
361 exp->expectfn = NULL;
362 if (ip_conntrack_expect_related(exp) == 0) {
363 DEBUGP("ip_ct_h323: expect T.120 "
364 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
365 NIPQUAD(exp->tuple.src.ip),
366 ntohs(exp->tuple.src.u.tcp.port),
367 NIPQUAD(exp->tuple.dst.ip),
368 ntohs(exp->tuple.dst.u.tcp.port));
369 } else
370 ret = -1;
371 }
372
373 ip_conntrack_expect_put(exp);
374
375 return ret;
376}
377
378/****************************************************************************/
379static int process_h245_channel(struct sk_buff **pskb,
380 struct ip_conntrack *ct,
381 enum ip_conntrack_info ctinfo,
382 unsigned char **data, int dataoff,
383 H2250LogicalChannelParameters * channel)
384{
385 int ret;
386
387 if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
388 /* RTP */
389 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
390 &channel->mediaChannel);
391 if (ret < 0)
392 return -1;
393 }
394
395 if (channel->
396 options & eH2250LogicalChannelParameters_mediaControlChannel) {
397 /* RTCP */
398 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
399 &channel->mediaControlChannel);
400 if (ret < 0)
401 return -1;
402 }
403
404 return 0;
405}
406
407/****************************************************************************/
408static int process_olc(struct sk_buff **pskb, struct ip_conntrack *ct,
409 enum ip_conntrack_info ctinfo,
410 unsigned char **data, int dataoff,
411 OpenLogicalChannel * olc)
412{
413 int ret;
414
415 DEBUGP("ip_ct_h323: OpenLogicalChannel\n");
416
417 if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
418 eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
419 {
420 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
421 &olc->
422 forwardLogicalChannelParameters.
423 multiplexParameters.
424 h2250LogicalChannelParameters);
425 if (ret < 0)
426 return -1;
427 }
428
429 if ((olc->options &
430 eOpenLogicalChannel_reverseLogicalChannelParameters) &&
431 (olc->reverseLogicalChannelParameters.options &
432 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters)
433 && (olc->reverseLogicalChannelParameters.multiplexParameters.
434 choice ==
435 eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
436 {
437 ret =
438 process_h245_channel(pskb, ct, ctinfo, data, dataoff,
439 &olc->
440 reverseLogicalChannelParameters.
441 multiplexParameters.
442 h2250LogicalChannelParameters);
443 if (ret < 0)
444 return -1;
445 }
446
447 if ((olc->options & eOpenLogicalChannel_separateStack) &&
448 olc->forwardLogicalChannelParameters.dataType.choice ==
449 eDataType_data &&
450 olc->forwardLogicalChannelParameters.dataType.data.application.
451 choice == eDataApplicationCapability_application_t120 &&
452 olc->forwardLogicalChannelParameters.dataType.data.application.
453 t120.choice == eDataProtocolCapability_separateLANStack &&
454 olc->separateStack.networkAddress.choice ==
455 eNetworkAccessParameters_networkAddress_localAreaAddress) {
456 ret = expect_t120(pskb, ct, ctinfo, data, dataoff,
457 &olc->separateStack.networkAddress.
458 localAreaAddress);
459 if (ret < 0)
460 return -1;
461 }
462
463 return 0;
464}
465
466/****************************************************************************/
467static int process_olca(struct sk_buff **pskb, struct ip_conntrack *ct,
468 enum ip_conntrack_info ctinfo,
469 unsigned char **data, int dataoff,
470 OpenLogicalChannelAck * olca)
471{
472 H2250LogicalChannelAckParameters *ack;
473 int ret;
474
475 DEBUGP("ip_ct_h323: OpenLogicalChannelAck\n");
476
477 if ((olca->options &
478 eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
479 (olca->reverseLogicalChannelParameters.options &
480 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters)
481 && (olca->reverseLogicalChannelParameters.multiplexParameters.
482 choice ==
483 eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
484 {
485 ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff,
486 &olca->
487 reverseLogicalChannelParameters.
488 multiplexParameters.
489 h2250LogicalChannelParameters);
490 if (ret < 0)
491 return -1;
492 }
493
494 if ((olca->options &
495 eOpenLogicalChannelAck_forwardMultiplexAckParameters) &&
496 (olca->forwardMultiplexAckParameters.choice ==
497 eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters))
498 {
499 ack = &olca->forwardMultiplexAckParameters.
500 h2250LogicalChannelAckParameters;
501 if (ack->options &
502 eH2250LogicalChannelAckParameters_mediaChannel) {
503 /* RTP */
504 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
505 &ack->mediaChannel);
506 if (ret < 0)
507 return -1;
508 }
509
510 if (ack->options &
511 eH2250LogicalChannelAckParameters_mediaControlChannel) {
512 /* RTCP */
513 ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
514 &ack->mediaControlChannel);
515 if (ret < 0)
516 return -1;
517 }
518 }
519
520 return 0;
521}
522
523/****************************************************************************/
524static int process_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
525 enum ip_conntrack_info ctinfo,
526 unsigned char **data, int dataoff,
527 MultimediaSystemControlMessage * mscm)
528{
529 switch (mscm->choice) {
530 case eMultimediaSystemControlMessage_request:
531 if (mscm->request.choice ==
532 eRequestMessage_openLogicalChannel) {
533 return process_olc(pskb, ct, ctinfo, data, dataoff,
534 &mscm->request.openLogicalChannel);
535 }
536 DEBUGP("ip_ct_h323: H.245 Request %d\n",
537 mscm->request.choice);
538 break;
539 case eMultimediaSystemControlMessage_response:
540 if (mscm->response.choice ==
541 eResponseMessage_openLogicalChannelAck) {
542 return process_olca(pskb, ct, ctinfo, data, dataoff,
543 &mscm->response.
544 openLogicalChannelAck);
545 }
546 DEBUGP("ip_ct_h323: H.245 Response %d\n",
547 mscm->response.choice);
548 break;
549 default:
550 DEBUGP("ip_ct_h323: H.245 signal %d\n", mscm->choice);
551 break;
552 }
553
554 return 0;
555}
556
557/****************************************************************************/
558static int h245_help(struct sk_buff **pskb, struct ip_conntrack *ct,
559 enum ip_conntrack_info ctinfo)
560{
561 static MultimediaSystemControlMessage mscm;
562 unsigned char *data = NULL;
563 int datalen;
564 int dataoff;
565 int ret;
566
567 /* Until there's been traffic both ways, don't look in packets. */
568 if (ctinfo != IP_CT_ESTABLISHED
569 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
570 return NF_ACCEPT;
571 }
572 DEBUGP("ip_ct_h245: skblen = %u\n", (*pskb)->len);
573
574 spin_lock_bh(&ip_h323_lock);
575
576 /* Process each TPKT */
577 while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
578 DEBUGP("ip_ct_h245: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
579 NIPQUAD(ip_hdr(*pskb)->saddr),
580 NIPQUAD(ip_hdr(*pskb)->daddr), datalen);
581
582 /* Decode H.245 signal */
583 ret = DecodeMultimediaSystemControlMessage(data, datalen,
584 &mscm);
585 if (ret < 0) {
586 if (net_ratelimit())
587 printk("ip_ct_h245: decoding error: %s\n",
588 ret == H323_ERROR_BOUND ?
589 "out of bound" : "out of range");
590 /* We don't drop when decoding error */
591 break;
592 }
593
594 /* Process H.245 signal */
595 if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0)
596 goto drop;
597 }
598
599 spin_unlock_bh(&ip_h323_lock);
600 return NF_ACCEPT;
601
602 drop:
603 spin_unlock_bh(&ip_h323_lock);
604 if (net_ratelimit())
605 printk("ip_ct_h245: packet dropped\n");
606 return NF_DROP;
607}
608
609/****************************************************************************/
610static struct ip_conntrack_helper ip_conntrack_helper_h245 = {
611 .name = "H.245",
612 .me = THIS_MODULE,
613 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */ ,
614 .timeout = 240,
615 .tuple = {.dst = {.protonum = IPPROTO_TCP}},
616 .mask = {.src = {.u = {0xFFFF}},
617 .dst = {.protonum = 0xFF}},
618 .help = h245_help
619};
620
621/****************************************************************************/
622void ip_conntrack_h245_expect(struct ip_conntrack *new,
623 struct ip_conntrack_expect *this)
624{
625 write_lock_bh(&ip_conntrack_lock);
626 new->helper = &ip_conntrack_helper_h245;
627 write_unlock_bh(&ip_conntrack_lock);
628}
629
630/****************************************************************************/
631int get_h225_addr(unsigned char *data, TransportAddress * addr,
632 __be32 * ip, u_int16_t * port)
633{
634 unsigned char *p;
635
636 if (addr->choice != eTransportAddress_ipAddress)
637 return 0;
638
639 p = data + addr->ipAddress.ip;
640 *ip = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
641 *port = (p[4] << 8) | (p[5]);
642
643 return 1;
644}
645
646/****************************************************************************/
647static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
648 enum ip_conntrack_info ctinfo,
649 unsigned char **data, int dataoff,
650 TransportAddress * addr)
651{
652 int dir = CTINFO2DIR(ctinfo);
653 int ret = 0;
654 __be32 ip;
655 u_int16_t port;
656 struct ip_conntrack_expect *exp = NULL;
657 typeof(nat_h245_hook) nat_h245;
658
659 /* Read h245Address */
660 if (!get_h225_addr(*data, addr, &ip, &port) ||
661 ip != ct->tuplehash[dir].tuple.src.ip || port == 0)
662 return 0;
663
664 /* Create expect for h245 connection */
665 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
666 return -1;
667 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
668 exp->tuple.src.u.tcp.port = 0;
669 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
670 exp->tuple.dst.u.tcp.port = htons(port);
671 exp->tuple.dst.protonum = IPPROTO_TCP;
672 exp->mask.src.ip = htonl(0xFFFFFFFF);
673 exp->mask.src.u.tcp.port = 0;
674 exp->mask.dst.ip = htonl(0xFFFFFFFF);
675 exp->mask.dst.u.tcp.port = htons(0xFFFF);
676 exp->mask.dst.protonum = 0xFF;
677 exp->flags = 0;
678
679 if (ct->tuplehash[dir].tuple.src.ip !=
680 ct->tuplehash[!dir].tuple.dst.ip &&
681 (nat_h245 = rcu_dereference(nat_h245_hook))) {
682 /* NAT needed */
683 ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr,
684 port, exp);
685 } else { /* Conntrack only */
686 exp->expectfn = ip_conntrack_h245_expect;
687
688 if (ip_conntrack_expect_related(exp) == 0) {
689 DEBUGP("ip_ct_q931: expect H.245 "
690 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
691 NIPQUAD(exp->tuple.src.ip),
692 ntohs(exp->tuple.src.u.tcp.port),
693 NIPQUAD(exp->tuple.dst.ip),
694 ntohs(exp->tuple.dst.u.tcp.port));
695 } else
696 ret = -1;
697 }
698
699 ip_conntrack_expect_put(exp);
700
701 return ret;
702}
703
704/* Forwarding declaration */
705void ip_conntrack_q931_expect(struct ip_conntrack *new,
706 struct ip_conntrack_expect *this);
707
708/****************************************************************************/
709static int expect_callforwarding(struct sk_buff **pskb,
710 struct ip_conntrack *ct,
711 enum ip_conntrack_info ctinfo,
712 unsigned char **data, int dataoff,
713 TransportAddress * addr)
714{
715 int dir = CTINFO2DIR(ctinfo);
716 int ret = 0;
717 __be32 ip;
718 u_int16_t port;
719 struct ip_conntrack_expect *exp = NULL;
720 typeof(nat_callforwarding_hook) nat_callforwarding;
721
722 /* Read alternativeAddress */
723 if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
724 return 0;
725
726 /* If the calling party is on the same side of the forward-to party,
727 * we don't need to track the second call */
728 if (callforward_filter) {
729 struct rtable *rt1, *rt2;
730 struct flowi fl1 = {
731 .fl4_dst = ip,
732 };
733 struct flowi fl2 = {
734 .fl4_dst = ct->tuplehash[!dir].tuple.src.ip,
735 };
736
737 if (ip_route_output_key(&rt1, &fl1) == 0) {
738 if (ip_route_output_key(&rt2, &fl2) == 0) {
739 if (rt1->rt_gateway == rt2->rt_gateway &&
740 rt1->u.dst.dev == rt2->u.dst.dev)
741 ret = 1;
742 dst_release(&rt2->u.dst);
743 }
744 dst_release(&rt1->u.dst);
745 }
746 if (ret) {
747 DEBUGP("ip_ct_q931: Call Forwarding not tracked\n");
748 return 0;
749 }
750 }
751
752 /* Create expect for the second call leg */
753 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
754 return -1;
755 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
756 exp->tuple.src.u.tcp.port = 0;
757 exp->tuple.dst.ip = ip;
758 exp->tuple.dst.u.tcp.port = htons(port);
759 exp->tuple.dst.protonum = IPPROTO_TCP;
760 exp->mask.src.ip = htonl(0xFFFFFFFF);
761 exp->mask.src.u.tcp.port = 0;
762 exp->mask.dst.ip = htonl(0xFFFFFFFF);
763 exp->mask.dst.u.tcp.port = htons(0xFFFF);
764 exp->mask.dst.protonum = 0xFF;
765 exp->flags = 0;
766
767 if (ct->tuplehash[dir].tuple.src.ip !=
768 ct->tuplehash[!dir].tuple.dst.ip &&
769 (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) {
770 /* Need NAT */
771 ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
772 addr, port, exp);
773 } else { /* Conntrack only */
774 exp->expectfn = ip_conntrack_q931_expect;
775
776 if (ip_conntrack_expect_related(exp) == 0) {
777 DEBUGP("ip_ct_q931: expect Call Forwarding "
778 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
779 NIPQUAD(exp->tuple.src.ip),
780 ntohs(exp->tuple.src.u.tcp.port),
781 NIPQUAD(exp->tuple.dst.ip),
782 ntohs(exp->tuple.dst.u.tcp.port));
783 } else
784 ret = -1;
785 }
786
787 ip_conntrack_expect_put(exp);
788
789 return ret;
790}
791
792/****************************************************************************/
793static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
794 enum ip_conntrack_info ctinfo,
795 unsigned char **data, int dataoff,
796 Setup_UUIE * setup)
797{
798 int dir = CTINFO2DIR(ctinfo);
799 int ret;
800 int i;
801 __be32 ip;
802 u_int16_t port;
803 typeof(set_h225_addr_hook) set_h225_addr;
804
805 DEBUGP("ip_ct_q931: Setup\n");
806
807 if (setup->options & eSetup_UUIE_h245Address) {
808 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
809 &setup->h245Address);
810 if (ret < 0)
811 return -1;
812 }
813
814 set_h225_addr = rcu_dereference(set_h225_addr_hook);
815
816 if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
817 (set_h225_addr) &&
818 get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
819 ip != ct->tuplehash[!dir].tuple.src.ip) {
820 DEBUGP("ip_ct_q931: set destCallSignalAddress "
821 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
822 NIPQUAD(ip), port,
823 NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
824 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
825 ret = set_h225_addr(pskb, data, dataoff,
826 &setup->destCallSignalAddress,
827 ct->tuplehash[!dir].tuple.src.ip,
828 ntohs(ct->tuplehash[!dir].tuple.src.
829 u.tcp.port));
830 if (ret < 0)
831 return -1;
832 }
833
834 if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
835 (set_h225_addr) &&
836 get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
837 && ip != ct->tuplehash[!dir].tuple.dst.ip) {
838 DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
839 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
840 NIPQUAD(ip), port,
841 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
842 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
843 ret = set_h225_addr(pskb, data, dataoff,
844 &setup->sourceCallSignalAddress,
845 ct->tuplehash[!dir].tuple.dst.ip,
846 ntohs(ct->tuplehash[!dir].tuple.dst.
847 u.tcp.port));
848 if (ret < 0)
849 return -1;
850 }
851
852 if (setup->options & eSetup_UUIE_fastStart) {
853 for (i = 0; i < setup->fastStart.count; i++) {
854 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
855 &setup->fastStart.item[i]);
856 if (ret < 0)
857 return -1;
858 }
859 }
860
861 return 0;
862}
863
864/****************************************************************************/
865static int process_callproceeding(struct sk_buff **pskb,
866 struct ip_conntrack *ct,
867 enum ip_conntrack_info ctinfo,
868 unsigned char **data, int dataoff,
869 CallProceeding_UUIE * callproc)
870{
871 int ret;
872 int i;
873
874 DEBUGP("ip_ct_q931: CallProceeding\n");
875
876 if (callproc->options & eCallProceeding_UUIE_h245Address) {
877 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
878 &callproc->h245Address);
879 if (ret < 0)
880 return -1;
881 }
882
883 if (callproc->options & eCallProceeding_UUIE_fastStart) {
884 for (i = 0; i < callproc->fastStart.count; i++) {
885 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
886 &callproc->fastStart.item[i]);
887 if (ret < 0)
888 return -1;
889 }
890 }
891
892 return 0;
893}
894
895/****************************************************************************/
896static int process_connect(struct sk_buff **pskb, struct ip_conntrack *ct,
897 enum ip_conntrack_info ctinfo,
898 unsigned char **data, int dataoff,
899 Connect_UUIE * connect)
900{
901 int ret;
902 int i;
903
904 DEBUGP("ip_ct_q931: Connect\n");
905
906 if (connect->options & eConnect_UUIE_h245Address) {
907 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
908 &connect->h245Address);
909 if (ret < 0)
910 return -1;
911 }
912
913 if (connect->options & eConnect_UUIE_fastStart) {
914 for (i = 0; i < connect->fastStart.count; i++) {
915 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
916 &connect->fastStart.item[i]);
917 if (ret < 0)
918 return -1;
919 }
920 }
921
922 return 0;
923}
924
925/****************************************************************************/
926static int process_alerting(struct sk_buff **pskb, struct ip_conntrack *ct,
927 enum ip_conntrack_info ctinfo,
928 unsigned char **data, int dataoff,
929 Alerting_UUIE * alert)
930{
931 int ret;
932 int i;
933
934 DEBUGP("ip_ct_q931: Alerting\n");
935
936 if (alert->options & eAlerting_UUIE_h245Address) {
937 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
938 &alert->h245Address);
939 if (ret < 0)
940 return -1;
941 }
942
943 if (alert->options & eAlerting_UUIE_fastStart) {
944 for (i = 0; i < alert->fastStart.count; i++) {
945 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
946 &alert->fastStart.item[i]);
947 if (ret < 0)
948 return -1;
949 }
950 }
951
952 return 0;
953}
954
955/****************************************************************************/
956static int process_information(struct sk_buff **pskb,
957 struct ip_conntrack *ct,
958 enum ip_conntrack_info ctinfo,
959 unsigned char **data, int dataoff,
960 Information_UUIE * info)
961{
962 int ret;
963 int i;
964
965 DEBUGP("ip_ct_q931: Information\n");
966
967 if (info->options & eInformation_UUIE_fastStart) {
968 for (i = 0; i < info->fastStart.count; i++) {
969 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
970 &info->fastStart.item[i]);
971 if (ret < 0)
972 return -1;
973 }
974 }
975
976 return 0;
977}
978
979/****************************************************************************/
980static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
981 enum ip_conntrack_info ctinfo,
982 unsigned char **data, int dataoff,
983 Facility_UUIE * facility)
984{
985 int ret;
986 int i;
987
988 DEBUGP("ip_ct_q931: Facility\n");
989
990 if (facility->reason.choice == eFacilityReason_callForwarded) {
991 if (facility->options & eFacility_UUIE_alternativeAddress)
992 return expect_callforwarding(pskb, ct, ctinfo, data,
993 dataoff,
994 &facility->
995 alternativeAddress);
996 return 0;
997 }
998
999 if (facility->options & eFacility_UUIE_h245Address) {
1000 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
1001 &facility->h245Address);
1002 if (ret < 0)
1003 return -1;
1004 }
1005
1006 if (facility->options & eFacility_UUIE_fastStart) {
1007 for (i = 0; i < facility->fastStart.count; i++) {
1008 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
1009 &facility->fastStart.item[i]);
1010 if (ret < 0)
1011 return -1;
1012 }
1013 }
1014
1015 return 0;
1016}
1017
1018/****************************************************************************/
1019static int process_progress(struct sk_buff **pskb, struct ip_conntrack *ct,
1020 enum ip_conntrack_info ctinfo,
1021 unsigned char **data, int dataoff,
1022 Progress_UUIE * progress)
1023{
1024 int ret;
1025 int i;
1026
1027 DEBUGP("ip_ct_q931: Progress\n");
1028
1029 if (progress->options & eProgress_UUIE_h245Address) {
1030 ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
1031 &progress->h245Address);
1032 if (ret < 0)
1033 return -1;
1034 }
1035
1036 if (progress->options & eProgress_UUIE_fastStart) {
1037 for (i = 0; i < progress->fastStart.count; i++) {
1038 ret = process_olc(pskb, ct, ctinfo, data, dataoff,
1039 &progress->fastStart.item[i]);
1040 if (ret < 0)
1041 return -1;
1042 }
1043 }
1044
1045 return 0;
1046}
1047
1048/****************************************************************************/
1049static int process_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
1050 enum ip_conntrack_info ctinfo,
1051 unsigned char **data, int dataoff, Q931 * q931)
1052{
1053 H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
1054 int i;
1055 int ret = 0;
1056
1057 switch (pdu->h323_message_body.choice) {
1058 case eH323_UU_PDU_h323_message_body_setup:
1059 ret = process_setup(pskb, ct, ctinfo, data, dataoff,
1060 &pdu->h323_message_body.setup);
1061 break;
1062 case eH323_UU_PDU_h323_message_body_callProceeding:
1063 ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff,
1064 &pdu->h323_message_body.
1065 callProceeding);
1066 break;
1067 case eH323_UU_PDU_h323_message_body_connect:
1068 ret = process_connect(pskb, ct, ctinfo, data, dataoff,
1069 &pdu->h323_message_body.connect);
1070 break;
1071 case eH323_UU_PDU_h323_message_body_alerting:
1072 ret = process_alerting(pskb, ct, ctinfo, data, dataoff,
1073 &pdu->h323_message_body.alerting);
1074 break;
1075 case eH323_UU_PDU_h323_message_body_information:
1076 ret = process_information(pskb, ct, ctinfo, data, dataoff,
1077 &pdu->h323_message_body.
1078 information);
1079 break;
1080 case eH323_UU_PDU_h323_message_body_facility:
1081 ret = process_facility(pskb, ct, ctinfo, data, dataoff,
1082 &pdu->h323_message_body.facility);
1083 break;
1084 case eH323_UU_PDU_h323_message_body_progress:
1085 ret = process_progress(pskb, ct, ctinfo, data, dataoff,
1086 &pdu->h323_message_body.progress);
1087 break;
1088 default:
1089 DEBUGP("ip_ct_q931: Q.931 signal %d\n",
1090 pdu->h323_message_body.choice);
1091 break;
1092 }
1093
1094 if (ret < 0)
1095 return -1;
1096
1097 if (pdu->options & eH323_UU_PDU_h245Control) {
1098 for (i = 0; i < pdu->h245Control.count; i++) {
1099 ret = process_h245(pskb, ct, ctinfo, data, dataoff,
1100 &pdu->h245Control.item[i]);
1101 if (ret < 0)
1102 return -1;
1103 }
1104 }
1105
1106 return 0;
1107}
1108
1109/****************************************************************************/
1110static int q931_help(struct sk_buff **pskb, struct ip_conntrack *ct,
1111 enum ip_conntrack_info ctinfo)
1112{
1113 static Q931 q931;
1114 unsigned char *data = NULL;
1115 int datalen;
1116 int dataoff;
1117 int ret;
1118
1119 /* Until there's been traffic both ways, don't look in packets. */
1120 if (ctinfo != IP_CT_ESTABLISHED
1121 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1122 return NF_ACCEPT;
1123 }
1124 DEBUGP("ip_ct_q931: skblen = %u\n", (*pskb)->len);
1125
1126 spin_lock_bh(&ip_h323_lock);
1127
1128 /* Process each TPKT */
1129 while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
1130 DEBUGP("ip_ct_q931: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
1131 NIPQUAD(ip_hdr(*pskb)->saddr),
1132 NIPQUAD(ip_hdr(*pskb)->daddr), datalen);
1133
1134 /* Decode Q.931 signal */
1135 ret = DecodeQ931(data, datalen, &q931);
1136 if (ret < 0) {
1137 if (net_ratelimit())
1138 printk("ip_ct_q931: decoding error: %s\n",
1139 ret == H323_ERROR_BOUND ?
1140 "out of bound" : "out of range");
1141 /* We don't drop when decoding error */
1142 break;
1143 }
1144
1145 /* Process Q.931 signal */
1146 if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0)
1147 goto drop;
1148 }
1149
1150 spin_unlock_bh(&ip_h323_lock);
1151 return NF_ACCEPT;
1152
1153 drop:
1154 spin_unlock_bh(&ip_h323_lock);
1155 if (net_ratelimit())
1156 printk("ip_ct_q931: packet dropped\n");
1157 return NF_DROP;
1158}
1159
1160/****************************************************************************/
1161static struct ip_conntrack_helper ip_conntrack_helper_q931 = {
1162 .name = "Q.931",
1163 .me = THIS_MODULE,
1164 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ ,
1165 .timeout = 240,
1166 .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(Q931_PORT)}}},
1167 .dst = {.protonum = IPPROTO_TCP}},
1168 .mask = {.src = {.u = {0xFFFF}},
1169 .dst = {.protonum = 0xFF}},
1170 .help = q931_help
1171};
1172
1173/****************************************************************************/
1174void ip_conntrack_q931_expect(struct ip_conntrack *new,
1175 struct ip_conntrack_expect *this)
1176{
1177 write_lock_bh(&ip_conntrack_lock);
1178 new->helper = &ip_conntrack_helper_q931;
1179 write_unlock_bh(&ip_conntrack_lock);
1180}
1181
1182/****************************************************************************/
1183static unsigned char *get_udp_data(struct sk_buff **pskb, int *datalen)
1184{
1185 struct udphdr _uh, *uh;
1186 int dataoff;
1187
1188 uh = skb_header_pointer(*pskb, ip_hdrlen(*pskb), sizeof(_uh), &_uh);
1189 if (uh == NULL)
1190 return NULL;
1191 dataoff = ip_hdrlen(*pskb) + sizeof(_uh);
1192 if (dataoff >= (*pskb)->len)
1193 return NULL;
1194 *datalen = (*pskb)->len - dataoff;
1195 return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer);
1196}
1197
1198/****************************************************************************/
1199static struct ip_conntrack_expect *find_expect(struct ip_conntrack *ct,
1200 __be32 ip, u_int16_t port)
1201{
1202 struct ip_conntrack_expect *exp;
1203 struct ip_conntrack_tuple tuple;
1204
1205 tuple.src.ip = 0;
1206 tuple.src.u.tcp.port = 0;
1207 tuple.dst.ip = ip;
1208 tuple.dst.u.tcp.port = htons(port);
1209 tuple.dst.protonum = IPPROTO_TCP;
1210
1211 exp = __ip_conntrack_expect_find(&tuple);
1212 if (exp && exp->master == ct)
1213 return exp;
1214 return NULL;
1215}
1216
1217/****************************************************************************/
1218static int set_expect_timeout(struct ip_conntrack_expect *exp,
1219 unsigned timeout)
1220{
1221 if (!exp || !del_timer(&exp->timeout))
1222 return 0;
1223
1224 exp->timeout.expires = jiffies + timeout * HZ;
1225 add_timer(&exp->timeout);
1226
1227 return 1;
1228}
1229
1230/****************************************************************************/
1231static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
1232 enum ip_conntrack_info ctinfo,
1233 unsigned char **data,
1234 TransportAddress * addr, int count)
1235{
1236 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1237 int dir = CTINFO2DIR(ctinfo);
1238 int ret = 0;
1239 int i;
1240 __be32 ip;
1241 u_int16_t port;
1242 struct ip_conntrack_expect *exp;
1243 typeof(nat_q931_hook) nat_q931;
1244
1245 /* Look for the first related address */
1246 for (i = 0; i < count; i++) {
1247 if (get_h225_addr(*data, &addr[i], &ip, &port) &&
1248 ip == ct->tuplehash[dir].tuple.src.ip && port != 0)
1249 break;
1250 }
1251
1252 if (i >= count) /* Not found */
1253 return 0;
1254
1255 /* Create expect for Q.931 */
1256 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1257 return -1;
1258 exp->tuple.src.ip = gkrouted_only ? /* only accept calls from GK? */
1259 ct->tuplehash[!dir].tuple.src.ip : 0;
1260 exp->tuple.src.u.tcp.port = 0;
1261 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
1262 exp->tuple.dst.u.tcp.port = htons(port);
1263 exp->tuple.dst.protonum = IPPROTO_TCP;
1264 exp->mask.src.ip = gkrouted_only ? htonl(0xFFFFFFFF) : 0;
1265 exp->mask.src.u.tcp.port = 0;
1266 exp->mask.dst.ip = htonl(0xFFFFFFFF);
1267 exp->mask.dst.u.tcp.port = htons(0xFFFF);
1268 exp->mask.dst.protonum = 0xFF;
1269 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */
1270
1271 nat_q931 = rcu_dereference(nat_q931_hook);
1272 if (nat_q931) { /* Need NAT */
1273 ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp);
1274 } else { /* Conntrack only */
1275 exp->expectfn = ip_conntrack_q931_expect;
1276
1277 if (ip_conntrack_expect_related(exp) == 0) {
1278 DEBUGP("ip_ct_ras: expect Q.931 "
1279 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1280 NIPQUAD(exp->tuple.src.ip),
1281 ntohs(exp->tuple.src.u.tcp.port),
1282 NIPQUAD(exp->tuple.dst.ip),
1283 ntohs(exp->tuple.dst.u.tcp.port));
1284
1285 /* Save port for looking up expect in processing RCF */
1286 info->sig_port[dir] = port;
1287 } else
1288 ret = -1;
1289 }
1290
1291 ip_conntrack_expect_put(exp);
1292
1293 return ret;
1294}
1295
1296/****************************************************************************/
1297static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct,
1298 enum ip_conntrack_info ctinfo,
1299 unsigned char **data, GatekeeperRequest * grq)
1300{
1301 typeof(set_ras_addr_hook) set_ras_addr;
1302
1303 DEBUGP("ip_ct_ras: GRQ\n");
1304
1305 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1306 if (set_ras_addr) /* NATed */
1307 return set_ras_addr(pskb, ct, ctinfo, data,
1308 &grq->rasAddress, 1);
1309 return 0;
1310}
1311
1312/* Declare before using */
1313static void ip_conntrack_ras_expect(struct ip_conntrack *new,
1314 struct ip_conntrack_expect *this);
1315
1316/****************************************************************************/
1317static int process_gcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1318 enum ip_conntrack_info ctinfo,
1319 unsigned char **data, GatekeeperConfirm * gcf)
1320{
1321 int dir = CTINFO2DIR(ctinfo);
1322 int ret = 0;
1323 __be32 ip;
1324 u_int16_t port;
1325 struct ip_conntrack_expect *exp;
1326
1327 DEBUGP("ip_ct_ras: GCF\n");
1328
1329 if (!get_h225_addr(*data, &gcf->rasAddress, &ip, &port))
1330 return 0;
1331
1332 /* Registration port is the same as discovery port */
1333 if (ip == ct->tuplehash[dir].tuple.src.ip &&
1334 port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port))
1335 return 0;
1336
1337 /* Avoid RAS expectation loops. A GCF is never expected. */
1338 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
1339 return 0;
1340
1341 /* Need new expect */
1342 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1343 return -1;
1344 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1345 exp->tuple.src.u.tcp.port = 0;
1346 exp->tuple.dst.ip = ip;
1347 exp->tuple.dst.u.tcp.port = htons(port);
1348 exp->tuple.dst.protonum = IPPROTO_UDP;
1349 exp->mask.src.ip = htonl(0xFFFFFFFF);
1350 exp->mask.src.u.tcp.port = 0;
1351 exp->mask.dst.ip = htonl(0xFFFFFFFF);
1352 exp->mask.dst.u.tcp.port = htons(0xFFFF);
1353 exp->mask.dst.protonum = 0xFF;
1354 exp->flags = 0;
1355 exp->expectfn = ip_conntrack_ras_expect;
1356 if (ip_conntrack_expect_related(exp) == 0) {
1357 DEBUGP("ip_ct_ras: expect RAS "
1358 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1359 NIPQUAD(exp->tuple.src.ip),
1360 ntohs(exp->tuple.src.u.tcp.port),
1361 NIPQUAD(exp->tuple.dst.ip),
1362 ntohs(exp->tuple.dst.u.tcp.port));
1363 } else
1364 ret = -1;
1365
1366 ip_conntrack_expect_put(exp);
1367
1368 return ret;
1369}
1370
1371/****************************************************************************/
1372static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1373 enum ip_conntrack_info ctinfo,
1374 unsigned char **data, RegistrationRequest * rrq)
1375{
1376 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1377 int ret;
1378 typeof(set_ras_addr_hook) set_ras_addr;
1379
1380 DEBUGP("ip_ct_ras: RRQ\n");
1381
1382 ret = expect_q931(pskb, ct, ctinfo, data,
1383 rrq->callSignalAddress.item,
1384 rrq->callSignalAddress.count);
1385 if (ret < 0)
1386 return -1;
1387
1388 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1389 if (set_ras_addr) {
1390 ret = set_ras_addr(pskb, ct, ctinfo, data,
1391 rrq->rasAddress.item,
1392 rrq->rasAddress.count);
1393 if (ret < 0)
1394 return -1;
1395 }
1396
1397 if (rrq->options & eRegistrationRequest_timeToLive) {
1398 DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
1399 info->timeout = rrq->timeToLive;
1400 } else
1401 info->timeout = default_rrq_ttl;
1402
1403 return 0;
1404}
1405
1406/****************************************************************************/
1407static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1408 enum ip_conntrack_info ctinfo,
1409 unsigned char **data, RegistrationConfirm * rcf)
1410{
1411 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1412 int dir = CTINFO2DIR(ctinfo);
1413 int ret;
1414 struct ip_conntrack_expect *exp;
1415 typeof(set_sig_addr_hook) set_sig_addr;
1416
1417 DEBUGP("ip_ct_ras: RCF\n");
1418
1419 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1420 if (set_sig_addr) {
1421 ret = set_sig_addr(pskb, ct, ctinfo, data,
1422 rcf->callSignalAddress.item,
1423 rcf->callSignalAddress.count);
1424 if (ret < 0)
1425 return -1;
1426 }
1427
1428 if (rcf->options & eRegistrationConfirm_timeToLive) {
1429 DEBUGP("ip_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
1430 info->timeout = rcf->timeToLive;
1431 }
1432
1433 if (info->timeout > 0) {
1434 DEBUGP
1435 ("ip_ct_ras: set RAS connection timeout to %u seconds\n",
1436 info->timeout);
1437 ip_ct_refresh(ct, *pskb, info->timeout * HZ);
1438
1439 /* Set expect timeout */
1440 read_lock_bh(&ip_conntrack_lock);
1441 exp = find_expect(ct, ct->tuplehash[dir].tuple.dst.ip,
1442 info->sig_port[!dir]);
1443 if (exp) {
1444 DEBUGP("ip_ct_ras: set Q.931 expect "
1445 "(%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu) "
1446 "timeout to %u seconds\n",
1447 NIPQUAD(exp->tuple.src.ip),
1448 ntohs(exp->tuple.src.u.tcp.port),
1449 NIPQUAD(exp->tuple.dst.ip),
1450 ntohs(exp->tuple.dst.u.tcp.port),
1451 info->timeout);
1452 set_expect_timeout(exp, info->timeout);
1453 }
1454 read_unlock_bh(&ip_conntrack_lock);
1455 }
1456
1457 return 0;
1458}
1459
1460/****************************************************************************/
1461static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
1462 enum ip_conntrack_info ctinfo,
1463 unsigned char **data, UnregistrationRequest * urq)
1464{
1465 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1466 int dir = CTINFO2DIR(ctinfo);
1467 int ret;
1468 typeof(set_sig_addr_hook) set_sig_addr;
1469
1470 DEBUGP("ip_ct_ras: URQ\n");
1471
1472 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1473 if (set_sig_addr) {
1474 ret = set_sig_addr(pskb, ct, ctinfo, data,
1475 urq->callSignalAddress.item,
1476 urq->callSignalAddress.count);
1477 if (ret < 0)
1478 return -1;
1479 }
1480
1481 /* Clear old expect */
1482 ip_ct_remove_expectations(ct);
1483 info->sig_port[dir] = 0;
1484 info->sig_port[!dir] = 0;
1485
1486 /* Give it 30 seconds for UCF or URJ */
1487 ip_ct_refresh(ct, *pskb, 30 * HZ);
1488
1489 return 0;
1490}
1491
1492/****************************************************************************/
1493static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
1494 enum ip_conntrack_info ctinfo,
1495 unsigned char **data, AdmissionRequest * arq)
1496{
1497 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1498 int dir = CTINFO2DIR(ctinfo);
1499 __be32 ip;
1500 u_int16_t port;
1501 typeof(set_h225_addr_hook) set_h225_addr;
1502
1503 DEBUGP("ip_ct_ras: ARQ\n");
1504
1505 set_h225_addr = rcu_dereference(set_h225_addr_hook);
1506 if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
1507 get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
1508 ip == ct->tuplehash[dir].tuple.src.ip &&
1509 port == info->sig_port[dir] && set_h225_addr) {
1510 /* Answering ARQ */
1511 return set_h225_addr(pskb, data, 0,
1512 &arq->destCallSignalAddress,
1513 ct->tuplehash[!dir].tuple.dst.ip,
1514 info->sig_port[!dir]);
1515 }
1516
1517 if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
1518 get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
1519 ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) {
1520 /* Calling ARQ */
1521 return set_h225_addr(pskb, data, 0,
1522 &arq->srcCallSignalAddress,
1523 ct->tuplehash[!dir].tuple.dst.ip,
1524 port);
1525 }
1526
1527 return 0;
1528}
1529
1530/****************************************************************************/
1531static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
1532 enum ip_conntrack_info ctinfo,
1533 unsigned char **data, AdmissionConfirm * acf)
1534{
1535 int dir = CTINFO2DIR(ctinfo);
1536 int ret = 0;
1537 __be32 ip;
1538 u_int16_t port;
1539 struct ip_conntrack_expect *exp;
1540 typeof(set_sig_addr_hook) set_sig_addr;
1541
1542 DEBUGP("ip_ct_ras: ACF\n");
1543
1544 if (!get_h225_addr(*data, &acf->destCallSignalAddress, &ip, &port))
1545 return 0;
1546
1547 if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */
1548 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1549 if (set_sig_addr)
1550 return set_sig_addr(pskb, ct, ctinfo, data,
1551 &acf->destCallSignalAddress, 1);
1552 return 0;
1553 }
1554
1555 /* Need new expect */
1556 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1557 return -1;
1558 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1559 exp->tuple.src.u.tcp.port = 0;
1560 exp->tuple.dst.ip = ip;
1561 exp->tuple.dst.u.tcp.port = htons(port);
1562 exp->tuple.dst.protonum = IPPROTO_TCP;
1563 exp->mask.src.ip = htonl(0xFFFFFFFF);
1564 exp->mask.src.u.tcp.port = 0;
1565 exp->mask.dst.ip = htonl(0xFFFFFFFF);
1566 exp->mask.dst.u.tcp.port = htons(0xFFFF);
1567 exp->mask.dst.protonum = 0xFF;
1568 exp->flags = IP_CT_EXPECT_PERMANENT;
1569 exp->expectfn = ip_conntrack_q931_expect;
1570
1571 if (ip_conntrack_expect_related(exp) == 0) {
1572 DEBUGP("ip_ct_ras: expect Q.931 "
1573 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1574 NIPQUAD(exp->tuple.src.ip),
1575 ntohs(exp->tuple.src.u.tcp.port),
1576 NIPQUAD(exp->tuple.dst.ip),
1577 ntohs(exp->tuple.dst.u.tcp.port));
1578 } else
1579 ret = -1;
1580
1581 ip_conntrack_expect_put(exp);
1582
1583 return ret;
1584}
1585
1586/****************************************************************************/
1587static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1588 enum ip_conntrack_info ctinfo,
1589 unsigned char **data, LocationRequest * lrq)
1590{
1591 typeof(set_ras_addr_hook) set_ras_addr;
1592
1593 DEBUGP("ip_ct_ras: LRQ\n");
1594
1595 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1596 if (set_ras_addr)
1597 return set_ras_addr(pskb, ct, ctinfo, data,
1598 &lrq->replyAddress, 1);
1599 return 0;
1600}
1601
1602/****************************************************************************/
1603static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1604 enum ip_conntrack_info ctinfo,
1605 unsigned char **data, LocationConfirm * lcf)
1606{
1607 int dir = CTINFO2DIR(ctinfo);
1608 int ret = 0;
1609 __be32 ip;
1610 u_int16_t port;
1611 struct ip_conntrack_expect *exp = NULL;
1612
1613 DEBUGP("ip_ct_ras: LCF\n");
1614
1615 if (!get_h225_addr(*data, &lcf->callSignalAddress, &ip, &port))
1616 return 0;
1617
1618 /* Need new expect for call signal */
1619 if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
1620 return -1;
1621 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1622 exp->tuple.src.u.tcp.port = 0;
1623 exp->tuple.dst.ip = ip;
1624 exp->tuple.dst.u.tcp.port = htons(port);
1625 exp->tuple.dst.protonum = IPPROTO_TCP;
1626 exp->mask.src.ip = htonl(0xFFFFFFFF);
1627 exp->mask.src.u.tcp.port = 0;
1628 exp->mask.dst.ip = htonl(0xFFFFFFFF);
1629 exp->mask.dst.u.tcp.port = htons(0xFFFF);
1630 exp->mask.dst.protonum = 0xFF;
1631 exp->flags = IP_CT_EXPECT_PERMANENT;
1632 exp->expectfn = ip_conntrack_q931_expect;
1633
1634 if (ip_conntrack_expect_related(exp) == 0) {
1635 DEBUGP("ip_ct_ras: expect Q.931 "
1636 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
1637 NIPQUAD(exp->tuple.src.ip),
1638 ntohs(exp->tuple.src.u.tcp.port),
1639 NIPQUAD(exp->tuple.dst.ip),
1640 ntohs(exp->tuple.dst.u.tcp.port));
1641 } else
1642 ret = -1;
1643
1644 ip_conntrack_expect_put(exp);
1645
1646 /* Ignore rasAddress */
1647
1648 return ret;
1649}
1650
1651/****************************************************************************/
1652static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct,
1653 enum ip_conntrack_info ctinfo,
1654 unsigned char **data, InfoRequestResponse * irr)
1655{
1656 int ret;
1657 typeof(set_ras_addr_hook) set_ras_addr;
1658 typeof(set_sig_addr_hook) set_sig_addr;
1659
1660 DEBUGP("ip_ct_ras: IRR\n");
1661
1662 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1663 if (set_ras_addr) {
1664 ret = set_ras_addr(pskb, ct, ctinfo, data,
1665 &irr->rasAddress, 1);
1666 if (ret < 0)
1667 return -1;
1668 }
1669
1670 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1671 if (set_sig_addr) {
1672 ret = set_sig_addr(pskb, ct, ctinfo, data,
1673 irr->callSignalAddress.item,
1674 irr->callSignalAddress.count);
1675 if (ret < 0)
1676 return -1;
1677 }
1678
1679 return 0;
1680}
1681
1682/****************************************************************************/
1683static int process_ras(struct sk_buff **pskb, struct ip_conntrack *ct,
1684 enum ip_conntrack_info ctinfo,
1685 unsigned char **data, RasMessage * ras)
1686{
1687 switch (ras->choice) {
1688 case eRasMessage_gatekeeperRequest:
1689 return process_grq(pskb, ct, ctinfo, data,
1690 &ras->gatekeeperRequest);
1691 case eRasMessage_gatekeeperConfirm:
1692 return process_gcf(pskb, ct, ctinfo, data,
1693 &ras->gatekeeperConfirm);
1694 case eRasMessage_registrationRequest:
1695 return process_rrq(pskb, ct, ctinfo, data,
1696 &ras->registrationRequest);
1697 case eRasMessage_registrationConfirm:
1698 return process_rcf(pskb, ct, ctinfo, data,
1699 &ras->registrationConfirm);
1700 case eRasMessage_unregistrationRequest:
1701 return process_urq(pskb, ct, ctinfo, data,
1702 &ras->unregistrationRequest);
1703 case eRasMessage_admissionRequest:
1704 return process_arq(pskb, ct, ctinfo, data,
1705 &ras->admissionRequest);
1706 case eRasMessage_admissionConfirm:
1707 return process_acf(pskb, ct, ctinfo, data,
1708 &ras->admissionConfirm);
1709 case eRasMessage_locationRequest:
1710 return process_lrq(pskb, ct, ctinfo, data,
1711 &ras->locationRequest);
1712 case eRasMessage_locationConfirm:
1713 return process_lcf(pskb, ct, ctinfo, data,
1714 &ras->locationConfirm);
1715 case eRasMessage_infoRequestResponse:
1716 return process_irr(pskb, ct, ctinfo, data,
1717 &ras->infoRequestResponse);
1718 default:
1719 DEBUGP("ip_ct_ras: RAS message %d\n", ras->choice);
1720 break;
1721 }
1722
1723 return 0;
1724}
1725
1726/****************************************************************************/
1727static int ras_help(struct sk_buff **pskb, struct ip_conntrack *ct,
1728 enum ip_conntrack_info ctinfo)
1729{
1730 static RasMessage ras;
1731 unsigned char *data;
1732 int datalen = 0;
1733 int ret;
1734
1735 DEBUGP("ip_ct_ras: skblen = %u\n", (*pskb)->len);
1736
1737 spin_lock_bh(&ip_h323_lock);
1738
1739 /* Get UDP data */
1740 data = get_udp_data(pskb, &datalen);
1741 if (data == NULL)
1742 goto accept;
1743 DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
1744 NIPQUAD(ip_hdr(*pskb)->saddr),
1745 NIPQUAD(ip_hdr(*pskb)->daddr), datalen);
1746
1747 /* Decode RAS message */
1748 ret = DecodeRasMessage(data, datalen, &ras);
1749 if (ret < 0) {
1750 if (net_ratelimit())
1751 printk("ip_ct_ras: decoding error: %s\n",
1752 ret == H323_ERROR_BOUND ?
1753 "out of bound" : "out of range");
1754 goto accept;
1755 }
1756
1757 /* Process RAS message */
1758 if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0)
1759 goto drop;
1760
1761 accept:
1762 spin_unlock_bh(&ip_h323_lock);
1763 return NF_ACCEPT;
1764
1765 drop:
1766 spin_unlock_bh(&ip_h323_lock);
1767 if (net_ratelimit())
1768 printk("ip_ct_ras: packet dropped\n");
1769 return NF_DROP;
1770}
1771
1772/****************************************************************************/
1773static struct ip_conntrack_helper ip_conntrack_helper_ras = {
1774 .name = "RAS",
1775 .me = THIS_MODULE,
1776 .max_expected = 32,
1777 .timeout = 240,
1778 .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(RAS_PORT)}}},
1779 .dst = {.protonum = IPPROTO_UDP}},
1780 .mask = {.src = {.u = {0xFFFE}},
1781 .dst = {.protonum = 0xFF}},
1782 .help = ras_help,
1783};
1784
1785/****************************************************************************/
1786static void ip_conntrack_ras_expect(struct ip_conntrack *new,
1787 struct ip_conntrack_expect *this)
1788{
1789 write_lock_bh(&ip_conntrack_lock);
1790 new->helper = &ip_conntrack_helper_ras;
1791 write_unlock_bh(&ip_conntrack_lock);
1792}
1793
1794/****************************************************************************/
1795/* Not __exit - called from init() */
1796static void fini(void)
1797{
1798 ip_conntrack_helper_unregister(&ip_conntrack_helper_ras);
1799 ip_conntrack_helper_unregister(&ip_conntrack_helper_q931);
1800 kfree(h323_buffer);
1801 DEBUGP("ip_ct_h323: fini\n");
1802}
1803
1804/****************************************************************************/
1805static int __init init(void)
1806{
1807 int ret;
1808
1809 h323_buffer = kmalloc(65536, GFP_KERNEL);
1810 if (!h323_buffer)
1811 return -ENOMEM;
1812 if ((ret = ip_conntrack_helper_register(&ip_conntrack_helper_q931)) ||
1813 (ret = ip_conntrack_helper_register(&ip_conntrack_helper_ras))) {
1814 fini();
1815 return ret;
1816 }
1817 DEBUGP("ip_ct_h323: init success\n");
1818 return 0;
1819}
1820
1821/****************************************************************************/
1822module_init(init);
1823module_exit(fini);
1824
1825EXPORT_SYMBOL_GPL(get_h225_addr);
1826EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
1827EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
1828EXPORT_SYMBOL_GPL(set_h245_addr_hook);
1829EXPORT_SYMBOL_GPL(set_h225_addr_hook);
1830EXPORT_SYMBOL_GPL(set_sig_addr_hook);
1831EXPORT_SYMBOL_GPL(set_ras_addr_hook);
1832EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
1833EXPORT_SYMBOL_GPL(nat_t120_hook);
1834EXPORT_SYMBOL_GPL(nat_h245_hook);
1835EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
1836EXPORT_SYMBOL_GPL(nat_q931_hook);
1837
1838MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
1839MODULE_DESCRIPTION("H.323 connection tracking helper");
1840MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
deleted file mode 100644
index f5ab8e4b97cb..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ /dev/null
@@ -1,684 +0,0 @@
1/*
2 * ip_conntrack_pptp.c - Version 3.0
3 *
4 * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
5 * PPTP is a a protocol for creating virtual private networks.
6 * It is a specification defined by Microsoft and some vendors
7 * working with Microsoft. PPTP is built on top of a modified
8 * version of the Internet Generic Routing Encapsulation Protocol.
9 * GRE is defined in RFC 1701 and RFC 1702. Documentation of
10 * PPTP can be found in RFC 2637
11 *
12 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
13 *
14 * Development of this code funded by Astaro AG (http://www.astaro.com/)
15 *
16 * Limitations:
17 * - We blindly assume that control connections are always
18 * established in PNS->PAC direction. This is a violation
19 * of RFFC2673
20 * - We can only support one single call within each session
21 *
22 * TODO:
23 * - testing of incoming PPTP calls
24 *
25 * Changes:
26 * 2002-02-05 - Version 1.3
27 * - Call ip_conntrack_unexpect_related() from
28 * pptp_destroy_siblings() to destroy expectations in case
29 * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
30 * (Philip Craig <philipc@snapgear.com>)
31 * - Add Version information at module loadtime
32 * 2002-02-10 - Version 1.6
33 * - move to C99 style initializers
34 * - remove second expectation if first arrives
35 * 2004-10-22 - Version 2.0
36 * - merge Mandrake's 2.6.x port with recent 2.6.x API changes
37 * - fix lots of linear skb assumptions from Mandrake's port
38 * 2005-06-10 - Version 2.1
39 * - use ip_conntrack_expect_free() instead of kfree() on the
40 * expect's (which are from the slab for quite some time)
41 * 2005-06-10 - Version 3.0
42 * - port helper to post-2.6.11 API changes,
43 * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
44 * 2005-07-30 - Version 3.1
45 * - port helper to 2.6.13 API changes
46 *
47 */
48
49#include <linux/module.h>
50#include <linux/netfilter.h>
51#include <linux/ip.h>
52#include <net/checksum.h>
53#include <net/tcp.h>
54
55#include <linux/netfilter_ipv4/ip_conntrack.h>
56#include <linux/netfilter_ipv4/ip_conntrack_core.h>
57#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
58#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
59#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
60
61#define IP_CT_PPTP_VERSION "3.1"
62
63MODULE_LICENSE("GPL");
64MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
65MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
66
67static DEFINE_SPINLOCK(ip_pptp_lock);
68
69int
70(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
71 struct ip_conntrack *ct,
72 enum ip_conntrack_info ctinfo,
73 struct PptpControlHeader *ctlh,
74 union pptp_ctrl_union *pptpReq);
75
76int
77(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
78 struct ip_conntrack *ct,
79 enum ip_conntrack_info ctinfo,
80 struct PptpControlHeader *ctlh,
81 union pptp_ctrl_union *pptpReq);
82
83void
84(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
85 struct ip_conntrack_expect *expect_reply);
86
87void
88(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
89 struct ip_conntrack_expect *exp);
90
91#if 0
92/* PptpControlMessageType names */
93const char *pptp_msg_name[] = {
94 "UNKNOWN_MESSAGE",
95 "START_SESSION_REQUEST",
96 "START_SESSION_REPLY",
97 "STOP_SESSION_REQUEST",
98 "STOP_SESSION_REPLY",
99 "ECHO_REQUEST",
100 "ECHO_REPLY",
101 "OUT_CALL_REQUEST",
102 "OUT_CALL_REPLY",
103 "IN_CALL_REQUEST",
104 "IN_CALL_REPLY",
105 "IN_CALL_CONNECT",
106 "CALL_CLEAR_REQUEST",
107 "CALL_DISCONNECT_NOTIFY",
108 "WAN_ERROR_NOTIFY",
109 "SET_LINK_INFO"
110};
111EXPORT_SYMBOL(pptp_msg_name);
112#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
113#else
114#define DEBUGP(format, args...)
115#endif
116
117#define SECS *HZ
118#define MINS * 60 SECS
119#define HOURS * 60 MINS
120
121#define PPTP_GRE_TIMEOUT (10 MINS)
122#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS)
123
124static void pptp_expectfn(struct ip_conntrack *ct,
125 struct ip_conntrack_expect *exp)
126{
127 typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn;
128
129 DEBUGP("increasing timeouts\n");
130
131 /* increase timeout of GRE data channel conntrack entry */
132 ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
133 ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
134
135 /* Can you see how rusty this code is, compared with the pre-2.6.11
136 * one? That's what happened to my shiny newnat of 2002 ;( -HW */
137
138 rcu_read_lock();
139 ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn);
140 if (!ip_nat_pptp_expectfn) {
141 struct ip_conntrack_tuple inv_t;
142 struct ip_conntrack_expect *exp_other;
143
144 /* obviously this tuple inversion only works until you do NAT */
145 invert_tuplepr(&inv_t, &exp->tuple);
146 DEBUGP("trying to unexpect other dir: ");
147 DUMP_TUPLE(&inv_t);
148
149 exp_other = ip_conntrack_expect_find_get(&inv_t);
150 if (exp_other) {
151 /* delete other expectation. */
152 DEBUGP("found\n");
153 ip_conntrack_unexpect_related(exp_other);
154 ip_conntrack_expect_put(exp_other);
155 } else {
156 DEBUGP("not found\n");
157 }
158 } else {
159 /* we need more than simple inversion */
160 ip_nat_pptp_expectfn(ct, exp);
161 }
162 rcu_read_unlock();
163}
164
165static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
166{
167 struct ip_conntrack_tuple_hash *h;
168 struct ip_conntrack_expect *exp;
169
170 DEBUGP("trying to timeout ct or exp for tuple ");
171 DUMP_TUPLE(t);
172
173 h = ip_conntrack_find_get(t, NULL);
174 if (h) {
175 struct ip_conntrack *sibling = tuplehash_to_ctrack(h);
176 DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
177 sibling->proto.gre.timeout = 0;
178 sibling->proto.gre.stream_timeout = 0;
179 if (del_timer(&sibling->timeout))
180 sibling->timeout.function((unsigned long)sibling);
181 ip_conntrack_put(sibling);
182 return 1;
183 } else {
184 exp = ip_conntrack_expect_find_get(t);
185 if (exp) {
186 DEBUGP("unexpect_related of expect %p\n", exp);
187 ip_conntrack_unexpect_related(exp);
188 ip_conntrack_expect_put(exp);
189 return 1;
190 }
191 }
192
193 return 0;
194}
195
196
197/* timeout GRE data connections */
198static void pptp_destroy_siblings(struct ip_conntrack *ct)
199{
200 struct ip_conntrack_tuple t;
201
202 ip_ct_gre_keymap_destroy(ct);
203 /* Since ct->sibling_list has literally rusted away in 2.6.11,
204 * we now need another way to find out about our sibling
205 * contrack and expects... -HW */
206
207 /* try original (pns->pac) tuple */
208 memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
209 t.dst.protonum = IPPROTO_GRE;
210 t.src.u.gre.key = ct->help.ct_pptp_info.pns_call_id;
211 t.dst.u.gre.key = ct->help.ct_pptp_info.pac_call_id;
212
213 if (!destroy_sibling_or_exp(&t))
214 DEBUGP("failed to timeout original pns->pac ct/exp\n");
215
216 /* try reply (pac->pns) tuple */
217 memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
218 t.dst.protonum = IPPROTO_GRE;
219 t.src.u.gre.key = ct->help.ct_pptp_info.pac_call_id;
220 t.dst.u.gre.key = ct->help.ct_pptp_info.pns_call_id;
221
222 if (!destroy_sibling_or_exp(&t))
223 DEBUGP("failed to timeout reply pac->pns ct/exp\n");
224}
225
226/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
227static inline int
228exp_gre(struct ip_conntrack *ct,
229 __be16 callid,
230 __be16 peer_callid)
231{
232 struct ip_conntrack_expect *exp_orig, *exp_reply;
233 int ret = 1;
234 typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre;
235
236 exp_orig = ip_conntrack_expect_alloc(ct);
237 if (exp_orig == NULL)
238 goto out;
239
240 exp_reply = ip_conntrack_expect_alloc(ct);
241 if (exp_reply == NULL)
242 goto out_put_orig;
243
244 /* original direction, PNS->PAC */
245 exp_orig->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
246 exp_orig->tuple.src.u.gre.key = peer_callid;
247 exp_orig->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
248 exp_orig->tuple.dst.u.gre.key = callid;
249 exp_orig->tuple.dst.protonum = IPPROTO_GRE;
250
251 exp_orig->mask.src.ip = htonl(0xffffffff);
252 exp_orig->mask.src.u.all = 0;
253 exp_orig->mask.dst.u.gre.key = htons(0xffff);
254 exp_orig->mask.dst.ip = htonl(0xffffffff);
255 exp_orig->mask.dst.protonum = 0xff;
256
257 exp_orig->master = ct;
258 exp_orig->expectfn = pptp_expectfn;
259 exp_orig->flags = 0;
260
261 /* both expectations are identical apart from tuple */
262 memcpy(exp_reply, exp_orig, sizeof(*exp_reply));
263
264 /* reply direction, PAC->PNS */
265 exp_reply->tuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
266 exp_reply->tuple.src.u.gre.key = callid;
267 exp_reply->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
268 exp_reply->tuple.dst.u.gre.key = peer_callid;
269 exp_reply->tuple.dst.protonum = IPPROTO_GRE;
270
271 ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre);
272 if (ip_nat_pptp_exp_gre)
273 ip_nat_pptp_exp_gre(exp_orig, exp_reply);
274 if (ip_conntrack_expect_related(exp_orig) != 0)
275 goto out_put_both;
276 if (ip_conntrack_expect_related(exp_reply) != 0)
277 goto out_unexpect_orig;
278
279 /* Add GRE keymap entries */
280 if (ip_ct_gre_keymap_add(ct, &exp_orig->tuple, 0) != 0)
281 goto out_unexpect_both;
282 if (ip_ct_gre_keymap_add(ct, &exp_reply->tuple, 1) != 0) {
283 ip_ct_gre_keymap_destroy(ct);
284 goto out_unexpect_both;
285 }
286 ret = 0;
287
288out_put_both:
289 ip_conntrack_expect_put(exp_reply);
290out_put_orig:
291 ip_conntrack_expect_put(exp_orig);
292out:
293 return ret;
294
295out_unexpect_both:
296 ip_conntrack_unexpect_related(exp_reply);
297out_unexpect_orig:
298 ip_conntrack_unexpect_related(exp_orig);
299 goto out_put_both;
300}
301
302static inline int
303pptp_inbound_pkt(struct sk_buff **pskb,
304 struct PptpControlHeader *ctlh,
305 union pptp_ctrl_union *pptpReq,
306 unsigned int reqlen,
307 struct ip_conntrack *ct,
308 enum ip_conntrack_info ctinfo)
309{
310 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
311 u_int16_t msg;
312 __be16 cid = 0, pcid = 0;
313 typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound;
314
315 msg = ntohs(ctlh->messageType);
316 DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
317
318 switch (msg) {
319 case PPTP_START_SESSION_REPLY:
320 /* server confirms new control session */
321 if (info->sstate < PPTP_SESSION_REQUESTED)
322 goto invalid;
323 if (pptpReq->srep.resultCode == PPTP_START_OK)
324 info->sstate = PPTP_SESSION_CONFIRMED;
325 else
326 info->sstate = PPTP_SESSION_ERROR;
327 break;
328
329 case PPTP_STOP_SESSION_REPLY:
330 /* server confirms end of control session */
331 if (info->sstate > PPTP_SESSION_STOPREQ)
332 goto invalid;
333 if (pptpReq->strep.resultCode == PPTP_STOP_OK)
334 info->sstate = PPTP_SESSION_NONE;
335 else
336 info->sstate = PPTP_SESSION_ERROR;
337 break;
338
339 case PPTP_OUT_CALL_REPLY:
340 /* server accepted call, we now expect GRE frames */
341 if (info->sstate != PPTP_SESSION_CONFIRMED)
342 goto invalid;
343 if (info->cstate != PPTP_CALL_OUT_REQ &&
344 info->cstate != PPTP_CALL_OUT_CONF)
345 goto invalid;
346
347 cid = pptpReq->ocack.callID;
348 pcid = pptpReq->ocack.peersCallID;
349 if (info->pns_call_id != pcid)
350 goto invalid;
351 DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
352 ntohs(cid), ntohs(pcid));
353
354 if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
355 info->cstate = PPTP_CALL_OUT_CONF;
356 info->pac_call_id = cid;
357 exp_gre(ct, cid, pcid);
358 } else
359 info->cstate = PPTP_CALL_NONE;
360 break;
361
362 case PPTP_IN_CALL_REQUEST:
363 /* server tells us about incoming call request */
364 if (info->sstate != PPTP_SESSION_CONFIRMED)
365 goto invalid;
366
367 cid = pptpReq->icreq.callID;
368 DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
369 info->cstate = PPTP_CALL_IN_REQ;
370 info->pac_call_id = cid;
371 break;
372
373 case PPTP_IN_CALL_CONNECT:
374 /* server tells us about incoming call established */
375 if (info->sstate != PPTP_SESSION_CONFIRMED)
376 goto invalid;
377 if (info->cstate != PPTP_CALL_IN_REP &&
378 info->cstate != PPTP_CALL_IN_CONF)
379 goto invalid;
380
381 pcid = pptpReq->iccon.peersCallID;
382 cid = info->pac_call_id;
383
384 if (info->pns_call_id != pcid)
385 goto invalid;
386
387 DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
388 info->cstate = PPTP_CALL_IN_CONF;
389
390 /* we expect a GRE connection from PAC to PNS */
391 exp_gre(ct, cid, pcid);
392 break;
393
394 case PPTP_CALL_DISCONNECT_NOTIFY:
395 /* server confirms disconnect */
396 cid = pptpReq->disc.callID;
397 DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
398 info->cstate = PPTP_CALL_NONE;
399
400 /* untrack this call id, unexpect GRE packets */
401 pptp_destroy_siblings(ct);
402 break;
403
404 case PPTP_WAN_ERROR_NOTIFY:
405 case PPTP_ECHO_REQUEST:
406 case PPTP_ECHO_REPLY:
407 /* I don't have to explain these ;) */
408 break;
409 default:
410 goto invalid;
411 }
412
413 ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound);
414 if (ip_nat_pptp_inbound)
415 return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
416 return NF_ACCEPT;
417
418invalid:
419 DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
420 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
421 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
422 msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
423 ntohs(info->pns_call_id), ntohs(info->pac_call_id));
424 return NF_ACCEPT;
425}
426
427static inline int
428pptp_outbound_pkt(struct sk_buff **pskb,
429 struct PptpControlHeader *ctlh,
430 union pptp_ctrl_union *pptpReq,
431 unsigned int reqlen,
432 struct ip_conntrack *ct,
433 enum ip_conntrack_info ctinfo)
434{
435 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
436 u_int16_t msg;
437 __be16 cid = 0, pcid = 0;
438 typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound;
439
440 msg = ntohs(ctlh->messageType);
441 DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
442
443 switch (msg) {
444 case PPTP_START_SESSION_REQUEST:
445 /* client requests for new control session */
446 if (info->sstate != PPTP_SESSION_NONE)
447 goto invalid;
448 info->sstate = PPTP_SESSION_REQUESTED;
449 break;
450 case PPTP_STOP_SESSION_REQUEST:
451 /* client requests end of control session */
452 info->sstate = PPTP_SESSION_STOPREQ;
453 break;
454
455 case PPTP_OUT_CALL_REQUEST:
456 /* client initiating connection to server */
457 if (info->sstate != PPTP_SESSION_CONFIRMED)
458 goto invalid;
459 info->cstate = PPTP_CALL_OUT_REQ;
460 /* track PNS call id */
461 cid = pptpReq->ocreq.callID;
462 DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
463 info->pns_call_id = cid;
464 break;
465 case PPTP_IN_CALL_REPLY:
466 /* client answers incoming call */
467 if (info->cstate != PPTP_CALL_IN_REQ &&
468 info->cstate != PPTP_CALL_IN_REP)
469 goto invalid;
470
471 cid = pptpReq->icack.callID;
472 pcid = pptpReq->icack.peersCallID;
473 if (info->pac_call_id != pcid)
474 goto invalid;
475 DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
476 ntohs(cid), ntohs(pcid));
477
478 if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
479 /* part two of the three-way handshake */
480 info->cstate = PPTP_CALL_IN_REP;
481 info->pns_call_id = cid;
482 } else
483 info->cstate = PPTP_CALL_NONE;
484 break;
485
486 case PPTP_CALL_CLEAR_REQUEST:
487 /* client requests hangup of call */
488 if (info->sstate != PPTP_SESSION_CONFIRMED)
489 goto invalid;
490 /* FUTURE: iterate over all calls and check if
491 * call ID is valid. We don't do this without newnat,
492 * because we only know about last call */
493 info->cstate = PPTP_CALL_CLEAR_REQ;
494 break;
495 case PPTP_SET_LINK_INFO:
496 case PPTP_ECHO_REQUEST:
497 case PPTP_ECHO_REPLY:
498 /* I don't have to explain these ;) */
499 break;
500 default:
501 goto invalid;
502 }
503
504 ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound);
505 if (ip_nat_pptp_outbound)
506 return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
507 return NF_ACCEPT;
508
509invalid:
510 DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
511 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
512 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
513 msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
514 ntohs(info->pns_call_id), ntohs(info->pac_call_id));
515 return NF_ACCEPT;
516}
517
518static const unsigned int pptp_msg_size[] = {
519 [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest),
520 [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply),
521 [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest),
522 [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply),
523 [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest),
524 [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply),
525 [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest),
526 [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply),
527 [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected),
528 [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest),
529 [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),
530 [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify),
531 [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo),
532};
533
534/* track caller id inside control connection, call expect_related */
535static int
536conntrack_pptp_help(struct sk_buff **pskb,
537 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
538
539{
540 int dir = CTINFO2DIR(ctinfo);
541 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
542 struct tcphdr _tcph, *tcph;
543 struct pptp_pkt_hdr _pptph, *pptph;
544 struct PptpControlHeader _ctlh, *ctlh;
545 union pptp_ctrl_union _pptpReq, *pptpReq;
546 unsigned int tcplen = (*pskb)->len - ip_hdrlen(*pskb);
547 unsigned int datalen, reqlen, nexthdr_off;
548 int oldsstate, oldcstate;
549 int ret;
550 u_int16_t msg;
551
552 /* don't do any tracking before tcp handshake complete */
553 if (ctinfo != IP_CT_ESTABLISHED
554 && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
555 DEBUGP("ctinfo = %u, skipping\n", ctinfo);
556 return NF_ACCEPT;
557 }
558
559 nexthdr_off = ip_hdrlen(*pskb);
560 tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
561 BUG_ON(!tcph);
562 nexthdr_off += tcph->doff * 4;
563 datalen = tcplen - tcph->doff * 4;
564
565 pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
566 if (!pptph) {
567 DEBUGP("no full PPTP header, can't track\n");
568 return NF_ACCEPT;
569 }
570 nexthdr_off += sizeof(_pptph);
571 datalen -= sizeof(_pptph);
572
573 /* if it's not a control message we can't do anything with it */
574 if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
575 ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
576 DEBUGP("not a control packet\n");
577 return NF_ACCEPT;
578 }
579
580 ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
581 if (!ctlh)
582 return NF_ACCEPT;
583 nexthdr_off += sizeof(_ctlh);
584 datalen -= sizeof(_ctlh);
585
586 reqlen = datalen;
587 msg = ntohs(ctlh->messageType);
588 if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
589 return NF_ACCEPT;
590 if (reqlen > sizeof(*pptpReq))
591 reqlen = sizeof(*pptpReq);
592
593 pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
594 if (!pptpReq)
595 return NF_ACCEPT;
596
597 oldsstate = info->sstate;
598 oldcstate = info->cstate;
599
600 spin_lock_bh(&ip_pptp_lock);
601
602 /* FIXME: We just blindly assume that the control connection is always
603 * established from PNS->PAC. However, RFC makes no guarantee */
604 if (dir == IP_CT_DIR_ORIGINAL)
605 /* client -> server (PNS -> PAC) */
606 ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
607 ctinfo);
608 else
609 /* server -> client (PAC -> PNS) */
610 ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
611 ctinfo);
612 DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
613 oldsstate, info->sstate, oldcstate, info->cstate);
614 spin_unlock_bh(&ip_pptp_lock);
615
616 return ret;
617}
618
619/* control protocol helper */
620static struct ip_conntrack_helper pptp = {
621 .list = { NULL, NULL },
622 .name = "pptp",
623 .me = THIS_MODULE,
624 .max_expected = 2,
625 .timeout = 5 * 60,
626 .tuple = { .src = { .ip = 0,
627 .u = { .tcp = { .port =
628 __constant_htons(PPTP_CONTROL_PORT) } }
629 },
630 .dst = { .ip = 0,
631 .u = { .all = 0 },
632 .protonum = IPPROTO_TCP
633 }
634 },
635 .mask = { .src = { .ip = 0,
636 .u = { .tcp = { .port = __constant_htons(0xffff) } }
637 },
638 .dst = { .ip = 0,
639 .u = { .all = 0 },
640 .protonum = 0xff
641 }
642 },
643 .help = conntrack_pptp_help,
644 .destroy = pptp_destroy_siblings,
645};
646
647extern void ip_ct_proto_gre_fini(void);
648extern int __init ip_ct_proto_gre_init(void);
649
650/* ip_conntrack_pptp initialization */
651static int __init ip_conntrack_helper_pptp_init(void)
652{
653 int retcode;
654
655 retcode = ip_ct_proto_gre_init();
656 if (retcode < 0)
657 return retcode;
658
659 DEBUGP(" registering helper\n");
660 if ((retcode = ip_conntrack_helper_register(&pptp))) {
661 printk(KERN_ERR "Unable to register conntrack application "
662 "helper for pptp: %d\n", retcode);
663 ip_ct_proto_gre_fini();
664 return retcode;
665 }
666
667 printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
668 return 0;
669}
670
671static void __exit ip_conntrack_helper_pptp_fini(void)
672{
673 ip_conntrack_helper_unregister(&pptp);
674 ip_ct_proto_gre_fini();
675 printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
676}
677
678module_init(ip_conntrack_helper_pptp_init);
679module_exit(ip_conntrack_helper_pptp_fini);
680
681EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
682EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
683EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);
684EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
deleted file mode 100644
index ee99abe482e3..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ /dev/null
@@ -1,314 +0,0 @@
1/* IRC extension for IP connection tracking, Version 1.21
2 * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
3 * based on RR's ip_conntrack_ftp.c
4 *
5 * ip_conntrack_irc.c,v 1.21 2002/02/05 14:49:26 laforge Exp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 **
12 * Module load syntax:
13 * insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS>
14 * max_dcc_channels=n dcc_timeout=secs
15 *
16 * please give the ports of all IRC servers You wish to connect to.
17 * If You don't specify ports, the default will be port 6667.
18 * With max_dcc_channels you can define the maximum number of not
19 * yet answered DCC channels per IRC session (default 8).
20 * With dcc_timeout you can specify how long the system waits for
21 * an expected DCC channel (default 300 seconds).
22 *
23 */
24
25#include <linux/module.h>
26#include <linux/netfilter.h>
27#include <linux/ip.h>
28#include <net/checksum.h>
29#include <net/tcp.h>
30
31#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
32#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
33#include <linux/moduleparam.h>
34
35#define MAX_PORTS 8
36static unsigned short ports[MAX_PORTS];
37static int ports_c;
38static unsigned int max_dcc_channels = 8;
39static unsigned int dcc_timeout = 300;
40/* This is slow, but it's simple. --RR */
41static char *irc_buffer;
42static DEFINE_SPINLOCK(irc_buffer_lock);
43
44unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
45 enum ip_conntrack_info ctinfo,
46 unsigned int matchoff,
47 unsigned int matchlen,
48 struct ip_conntrack_expect *exp);
49EXPORT_SYMBOL_GPL(ip_nat_irc_hook);
50
51MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
52MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
53MODULE_LICENSE("GPL");
54module_param_array(ports, ushort, &ports_c, 0400);
55MODULE_PARM_DESC(ports, "port numbers of IRC servers");
56module_param(max_dcc_channels, uint, 0400);
57MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
58module_param(dcc_timeout, uint, 0400);
59MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
60
61static const char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
62#define MINMATCHLEN 5
63
64#if 0
65#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
66 __FILE__, __FUNCTION__ , ## args)
67#else
68#define DEBUGP(format, args...)
69#endif
70
71static int parse_dcc(char *data, char *data_end, u_int32_t *ip,
72 u_int16_t *port, char **ad_beg_p, char **ad_end_p)
73/* tries to get the ip_addr and port out of a dcc command
74 return value: -1 on failure, 0 on success
75 data pointer to first byte of DCC command data
76 data_end pointer to last byte of dcc command data
77 ip returns parsed ip of dcc command
78 port returns parsed port of dcc command
79 ad_beg_p returns pointer to first byte of addr data
80 ad_end_p returns pointer to last byte of addr data */
81{
82
83 /* at least 12: "AAAAAAAA P\1\n" */
84 while (*data++ != ' ')
85 if (data > data_end - 12)
86 return -1;
87
88 *ad_beg_p = data;
89 *ip = simple_strtoul(data, &data, 10);
90
91 /* skip blanks between ip and port */
92 while (*data == ' ') {
93 if (data >= data_end)
94 return -1;
95 data++;
96 }
97
98 *port = simple_strtoul(data, &data, 10);
99 *ad_end_p = data;
100
101 return 0;
102}
103
104static int help(struct sk_buff **pskb,
105 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
106{
107 unsigned int dataoff;
108 struct tcphdr _tcph, *th;
109 char *data, *data_limit, *ib_ptr;
110 int dir = CTINFO2DIR(ctinfo);
111 struct ip_conntrack_expect *exp;
112 u32 seq;
113 u_int32_t dcc_ip;
114 u_int16_t dcc_port;
115 int i, ret = NF_ACCEPT;
116 char *addr_beg_p, *addr_end_p;
117 typeof(ip_nat_irc_hook) ip_nat_irc;
118
119 DEBUGP("entered\n");
120
121 /* If packet is coming from IRC server */
122 if (dir == IP_CT_DIR_REPLY)
123 return NF_ACCEPT;
124
125 /* Until there's been traffic both ways, don't look in packets. */
126 if (ctinfo != IP_CT_ESTABLISHED
127 && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
128 DEBUGP("Conntrackinfo = %u\n", ctinfo);
129 return NF_ACCEPT;
130 }
131
132 /* Not a full tcp header? */
133 th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
134 sizeof(_tcph), &_tcph);
135 if (th == NULL)
136 return NF_ACCEPT;
137
138 /* No data? */
139 dataoff = ip_hdrlen(*pskb) + th->doff * 4;
140 if (dataoff >= (*pskb)->len)
141 return NF_ACCEPT;
142
143 spin_lock_bh(&irc_buffer_lock);
144 ib_ptr = skb_header_pointer(*pskb, dataoff,
145 (*pskb)->len - dataoff, irc_buffer);
146 BUG_ON(ib_ptr == NULL);
147
148 data = ib_ptr;
149 data_limit = ib_ptr + (*pskb)->len - dataoff;
150
151 /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
152 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
153 while (data < (data_limit - (19 + MINMATCHLEN))) {
154 if (memcmp(data, "\1DCC ", 5)) {
155 data++;
156 continue;
157 }
158
159 data += 5;
160 /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
161
162 DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
163 NIPQUAD(iph->saddr), ntohs(th->source),
164 NIPQUAD(iph->daddr), ntohs(th->dest));
165
166 for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
167 if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
168 /* no match */
169 continue;
170 }
171
172 DEBUGP("DCC %s detected\n", dccprotos[i]);
173 data += strlen(dccprotos[i]);
174 /* we have at least
175 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
176 * data left (== 14/13 bytes) */
177 if (parse_dcc((char *)data, data_limit, &dcc_ip,
178 &dcc_port, &addr_beg_p, &addr_end_p)) {
179 /* unable to parse */
180 DEBUGP("unable to parse dcc command\n");
181 continue;
182 }
183 DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
184 HIPQUAD(dcc_ip), dcc_port);
185
186 /* dcc_ip can be the internal OR external (NAT'ed) IP
187 * Tiago Sousa <mirage@kaotik.org> */
188 if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip)
189 && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != htonl(dcc_ip)) {
190 if (net_ratelimit())
191 printk(KERN_WARNING
192 "Forged DCC command from "
193 "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
194 NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
195 HIPQUAD(dcc_ip), dcc_port);
196
197 continue;
198 }
199
200 exp = ip_conntrack_expect_alloc(ct);
201 if (exp == NULL) {
202 ret = NF_DROP;
203 goto out;
204 }
205
206 /* save position of address in dcc string,
207 * necessary for NAT */
208 DEBUGP("tcph->seq = %u\n", th->seq);
209 seq = ntohl(th->seq) + (addr_beg_p - ib_ptr);
210
211 /* We refer to the reverse direction ("!dir")
212 * tuples here, because we're expecting
213 * something in the other * direction.
214 * Doesn't matter unless NAT is happening. */
215 exp->tuple = ((struct ip_conntrack_tuple)
216 { { 0, { 0 } },
217 { ct->tuplehash[!dir].tuple.dst.ip,
218 { .tcp = { htons(dcc_port) } },
219 IPPROTO_TCP }});
220 exp->mask = ((struct ip_conntrack_tuple)
221 { { 0, { 0 } },
222 { htonl(0xFFFFFFFF),
223 { .tcp = { htons(0xFFFF) } }, 0xFF }});
224 exp->expectfn = NULL;
225 exp->flags = 0;
226 ip_nat_irc = rcu_dereference(ip_nat_irc_hook);
227 if (ip_nat_irc)
228 ret = ip_nat_irc(pskb, ctinfo,
229 addr_beg_p - ib_ptr,
230 addr_end_p - addr_beg_p,
231 exp);
232 else if (ip_conntrack_expect_related(exp) != 0)
233 ret = NF_DROP;
234 ip_conntrack_expect_put(exp);
235 goto out;
236 } /* for .. NUM_DCCPROTO */
237 } /* while data < ... */
238
239 out:
240 spin_unlock_bh(&irc_buffer_lock);
241 return ret;
242}
243
244static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
245static char irc_names[MAX_PORTS][sizeof("irc-65535")];
246
247static void ip_conntrack_irc_fini(void);
248
249static int __init ip_conntrack_irc_init(void)
250{
251 int i, ret;
252 struct ip_conntrack_helper *hlpr;
253 char *tmpname;
254
255 if (max_dcc_channels < 1) {
256 printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n");
257 return -EBUSY;
258 }
259
260 irc_buffer = kmalloc(65536, GFP_KERNEL);
261 if (!irc_buffer)
262 return -ENOMEM;
263
264 /* If no port given, default to standard irc port */
265 if (ports_c == 0)
266 ports[ports_c++] = IRC_PORT;
267
268 for (i = 0; i < ports_c; i++) {
269 hlpr = &irc_helpers[i];
270 hlpr->tuple.src.u.tcp.port = htons(ports[i]);
271 hlpr->tuple.dst.protonum = IPPROTO_TCP;
272 hlpr->mask.src.u.tcp.port = htons(0xFFFF);
273 hlpr->mask.dst.protonum = 0xFF;
274 hlpr->max_expected = max_dcc_channels;
275 hlpr->timeout = dcc_timeout;
276 hlpr->me = THIS_MODULE;
277 hlpr->help = help;
278
279 tmpname = &irc_names[i][0];
280 if (ports[i] == IRC_PORT)
281 sprintf(tmpname, "irc");
282 else
283 sprintf(tmpname, "irc-%d", i);
284 hlpr->name = tmpname;
285
286 DEBUGP("port #%d: %d\n", i, ports[i]);
287
288 ret = ip_conntrack_helper_register(hlpr);
289
290 if (ret) {
291 printk("ip_conntrack_irc: ERROR registering port %d\n",
292 ports[i]);
293 ip_conntrack_irc_fini();
294 return -EBUSY;
295 }
296 }
297 return 0;
298}
299
300/* This function is intentionally _NOT_ defined as __exit, because
301 * it is needed by the init function */
302static void ip_conntrack_irc_fini(void)
303{
304 int i;
305 for (i = 0; i < ports_c; i++) {
306 DEBUGP("unregistering port %d\n",
307 ports[i]);
308 ip_conntrack_helper_unregister(&irc_helpers[i]);
309 }
310 kfree(irc_buffer);
311}
312
313module_init(ip_conntrack_irc_init);
314module_exit(ip_conntrack_irc_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
deleted file mode 100644
index df07c5f1d874..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ /dev/null
@@ -1,143 +0,0 @@
1/*
2 * NetBIOS name service broadcast connection tracking helper
3 *
4 * (c) 2005 Patrick McHardy <kaber@trash.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11/*
12 * This helper tracks locally originating NetBIOS name service
13 * requests by issuing permanent expectations (valid until
14 * timing out) matching all reply connections from the
15 * destination network. The only NetBIOS specific thing is
16 * actually the port number.
17 */
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/skbuff.h>
22#include <linux/netdevice.h>
23#include <linux/inetdevice.h>
24#include <linux/if_addr.h>
25#include <linux/in.h>
26#include <linux/ip.h>
27#include <net/route.h>
28
29#include <linux/netfilter.h>
30#include <linux/netfilter_ipv4.h>
31#include <linux/netfilter_ipv4/ip_conntrack.h>
32#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
33
34#define NMBD_PORT 137
35
36MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
37MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
38MODULE_LICENSE("GPL");
39
40static unsigned int timeout = 3;
41module_param(timeout, uint, 0400);
42MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
43
44static int help(struct sk_buff **pskb,
45 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
46{
47 struct ip_conntrack_expect *exp;
48 struct iphdr *iph = ip_hdr(*pskb);
49 struct rtable *rt = (struct rtable *)(*pskb)->dst;
50 struct in_device *in_dev;
51 __be32 mask = 0;
52
53 /* we're only interested in locally generated packets */
54 if ((*pskb)->sk == NULL)
55 goto out;
56 if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
57 goto out;
58 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
59 goto out;
60
61 rcu_read_lock();
62 in_dev = __in_dev_get_rcu(rt->u.dst.dev);
63 if (in_dev != NULL) {
64 for_primary_ifa(in_dev) {
65 if (ifa->ifa_broadcast == iph->daddr) {
66 mask = ifa->ifa_mask;
67 break;
68 }
69 } endfor_ifa(in_dev);
70 }
71 rcu_read_unlock();
72
73 if (mask == 0)
74 goto out;
75
76 exp = ip_conntrack_expect_alloc(ct);
77 if (exp == NULL)
78 goto out;
79
80 exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
81 exp->tuple.src.u.udp.port = htons(NMBD_PORT);
82
83 exp->mask.src.ip = mask;
84 exp->mask.src.u.udp.port = htons(0xFFFF);
85 exp->mask.dst.ip = htonl(0xFFFFFFFF);
86 exp->mask.dst.u.udp.port = htons(0xFFFF);
87 exp->mask.dst.protonum = 0xFF;
88
89 exp->expectfn = NULL;
90 exp->flags = IP_CT_EXPECT_PERMANENT;
91
92 ip_conntrack_expect_related(exp);
93 ip_conntrack_expect_put(exp);
94
95 ip_ct_refresh(ct, *pskb, timeout * HZ);
96out:
97 return NF_ACCEPT;
98}
99
100static struct ip_conntrack_helper helper = {
101 .name = "netbios-ns",
102 .tuple = {
103 .src = {
104 .u = {
105 .udp = {
106 .port = __constant_htons(NMBD_PORT),
107 }
108 }
109 },
110 .dst = {
111 .protonum = IPPROTO_UDP,
112 },
113 },
114 .mask = {
115 .src = {
116 .u = {
117 .udp = {
118 .port = __constant_htons(0xFFFF),
119 }
120 }
121 },
122 .dst = {
123 .protonum = 0xFF,
124 },
125 },
126 .max_expected = 1,
127 .me = THIS_MODULE,
128 .help = help,
129};
130
131static int __init ip_conntrack_netbios_ns_init(void)
132{
133 helper.timeout = timeout;
134 return ip_conntrack_helper_register(&helper);
135}
136
137static void __exit ip_conntrack_netbios_ns_fini(void)
138{
139 ip_conntrack_helper_unregister(&helper);
140}
141
142module_init(ip_conntrack_netbios_ns_init);
143module_exit(ip_conntrack_netbios_ns_fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
deleted file mode 100644
index 9228b76ccd9a..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ /dev/null
@@ -1,1577 +0,0 @@
1/* Connection tracking via netlink socket. Allows for user space
2 * protocol helpers and general trouble making from userspace.
3 *
4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7 * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8 *
9 * I've reworked this stuff to use attributes instead of conntrack
10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
11 *
12 * Initial connection tracking via netlink development funded and
13 * generally made possible by Network Robots, Inc. (www.networkrobots.com)
14 *
15 * Further development of this code funded by Astaro AG (http://www.astaro.com)
16 *
17 * This software may be used and distributed according to the terms
18 * of the GNU General Public License, incorporated herein by reference.
19 */
20
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/types.h>
25#include <linux/timer.h>
26#include <linux/skbuff.h>
27#include <linux/errno.h>
28#include <linux/netlink.h>
29#include <linux/spinlock.h>
30#include <linux/interrupt.h>
31#include <linux/notifier.h>
32
33#include <linux/netfilter.h>
34#include <linux/netfilter_ipv4/ip_conntrack.h>
35#include <linux/netfilter_ipv4/ip_conntrack_core.h>
36#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
37#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
38#include <linux/netfilter_ipv4/ip_nat_protocol.h>
39
40#include <linux/netfilter/nfnetlink.h>
41#include <linux/netfilter/nfnetlink_conntrack.h>
42
43MODULE_LICENSE("GPL");
44
45static char __initdata version[] = "0.90";
46
47static inline int
48ctnetlink_dump_tuples_proto(struct sk_buff *skb,
49 const struct ip_conntrack_tuple *tuple,
50 struct ip_conntrack_protocol *proto)
51{
52 int ret = 0;
53 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
54
55 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
56
57 if (likely(proto->tuple_to_nfattr))
58 ret = proto->tuple_to_nfattr(skb, tuple);
59
60 NFA_NEST_END(skb, nest_parms);
61
62 return ret;
63
64nfattr_failure:
65 return -1;
66}
67
68static inline int
69ctnetlink_dump_tuples_ip(struct sk_buff *skb,
70 const struct ip_conntrack_tuple *tuple)
71{
72 struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
73
74 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(__be32), &tuple->src.ip);
75 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(__be32), &tuple->dst.ip);
76
77 NFA_NEST_END(skb, nest_parms);
78
79 return 0;
80
81nfattr_failure:
82 return -1;
83}
84
85static inline int
86ctnetlink_dump_tuples(struct sk_buff *skb,
87 const struct ip_conntrack_tuple *tuple)
88{
89 int ret;
90 struct ip_conntrack_protocol *proto;
91
92 ret = ctnetlink_dump_tuples_ip(skb, tuple);
93 if (unlikely(ret < 0))
94 return ret;
95
96 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
97 ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
98 ip_conntrack_proto_put(proto);
99
100 return ret;
101}
102
103static inline int
104ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
105{
106 __be32 status = htonl((u_int32_t) ct->status);
107 NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
108 return 0;
109
110nfattr_failure:
111 return -1;
112}
113
114static inline int
115ctnetlink_dump_timeout(struct sk_buff *skb, const struct ip_conntrack *ct)
116{
117 long timeout_l = ct->timeout.expires - jiffies;
118 __be32 timeout;
119
120 if (timeout_l < 0)
121 timeout = 0;
122 else
123 timeout = htonl(timeout_l / HZ);
124
125 NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
126 return 0;
127
128nfattr_failure:
129 return -1;
130}
131
132static inline int
133ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
134{
135 struct ip_conntrack_protocol *proto = ip_conntrack_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
136
137 struct nfattr *nest_proto;
138 int ret;
139
140 if (!proto->to_nfattr) {
141 ip_conntrack_proto_put(proto);
142 return 0;
143 }
144
145 nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
146
147 ret = proto->to_nfattr(skb, nest_proto, ct);
148
149 ip_conntrack_proto_put(proto);
150
151 NFA_NEST_END(skb, nest_proto);
152
153 return ret;
154
155nfattr_failure:
156 ip_conntrack_proto_put(proto);
157 return -1;
158}
159
160static inline int
161ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
162{
163 struct nfattr *nest_helper;
164
165 if (!ct->helper)
166 return 0;
167
168 nest_helper = NFA_NEST(skb, CTA_HELP);
169 NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name);
170
171 if (ct->helper->to_nfattr)
172 ct->helper->to_nfattr(skb, ct);
173
174 NFA_NEST_END(skb, nest_helper);
175
176 return 0;
177
178nfattr_failure:
179 return -1;
180}
181
182#ifdef CONFIG_IP_NF_CT_ACCT
183static inline int
184ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct,
185 enum ip_conntrack_dir dir)
186{
187 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
188 struct nfattr *nest_count = NFA_NEST(skb, type);
189 __be32 tmp;
190
191 tmp = htonl(ct->counters[dir].packets);
192 NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(__be32), &tmp);
193
194 tmp = htonl(ct->counters[dir].bytes);
195 NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(__be32), &tmp);
196
197 NFA_NEST_END(skb, nest_count);
198
199 return 0;
200
201nfattr_failure:
202 return -1;
203}
204#else
205#define ctnetlink_dump_counters(a, b, c) (0)
206#endif
207
208#ifdef CONFIG_IP_NF_CONNTRACK_MARK
209static inline int
210ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
211{
212 __be32 mark = htonl(ct->mark);
213
214 NFA_PUT(skb, CTA_MARK, sizeof(__be32), &mark);
215 return 0;
216
217nfattr_failure:
218 return -1;
219}
220#else
221#define ctnetlink_dump_mark(a, b) (0)
222#endif
223
224static inline int
225ctnetlink_dump_id(struct sk_buff *skb, const struct ip_conntrack *ct)
226{
227 __be32 id = htonl(ct->id);
228 NFA_PUT(skb, CTA_ID, sizeof(__be32), &id);
229 return 0;
230
231nfattr_failure:
232 return -1;
233}
234
235static inline int
236ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct)
237{
238 __be32 use = htonl(atomic_read(&ct->ct_general.use));
239
240 NFA_PUT(skb, CTA_USE, sizeof(__be32), &use);
241 return 0;
242
243nfattr_failure:
244 return -1;
245}
246
247#define tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
248
249static int
250ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
251 int event, int nowait,
252 const struct ip_conntrack *ct)
253{
254 struct nlmsghdr *nlh;
255 struct nfgenmsg *nfmsg;
256 struct nfattr *nest_parms;
257 unsigned char *b;
258
259 b = skb->tail;
260
261 event |= NFNL_SUBSYS_CTNETLINK << 8;
262 nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
263 nfmsg = NLMSG_DATA(nlh);
264
265 nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
266 nfmsg->nfgen_family = AF_INET;
267 nfmsg->version = NFNETLINK_V0;
268 nfmsg->res_id = 0;
269
270 nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
271 if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
272 goto nfattr_failure;
273 NFA_NEST_END(skb, nest_parms);
274
275 nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
276 if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
277 goto nfattr_failure;
278 NFA_NEST_END(skb, nest_parms);
279
280 if (ctnetlink_dump_status(skb, ct) < 0 ||
281 ctnetlink_dump_timeout(skb, ct) < 0 ||
282 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
283 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
284 ctnetlink_dump_protoinfo(skb, ct) < 0 ||
285 ctnetlink_dump_helpinfo(skb, ct) < 0 ||
286 ctnetlink_dump_mark(skb, ct) < 0 ||
287 ctnetlink_dump_id(skb, ct) < 0 ||
288 ctnetlink_dump_use(skb, ct) < 0)
289 goto nfattr_failure;
290
291 nlh->nlmsg_len = skb->tail - b;
292 return skb->len;
293
294nlmsg_failure:
295nfattr_failure:
296 skb_trim(skb, b - skb->data);
297 return -1;
298}
299
300#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
301static int ctnetlink_conntrack_event(struct notifier_block *this,
302 unsigned long events, void *ptr)
303{
304 struct nlmsghdr *nlh;
305 struct nfgenmsg *nfmsg;
306 struct nfattr *nest_parms;
307 struct ip_conntrack *ct = (struct ip_conntrack *)ptr;
308 struct sk_buff *skb;
309 unsigned int type;
310 unsigned char *b;
311 unsigned int flags = 0, group;
312
313 /* ignore our fake conntrack entry */
314 if (ct == &ip_conntrack_untracked)
315 return NOTIFY_DONE;
316
317 if (events & IPCT_DESTROY) {
318 type = IPCTNL_MSG_CT_DELETE;
319 group = NFNLGRP_CONNTRACK_DESTROY;
320 } else if (events & (IPCT_NEW | IPCT_RELATED)) {
321 type = IPCTNL_MSG_CT_NEW;
322 flags = NLM_F_CREATE|NLM_F_EXCL;
323 group = NFNLGRP_CONNTRACK_NEW;
324 } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
325 type = IPCTNL_MSG_CT_NEW;
326 group = NFNLGRP_CONNTRACK_UPDATE;
327 } else
328 return NOTIFY_DONE;
329
330 if (!nfnetlink_has_listeners(group))
331 return NOTIFY_DONE;
332
333 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
334 if (!skb)
335 return NOTIFY_DONE;
336
337 b = skb->tail;
338
339 type |= NFNL_SUBSYS_CTNETLINK << 8;
340 nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
341 nfmsg = NLMSG_DATA(nlh);
342
343 nlh->nlmsg_flags = flags;
344 nfmsg->nfgen_family = AF_INET;
345 nfmsg->version = NFNETLINK_V0;
346 nfmsg->res_id = 0;
347
348 nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
349 if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
350 goto nfattr_failure;
351 NFA_NEST_END(skb, nest_parms);
352
353 nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
354 if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
355 goto nfattr_failure;
356 NFA_NEST_END(skb, nest_parms);
357
358 if (events & IPCT_DESTROY) {
359 if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
360 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
361 goto nfattr_failure;
362 } else {
363 if (ctnetlink_dump_status(skb, ct) < 0)
364 goto nfattr_failure;
365
366 if (ctnetlink_dump_timeout(skb, ct) < 0)
367 goto nfattr_failure;
368
369 if (events & IPCT_PROTOINFO
370 && ctnetlink_dump_protoinfo(skb, ct) < 0)
371 goto nfattr_failure;
372
373 if ((events & IPCT_HELPER || ct->helper)
374 && ctnetlink_dump_helpinfo(skb, ct) < 0)
375 goto nfattr_failure;
376
377#ifdef CONFIG_IP_NF_CONNTRACK_MARK
378 if ((events & IPCT_MARK || ct->mark)
379 && ctnetlink_dump_mark(skb, ct) < 0)
380 goto nfattr_failure;
381#endif
382
383 if (events & IPCT_COUNTER_FILLING &&
384 (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
385 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
386 goto nfattr_failure;
387 }
388
389 nlh->nlmsg_len = skb->tail - b;
390 nfnetlink_send(skb, 0, group, 0);
391 return NOTIFY_DONE;
392
393nlmsg_failure:
394nfattr_failure:
395 kfree_skb(skb);
396 return NOTIFY_DONE;
397}
398#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
399
400static int ctnetlink_done(struct netlink_callback *cb)
401{
402 if (cb->args[1])
403 ip_conntrack_put((struct ip_conntrack *)cb->args[1]);
404 return 0;
405}
406
407static int
408ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
409{
410 struct ip_conntrack *ct, *last;
411 struct ip_conntrack_tuple_hash *h;
412 struct list_head *i;
413
414 read_lock_bh(&ip_conntrack_lock);
415 last = (struct ip_conntrack *)cb->args[1];
416 for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
417restart:
418 list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
419 h = (struct ip_conntrack_tuple_hash *) i;
420 if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
421 continue;
422 ct = tuplehash_to_ctrack(h);
423 if (cb->args[1]) {
424 if (ct != last)
425 continue;
426 cb->args[1] = 0;
427 }
428 if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
429 cb->nlh->nlmsg_seq,
430 IPCTNL_MSG_CT_NEW,
431 1, ct) < 0) {
432 nf_conntrack_get(&ct->ct_general);
433 cb->args[1] = (unsigned long)ct;
434 goto out;
435 }
436#ifdef CONFIG_NF_CT_ACCT
437 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
438 IPCTNL_MSG_CT_GET_CTRZERO)
439 memset(&ct->counters, 0, sizeof(ct->counters));
440#endif
441 }
442 if (cb->args[1]) {
443 cb->args[1] = 0;
444 goto restart;
445 }
446 }
447out:
448 read_unlock_bh(&ip_conntrack_lock);
449 if (last)
450 ip_conntrack_put(last);
451
452 return skb->len;
453}
454
455static const size_t cta_min_ip[CTA_IP_MAX] = {
456 [CTA_IP_V4_SRC-1] = sizeof(__be32),
457 [CTA_IP_V4_DST-1] = sizeof(__be32),
458};
459
460static inline int
461ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
462{
463 struct nfattr *tb[CTA_IP_MAX];
464
465 nfattr_parse_nested(tb, CTA_IP_MAX, attr);
466
467 if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
468 return -EINVAL;
469
470 if (!tb[CTA_IP_V4_SRC-1])
471 return -EINVAL;
472 tuple->src.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
473
474 if (!tb[CTA_IP_V4_DST-1])
475 return -EINVAL;
476 tuple->dst.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
477
478 return 0;
479}
480
481static const size_t cta_min_proto[CTA_PROTO_MAX] = {
482 [CTA_PROTO_NUM-1] = sizeof(u_int8_t),
483 [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t),
484 [CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t),
485 [CTA_PROTO_ICMP_TYPE-1] = sizeof(u_int8_t),
486 [CTA_PROTO_ICMP_CODE-1] = sizeof(u_int8_t),
487 [CTA_PROTO_ICMP_ID-1] = sizeof(u_int16_t),
488};
489
490static inline int
491ctnetlink_parse_tuple_proto(struct nfattr *attr,
492 struct ip_conntrack_tuple *tuple)
493{
494 struct nfattr *tb[CTA_PROTO_MAX];
495 struct ip_conntrack_protocol *proto;
496 int ret = 0;
497
498 nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
499
500 if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
501 return -EINVAL;
502
503 if (!tb[CTA_PROTO_NUM-1])
504 return -EINVAL;
505 tuple->dst.protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
506
507 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
508
509 if (likely(proto->nfattr_to_tuple))
510 ret = proto->nfattr_to_tuple(tb, tuple);
511
512 ip_conntrack_proto_put(proto);
513
514 return ret;
515}
516
517static inline int
518ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple,
519 enum ctattr_tuple type)
520{
521 struct nfattr *tb[CTA_TUPLE_MAX];
522 int err;
523
524 memset(tuple, 0, sizeof(*tuple));
525
526 nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
527
528 if (!tb[CTA_TUPLE_IP-1])
529 return -EINVAL;
530
531 err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP-1], tuple);
532 if (err < 0)
533 return err;
534
535 if (!tb[CTA_TUPLE_PROTO-1])
536 return -EINVAL;
537
538 err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO-1], tuple);
539 if (err < 0)
540 return err;
541
542 /* orig and expect tuples get DIR_ORIGINAL */
543 if (type == CTA_TUPLE_REPLY)
544 tuple->dst.dir = IP_CT_DIR_REPLY;
545 else
546 tuple->dst.dir = IP_CT_DIR_ORIGINAL;
547
548 return 0;
549}
550
551#ifdef CONFIG_IP_NF_NAT_NEEDED
552static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = {
553 [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t),
554 [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t),
555};
556
557static int ctnetlink_parse_nat_proto(struct nfattr *attr,
558 const struct ip_conntrack *ct,
559 struct ip_nat_range *range)
560{
561 struct nfattr *tb[CTA_PROTONAT_MAX];
562 struct ip_nat_protocol *npt;
563
564 nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
565
566 if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
567 return -EINVAL;
568
569 npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
570
571 if (!npt->nfattr_to_range) {
572 ip_nat_proto_put(npt);
573 return 0;
574 }
575
576 /* nfattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
577 if (npt->nfattr_to_range(tb, range) > 0)
578 range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
579
580 ip_nat_proto_put(npt);
581
582 return 0;
583}
584
585static const size_t cta_min_nat[CTA_NAT_MAX] = {
586 [CTA_NAT_MINIP-1] = sizeof(__be32),
587 [CTA_NAT_MAXIP-1] = sizeof(__be32),
588};
589
590static inline int
591ctnetlink_parse_nat(struct nfattr *nat,
592 const struct ip_conntrack *ct, struct ip_nat_range *range)
593{
594 struct nfattr *tb[CTA_NAT_MAX];
595 int err;
596
597 memset(range, 0, sizeof(*range));
598
599 nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
600
601 if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
602 return -EINVAL;
603
604 if (tb[CTA_NAT_MINIP-1])
605 range->min_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
606
607 if (!tb[CTA_NAT_MAXIP-1])
608 range->max_ip = range->min_ip;
609 else
610 range->max_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
611
612 if (range->min_ip)
613 range->flags |= IP_NAT_RANGE_MAP_IPS;
614
615 if (!tb[CTA_NAT_PROTO-1])
616 return 0;
617
618 err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
619 if (err < 0)
620 return err;
621
622 return 0;
623}
624#endif
625
626static inline int
627ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
628{
629 struct nfattr *tb[CTA_HELP_MAX];
630
631 nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
632
633 if (!tb[CTA_HELP_NAME-1])
634 return -EINVAL;
635
636 *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]);
637
638 return 0;
639}
640
641static const size_t cta_min[CTA_MAX] = {
642 [CTA_STATUS-1] = sizeof(__be32),
643 [CTA_TIMEOUT-1] = sizeof(__be32),
644 [CTA_MARK-1] = sizeof(__be32),
645 [CTA_USE-1] = sizeof(__be32),
646 [CTA_ID-1] = sizeof(__be32)
647};
648
649static int
650ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
651 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
652{
653 struct ip_conntrack_tuple_hash *h;
654 struct ip_conntrack_tuple tuple;
655 struct ip_conntrack *ct;
656 int err = 0;
657
658 if (nfattr_bad_size(cda, CTA_MAX, cta_min))
659 return -EINVAL;
660
661 if (cda[CTA_TUPLE_ORIG-1])
662 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG);
663 else if (cda[CTA_TUPLE_REPLY-1])
664 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY);
665 else {
666 /* Flush the whole table */
667 ip_conntrack_flush();
668 return 0;
669 }
670
671 if (err < 0)
672 return err;
673
674 h = ip_conntrack_find_get(&tuple, NULL);
675 if (!h)
676 return -ENOENT;
677
678 ct = tuplehash_to_ctrack(h);
679
680 if (cda[CTA_ID-1]) {
681 u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
682 if (ct->id != id) {
683 ip_conntrack_put(ct);
684 return -ENOENT;
685 }
686 }
687 if (del_timer(&ct->timeout))
688 ct->timeout.function((unsigned long)ct);
689
690 ip_conntrack_put(ct);
691
692 return 0;
693}
694
695static int
696ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
697 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
698{
699 struct ip_conntrack_tuple_hash *h;
700 struct ip_conntrack_tuple tuple;
701 struct ip_conntrack *ct;
702 struct sk_buff *skb2 = NULL;
703 int err = 0;
704
705 if (nlh->nlmsg_flags & NLM_F_DUMP) {
706 struct nfgenmsg *msg = NLMSG_DATA(nlh);
707 u32 rlen;
708
709 if (msg->nfgen_family != AF_INET)
710 return -EAFNOSUPPORT;
711
712#ifndef CONFIG_IP_NF_CT_ACCT
713 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
714 return -ENOTSUPP;
715#endif
716 if ((*errp = netlink_dump_start(ctnl, skb, nlh,
717 ctnetlink_dump_table,
718 ctnetlink_done)) != 0)
719 return -EINVAL;
720
721 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
722 if (rlen > skb->len)
723 rlen = skb->len;
724 skb_pull(skb, rlen);
725 return 0;
726 }
727
728 if (nfattr_bad_size(cda, CTA_MAX, cta_min))
729 return -EINVAL;
730
731 if (cda[CTA_TUPLE_ORIG-1])
732 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG);
733 else if (cda[CTA_TUPLE_REPLY-1])
734 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY);
735 else
736 return -EINVAL;
737
738 if (err < 0)
739 return err;
740
741 h = ip_conntrack_find_get(&tuple, NULL);
742 if (!h)
743 return -ENOENT;
744
745 ct = tuplehash_to_ctrack(h);
746
747 err = -ENOMEM;
748 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
749 if (!skb2) {
750 ip_conntrack_put(ct);
751 return -ENOMEM;
752 }
753
754 err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
755 IPCTNL_MSG_CT_NEW, 1, ct);
756 ip_conntrack_put(ct);
757 if (err <= 0)
758 goto free;
759
760 err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
761 if (err < 0)
762 goto out;
763
764 return 0;
765
766free:
767 kfree_skb(skb2);
768out:
769 return err;
770}
771
772static inline int
773ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
774{
775 unsigned long d;
776 unsigned status = ntohl(*(__be32 *)NFA_DATA(cda[CTA_STATUS-1]));
777 d = ct->status ^ status;
778
779 if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
780 /* unchangeable */
781 return -EINVAL;
782
783 if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
784 /* SEEN_REPLY bit can only be set */
785 return -EINVAL;
786
787
788 if (d & IPS_ASSURED && !(status & IPS_ASSURED))
789 /* ASSURED bit can only be set */
790 return -EINVAL;
791
792 if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
793#ifndef CONFIG_IP_NF_NAT_NEEDED
794 return -EINVAL;
795#else
796 struct ip_nat_range range;
797
798 if (cda[CTA_NAT_DST-1]) {
799 if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
800 &range) < 0)
801 return -EINVAL;
802 if (ip_nat_initialized(ct,
803 HOOK2MANIP(NF_IP_PRE_ROUTING)))
804 return -EEXIST;
805 ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
806 }
807 if (cda[CTA_NAT_SRC-1]) {
808 if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
809 &range) < 0)
810 return -EINVAL;
811 if (ip_nat_initialized(ct,
812 HOOK2MANIP(NF_IP_POST_ROUTING)))
813 return -EEXIST;
814 ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
815 }
816#endif
817 }
818
819 /* Be careful here, modifying NAT bits can screw up things,
820 * so don't let users modify them directly if they don't pass
821 * ip_nat_range. */
822 ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
823 return 0;
824}
825
826
827static inline int
828ctnetlink_change_helper(struct ip_conntrack *ct, struct nfattr *cda[])
829{
830 struct ip_conntrack_helper *helper;
831 char *helpname;
832 int err;
833
834 /* don't change helper of sibling connections */
835 if (ct->master)
836 return -EINVAL;
837
838 err = ctnetlink_parse_help(cda[CTA_HELP-1], &helpname);
839 if (err < 0)
840 return err;
841
842 helper = __ip_conntrack_helper_find_byname(helpname);
843 if (!helper) {
844 if (!strcmp(helpname, ""))
845 helper = NULL;
846 else
847 return -EINVAL;
848 }
849
850 if (ct->helper) {
851 if (!helper) {
852 /* we had a helper before ... */
853 ip_ct_remove_expectations(ct);
854 ct->helper = NULL;
855 } else {
856 /* need to zero data of old helper */
857 memset(&ct->help, 0, sizeof(ct->help));
858 }
859 }
860
861 ct->helper = helper;
862
863 return 0;
864}
865
866static inline int
867ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[])
868{
869 u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
870
871 if (!del_timer(&ct->timeout))
872 return -ETIME;
873
874 ct->timeout.expires = jiffies + timeout * HZ;
875 add_timer(&ct->timeout);
876
877 return 0;
878}
879
880static inline int
881ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[])
882{
883 struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
884 struct ip_conntrack_protocol *proto;
885 u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
886 int err = 0;
887
888 nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
889
890 proto = ip_conntrack_proto_find_get(npt);
891
892 if (proto->from_nfattr)
893 err = proto->from_nfattr(tb, ct);
894 ip_conntrack_proto_put(proto);
895
896 return err;
897}
898
899static int
900ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
901{
902 int err;
903
904 if (cda[CTA_HELP-1]) {
905 err = ctnetlink_change_helper(ct, cda);
906 if (err < 0)
907 return err;
908 }
909
910 if (cda[CTA_TIMEOUT-1]) {
911 err = ctnetlink_change_timeout(ct, cda);
912 if (err < 0)
913 return err;
914 }
915
916 if (cda[CTA_STATUS-1]) {
917 err = ctnetlink_change_status(ct, cda);
918 if (err < 0)
919 return err;
920 }
921
922 if (cda[CTA_PROTOINFO-1]) {
923 err = ctnetlink_change_protoinfo(ct, cda);
924 if (err < 0)
925 return err;
926 }
927
928#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
929 if (cda[CTA_MARK-1])
930 ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
931#endif
932
933 return 0;
934}
935
936static int
937ctnetlink_create_conntrack(struct nfattr *cda[],
938 struct ip_conntrack_tuple *otuple,
939 struct ip_conntrack_tuple *rtuple)
940{
941 struct ip_conntrack *ct;
942 int err = -EINVAL;
943
944 ct = ip_conntrack_alloc(otuple, rtuple);
945 if (ct == NULL || IS_ERR(ct))
946 return -ENOMEM;
947
948 if (!cda[CTA_TIMEOUT-1])
949 goto err;
950 ct->timeout.expires = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
951
952 ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
953 ct->status |= IPS_CONFIRMED;
954
955 if (cda[CTA_STATUS-1]) {
956 err = ctnetlink_change_status(ct, cda);
957 if (err < 0)
958 goto err;
959 }
960
961 if (cda[CTA_PROTOINFO-1]) {
962 err = ctnetlink_change_protoinfo(ct, cda);
963 if (err < 0)
964 goto err;
965 }
966
967#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
968 if (cda[CTA_MARK-1])
969 ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
970#endif
971
972 ct->helper = ip_conntrack_helper_find_get(rtuple);
973
974 add_timer(&ct->timeout);
975 ip_conntrack_hash_insert(ct);
976
977 if (ct->helper)
978 ip_conntrack_helper_put(ct->helper);
979
980 return 0;
981
982err:
983 ip_conntrack_free(ct);
984 return err;
985}
986
987static int
988ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
989 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
990{
991 struct ip_conntrack_tuple otuple, rtuple;
992 struct ip_conntrack_tuple_hash *h = NULL;
993 int err = 0;
994
995 if (nfattr_bad_size(cda, CTA_MAX, cta_min))
996 return -EINVAL;
997
998 if (cda[CTA_TUPLE_ORIG-1]) {
999 err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG);
1000 if (err < 0)
1001 return err;
1002 }
1003
1004 if (cda[CTA_TUPLE_REPLY-1]) {
1005 err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY);
1006 if (err < 0)
1007 return err;
1008 }
1009
1010 write_lock_bh(&ip_conntrack_lock);
1011 if (cda[CTA_TUPLE_ORIG-1])
1012 h = __ip_conntrack_find(&otuple, NULL);
1013 else if (cda[CTA_TUPLE_REPLY-1])
1014 h = __ip_conntrack_find(&rtuple, NULL);
1015
1016 if (h == NULL) {
1017 write_unlock_bh(&ip_conntrack_lock);
1018 err = -ENOENT;
1019 if (nlh->nlmsg_flags & NLM_F_CREATE)
1020 err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
1021 return err;
1022 }
1023 /* implicit 'else' */
1024
1025 /* we only allow nat config for new conntracks */
1026 if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
1027 err = -EINVAL;
1028 goto out_unlock;
1029 }
1030
1031 /* We manipulate the conntrack inside the global conntrack table lock,
1032 * so there's no need to increase the refcount */
1033 err = -EEXIST;
1034 if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1035 err = ctnetlink_change_conntrack(tuplehash_to_ctrack(h), cda);
1036
1037out_unlock:
1038 write_unlock_bh(&ip_conntrack_lock);
1039 return err;
1040}
1041
1042/***********************************************************************
1043 * EXPECT
1044 ***********************************************************************/
1045
1046static inline int
1047ctnetlink_exp_dump_tuple(struct sk_buff *skb,
1048 const struct ip_conntrack_tuple *tuple,
1049 enum ctattr_expect type)
1050{
1051 struct nfattr *nest_parms = NFA_NEST(skb, type);
1052
1053 if (ctnetlink_dump_tuples(skb, tuple) < 0)
1054 goto nfattr_failure;
1055
1056 NFA_NEST_END(skb, nest_parms);
1057
1058 return 0;
1059
1060nfattr_failure:
1061 return -1;
1062}
1063
1064static inline int
1065ctnetlink_exp_dump_mask(struct sk_buff *skb,
1066 const struct ip_conntrack_tuple *tuple,
1067 const struct ip_conntrack_tuple *mask)
1068{
1069 int ret;
1070 struct ip_conntrack_protocol *proto;
1071 struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
1072
1073 ret = ctnetlink_dump_tuples_ip(skb, mask);
1074 if (unlikely(ret < 0))
1075 goto nfattr_failure;
1076
1077 proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
1078 ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
1079 ip_conntrack_proto_put(proto);
1080 if (unlikely(ret < 0))
1081 goto nfattr_failure;
1082
1083 NFA_NEST_END(skb, nest_parms);
1084
1085 return 0;
1086
1087nfattr_failure:
1088 return -1;
1089}
1090
1091static inline int
1092ctnetlink_exp_dump_expect(struct sk_buff *skb,
1093 const struct ip_conntrack_expect *exp)
1094{
1095 struct ip_conntrack *master = exp->master;
1096 __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
1097 __be32 id = htonl(exp->id);
1098
1099 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1100 goto nfattr_failure;
1101 if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1102 goto nfattr_failure;
1103 if (ctnetlink_exp_dump_tuple(skb,
1104 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1105 CTA_EXPECT_MASTER) < 0)
1106 goto nfattr_failure;
1107
1108 NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(__be32), &timeout);
1109 NFA_PUT(skb, CTA_EXPECT_ID, sizeof(__be32), &id);
1110
1111 return 0;
1112
1113nfattr_failure:
1114 return -1;
1115}
1116
1117static int
1118ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1119 int event,
1120 int nowait,
1121 const struct ip_conntrack_expect *exp)
1122{
1123 struct nlmsghdr *nlh;
1124 struct nfgenmsg *nfmsg;
1125 unsigned char *b;
1126
1127 b = skb->tail;
1128
1129 event |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1130 nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
1131 nfmsg = NLMSG_DATA(nlh);
1132
1133 nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
1134 nfmsg->nfgen_family = AF_INET;
1135 nfmsg->version = NFNETLINK_V0;
1136 nfmsg->res_id = 0;
1137
1138 if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1139 goto nfattr_failure;
1140
1141 nlh->nlmsg_len = skb->tail - b;
1142 return skb->len;
1143
1144nlmsg_failure:
1145nfattr_failure:
1146 skb_trim(skb, b - skb->data);
1147 return -1;
1148}
1149
1150#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
1151static int ctnetlink_expect_event(struct notifier_block *this,
1152 unsigned long events, void *ptr)
1153{
1154 struct nlmsghdr *nlh;
1155 struct nfgenmsg *nfmsg;
1156 struct ip_conntrack_expect *exp = (struct ip_conntrack_expect *)ptr;
1157 struct sk_buff *skb;
1158 unsigned int type;
1159 unsigned char *b;
1160 int flags = 0;
1161
1162 if (events & IPEXP_NEW) {
1163 type = IPCTNL_MSG_EXP_NEW;
1164 flags = NLM_F_CREATE|NLM_F_EXCL;
1165 } else
1166 return NOTIFY_DONE;
1167
1168 if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
1169 return NOTIFY_DONE;
1170
1171 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
1172 if (!skb)
1173 return NOTIFY_DONE;
1174
1175 b = skb->tail;
1176
1177 type |= NFNL_SUBSYS_CTNETLINK_EXP << 8;
1178 nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
1179 nfmsg = NLMSG_DATA(nlh);
1180
1181 nlh->nlmsg_flags = flags;
1182 nfmsg->nfgen_family = AF_INET;
1183 nfmsg->version = NFNETLINK_V0;
1184 nfmsg->res_id = 0;
1185
1186 if (ctnetlink_exp_dump_expect(skb, exp) < 0)
1187 goto nfattr_failure;
1188
1189 nlh->nlmsg_len = skb->tail - b;
1190 nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
1191 return NOTIFY_DONE;
1192
1193nlmsg_failure:
1194nfattr_failure:
1195 kfree_skb(skb);
1196 return NOTIFY_DONE;
1197}
1198#endif
1199
1200static int
1201ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
1202{
1203 struct ip_conntrack_expect *exp = NULL;
1204 struct list_head *i;
1205 u_int32_t *id = (u_int32_t *) &cb->args[0];
1206
1207 read_lock_bh(&ip_conntrack_lock);
1208 list_for_each_prev(i, &ip_conntrack_expect_list) {
1209 exp = (struct ip_conntrack_expect *) i;
1210 if (exp->id <= *id)
1211 continue;
1212 if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
1213 cb->nlh->nlmsg_seq,
1214 IPCTNL_MSG_EXP_NEW,
1215 1, exp) < 0)
1216 goto out;
1217 *id = exp->id;
1218 }
1219out:
1220 read_unlock_bh(&ip_conntrack_lock);
1221
1222 return skb->len;
1223}
1224
1225static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
1226 [CTA_EXPECT_TIMEOUT-1] = sizeof(__be32),
1227 [CTA_EXPECT_ID-1] = sizeof(__be32)
1228};
1229
1230static int
1231ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1232 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1233{
1234 struct ip_conntrack_tuple tuple;
1235 struct ip_conntrack_expect *exp;
1236 struct sk_buff *skb2;
1237 int err = 0;
1238
1239 if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1240 return -EINVAL;
1241
1242 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1243 struct nfgenmsg *msg = NLMSG_DATA(nlh);
1244 u32 rlen;
1245
1246 if (msg->nfgen_family != AF_INET)
1247 return -EAFNOSUPPORT;
1248
1249 if ((*errp = netlink_dump_start(ctnl, skb, nlh,
1250 ctnetlink_exp_dump_table,
1251 ctnetlink_done)) != 0)
1252 return -EINVAL;
1253 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
1254 if (rlen > skb->len)
1255 rlen = skb->len;
1256 skb_pull(skb, rlen);
1257 return 0;
1258 }
1259
1260 if (cda[CTA_EXPECT_MASTER-1])
1261 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER);
1262 else
1263 return -EINVAL;
1264
1265 if (err < 0)
1266 return err;
1267
1268 exp = ip_conntrack_expect_find_get(&tuple);
1269 if (!exp)
1270 return -ENOENT;
1271
1272 if (cda[CTA_EXPECT_ID-1]) {
1273 __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
1274 if (exp->id != ntohl(id)) {
1275 ip_conntrack_expect_put(exp);
1276 return -ENOENT;
1277 }
1278 }
1279
1280 err = -ENOMEM;
1281 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1282 if (!skb2)
1283 goto out;
1284
1285 err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
1286 nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1287 1, exp);
1288 if (err <= 0)
1289 goto free;
1290
1291 ip_conntrack_expect_put(exp);
1292
1293 return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1294
1295free:
1296 kfree_skb(skb2);
1297out:
1298 ip_conntrack_expect_put(exp);
1299 return err;
1300}
1301
1302static int
1303ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1304 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1305{
1306 struct ip_conntrack_expect *exp, *tmp;
1307 struct ip_conntrack_tuple tuple;
1308 struct ip_conntrack_helper *h;
1309 int err;
1310
1311 if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1312 return -EINVAL;
1313
1314 if (cda[CTA_EXPECT_TUPLE-1]) {
1315 /* delete a single expect by tuple */
1316 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
1317 if (err < 0)
1318 return err;
1319
1320 /* bump usage count to 2 */
1321 exp = ip_conntrack_expect_find_get(&tuple);
1322 if (!exp)
1323 return -ENOENT;
1324
1325 if (cda[CTA_EXPECT_ID-1]) {
1326 __be32 id =
1327 *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
1328 if (exp->id != ntohl(id)) {
1329 ip_conntrack_expect_put(exp);
1330 return -ENOENT;
1331 }
1332 }
1333
1334 /* after list removal, usage count == 1 */
1335 ip_conntrack_unexpect_related(exp);
1336 /* have to put what we 'get' above.
1337 * after this line usage count == 0 */
1338 ip_conntrack_expect_put(exp);
1339 } else if (cda[CTA_EXPECT_HELP_NAME-1]) {
1340 char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
1341
1342 /* delete all expectations for this helper */
1343 write_lock_bh(&ip_conntrack_lock);
1344 h = __ip_conntrack_helper_find_byname(name);
1345 if (!h) {
1346 write_unlock_bh(&ip_conntrack_lock);
1347 return -EINVAL;
1348 }
1349 list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
1350 list) {
1351 if (exp->master->helper == h
1352 && del_timer(&exp->timeout)) {
1353 ip_ct_unlink_expect(exp);
1354 ip_conntrack_expect_put(exp);
1355 }
1356 }
1357 write_unlock_bh(&ip_conntrack_lock);
1358 } else {
1359 /* This basically means we have to flush everything*/
1360 write_lock_bh(&ip_conntrack_lock);
1361 list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list,
1362 list) {
1363 if (del_timer(&exp->timeout)) {
1364 ip_ct_unlink_expect(exp);
1365 ip_conntrack_expect_put(exp);
1366 }
1367 }
1368 write_unlock_bh(&ip_conntrack_lock);
1369 }
1370
1371 return 0;
1372}
1373static int
1374ctnetlink_change_expect(struct ip_conntrack_expect *x, struct nfattr *cda[])
1375{
1376 return -EOPNOTSUPP;
1377}
1378
1379static int
1380ctnetlink_create_expect(struct nfattr *cda[])
1381{
1382 struct ip_conntrack_tuple tuple, mask, master_tuple;
1383 struct ip_conntrack_tuple_hash *h = NULL;
1384 struct ip_conntrack_expect *exp;
1385 struct ip_conntrack *ct;
1386 int err = 0;
1387
1388 /* caller guarantees that those three CTA_EXPECT_* exist */
1389 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
1390 if (err < 0)
1391 return err;
1392 err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK);
1393 if (err < 0)
1394 return err;
1395 err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER);
1396 if (err < 0)
1397 return err;
1398
1399 /* Look for master conntrack of this expectation */
1400 h = ip_conntrack_find_get(&master_tuple, NULL);
1401 if (!h)
1402 return -ENOENT;
1403 ct = tuplehash_to_ctrack(h);
1404
1405 if (!ct->helper) {
1406 /* such conntrack hasn't got any helper, abort */
1407 err = -EINVAL;
1408 goto out;
1409 }
1410
1411 exp = ip_conntrack_expect_alloc(ct);
1412 if (!exp) {
1413 err = -ENOMEM;
1414 goto out;
1415 }
1416
1417 exp->expectfn = NULL;
1418 exp->flags = 0;
1419 exp->master = ct;
1420 memcpy(&exp->tuple, &tuple, sizeof(struct ip_conntrack_tuple));
1421 memcpy(&exp->mask, &mask, sizeof(struct ip_conntrack_tuple));
1422
1423 err = ip_conntrack_expect_related(exp);
1424 ip_conntrack_expect_put(exp);
1425
1426out:
1427 ip_conntrack_put(tuplehash_to_ctrack(h));
1428 return err;
1429}
1430
1431static int
1432ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
1433 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
1434{
1435 struct ip_conntrack_tuple tuple;
1436 struct ip_conntrack_expect *exp;
1437 int err = 0;
1438
1439 if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
1440 return -EINVAL;
1441
1442 if (!cda[CTA_EXPECT_TUPLE-1]
1443 || !cda[CTA_EXPECT_MASK-1]
1444 || !cda[CTA_EXPECT_MASTER-1])
1445 return -EINVAL;
1446
1447 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE);
1448 if (err < 0)
1449 return err;
1450
1451 write_lock_bh(&ip_conntrack_lock);
1452 exp = __ip_conntrack_expect_find(&tuple);
1453
1454 if (!exp) {
1455 write_unlock_bh(&ip_conntrack_lock);
1456 err = -ENOENT;
1457 if (nlh->nlmsg_flags & NLM_F_CREATE)
1458 err = ctnetlink_create_expect(cda);
1459 return err;
1460 }
1461
1462 err = -EEXIST;
1463 if (!(nlh->nlmsg_flags & NLM_F_EXCL))
1464 err = ctnetlink_change_expect(exp, cda);
1465 write_unlock_bh(&ip_conntrack_lock);
1466
1467 return err;
1468}
1469
1470#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
1471static struct notifier_block ctnl_notifier = {
1472 .notifier_call = ctnetlink_conntrack_event,
1473};
1474
1475static struct notifier_block ctnl_notifier_exp = {
1476 .notifier_call = ctnetlink_expect_event,
1477};
1478#endif
1479
1480static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
1481 [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack,
1482 .attr_count = CTA_MAX, },
1483 [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack,
1484 .attr_count = CTA_MAX, },
1485 [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack,
1486 .attr_count = CTA_MAX, },
1487 [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack,
1488 .attr_count = CTA_MAX, },
1489};
1490
1491static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
1492 [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect,
1493 .attr_count = CTA_EXPECT_MAX, },
1494 [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect,
1495 .attr_count = CTA_EXPECT_MAX, },
1496 [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect,
1497 .attr_count = CTA_EXPECT_MAX, },
1498};
1499
1500static struct nfnetlink_subsystem ctnl_subsys = {
1501 .name = "conntrack",
1502 .subsys_id = NFNL_SUBSYS_CTNETLINK,
1503 .cb_count = IPCTNL_MSG_MAX,
1504 .cb = ctnl_cb,
1505};
1506
1507static struct nfnetlink_subsystem ctnl_exp_subsys = {
1508 .name = "conntrack_expect",
1509 .subsys_id = NFNL_SUBSYS_CTNETLINK_EXP,
1510 .cb_count = IPCTNL_MSG_EXP_MAX,
1511 .cb = ctnl_exp_cb,
1512};
1513
1514MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
1515MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
1516
1517static int __init ctnetlink_init(void)
1518{
1519 int ret;
1520
1521 printk("ctnetlink v%s: registering with nfnetlink.\n", version);
1522 ret = nfnetlink_subsys_register(&ctnl_subsys);
1523 if (ret < 0) {
1524 printk("ctnetlink_init: cannot register with nfnetlink.\n");
1525 goto err_out;
1526 }
1527
1528 ret = nfnetlink_subsys_register(&ctnl_exp_subsys);
1529 if (ret < 0) {
1530 printk("ctnetlink_init: cannot register exp with nfnetlink.\n");
1531 goto err_unreg_subsys;
1532 }
1533
1534#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
1535 ret = ip_conntrack_register_notifier(&ctnl_notifier);
1536 if (ret < 0) {
1537 printk("ctnetlink_init: cannot register notifier.\n");
1538 goto err_unreg_exp_subsys;
1539 }
1540
1541 ret = ip_conntrack_expect_register_notifier(&ctnl_notifier_exp);
1542 if (ret < 0) {
1543 printk("ctnetlink_init: cannot expect register notifier.\n");
1544 goto err_unreg_notifier;
1545 }
1546#endif
1547
1548 return 0;
1549
1550#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
1551err_unreg_notifier:
1552 ip_conntrack_unregister_notifier(&ctnl_notifier);
1553err_unreg_exp_subsys:
1554 nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1555#endif
1556err_unreg_subsys:
1557 nfnetlink_subsys_unregister(&ctnl_subsys);
1558err_out:
1559 return ret;
1560}
1561
1562static void __exit ctnetlink_exit(void)
1563{
1564 printk("ctnetlink: unregistering from nfnetlink.\n");
1565
1566#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
1567 ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
1568 ip_conntrack_unregister_notifier(&ctnl_notifier);
1569#endif
1570
1571 nfnetlink_subsys_unregister(&ctnl_exp_subsys);
1572 nfnetlink_subsys_unregister(&ctnl_subsys);
1573 return;
1574}
1575
1576module_init(ctnetlink_init);
1577module_exit(ctnetlink_exit);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
deleted file mode 100644
index 88af82e98658..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c
+++ /dev/null
@@ -1,74 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/timer.h>
11#include <linux/netfilter.h>
12#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
13
14unsigned int ip_ct_generic_timeout __read_mostly = 600*HZ;
15
16static int generic_pkt_to_tuple(const struct sk_buff *skb,
17 unsigned int dataoff,
18 struct ip_conntrack_tuple *tuple)
19{
20 tuple->src.u.all = 0;
21 tuple->dst.u.all = 0;
22
23 return 1;
24}
25
26static int generic_invert_tuple(struct ip_conntrack_tuple *tuple,
27 const struct ip_conntrack_tuple *orig)
28{
29 tuple->src.u.all = 0;
30 tuple->dst.u.all = 0;
31
32 return 1;
33}
34
35/* Print out the per-protocol part of the tuple. */
36static int generic_print_tuple(struct seq_file *s,
37 const struct ip_conntrack_tuple *tuple)
38{
39 return 0;
40}
41
42/* Print out the private part of the conntrack. */
43static int generic_print_conntrack(struct seq_file *s,
44 const struct ip_conntrack *state)
45{
46 return 0;
47}
48
49/* Returns verdict for packet, or -1 for invalid. */
50static int packet(struct ip_conntrack *conntrack,
51 const struct sk_buff *skb,
52 enum ip_conntrack_info ctinfo)
53{
54 ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
55 return NF_ACCEPT;
56}
57
58/* Called when a new connection for this protocol found. */
59static int new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
60{
61 return 1;
62}
63
64struct ip_conntrack_protocol ip_conntrack_generic_protocol =
65{
66 .proto = 0,
67 .name = "unknown",
68 .pkt_to_tuple = generic_pkt_to_tuple,
69 .invert_tuple = generic_invert_tuple,
70 .print_tuple = generic_print_tuple,
71 .print_conntrack = generic_print_conntrack,
72 .packet = packet,
73 .new = new,
74};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
deleted file mode 100644
index ac1c49ef36a9..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ /dev/null
@@ -1,328 +0,0 @@
1/*
2 * ip_conntrack_proto_gre.c - Version 3.0
3 *
4 * Connection tracking protocol helper module for GRE.
5 *
6 * GRE is a generic encapsulation protocol, which is generally not very
7 * suited for NAT, as it has no protocol-specific part as port numbers.
8 *
9 * It has an optional key field, which may help us distinguishing two
10 * connections between the same two hosts.
11 *
12 * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
13 *
14 * PPTP is built on top of a modified version of GRE, and has a mandatory
15 * field called "CallID", which serves us for the same purpose as the key
16 * field in plain GRE.
17 *
18 * Documentation about PPTP can be found in RFC 2637
19 *
20 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
21 *
22 * Development of this code funded by Astaro AG (http://www.astaro.com/)
23 *
24 */
25
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/timer.h>
29#include <linux/netfilter.h>
30#include <linux/ip.h>
31#include <linux/in.h>
32#include <linux/list.h>
33#include <linux/seq_file.h>
34#include <linux/interrupt.h>
35
36static DEFINE_RWLOCK(ip_ct_gre_lock);
37
38#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
39#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
40#include <linux/netfilter_ipv4/ip_conntrack_core.h>
41
42#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
43#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
44
45MODULE_LICENSE("GPL");
46MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
47MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
48
49/* shamelessly stolen from ip_conntrack_proto_udp.c */
50#define GRE_TIMEOUT (30*HZ)
51#define GRE_STREAM_TIMEOUT (180*HZ)
52
53#if 0
54#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
55#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \
56 NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \
57 NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key))
58#else
59#define DEBUGP(x, args...)
60#define DUMP_TUPLE_GRE(x)
61#endif
62
63/* GRE KEYMAP HANDLING FUNCTIONS */
64static LIST_HEAD(gre_keymap_list);
65
66static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
67 const struct ip_conntrack_tuple *t)
68{
69 return ((km->tuple.src.ip == t->src.ip) &&
70 (km->tuple.dst.ip == t->dst.ip) &&
71 (km->tuple.dst.protonum == t->dst.protonum) &&
72 (km->tuple.dst.u.all == t->dst.u.all));
73}
74
75/* look up the source key for a given tuple */
76static __be16 gre_keymap_lookup(struct ip_conntrack_tuple *t)
77{
78 struct ip_ct_gre_keymap *km;
79 __be16 key = 0;
80
81 read_lock_bh(&ip_ct_gre_lock);
82 list_for_each_entry(km, &gre_keymap_list, list) {
83 if (gre_key_cmpfn(km, t)) {
84 key = km->tuple.src.u.gre.key;
85 break;
86 }
87 }
88 read_unlock_bh(&ip_ct_gre_lock);
89
90 DEBUGP("lookup src key 0x%x up key for ", key);
91 DUMP_TUPLE_GRE(t);
92
93 return key;
94}
95
96/* add a single keymap entry, associate with specified master ct */
97int
98ip_ct_gre_keymap_add(struct ip_conntrack *ct,
99 struct ip_conntrack_tuple *t, int reply)
100{
101 struct ip_ct_gre_keymap **exist_km, *km;
102
103 if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
104 DEBUGP("refusing to add GRE keymap to non-pptp session\n");
105 return -1;
106 }
107
108 if (!reply)
109 exist_km = &ct->help.ct_pptp_info.keymap_orig;
110 else
111 exist_km = &ct->help.ct_pptp_info.keymap_reply;
112
113 if (*exist_km) {
114 /* check whether it's a retransmission */
115 list_for_each_entry(km, &gre_keymap_list, list) {
116 if (gre_key_cmpfn(km, t) && km == *exist_km)
117 return 0;
118 }
119 DEBUGP("trying to override keymap_%s for ct %p\n",
120 reply? "reply":"orig", ct);
121 return -EEXIST;
122 }
123
124 km = kmalloc(sizeof(*km), GFP_ATOMIC);
125 if (!km)
126 return -ENOMEM;
127
128 memcpy(&km->tuple, t, sizeof(*t));
129 *exist_km = km;
130
131 DEBUGP("adding new entry %p: ", km);
132 DUMP_TUPLE_GRE(&km->tuple);
133
134 write_lock_bh(&ip_ct_gre_lock);
135 list_add_tail(&km->list, &gre_keymap_list);
136 write_unlock_bh(&ip_ct_gre_lock);
137
138 return 0;
139}
140
141/* destroy the keymap entries associated with specified master ct */
142void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct)
143{
144 DEBUGP("entering for ct %p\n", ct);
145
146 if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
147 DEBUGP("refusing to destroy GRE keymap to non-pptp session\n");
148 return;
149 }
150
151 write_lock_bh(&ip_ct_gre_lock);
152 if (ct->help.ct_pptp_info.keymap_orig) {
153 DEBUGP("removing %p from list\n",
154 ct->help.ct_pptp_info.keymap_orig);
155 list_del(&ct->help.ct_pptp_info.keymap_orig->list);
156 kfree(ct->help.ct_pptp_info.keymap_orig);
157 ct->help.ct_pptp_info.keymap_orig = NULL;
158 }
159 if (ct->help.ct_pptp_info.keymap_reply) {
160 DEBUGP("removing %p from list\n",
161 ct->help.ct_pptp_info.keymap_reply);
162 list_del(&ct->help.ct_pptp_info.keymap_reply->list);
163 kfree(ct->help.ct_pptp_info.keymap_reply);
164 ct->help.ct_pptp_info.keymap_reply = NULL;
165 }
166 write_unlock_bh(&ip_ct_gre_lock);
167}
168
169
170/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
171
172/* invert gre part of tuple */
173static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
174 const struct ip_conntrack_tuple *orig)
175{
176 tuple->dst.u.gre.key = orig->src.u.gre.key;
177 tuple->src.u.gre.key = orig->dst.u.gre.key;
178
179 return 1;
180}
181
182/* gre hdr info to tuple */
183static int gre_pkt_to_tuple(const struct sk_buff *skb,
184 unsigned int dataoff,
185 struct ip_conntrack_tuple *tuple)
186{
187 struct gre_hdr_pptp _pgrehdr, *pgrehdr;
188 __be16 srckey;
189 struct gre_hdr _grehdr, *grehdr;
190
191 /* first only delinearize old RFC1701 GRE header */
192 grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr);
193 if (!grehdr || grehdr->version != GRE_VERSION_PPTP) {
194 /* try to behave like "ip_conntrack_proto_generic" */
195 tuple->src.u.all = 0;
196 tuple->dst.u.all = 0;
197 return 1;
198 }
199
200 /* PPTP header is variable length, only need up to the call_id field */
201 pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
202 if (!pgrehdr)
203 return 1;
204
205 if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
206 DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
207 return 0;
208 }
209
210 tuple->dst.u.gre.key = pgrehdr->call_id;
211 srckey = gre_keymap_lookup(tuple);
212 tuple->src.u.gre.key = srckey;
213
214 return 1;
215}
216
217/* print gre part of tuple */
218static int gre_print_tuple(struct seq_file *s,
219 const struct ip_conntrack_tuple *tuple)
220{
221 return seq_printf(s, "srckey=0x%x dstkey=0x%x ",
222 ntohs(tuple->src.u.gre.key),
223 ntohs(tuple->dst.u.gre.key));
224}
225
226/* print private data for conntrack */
227static int gre_print_conntrack(struct seq_file *s,
228 const struct ip_conntrack *ct)
229{
230 return seq_printf(s, "timeout=%u, stream_timeout=%u ",
231 (ct->proto.gre.timeout / HZ),
232 (ct->proto.gre.stream_timeout / HZ));
233}
234
235/* Returns verdict for packet, and may modify conntrack */
236static int gre_packet(struct ip_conntrack *ct,
237 const struct sk_buff *skb,
238 enum ip_conntrack_info conntrackinfo)
239{
240 /* If we've seen traffic both ways, this is a GRE connection.
241 * Extend timeout. */
242 if (ct->status & IPS_SEEN_REPLY) {
243 ip_ct_refresh_acct(ct, conntrackinfo, skb,
244 ct->proto.gre.stream_timeout);
245 /* Also, more likely to be important, and not a probe. */
246 set_bit(IPS_ASSURED_BIT, &ct->status);
247 ip_conntrack_event_cache(IPCT_STATUS, skb);
248 } else
249 ip_ct_refresh_acct(ct, conntrackinfo, skb,
250 ct->proto.gre.timeout);
251
252 return NF_ACCEPT;
253}
254
255/* Called when a new connection for this protocol found. */
256static int gre_new(struct ip_conntrack *ct,
257 const struct sk_buff *skb)
258{
259 DEBUGP(": ");
260 DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
261
262 /* initialize to sane value. Ideally a conntrack helper
263 * (e.g. in case of pptp) is increasing them */
264 ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
265 ct->proto.gre.timeout = GRE_TIMEOUT;
266
267 return 1;
268}
269
270/* Called when a conntrack entry has already been removed from the hashes
271 * and is about to be deleted from memory */
272static void gre_destroy(struct ip_conntrack *ct)
273{
274 struct ip_conntrack *master = ct->master;
275 DEBUGP(" entering\n");
276
277 if (!master)
278 DEBUGP("no master !?!\n");
279 else
280 ip_ct_gre_keymap_destroy(master);
281}
282
283/* protocol helper struct */
284static struct ip_conntrack_protocol gre = {
285 .proto = IPPROTO_GRE,
286 .name = "gre",
287 .pkt_to_tuple = gre_pkt_to_tuple,
288 .invert_tuple = gre_invert_tuple,
289 .print_tuple = gre_print_tuple,
290 .print_conntrack = gre_print_conntrack,
291 .packet = gre_packet,
292 .new = gre_new,
293 .destroy = gre_destroy,
294 .me = THIS_MODULE,
295#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
296 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
297 .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
298 .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
299#endif
300};
301
302/* ip_conntrack_proto_gre initialization */
303int __init ip_ct_proto_gre_init(void)
304{
305 return ip_conntrack_protocol_register(&gre);
306}
307
308/* This cannot be __exit, as it is invoked from ip_conntrack_helper_pptp.c's
309 * init() code on errors.
310 */
311void ip_ct_proto_gre_fini(void)
312{
313 struct list_head *pos, *n;
314
315 /* delete all keymap entries */
316 write_lock_bh(&ip_ct_gre_lock);
317 list_for_each_safe(pos, n, &gre_keymap_list) {
318 DEBUGP("deleting keymap %p at module unload time\n", pos);
319 list_del(pos);
320 kfree(pos);
321 }
322 write_unlock_bh(&ip_ct_gre_lock);
323
324 ip_conntrack_protocol_unregister(&gre);
325}
326
327EXPORT_SYMBOL(ip_ct_gre_keymap_add);
328EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
deleted file mode 100644
index e253f3ee52d0..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ /dev/null
@@ -1,315 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/timer.h>
11#include <linux/netfilter.h>
12#include <linux/in.h>
13#include <linux/icmp.h>
14#include <linux/seq_file.h>
15#include <linux/skbuff.h>
16#include <net/ip.h>
17#include <net/checksum.h>
18#include <linux/netfilter_ipv4.h>
19#include <linux/netfilter_ipv4/ip_conntrack.h>
20#include <linux/netfilter_ipv4/ip_conntrack_core.h>
21#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
22
23unsigned int ip_ct_icmp_timeout __read_mostly = 30*HZ;
24
25#if 0
26#define DEBUGP printk
27#else
28#define DEBUGP(format, args...)
29#endif
30
31static int icmp_pkt_to_tuple(const struct sk_buff *skb,
32 unsigned int dataoff,
33 struct ip_conntrack_tuple *tuple)
34{
35 struct icmphdr _hdr, *hp;
36
37 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
38 if (hp == NULL)
39 return 0;
40
41 tuple->dst.u.icmp.type = hp->type;
42 tuple->src.u.icmp.id = hp->un.echo.id;
43 tuple->dst.u.icmp.code = hp->code;
44
45 return 1;
46}
47
48/* Add 1; spaces filled with 0. */
49static const u_int8_t invmap[] = {
50 [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
51 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
52 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
53 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
54 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
55 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
56 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
57 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
58};
59
60static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple,
61 const struct ip_conntrack_tuple *orig)
62{
63 if (orig->dst.u.icmp.type >= sizeof(invmap)
64 || !invmap[orig->dst.u.icmp.type])
65 return 0;
66
67 tuple->src.u.icmp.id = orig->src.u.icmp.id;
68 tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
69 tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
70 return 1;
71}
72
73/* Print out the per-protocol part of the tuple. */
74static int icmp_print_tuple(struct seq_file *s,
75 const struct ip_conntrack_tuple *tuple)
76{
77 return seq_printf(s, "type=%u code=%u id=%u ",
78 tuple->dst.u.icmp.type,
79 tuple->dst.u.icmp.code,
80 ntohs(tuple->src.u.icmp.id));
81}
82
83/* Print out the private part of the conntrack. */
84static int icmp_print_conntrack(struct seq_file *s,
85 const struct ip_conntrack *conntrack)
86{
87 return 0;
88}
89
90/* Returns verdict for packet, or -1 for invalid. */
91static int icmp_packet(struct ip_conntrack *ct,
92 const struct sk_buff *skb,
93 enum ip_conntrack_info ctinfo)
94{
95 /* Try to delete connection immediately after all replies:
96 won't actually vanish as we still have skb, and del_timer
97 means this will only run once even if count hits zero twice
98 (theoretically possible with SMP) */
99 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
100 if (atomic_dec_and_test(&ct->proto.icmp.count)
101 && del_timer(&ct->timeout))
102 ct->timeout.function((unsigned long)ct);
103 } else {
104 atomic_inc(&ct->proto.icmp.count);
105 ip_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
106 ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
107 }
108
109 return NF_ACCEPT;
110}
111
112/* Called when a new connection for this protocol found. */
113static int icmp_new(struct ip_conntrack *conntrack,
114 const struct sk_buff *skb)
115{
116 static const u_int8_t valid_new[] = {
117 [ICMP_ECHO] = 1,
118 [ICMP_TIMESTAMP] = 1,
119 [ICMP_INFO_REQUEST] = 1,
120 [ICMP_ADDRESS] = 1
121 };
122
123 if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
124 || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
125 /* Can't create a new ICMP `conn' with this. */
126 DEBUGP("icmp: can't create new conn with type %u\n",
127 conntrack->tuplehash[0].tuple.dst.u.icmp.type);
128 DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
129 return 0;
130 }
131 atomic_set(&conntrack->proto.icmp.count, 0);
132 return 1;
133}
134
135static int
136icmp_error_message(struct sk_buff *skb,
137 enum ip_conntrack_info *ctinfo,
138 unsigned int hooknum)
139{
140 struct ip_conntrack_tuple innertuple, origtuple;
141 struct {
142 struct icmphdr icmp;
143 struct iphdr ip;
144 } _in, *inside;
145 struct ip_conntrack_protocol *innerproto;
146 struct ip_conntrack_tuple_hash *h;
147 int dataoff;
148
149 IP_NF_ASSERT(skb->nfct == NULL);
150
151 /* Not enough header? */
152 inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in);
153 if (inside == NULL)
154 return -NF_ACCEPT;
155
156 /* Ignore ICMP's containing fragments (shouldn't happen) */
157 if (inside->ip.frag_off & htons(IP_OFFSET)) {
158 DEBUGP("icmp_error_track: fragment of proto %u\n",
159 inside->ip.protocol);
160 return -NF_ACCEPT;
161 }
162
163 innerproto = ip_conntrack_proto_find_get(inside->ip.protocol);
164 dataoff = ip_hdrlen(skb) + sizeof(inside->icmp) + inside->ip.ihl * 4;
165 /* Are they talking about one of our connections? */
166 if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) {
167 DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol);
168 ip_conntrack_proto_put(innerproto);
169 return -NF_ACCEPT;
170 }
171
172 /* Ordinarily, we'd expect the inverted tupleproto, but it's
173 been preserved inside the ICMP. */
174 if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
175 DEBUGP("icmp_error_track: Can't invert tuple\n");
176 ip_conntrack_proto_put(innerproto);
177 return -NF_ACCEPT;
178 }
179 ip_conntrack_proto_put(innerproto);
180
181 *ctinfo = IP_CT_RELATED;
182
183 h = ip_conntrack_find_get(&innertuple, NULL);
184 if (!h) {
185 /* Locally generated ICMPs will match inverted if they
186 haven't been SNAT'ed yet */
187 /* FIXME: NAT code has to handle half-done double NAT --RR */
188 if (hooknum == NF_IP_LOCAL_OUT)
189 h = ip_conntrack_find_get(&origtuple, NULL);
190
191 if (!h) {
192 DEBUGP("icmp_error_track: no match\n");
193 return -NF_ACCEPT;
194 }
195 /* Reverse direction from that found */
196 if (DIRECTION(h) != IP_CT_DIR_REPLY)
197 *ctinfo += IP_CT_IS_REPLY;
198 } else {
199 if (DIRECTION(h) == IP_CT_DIR_REPLY)
200 *ctinfo += IP_CT_IS_REPLY;
201 }
202
203 /* Update skb to refer to this connection */
204 skb->nfct = &tuplehash_to_ctrack(h)->ct_general;
205 skb->nfctinfo = *ctinfo;
206 return -NF_ACCEPT;
207}
208
209/* Small and modified version of icmp_rcv */
210static int
211icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
212 unsigned int hooknum)
213{
214 struct icmphdr _ih, *icmph;
215
216 /* Not enough header? */
217 icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
218 if (icmph == NULL) {
219 if (LOG_INVALID(IPPROTO_ICMP))
220 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
221 "ip_ct_icmp: short packet ");
222 return -NF_ACCEPT;
223 }
224
225 /* See ip_conntrack_proto_tcp.c */
226 if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
227 nf_ip_checksum(skb, hooknum, ip_hdrlen(skb), 0)) {
228 if (LOG_INVALID(IPPROTO_ICMP))
229 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
230 "ip_ct_icmp: bad ICMP checksum ");
231 return -NF_ACCEPT;
232 }
233
234 /*
235 * 18 is the highest 'known' ICMP type. Anything else is a mystery
236 *
237 * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently
238 * discarded.
239 */
240 if (icmph->type > NR_ICMP_TYPES) {
241 if (LOG_INVALID(IPPROTO_ICMP))
242 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
243 "ip_ct_icmp: invalid ICMP type ");
244 return -NF_ACCEPT;
245 }
246
247 /* Need to track icmp error message? */
248 if (icmph->type != ICMP_DEST_UNREACH
249 && icmph->type != ICMP_SOURCE_QUENCH
250 && icmph->type != ICMP_TIME_EXCEEDED
251 && icmph->type != ICMP_PARAMETERPROB
252 && icmph->type != ICMP_REDIRECT)
253 return NF_ACCEPT;
254
255 return icmp_error_message(skb, ctinfo, hooknum);
256}
257
258#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
259 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
260static int icmp_tuple_to_nfattr(struct sk_buff *skb,
261 const struct ip_conntrack_tuple *t)
262{
263 NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(__be16),
264 &t->src.u.icmp.id);
265 NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
266 &t->dst.u.icmp.type);
267 NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
268 &t->dst.u.icmp.code);
269
270 return 0;
271
272nfattr_failure:
273 return -1;
274}
275
276static int icmp_nfattr_to_tuple(struct nfattr *tb[],
277 struct ip_conntrack_tuple *tuple)
278{
279 if (!tb[CTA_PROTO_ICMP_TYPE-1]
280 || !tb[CTA_PROTO_ICMP_CODE-1]
281 || !tb[CTA_PROTO_ICMP_ID-1])
282 return -EINVAL;
283
284 tuple->dst.u.icmp.type =
285 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
286 tuple->dst.u.icmp.code =
287 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
288 tuple->src.u.icmp.id =
289 *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
290
291 if (tuple->dst.u.icmp.type >= sizeof(invmap)
292 || !invmap[tuple->dst.u.icmp.type])
293 return -EINVAL;
294
295 return 0;
296}
297#endif
298
299struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
300{
301 .proto = IPPROTO_ICMP,
302 .name = "icmp",
303 .pkt_to_tuple = icmp_pkt_to_tuple,
304 .invert_tuple = icmp_invert_tuple,
305 .print_tuple = icmp_print_tuple,
306 .print_conntrack = icmp_print_conntrack,
307 .packet = icmp_packet,
308 .new = icmp_new,
309 .error = icmp_error,
310#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
311 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
312 .tuple_to_nfattr = icmp_tuple_to_nfattr,
313 .nfattr_to_tuple = icmp_nfattr_to_tuple,
314#endif
315};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
deleted file mode 100644
index 91d0c05c8e86..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ /dev/null
@@ -1,659 +0,0 @@
1/*
2 * Connection tracking protocol helper module for SCTP.
3 *
4 * SCTP is defined in RFC 2960. References to various sections in this code
5 * are to this RFC.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12/*
13 * Added support for proc manipulation of timeouts.
14 */
15
16#include <linux/types.h>
17#include <linux/timer.h>
18#include <linux/interrupt.h>
19#include <linux/netfilter.h>
20#include <linux/module.h>
21#include <linux/in.h>
22#include <linux/ip.h>
23#include <linux/sctp.h>
24#include <linux/string.h>
25#include <linux/seq_file.h>
26
27#include <linux/netfilter_ipv4/ip_conntrack.h>
28#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
29
30#if 0
31#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
32#else
33#define DEBUGP(format, args...)
34#endif
35
36/* Protects conntrack->proto.sctp */
37static DEFINE_RWLOCK(sctp_lock);
38
39/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
40 closely. They're more complex. --RR
41
42 And so for me for SCTP :D -Kiran */
43
44static const char *sctp_conntrack_names[] = {
45 "NONE",
46 "CLOSED",
47 "COOKIE_WAIT",
48 "COOKIE_ECHOED",
49 "ESTABLISHED",
50 "SHUTDOWN_SENT",
51 "SHUTDOWN_RECD",
52 "SHUTDOWN_ACK_SENT",
53};
54
55#define SECS * HZ
56#define MINS * 60 SECS
57#define HOURS * 60 MINS
58#define DAYS * 24 HOURS
59
60static unsigned int ip_ct_sctp_timeout_closed __read_mostly = 10 SECS;
61static unsigned int ip_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS;
62static unsigned int ip_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS;
63static unsigned int ip_ct_sctp_timeout_established __read_mostly = 5 DAYS;
64static unsigned int ip_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000;
65static unsigned int ip_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000;
66static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS;
67
68static const unsigned int * sctp_timeouts[]
69= { NULL, /* SCTP_CONNTRACK_NONE */
70 &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
71 &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
72 &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
73 &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
74 &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
75 &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
76 &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
77 };
78
79#define sNO SCTP_CONNTRACK_NONE
80#define sCL SCTP_CONNTRACK_CLOSED
81#define sCW SCTP_CONNTRACK_COOKIE_WAIT
82#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
83#define sES SCTP_CONNTRACK_ESTABLISHED
84#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
85#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
86#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
87#define sIV SCTP_CONNTRACK_MAX
88
89/*
90 These are the descriptions of the states:
91
92NOTE: These state names are tantalizingly similar to the states of an
93SCTP endpoint. But the interpretation of the states is a little different,
94considering that these are the states of the connection and not of an end
95point. Please note the subtleties. -Kiran
96
97NONE - Nothing so far.
98COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
99 an INIT_ACK chunk in the reply direction.
100COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
101ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
102SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
103SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
104SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
105 to that of the SHUTDOWN chunk.
106CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
107 the SHUTDOWN chunk. Connection is closed.
108*/
109
110/* TODO
111 - I have assumed that the first INIT is in the original direction.
112 This messes things when an INIT comes in the reply direction in CLOSED
113 state.
114 - Check the error type in the reply dir before transitioning from
115cookie echoed to closed.
116 - Sec 5.2.4 of RFC 2960
117 - Multi Homing support.
118*/
119
120/* SCTP conntrack state transitions */
121static const enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
122 {
123/* ORIGINAL */
124/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
125/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
126/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
127/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
128/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
129/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
130/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
131/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
132/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
133/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
134 },
135 {
136/* REPLY */
137/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
138/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
139/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
140/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
141/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
142/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
143/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
144/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
145/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
146/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
147 }
148};
149
150static int sctp_pkt_to_tuple(const struct sk_buff *skb,
151 unsigned int dataoff,
152 struct ip_conntrack_tuple *tuple)
153{
154 sctp_sctphdr_t _hdr, *hp;
155
156 DEBUGP(__FUNCTION__);
157 DEBUGP("\n");
158
159 /* Actually only need first 8 bytes. */
160 hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
161 if (hp == NULL)
162 return 0;
163
164 tuple->src.u.sctp.port = hp->source;
165 tuple->dst.u.sctp.port = hp->dest;
166 return 1;
167}
168
169static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
170 const struct ip_conntrack_tuple *orig)
171{
172 DEBUGP(__FUNCTION__);
173 DEBUGP("\n");
174
175 tuple->src.u.sctp.port = orig->dst.u.sctp.port;
176 tuple->dst.u.sctp.port = orig->src.u.sctp.port;
177 return 1;
178}
179
180/* Print out the per-protocol part of the tuple. */
181static int sctp_print_tuple(struct seq_file *s,
182 const struct ip_conntrack_tuple *tuple)
183{
184 DEBUGP(__FUNCTION__);
185 DEBUGP("\n");
186
187 return seq_printf(s, "sport=%hu dport=%hu ",
188 ntohs(tuple->src.u.sctp.port),
189 ntohs(tuple->dst.u.sctp.port));
190}
191
192/* Print out the private part of the conntrack. */
193static int sctp_print_conntrack(struct seq_file *s,
194 const struct ip_conntrack *conntrack)
195{
196 enum sctp_conntrack state;
197
198 DEBUGP(__FUNCTION__);
199 DEBUGP("\n");
200
201 read_lock_bh(&sctp_lock);
202 state = conntrack->proto.sctp.state;
203 read_unlock_bh(&sctp_lock);
204
205 return seq_printf(s, "%s ", sctp_conntrack_names[state]);
206}
207
208#define for_each_sctp_chunk(skb, sch, _sch, offset, count) \
209for (offset = ip_hdrlen(skb) + sizeof(sctp_sctphdr_t), count = 0; \
210 offset < skb->len && \
211 (sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch)); \
212 offset += (ntohs(sch->length) + 3) & ~3, count++)
213
214/* Some validity checks to make sure the chunks are fine */
215static int do_basic_checks(struct ip_conntrack *conntrack,
216 const struct sk_buff *skb,
217 char *map)
218{
219 u_int32_t offset, count;
220 sctp_chunkhdr_t _sch, *sch;
221 int flag;
222
223 DEBUGP(__FUNCTION__);
224 DEBUGP("\n");
225
226 flag = 0;
227
228 for_each_sctp_chunk (skb, sch, _sch, offset, count) {
229 DEBUGP("Chunk Num: %d Type: %d\n", count, sch->type);
230
231 if (sch->type == SCTP_CID_INIT
232 || sch->type == SCTP_CID_INIT_ACK
233 || sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
234 flag = 1;
235 }
236
237 /*
238 * Cookie Ack/Echo chunks not the first OR
239 * Init / Init Ack / Shutdown compl chunks not the only chunks
240 * OR zero-length.
241 */
242 if (((sch->type == SCTP_CID_COOKIE_ACK
243 || sch->type == SCTP_CID_COOKIE_ECHO
244 || flag)
245 && count !=0) || !sch->length) {
246 DEBUGP("Basic checks failed\n");
247 return 1;
248 }
249
250 if (map) {
251 set_bit(sch->type, (void *)map);
252 }
253 }
254
255 DEBUGP("Basic checks passed\n");
256 return count == 0;
257}
258
259static int new_state(enum ip_conntrack_dir dir,
260 enum sctp_conntrack cur_state,
261 int chunk_type)
262{
263 int i;
264
265 DEBUGP(__FUNCTION__);
266 DEBUGP("\n");
267
268 DEBUGP("Chunk type: %d\n", chunk_type);
269
270 switch (chunk_type) {
271 case SCTP_CID_INIT:
272 DEBUGP("SCTP_CID_INIT\n");
273 i = 0; break;
274 case SCTP_CID_INIT_ACK:
275 DEBUGP("SCTP_CID_INIT_ACK\n");
276 i = 1; break;
277 case SCTP_CID_ABORT:
278 DEBUGP("SCTP_CID_ABORT\n");
279 i = 2; break;
280 case SCTP_CID_SHUTDOWN:
281 DEBUGP("SCTP_CID_SHUTDOWN\n");
282 i = 3; break;
283 case SCTP_CID_SHUTDOWN_ACK:
284 DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
285 i = 4; break;
286 case SCTP_CID_ERROR:
287 DEBUGP("SCTP_CID_ERROR\n");
288 i = 5; break;
289 case SCTP_CID_COOKIE_ECHO:
290 DEBUGP("SCTP_CID_COOKIE_ECHO\n");
291 i = 6; break;
292 case SCTP_CID_COOKIE_ACK:
293 DEBUGP("SCTP_CID_COOKIE_ACK\n");
294 i = 7; break;
295 case SCTP_CID_SHUTDOWN_COMPLETE:
296 DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
297 i = 8; break;
298 default:
299 /* Other chunks like DATA, SACK, HEARTBEAT and
300 its ACK do not cause a change in state */
301 DEBUGP("Unknown chunk type, Will stay in %s\n",
302 sctp_conntrack_names[cur_state]);
303 return cur_state;
304 }
305
306 DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
307 dir, sctp_conntrack_names[cur_state], chunk_type,
308 sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
309
310 return sctp_conntracks[dir][i][cur_state];
311}
312
313/* Returns verdict for packet, or -1 for invalid. */
314static int sctp_packet(struct ip_conntrack *conntrack,
315 const struct sk_buff *skb,
316 enum ip_conntrack_info ctinfo)
317{
318 enum sctp_conntrack newconntrack, oldsctpstate;
319 struct iphdr *iph = ip_hdr(skb);
320 sctp_sctphdr_t _sctph, *sh;
321 sctp_chunkhdr_t _sch, *sch;
322 u_int32_t offset, count;
323 char map[256 / sizeof (char)] = {0};
324
325 DEBUGP(__FUNCTION__);
326 DEBUGP("\n");
327
328 sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);
329 if (sh == NULL)
330 return -1;
331
332 if (do_basic_checks(conntrack, skb, map) != 0)
333 return -1;
334
335 /* Check the verification tag (Sec 8.5) */
336 if (!test_bit(SCTP_CID_INIT, (void *)map)
337 && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
338 && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
339 && !test_bit(SCTP_CID_ABORT, (void *)map)
340 && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
341 && (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
342 DEBUGP("Verification tag check failed\n");
343 return -1;
344 }
345
346 oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
347 for_each_sctp_chunk (skb, sch, _sch, offset, count) {
348 write_lock_bh(&sctp_lock);
349
350 /* Special cases of Verification tag check (Sec 8.5.1) */
351 if (sch->type == SCTP_CID_INIT) {
352 /* Sec 8.5.1 (A) */
353 if (sh->vtag != 0) {
354 write_unlock_bh(&sctp_lock);
355 return -1;
356 }
357 } else if (sch->type == SCTP_CID_ABORT) {
358 /* Sec 8.5.1 (B) */
359 if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
360 && !(sh->vtag == conntrack->proto.sctp.vtag
361 [1 - CTINFO2DIR(ctinfo)])) {
362 write_unlock_bh(&sctp_lock);
363 return -1;
364 }
365 } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
366 /* Sec 8.5.1 (C) */
367 if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
368 && !(sh->vtag == conntrack->proto.sctp.vtag
369 [1 - CTINFO2DIR(ctinfo)]
370 && (sch->flags & 1))) {
371 write_unlock_bh(&sctp_lock);
372 return -1;
373 }
374 } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
375 /* Sec 8.5.1 (D) */
376 if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
377 write_unlock_bh(&sctp_lock);
378 return -1;
379 }
380 }
381
382 oldsctpstate = conntrack->proto.sctp.state;
383 newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch->type);
384
385 /* Invalid */
386 if (newconntrack == SCTP_CONNTRACK_MAX) {
387 DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
388 CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
389 write_unlock_bh(&sctp_lock);
390 return -1;
391 }
392
393 /* If it is an INIT or an INIT ACK note down the vtag */
394 if (sch->type == SCTP_CID_INIT
395 || sch->type == SCTP_CID_INIT_ACK) {
396 sctp_inithdr_t _inithdr, *ih;
397
398 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
399 sizeof(_inithdr), &_inithdr);
400 if (ih == NULL) {
401 write_unlock_bh(&sctp_lock);
402 return -1;
403 }
404 DEBUGP("Setting vtag %x for dir %d\n",
405 ih->init_tag, !CTINFO2DIR(ctinfo));
406 conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
407 }
408
409 conntrack->proto.sctp.state = newconntrack;
410 if (oldsctpstate != newconntrack)
411 ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
412 write_unlock_bh(&sctp_lock);
413 }
414
415 ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
416
417 if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
418 && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
419 && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
420 DEBUGP("Setting assured bit\n");
421 set_bit(IPS_ASSURED_BIT, &conntrack->status);
422 ip_conntrack_event_cache(IPCT_STATUS, skb);
423 }
424
425 return NF_ACCEPT;
426}
427
428/* Called when a new connection for this protocol found. */
429static int sctp_new(struct ip_conntrack *conntrack,
430 const struct sk_buff *skb)
431{
432 enum sctp_conntrack newconntrack;
433 struct iphdr *iph = ip_hdr(skb);
434 sctp_sctphdr_t _sctph, *sh;
435 sctp_chunkhdr_t _sch, *sch;
436 u_int32_t offset, count;
437 char map[256 / sizeof (char)] = {0};
438
439 DEBUGP(__FUNCTION__);
440 DEBUGP("\n");
441
442 sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);
443 if (sh == NULL)
444 return 0;
445
446 if (do_basic_checks(conntrack, skb, map) != 0)
447 return 0;
448
449 /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
450 if ((test_bit (SCTP_CID_ABORT, (void *)map))
451 || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
452 || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
453 return 0;
454 }
455
456 newconntrack = SCTP_CONNTRACK_MAX;
457 for_each_sctp_chunk (skb, sch, _sch, offset, count) {
458 /* Don't need lock here: this conntrack not in circulation yet */
459 newconntrack = new_state (IP_CT_DIR_ORIGINAL,
460 SCTP_CONNTRACK_NONE, sch->type);
461
462 /* Invalid: delete conntrack */
463 if (newconntrack == SCTP_CONNTRACK_MAX) {
464 DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
465 return 0;
466 }
467
468 /* Copy the vtag into the state info */
469 if (sch->type == SCTP_CID_INIT) {
470 if (sh->vtag == 0) {
471 sctp_inithdr_t _inithdr, *ih;
472
473 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
474 sizeof(_inithdr), &_inithdr);
475 if (ih == NULL)
476 return 0;
477
478 DEBUGP("Setting vtag %x for new conn\n",
479 ih->init_tag);
480
481 conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
482 ih->init_tag;
483 } else {
484 /* Sec 8.5.1 (A) */
485 return 0;
486 }
487 }
488 /* If it is a shutdown ack OOTB packet, we expect a return
489 shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
490 else {
491 DEBUGP("Setting vtag %x for new conn OOTB\n",
492 sh->vtag);
493 conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
494 }
495
496 conntrack->proto.sctp.state = newconntrack;
497 }
498
499 return 1;
500}
501
502static struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
503 .proto = IPPROTO_SCTP,
504 .name = "sctp",
505 .pkt_to_tuple = sctp_pkt_to_tuple,
506 .invert_tuple = sctp_invert_tuple,
507 .print_tuple = sctp_print_tuple,
508 .print_conntrack = sctp_print_conntrack,
509 .packet = sctp_packet,
510 .new = sctp_new,
511 .destroy = NULL,
512 .me = THIS_MODULE,
513#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
514 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
515 .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
516 .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
517#endif
518};
519
520#ifdef CONFIG_SYSCTL
521static ctl_table ip_ct_sysctl_table[] = {
522 {
523 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
524 .procname = "ip_conntrack_sctp_timeout_closed",
525 .data = &ip_ct_sctp_timeout_closed,
526 .maxlen = sizeof(unsigned int),
527 .mode = 0644,
528 .proc_handler = &proc_dointvec_jiffies,
529 },
530 {
531 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
532 .procname = "ip_conntrack_sctp_timeout_cookie_wait",
533 .data = &ip_ct_sctp_timeout_cookie_wait,
534 .maxlen = sizeof(unsigned int),
535 .mode = 0644,
536 .proc_handler = &proc_dointvec_jiffies,
537 },
538 {
539 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
540 .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
541 .data = &ip_ct_sctp_timeout_cookie_echoed,
542 .maxlen = sizeof(unsigned int),
543 .mode = 0644,
544 .proc_handler = &proc_dointvec_jiffies,
545 },
546 {
547 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
548 .procname = "ip_conntrack_sctp_timeout_established",
549 .data = &ip_ct_sctp_timeout_established,
550 .maxlen = sizeof(unsigned int),
551 .mode = 0644,
552 .proc_handler = &proc_dointvec_jiffies,
553 },
554 {
555 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
556 .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
557 .data = &ip_ct_sctp_timeout_shutdown_sent,
558 .maxlen = sizeof(unsigned int),
559 .mode = 0644,
560 .proc_handler = &proc_dointvec_jiffies,
561 },
562 {
563 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
564 .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
565 .data = &ip_ct_sctp_timeout_shutdown_recd,
566 .maxlen = sizeof(unsigned int),
567 .mode = 0644,
568 .proc_handler = &proc_dointvec_jiffies,
569 },
570 {
571 .ctl_name = NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
572 .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
573 .data = &ip_ct_sctp_timeout_shutdown_ack_sent,
574 .maxlen = sizeof(unsigned int),
575 .mode = 0644,
576 .proc_handler = &proc_dointvec_jiffies,
577 },
578 { .ctl_name = 0 }
579};
580
581static ctl_table ip_ct_netfilter_table[] = {
582 {
583 .ctl_name = NET_IPV4_NETFILTER,
584 .procname = "netfilter",
585 .mode = 0555,
586 .child = ip_ct_sysctl_table,
587 },
588 { .ctl_name = 0 }
589};
590
591static ctl_table ip_ct_ipv4_table[] = {
592 {
593 .ctl_name = NET_IPV4,
594 .procname = "ipv4",
595 .mode = 0555,
596 .child = ip_ct_netfilter_table,
597 },
598 { .ctl_name = 0 }
599};
600
601static ctl_table ip_ct_net_table[] = {
602 {
603 .ctl_name = CTL_NET,
604 .procname = "net",
605 .mode = 0555,
606 .child = ip_ct_ipv4_table,
607 },
608 { .ctl_name = 0 }
609};
610
611static struct ctl_table_header *ip_ct_sysctl_header;
612#endif
613
614static int __init ip_conntrack_proto_sctp_init(void)
615{
616 int ret;
617
618 ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
619 if (ret) {
620 printk("ip_conntrack_proto_sctp: protocol register failed\n");
621 goto out;
622 }
623
624#ifdef CONFIG_SYSCTL
625 ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table);
626 if (ip_ct_sysctl_header == NULL) {
627 ret = -ENOMEM;
628 printk("ip_conntrack_proto_sctp: can't register to sysctl.\n");
629 goto cleanup;
630 }
631#endif
632
633 return ret;
634
635#ifdef CONFIG_SYSCTL
636 cleanup:
637 ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
638#endif
639 out:
640 DEBUGP("SCTP conntrack module loading %s\n",
641 ret ? "failed": "succeeded");
642 return ret;
643}
644
645static void __exit ip_conntrack_proto_sctp_fini(void)
646{
647 ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
648#ifdef CONFIG_SYSCTL
649 unregister_sysctl_table(ip_ct_sysctl_header);
650#endif
651 DEBUGP("SCTP conntrack module unloaded\n");
652}
653
654module_init(ip_conntrack_proto_sctp_init);
655module_exit(ip_conntrack_proto_sctp_fini);
656
657MODULE_LICENSE("GPL");
658MODULE_AUTHOR("Kiran Kumar Immidi");
659MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
deleted file mode 100644
index d03436edfd93..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ /dev/null
@@ -1,1163 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>:
9 * - Real stateful connection tracking
10 * - Modified state transitions table
11 * - Window scaling support added
12 * - SACK support added
13 *
14 * Willy Tarreau:
15 * - State table bugfixes
16 * - More robust state changes
17 * - Tuning timer parameters
18 *
19 * version 2.2
20 */
21
22#include <linux/types.h>
23#include <linux/timer.h>
24#include <linux/netfilter.h>
25#include <linux/module.h>
26#include <linux/in.h>
27#include <linux/ip.h>
28#include <linux/tcp.h>
29#include <linux/spinlock.h>
30
31#include <net/tcp.h>
32
33#include <linux/netfilter_ipv4.h>
34#include <linux/netfilter_ipv4/ip_conntrack.h>
35#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
36
37#if 0
38#define DEBUGP printk
39#define DEBUGP_VARS
40#else
41#define DEBUGP(format, args...)
42#endif
43
44/* Protects conntrack->proto.tcp */
45static DEFINE_RWLOCK(tcp_lock);
46
47/* "Be conservative in what you do,
48 be liberal in what you accept from others."
49 If it's non-zero, we mark only out of window RST segments as INVALID. */
50int ip_ct_tcp_be_liberal __read_mostly = 0;
51
52/* If it is set to zero, we disable picking up already established
53 connections. */
54int ip_ct_tcp_loose __read_mostly = 1;
55
56/* Max number of the retransmitted packets without receiving an (acceptable)
57 ACK from the destination. If this number is reached, a shorter timer
58 will be started. */
59int ip_ct_tcp_max_retrans __read_mostly = 3;
60
61 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
62 closely. They're more complex. --RR */
63
64static const char *tcp_conntrack_names[] = {
65 "NONE",
66 "SYN_SENT",
67 "SYN_RECV",
68 "ESTABLISHED",
69 "FIN_WAIT",
70 "CLOSE_WAIT",
71 "LAST_ACK",
72 "TIME_WAIT",
73 "CLOSE",
74 "LISTEN"
75};
76
77#define SECS * HZ
78#define MINS * 60 SECS
79#define HOURS * 60 MINS
80#define DAYS * 24 HOURS
81
82unsigned int ip_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
83unsigned int ip_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
84unsigned int ip_ct_tcp_timeout_established __read_mostly = 5 DAYS;
85unsigned int ip_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
86unsigned int ip_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
87unsigned int ip_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
88unsigned int ip_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
89unsigned int ip_ct_tcp_timeout_close __read_mostly = 10 SECS;
90
91/* RFC1122 says the R2 limit should be at least 100 seconds.
92 Linux uses 15 packets as limit, which corresponds
93 to ~13-30min depending on RTO. */
94unsigned int ip_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
95
96static const unsigned int * tcp_timeouts[]
97= { NULL, /* TCP_CONNTRACK_NONE */
98 &ip_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
99 &ip_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
100 &ip_ct_tcp_timeout_established, /* TCP_CONNTRACK_ESTABLISHED, */
101 &ip_ct_tcp_timeout_fin_wait, /* TCP_CONNTRACK_FIN_WAIT, */
102 &ip_ct_tcp_timeout_close_wait, /* TCP_CONNTRACK_CLOSE_WAIT, */
103 &ip_ct_tcp_timeout_last_ack, /* TCP_CONNTRACK_LAST_ACK, */
104 &ip_ct_tcp_timeout_time_wait, /* TCP_CONNTRACK_TIME_WAIT, */
105 &ip_ct_tcp_timeout_close, /* TCP_CONNTRACK_CLOSE, */
106 NULL, /* TCP_CONNTRACK_LISTEN */
107 };
108
109#define sNO TCP_CONNTRACK_NONE
110#define sSS TCP_CONNTRACK_SYN_SENT
111#define sSR TCP_CONNTRACK_SYN_RECV
112#define sES TCP_CONNTRACK_ESTABLISHED
113#define sFW TCP_CONNTRACK_FIN_WAIT
114#define sCW TCP_CONNTRACK_CLOSE_WAIT
115#define sLA TCP_CONNTRACK_LAST_ACK
116#define sTW TCP_CONNTRACK_TIME_WAIT
117#define sCL TCP_CONNTRACK_CLOSE
118#define sLI TCP_CONNTRACK_LISTEN
119#define sIV TCP_CONNTRACK_MAX
120#define sIG TCP_CONNTRACK_IGNORE
121
122/* What TCP flags are set from RST/SYN/FIN/ACK. */
123enum tcp_bit_set {
124 TCP_SYN_SET,
125 TCP_SYNACK_SET,
126 TCP_FIN_SET,
127 TCP_ACK_SET,
128 TCP_RST_SET,
129 TCP_NONE_SET,
130};
131
132/*
133 * The TCP state transition table needs a few words...
134 *
135 * We are the man in the middle. All the packets go through us
136 * but might get lost in transit to the destination.
137 * It is assumed that the destinations can't receive segments
138 * we haven't seen.
139 *
140 * The checked segment is in window, but our windows are *not*
141 * equivalent with the ones of the sender/receiver. We always
142 * try to guess the state of the current sender.
143 *
144 * The meaning of the states are:
145 *
146 * NONE: initial state
147 * SYN_SENT: SYN-only packet seen
148 * SYN_RECV: SYN-ACK packet seen
149 * ESTABLISHED: ACK packet seen
150 * FIN_WAIT: FIN packet seen
151 * CLOSE_WAIT: ACK seen (after FIN)
152 * LAST_ACK: FIN seen (after FIN)
153 * TIME_WAIT: last ACK seen
154 * CLOSE: closed connection
155 *
156 * LISTEN state is not used.
157 *
158 * Packets marked as IGNORED (sIG):
159 * if they may be either invalid or valid
160 * and the receiver may send back a connection
161 * closing RST or a SYN/ACK.
162 *
163 * Packets marked as INVALID (sIV):
164 * if they are invalid
165 * or we do not support the request (simultaneous open)
166 */
167static const enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
168 {
169/* ORIGINAL */
170/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
171/*syn*/ { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sIV },
172/*
173 * sNO -> sSS Initialize a new connection
174 * sSS -> sSS Retransmitted SYN
175 * sSR -> sIG Late retransmitted SYN?
176 * sES -> sIG Error: SYNs in window outside the SYN_SENT state
177 * are errors. Receiver will reply with RST
178 * and close the connection.
179 * Or we are not in sync and hold a dead connection.
180 * sFW -> sIG
181 * sCW -> sIG
182 * sLA -> sIG
183 * sTW -> sSS Reopened connection (RFC 1122).
184 * sCL -> sSS
185 */
186/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
187/*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
188/*
189 * A SYN/ACK from the client is always invalid:
190 * - either it tries to set up a simultaneous open, which is
191 * not supported;
192 * - or the firewall has just been inserted between the two hosts
193 * during the session set-up. The SYN will be retransmitted
194 * by the true client (or it'll time out).
195 */
196/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
197/*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
198/*
199 * sNO -> sIV Too late and no reason to do anything...
200 * sSS -> sIV Client migth not send FIN in this state:
201 * we enforce waiting for a SYN/ACK reply first.
202 * sSR -> sFW Close started.
203 * sES -> sFW
204 * sFW -> sLA FIN seen in both directions, waiting for
205 * the last ACK.
206 * Migth be a retransmitted FIN as well...
207 * sCW -> sLA
208 * sLA -> sLA Retransmitted FIN. Remain in the same state.
209 * sTW -> sTW
210 * sCL -> sCL
211 */
212/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
213/*ack*/ { sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV },
214/*
215 * sNO -> sES Assumed.
216 * sSS -> sIV ACK is invalid: we haven't seen a SYN/ACK yet.
217 * sSR -> sES Established state is reached.
218 * sES -> sES :-)
219 * sFW -> sCW Normal close request answered by ACK.
220 * sCW -> sCW
221 * sLA -> sTW Last ACK detected.
222 * sTW -> sTW Retransmitted last ACK. Remain in the same state.
223 * sCL -> sCL
224 */
225/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
226/*rst*/ { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
227/*none*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
228 },
229 {
230/* REPLY */
231/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
232/*syn*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
233/*
234 * sNO -> sIV Never reached.
235 * sSS -> sIV Simultaneous open, not supported
236 * sSR -> sIV Simultaneous open, not supported.
237 * sES -> sIV Server may not initiate a connection.
238 * sFW -> sIV
239 * sCW -> sIV
240 * sLA -> sIV
241 * sTW -> sIV Reopened connection, but server may not do it.
242 * sCL -> sIV
243 */
244/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
245/*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIV },
246/*
247 * sSS -> sSR Standard open.
248 * sSR -> sSR Retransmitted SYN/ACK.
249 * sES -> sIG Late retransmitted SYN/ACK?
250 * sFW -> sIG Might be SYN/ACK answering ignored SYN
251 * sCW -> sIG
252 * sLA -> sIG
253 * sTW -> sIG
254 * sCL -> sIG
255 */
256/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
257/*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
258/*
259 * sSS -> sIV Server might not send FIN in this state.
260 * sSR -> sFW Close started.
261 * sES -> sFW
262 * sFW -> sLA FIN seen in both directions.
263 * sCW -> sLA
264 * sLA -> sLA Retransmitted FIN.
265 * sTW -> sTW
266 * sCL -> sCL
267 */
268/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
269/*ack*/ { sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
270/*
271 * sSS -> sIG Might be a half-open connection.
272 * sSR -> sSR Might answer late resent SYN.
273 * sES -> sES :-)
274 * sFW -> sCW Normal close request answered by ACK.
275 * sCW -> sCW
276 * sLA -> sTW Last ACK detected.
277 * sTW -> sTW Retransmitted last ACK.
278 * sCL -> sCL
279 */
280/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
281/*rst*/ { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
282/*none*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
283 }
284};
285
286static int tcp_pkt_to_tuple(const struct sk_buff *skb,
287 unsigned int dataoff,
288 struct ip_conntrack_tuple *tuple)
289{
290 struct tcphdr _hdr, *hp;
291
292 /* Actually only need first 8 bytes. */
293 hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
294 if (hp == NULL)
295 return 0;
296
297 tuple->src.u.tcp.port = hp->source;
298 tuple->dst.u.tcp.port = hp->dest;
299
300 return 1;
301}
302
303static int tcp_invert_tuple(struct ip_conntrack_tuple *tuple,
304 const struct ip_conntrack_tuple *orig)
305{
306 tuple->src.u.tcp.port = orig->dst.u.tcp.port;
307 tuple->dst.u.tcp.port = orig->src.u.tcp.port;
308 return 1;
309}
310
311/* Print out the per-protocol part of the tuple. */
312static int tcp_print_tuple(struct seq_file *s,
313 const struct ip_conntrack_tuple *tuple)
314{
315 return seq_printf(s, "sport=%hu dport=%hu ",
316 ntohs(tuple->src.u.tcp.port),
317 ntohs(tuple->dst.u.tcp.port));
318}
319
320/* Print out the private part of the conntrack. */
321static int tcp_print_conntrack(struct seq_file *s,
322 const struct ip_conntrack *conntrack)
323{
324 enum tcp_conntrack state;
325
326 read_lock_bh(&tcp_lock);
327 state = conntrack->proto.tcp.state;
328 read_unlock_bh(&tcp_lock);
329
330 return seq_printf(s, "%s ", tcp_conntrack_names[state]);
331}
332
333#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
334 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
335static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
336 const struct ip_conntrack *ct)
337{
338 struct nfattr *nest_parms;
339
340 read_lock_bh(&tcp_lock);
341 nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
342 NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
343 &ct->proto.tcp.state);
344 read_unlock_bh(&tcp_lock);
345
346 NFA_NEST_END(skb, nest_parms);
347
348 return 0;
349
350nfattr_failure:
351 read_unlock_bh(&tcp_lock);
352 return -1;
353}
354
355static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
356 [CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
357};
358
359static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct)
360{
361 struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
362 struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
363
364 /* updates could not contain anything about the private
365 * protocol info, in that case skip the parsing */
366 if (!attr)
367 return 0;
368
369 nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
370
371 if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))
372 return -EINVAL;
373
374 if (!tb[CTA_PROTOINFO_TCP_STATE-1])
375 return -EINVAL;
376
377 write_lock_bh(&tcp_lock);
378 ct->proto.tcp.state =
379 *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
380 write_unlock_bh(&tcp_lock);
381
382 return 0;
383}
384#endif
385
386static unsigned int get_conntrack_index(const struct tcphdr *tcph)
387{
388 if (tcph->rst) return TCP_RST_SET;
389 else if (tcph->syn) return (tcph->ack ? TCP_SYNACK_SET : TCP_SYN_SET);
390 else if (tcph->fin) return TCP_FIN_SET;
391 else if (tcph->ack) return TCP_ACK_SET;
392 else return TCP_NONE_SET;
393}
394
395/* TCP connection tracking based on 'Real Stateful TCP Packet Filtering
396 in IP Filter' by Guido van Rooij.
397
398 http://www.nluug.nl/events/sane2000/papers.html
399 http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
400
401 The boundaries and the conditions are changed according to RFC793:
402 the packet must intersect the window (i.e. segments may be
403 after the right or before the left edge) and thus receivers may ACK
404 segments after the right edge of the window.
405
406 td_maxend = max(sack + max(win,1)) seen in reply packets
407 td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
408 td_maxwin += seq + len - sender.td_maxend
409 if seq + len > sender.td_maxend
410 td_end = max(seq + len) seen in sent packets
411
412 I. Upper bound for valid data: seq <= sender.td_maxend
413 II. Lower bound for valid data: seq + len >= sender.td_end - receiver.td_maxwin
414 III. Upper bound for valid ack: sack <= receiver.td_end
415 IV. Lower bound for valid ack: ack >= receiver.td_end - MAXACKWINDOW
416
417 where sack is the highest right edge of sack block found in the packet.
418
419 The upper bound limit for a valid ack is not ignored -
420 we doesn't have to deal with fragments.
421*/
422
423static inline __u32 segment_seq_plus_len(__u32 seq,
424 size_t len,
425 struct iphdr *iph,
426 struct tcphdr *tcph)
427{
428 return (seq + len - (iph->ihl + tcph->doff)*4
429 + (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
430}
431
432/* Fixme: what about big packets? */
433#define MAXACKWINCONST 66000
434#define MAXACKWINDOW(sender) \
435 ((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin \
436 : MAXACKWINCONST)
437
438/*
439 * Simplified tcp_parse_options routine from tcp_input.c
440 */
441static void tcp_options(const struct sk_buff *skb,
442 struct iphdr *iph,
443 struct tcphdr *tcph,
444 struct ip_ct_tcp_state *state)
445{
446 unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
447 unsigned char *ptr;
448 int length = (tcph->doff*4) - sizeof(struct tcphdr);
449
450 if (!length)
451 return;
452
453 ptr = skb_header_pointer(skb,
454 (iph->ihl * 4) + sizeof(struct tcphdr),
455 length, buff);
456 BUG_ON(ptr == NULL);
457
458 state->td_scale =
459 state->flags = 0;
460
461 while (length > 0) {
462 int opcode=*ptr++;
463 int opsize;
464
465 switch (opcode) {
466 case TCPOPT_EOL:
467 return;
468 case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
469 length--;
470 continue;
471 default:
472 opsize=*ptr++;
473 if (opsize < 2) /* "silly options" */
474 return;
475 if (opsize > length)
476 break; /* don't parse partial options */
477
478 if (opcode == TCPOPT_SACK_PERM
479 && opsize == TCPOLEN_SACK_PERM)
480 state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
481 else if (opcode == TCPOPT_WINDOW
482 && opsize == TCPOLEN_WINDOW) {
483 state->td_scale = *(u_int8_t *)ptr;
484
485 if (state->td_scale > 14) {
486 /* See RFC1323 */
487 state->td_scale = 14;
488 }
489 state->flags |=
490 IP_CT_TCP_FLAG_WINDOW_SCALE;
491 }
492 ptr += opsize - 2;
493 length -= opsize;
494 }
495 }
496}
497
498static void tcp_sack(const struct sk_buff *skb,
499 struct iphdr *iph,
500 struct tcphdr *tcph,
501 __u32 *sack)
502{
503 unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
504 unsigned char *ptr;
505 int length = (tcph->doff*4) - sizeof(struct tcphdr);
506 __u32 tmp;
507
508 if (!length)
509 return;
510
511 ptr = skb_header_pointer(skb,
512 (iph->ihl * 4) + sizeof(struct tcphdr),
513 length, buff);
514 BUG_ON(ptr == NULL);
515
516 /* Fast path for timestamp-only option */
517 if (length == TCPOLEN_TSTAMP_ALIGNED*4
518 && *(__be32 *)ptr == htonl((TCPOPT_NOP << 24)
519 | (TCPOPT_NOP << 16)
520 | (TCPOPT_TIMESTAMP << 8)
521 | TCPOLEN_TIMESTAMP))
522 return;
523
524 while (length > 0) {
525 int opcode=*ptr++;
526 int opsize, i;
527
528 switch (opcode) {
529 case TCPOPT_EOL:
530 return;
531 case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
532 length--;
533 continue;
534 default:
535 opsize=*ptr++;
536 if (opsize < 2) /* "silly options" */
537 return;
538 if (opsize > length)
539 break; /* don't parse partial options */
540
541 if (opcode == TCPOPT_SACK
542 && opsize >= (TCPOLEN_SACK_BASE
543 + TCPOLEN_SACK_PERBLOCK)
544 && !((opsize - TCPOLEN_SACK_BASE)
545 % TCPOLEN_SACK_PERBLOCK)) {
546 for (i = 0;
547 i < (opsize - TCPOLEN_SACK_BASE);
548 i += TCPOLEN_SACK_PERBLOCK) {
549 tmp = ntohl(*((__be32 *)(ptr+i)+1));
550
551 if (after(tmp, *sack))
552 *sack = tmp;
553 }
554 return;
555 }
556 ptr += opsize - 2;
557 length -= opsize;
558 }
559 }
560}
561
562static int tcp_in_window(struct ip_ct_tcp *state,
563 enum ip_conntrack_dir dir,
564 unsigned int index,
565 const struct sk_buff *skb,
566 struct iphdr *iph,
567 struct tcphdr *tcph)
568{
569 struct ip_ct_tcp_state *sender = &state->seen[dir];
570 struct ip_ct_tcp_state *receiver = &state->seen[!dir];
571 __u32 seq, ack, sack, end, win, swin;
572 int res;
573
574 /*
575 * Get the required data from the packet.
576 */
577 seq = ntohl(tcph->seq);
578 ack = sack = ntohl(tcph->ack_seq);
579 win = ntohs(tcph->window);
580 end = segment_seq_plus_len(seq, skb->len, iph, tcph);
581
582 if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
583 tcp_sack(skb, iph, tcph, &sack);
584
585 DEBUGP("tcp_in_window: START\n");
586 DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
587 "seq=%u ack=%u sack=%u win=%u end=%u\n",
588 NIPQUAD(iph->saddr), ntohs(tcph->source),
589 NIPQUAD(iph->daddr), ntohs(tcph->dest),
590 seq, ack, sack, win, end);
591 DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
592 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
593 sender->td_end, sender->td_maxend, sender->td_maxwin,
594 sender->td_scale,
595 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
596 receiver->td_scale);
597
598 if (sender->td_end == 0) {
599 /*
600 * Initialize sender data.
601 */
602 if (tcph->syn && tcph->ack) {
603 /*
604 * Outgoing SYN-ACK in reply to a SYN.
605 */
606 sender->td_end =
607 sender->td_maxend = end;
608 sender->td_maxwin = (win == 0 ? 1 : win);
609
610 tcp_options(skb, iph, tcph, sender);
611 /*
612 * RFC 1323:
613 * Both sides must send the Window Scale option
614 * to enable window scaling in either direction.
615 */
616 if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
617 && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
618 sender->td_scale =
619 receiver->td_scale = 0;
620 } else {
621 /*
622 * We are in the middle of a connection,
623 * its history is lost for us.
624 * Let's try to use the data from the packet.
625 */
626 sender->td_end = end;
627 sender->td_maxwin = (win == 0 ? 1 : win);
628 sender->td_maxend = end + sender->td_maxwin;
629 }
630 } else if (((state->state == TCP_CONNTRACK_SYN_SENT
631 && dir == IP_CT_DIR_ORIGINAL)
632 || (state->state == TCP_CONNTRACK_SYN_RECV
633 && dir == IP_CT_DIR_REPLY))
634 && after(end, sender->td_end)) {
635 /*
636 * RFC 793: "if a TCP is reinitialized ... then it need
637 * not wait at all; it must only be sure to use sequence
638 * numbers larger than those recently used."
639 */
640 sender->td_end =
641 sender->td_maxend = end;
642 sender->td_maxwin = (win == 0 ? 1 : win);
643
644 tcp_options(skb, iph, tcph, sender);
645 }
646
647 if (!(tcph->ack)) {
648 /*
649 * If there is no ACK, just pretend it was set and OK.
650 */
651 ack = sack = receiver->td_end;
652 } else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) ==
653 (TCP_FLAG_ACK|TCP_FLAG_RST))
654 && (ack == 0)) {
655 /*
656 * Broken TCP stacks, that set ACK in RST packets as well
657 * with zero ack value.
658 */
659 ack = sack = receiver->td_end;
660 }
661
662 if (seq == end
663 && (!tcph->rst
664 || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
665 /*
666 * Packets contains no data: we assume it is valid
667 * and check the ack value only.
668 * However RST segments are always validated by their
669 * SEQ number, except when seq == 0 (reset sent answering
670 * SYN.
671 */
672 seq = end = sender->td_end;
673
674 DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
675 "seq=%u ack=%u sack =%u win=%u end=%u\n",
676 NIPQUAD(iph->saddr), ntohs(tcph->source),
677 NIPQUAD(iph->daddr), ntohs(tcph->dest),
678 seq, ack, sack, win, end);
679 DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
680 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
681 sender->td_end, sender->td_maxend, sender->td_maxwin,
682 sender->td_scale,
683 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
684 receiver->td_scale);
685
686 DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
687 before(seq, sender->td_maxend + 1),
688 after(end, sender->td_end - receiver->td_maxwin - 1),
689 before(sack, receiver->td_end + 1),
690 after(ack, receiver->td_end - MAXACKWINDOW(sender)));
691
692 if (before(seq, sender->td_maxend + 1) &&
693 after(end, sender->td_end - receiver->td_maxwin - 1) &&
694 before(sack, receiver->td_end + 1) &&
695 after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
696 /*
697 * Take into account window scaling (RFC 1323).
698 */
699 if (!tcph->syn)
700 win <<= sender->td_scale;
701
702 /*
703 * Update sender data.
704 */
705 swin = win + (sack - ack);
706 if (sender->td_maxwin < swin)
707 sender->td_maxwin = swin;
708 if (after(end, sender->td_end))
709 sender->td_end = end;
710 /*
711 * Update receiver data.
712 */
713 if (after(end, sender->td_maxend))
714 receiver->td_maxwin += end - sender->td_maxend;
715 if (after(sack + win, receiver->td_maxend - 1)) {
716 receiver->td_maxend = sack + win;
717 if (win == 0)
718 receiver->td_maxend++;
719 }
720
721 /*
722 * Check retransmissions.
723 */
724 if (index == TCP_ACK_SET) {
725 if (state->last_dir == dir
726 && state->last_seq == seq
727 && state->last_ack == ack
728 && state->last_end == end
729 && state->last_win == win)
730 state->retrans++;
731 else {
732 state->last_dir = dir;
733 state->last_seq = seq;
734 state->last_ack = ack;
735 state->last_end = end;
736 state->last_win = win;
737 state->retrans = 0;
738 }
739 }
740 res = 1;
741 } else {
742 res = 0;
743 if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
744 ip_ct_tcp_be_liberal)
745 res = 1;
746 if (!res && LOG_INVALID(IPPROTO_TCP))
747 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
748 "ip_ct_tcp: %s ",
749 before(seq, sender->td_maxend + 1) ?
750 after(end, sender->td_end - receiver->td_maxwin - 1) ?
751 before(sack, receiver->td_end + 1) ?
752 after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
753 : "ACK is under the lower bound (possible overly delayed ACK)"
754 : "ACK is over the upper bound (ACKed data not seen yet)"
755 : "SEQ is under the lower bound (already ACKed data retransmitted)"
756 : "SEQ is over the upper bound (over the window of the receiver)");
757 }
758
759 DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
760 "receiver end=%u maxend=%u maxwin=%u\n",
761 res, sender->td_end, sender->td_maxend, sender->td_maxwin,
762 receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
763
764 return res;
765}
766
767#ifdef CONFIG_IP_NF_NAT_NEEDED
768/* Update sender->td_end after NAT successfully mangled the packet */
769void ip_conntrack_tcp_update(struct sk_buff *skb,
770 struct ip_conntrack *conntrack,
771 enum ip_conntrack_dir dir)
772{
773 struct iphdr *iph = ip_hdr(skb);
774 struct tcphdr *tcph = (void *)iph + ip_hdrlen(skb);
775 __u32 end;
776#ifdef DEBUGP_VARS
777 struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
778 struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir];
779#endif
780
781 end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph);
782
783 write_lock_bh(&tcp_lock);
784 /*
785 * We have to worry for the ack in the reply packet only...
786 */
787 if (after(end, conntrack->proto.tcp.seen[dir].td_end))
788 conntrack->proto.tcp.seen[dir].td_end = end;
789 conntrack->proto.tcp.last_end = end;
790 write_unlock_bh(&tcp_lock);
791 DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
792 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
793 sender->td_end, sender->td_maxend, sender->td_maxwin,
794 sender->td_scale,
795 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
796 receiver->td_scale);
797}
798
799#endif
800
801#define TH_FIN 0x01
802#define TH_SYN 0x02
803#define TH_RST 0x04
804#define TH_PUSH 0x08
805#define TH_ACK 0x10
806#define TH_URG 0x20
807#define TH_ECE 0x40
808#define TH_CWR 0x80
809
810/* table of valid flag combinations - ECE and CWR are always valid */
811static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
812{
813 [TH_SYN] = 1,
814 [TH_SYN|TH_PUSH] = 1,
815 [TH_SYN|TH_URG] = 1,
816 [TH_SYN|TH_PUSH|TH_URG] = 1,
817 [TH_SYN|TH_ACK] = 1,
818 [TH_SYN|TH_ACK|TH_PUSH] = 1,
819 [TH_RST] = 1,
820 [TH_RST|TH_ACK] = 1,
821 [TH_RST|TH_ACK|TH_PUSH] = 1,
822 [TH_FIN|TH_ACK] = 1,
823 [TH_ACK] = 1,
824 [TH_ACK|TH_PUSH] = 1,
825 [TH_ACK|TH_URG] = 1,
826 [TH_ACK|TH_URG|TH_PUSH] = 1,
827 [TH_FIN|TH_ACK|TH_PUSH] = 1,
828 [TH_FIN|TH_ACK|TH_URG] = 1,
829 [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1,
830};
831
832/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */
833static int tcp_error(struct sk_buff *skb,
834 enum ip_conntrack_info *ctinfo,
835 unsigned int hooknum)
836{
837 const unsigned int hdrlen = ip_hdrlen(skb);
838 struct tcphdr _tcph, *th;
839 unsigned int tcplen = skb->len - hdrlen;
840 u_int8_t tcpflags;
841
842 /* Smaller that minimal TCP header? */
843 th = skb_header_pointer(skb, hdrlen,
844 sizeof(_tcph), &_tcph);
845 if (th == NULL) {
846 if (LOG_INVALID(IPPROTO_TCP))
847 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
848 "ip_ct_tcp: short packet ");
849 return -NF_ACCEPT;
850 }
851
852 /* Not whole TCP header or malformed packet */
853 if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
854 if (LOG_INVALID(IPPROTO_TCP))
855 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
856 "ip_ct_tcp: truncated/malformed packet ");
857 return -NF_ACCEPT;
858 }
859
860 /* Checksum invalid? Ignore.
861 * We skip checking packets on the outgoing path
862 * because it is assumed to be correct.
863 */
864 /* FIXME: Source route IP option packets --RR */
865 if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
866 nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_TCP)) {
867 if (LOG_INVALID(IPPROTO_TCP))
868 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
869 "ip_ct_tcp: bad TCP checksum ");
870 return -NF_ACCEPT;
871 }
872
873 /* Check TCP flags. */
874 tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR));
875 if (!tcp_valid_flags[tcpflags]) {
876 if (LOG_INVALID(IPPROTO_TCP))
877 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
878 "ip_ct_tcp: invalid TCP flag combination ");
879 return -NF_ACCEPT;
880 }
881
882 return NF_ACCEPT;
883}
884
885/* Returns verdict for packet, or -1 for invalid. */
886static int tcp_packet(struct ip_conntrack *conntrack,
887 const struct sk_buff *skb,
888 enum ip_conntrack_info ctinfo)
889{
890 enum tcp_conntrack new_state, old_state;
891 enum ip_conntrack_dir dir;
892 struct iphdr *iph = ip_hdr(skb);
893 struct tcphdr *th, _tcph;
894 unsigned long timeout;
895 unsigned int index;
896
897 th = skb_header_pointer(skb, iph->ihl * 4,
898 sizeof(_tcph), &_tcph);
899 BUG_ON(th == NULL);
900
901 write_lock_bh(&tcp_lock);
902 old_state = conntrack->proto.tcp.state;
903 dir = CTINFO2DIR(ctinfo);
904 index = get_conntrack_index(th);
905 new_state = tcp_conntracks[dir][index][old_state];
906
907 switch (new_state) {
908 case TCP_CONNTRACK_IGNORE:
909 /* Ignored packets:
910 *
911 * a) SYN in ORIGINAL
912 * b) SYN/ACK in REPLY
913 * c) ACK in reply direction after initial SYN in original.
914 */
915 if (index == TCP_SYNACK_SET
916 && conntrack->proto.tcp.last_index == TCP_SYN_SET
917 && conntrack->proto.tcp.last_dir != dir
918 && ntohl(th->ack_seq) ==
919 conntrack->proto.tcp.last_end) {
920 /* This SYN/ACK acknowledges a SYN that we earlier
921 * ignored as invalid. This means that the client and
922 * the server are both in sync, while the firewall is
923 * not. We kill this session and block the SYN/ACK so
924 * that the client cannot but retransmit its SYN and
925 * thus initiate a clean new session.
926 */
927 write_unlock_bh(&tcp_lock);
928 if (LOG_INVALID(IPPROTO_TCP))
929 nf_log_packet(PF_INET, 0, skb, NULL, NULL,
930 NULL, "ip_ct_tcp: "
931 "killing out of sync session ");
932 if (del_timer(&conntrack->timeout))
933 conntrack->timeout.function((unsigned long)
934 conntrack);
935 return -NF_DROP;
936 }
937 conntrack->proto.tcp.last_index = index;
938 conntrack->proto.tcp.last_dir = dir;
939 conntrack->proto.tcp.last_seq = ntohl(th->seq);
940 conntrack->proto.tcp.last_end =
941 segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
942
943 write_unlock_bh(&tcp_lock);
944 if (LOG_INVALID(IPPROTO_TCP))
945 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
946 "ip_ct_tcp: invalid packet ignored ");
947 return NF_ACCEPT;
948 case TCP_CONNTRACK_MAX:
949 /* Invalid packet */
950 DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
951 dir, get_conntrack_index(th),
952 old_state);
953 write_unlock_bh(&tcp_lock);
954 if (LOG_INVALID(IPPROTO_TCP))
955 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
956 "ip_ct_tcp: invalid state ");
957 return -NF_ACCEPT;
958 case TCP_CONNTRACK_SYN_SENT:
959 if (old_state < TCP_CONNTRACK_TIME_WAIT)
960 break;
961 if ((conntrack->proto.tcp.seen[dir].flags &
962 IP_CT_TCP_FLAG_CLOSE_INIT)
963 || after(ntohl(th->seq),
964 conntrack->proto.tcp.seen[dir].td_end)) {
965 /* Attempt to reopen a closed connection.
966 * Delete this connection and look up again. */
967 write_unlock_bh(&tcp_lock);
968 if (del_timer(&conntrack->timeout))
969 conntrack->timeout.function((unsigned long)
970 conntrack);
971 return -NF_REPEAT;
972 } else {
973 write_unlock_bh(&tcp_lock);
974 if (LOG_INVALID(IPPROTO_TCP))
975 nf_log_packet(PF_INET, 0, skb, NULL, NULL,
976 NULL, "ip_ct_tcp: invalid SYN");
977 return -NF_ACCEPT;
978 }
979 case TCP_CONNTRACK_CLOSE:
980 if (index == TCP_RST_SET
981 && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
982 && conntrack->proto.tcp.last_index == TCP_SYN_SET)
983 || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
984 && conntrack->proto.tcp.last_index == TCP_ACK_SET))
985 && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
986 /* RST sent to invalid SYN or ACK we had let through
987 * at a) and c) above:
988 *
989 * a) SYN was in window then
990 * c) we hold a half-open connection.
991 *
992 * Delete our connection entry.
993 * We skip window checking, because packet might ACK
994 * segments we ignored. */
995 goto in_window;
996 }
997 /* Just fall through */
998 default:
999 /* Keep compilers happy. */
1000 break;
1001 }
1002
1003 if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
1004 skb, iph, th)) {
1005 write_unlock_bh(&tcp_lock);
1006 return -NF_ACCEPT;
1007 }
1008 in_window:
1009 /* From now on we have got in-window packets */
1010 conntrack->proto.tcp.last_index = index;
1011
1012 DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
1013 "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
1014 NIPQUAD(iph->saddr), ntohs(th->source),
1015 NIPQUAD(iph->daddr), ntohs(th->dest),
1016 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
1017 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
1018 old_state, new_state);
1019
1020 conntrack->proto.tcp.state = new_state;
1021 if (old_state != new_state
1022 && (new_state == TCP_CONNTRACK_FIN_WAIT
1023 || new_state == TCP_CONNTRACK_CLOSE))
1024 conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
1025 timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
1026 && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
1027 ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
1028 write_unlock_bh(&tcp_lock);
1029
1030 ip_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
1031 if (new_state != old_state)
1032 ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
1033
1034 if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
1035 /* If only reply is a RST, we can consider ourselves not to
1036 have an established connection: this is a fairly common
1037 problem case, so we can delete the conntrack
1038 immediately. --RR */
1039 if (th->rst) {
1040 if (del_timer(&conntrack->timeout))
1041 conntrack->timeout.function((unsigned long)
1042 conntrack);
1043 return NF_ACCEPT;
1044 }
1045 } else if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
1046 && (old_state == TCP_CONNTRACK_SYN_RECV
1047 || old_state == TCP_CONNTRACK_ESTABLISHED)
1048 && new_state == TCP_CONNTRACK_ESTABLISHED) {
1049 /* Set ASSURED if we see see valid ack in ESTABLISHED
1050 after SYN_RECV or a valid answer for a picked up
1051 connection. */
1052 set_bit(IPS_ASSURED_BIT, &conntrack->status);
1053 ip_conntrack_event_cache(IPCT_STATUS, skb);
1054 }
1055 ip_ct_refresh_acct(conntrack, ctinfo, skb, timeout);
1056
1057 return NF_ACCEPT;
1058}
1059
1060/* Called when a new connection for this protocol found. */
1061static int tcp_new(struct ip_conntrack *conntrack,
1062 const struct sk_buff *skb)
1063{
1064 enum tcp_conntrack new_state;
1065 struct iphdr *iph = ip_hdr(skb);
1066 struct tcphdr *th, _tcph;
1067#ifdef DEBUGP_VARS
1068 struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
1069 struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
1070#endif
1071
1072 th = skb_header_pointer(skb, iph->ihl * 4,
1073 sizeof(_tcph), &_tcph);
1074 BUG_ON(th == NULL);
1075
1076 /* Don't need lock here: this conntrack not in circulation yet */
1077 new_state
1078 = tcp_conntracks[0][get_conntrack_index(th)]
1079 [TCP_CONNTRACK_NONE];
1080
1081 /* Invalid: delete conntrack */
1082 if (new_state >= TCP_CONNTRACK_MAX) {
1083 DEBUGP("ip_ct_tcp: invalid new deleting.\n");
1084 return 0;
1085 }
1086
1087 if (new_state == TCP_CONNTRACK_SYN_SENT) {
1088 /* SYN packet */
1089 conntrack->proto.tcp.seen[0].td_end =
1090 segment_seq_plus_len(ntohl(th->seq), skb->len,
1091 iph, th);
1092 conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
1093 if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
1094 conntrack->proto.tcp.seen[0].td_maxwin = 1;
1095 conntrack->proto.tcp.seen[0].td_maxend =
1096 conntrack->proto.tcp.seen[0].td_end;
1097
1098 tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
1099 conntrack->proto.tcp.seen[1].flags = 0;
1100 } else if (ip_ct_tcp_loose == 0) {
1101 /* Don't try to pick up connections. */
1102 return 0;
1103 } else {
1104 /*
1105 * We are in the middle of a connection,
1106 * its history is lost for us.
1107 * Let's try to use the data from the packet.
1108 */
1109 conntrack->proto.tcp.seen[0].td_end =
1110 segment_seq_plus_len(ntohl(th->seq), skb->len,
1111 iph, th);
1112 conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
1113 if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
1114 conntrack->proto.tcp.seen[0].td_maxwin = 1;
1115 conntrack->proto.tcp.seen[0].td_maxend =
1116 conntrack->proto.tcp.seen[0].td_end +
1117 conntrack->proto.tcp.seen[0].td_maxwin;
1118 conntrack->proto.tcp.seen[0].td_scale = 0;
1119
1120 /* We assume SACK and liberal window checking to handle
1121 * window scaling */
1122 conntrack->proto.tcp.seen[0].flags =
1123 conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
1124 IP_CT_TCP_FLAG_BE_LIBERAL;
1125 }
1126
1127 conntrack->proto.tcp.seen[1].td_end = 0;
1128 conntrack->proto.tcp.seen[1].td_maxend = 0;
1129 conntrack->proto.tcp.seen[1].td_maxwin = 1;
1130 conntrack->proto.tcp.seen[1].td_scale = 0;
1131
1132 /* tcp_packet will set them */
1133 conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
1134 conntrack->proto.tcp.last_index = TCP_NONE_SET;
1135
1136 DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
1137 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
1138 sender->td_end, sender->td_maxend, sender->td_maxwin,
1139 sender->td_scale,
1140 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
1141 receiver->td_scale);
1142 return 1;
1143}
1144
1145struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
1146{
1147 .proto = IPPROTO_TCP,
1148 .name = "tcp",
1149 .pkt_to_tuple = tcp_pkt_to_tuple,
1150 .invert_tuple = tcp_invert_tuple,
1151 .print_tuple = tcp_print_tuple,
1152 .print_conntrack = tcp_print_conntrack,
1153 .packet = tcp_packet,
1154 .new = tcp_new,
1155 .error = tcp_error,
1156#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
1157 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
1158 .to_nfattr = tcp_to_nfattr,
1159 .from_nfattr = nfattr_to_tcp,
1160 .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
1161 .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
1162#endif
1163};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
deleted file mode 100644
index 3b47987bf1bb..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ /dev/null
@@ -1,148 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/timer.h>
11#include <linux/netfilter.h>
12#include <linux/in.h>
13#include <linux/ip.h>
14#include <linux/udp.h>
15#include <linux/seq_file.h>
16#include <net/checksum.h>
17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
19
20unsigned int ip_ct_udp_timeout __read_mostly = 30*HZ;
21unsigned int ip_ct_udp_timeout_stream __read_mostly = 180*HZ;
22
23static int udp_pkt_to_tuple(const struct sk_buff *skb,
24 unsigned int dataoff,
25 struct ip_conntrack_tuple *tuple)
26{
27 struct udphdr _hdr, *hp;
28
29 /* Actually only need first 8 bytes. */
30 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
31 if (hp == NULL)
32 return 0;
33
34 tuple->src.u.udp.port = hp->source;
35 tuple->dst.u.udp.port = hp->dest;
36
37 return 1;
38}
39
40static int udp_invert_tuple(struct ip_conntrack_tuple *tuple,
41 const struct ip_conntrack_tuple *orig)
42{
43 tuple->src.u.udp.port = orig->dst.u.udp.port;
44 tuple->dst.u.udp.port = orig->src.u.udp.port;
45 return 1;
46}
47
48/* Print out the per-protocol part of the tuple. */
49static int udp_print_tuple(struct seq_file *s,
50 const struct ip_conntrack_tuple *tuple)
51{
52 return seq_printf(s, "sport=%hu dport=%hu ",
53 ntohs(tuple->src.u.udp.port),
54 ntohs(tuple->dst.u.udp.port));
55}
56
57/* Print out the private part of the conntrack. */
58static int udp_print_conntrack(struct seq_file *s,
59 const struct ip_conntrack *conntrack)
60{
61 return 0;
62}
63
64/* Returns verdict for packet, and may modify conntracktype */
65static int udp_packet(struct ip_conntrack *conntrack,
66 const struct sk_buff *skb,
67 enum ip_conntrack_info ctinfo)
68{
69 /* If we've seen traffic both ways, this is some kind of UDP
70 stream. Extend timeout. */
71 if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
72 ip_ct_refresh_acct(conntrack, ctinfo, skb,
73 ip_ct_udp_timeout_stream);
74 /* Also, more likely to be important, and not a probe */
75 if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status))
76 ip_conntrack_event_cache(IPCT_STATUS, skb);
77 } else
78 ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
79
80 return NF_ACCEPT;
81}
82
83/* Called when a new connection for this protocol found. */
84static int udp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
85{
86 return 1;
87}
88
89static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
90 unsigned int hooknum)
91{
92 const unsigned int hdrlen = ip_hdrlen(skb);
93 unsigned int udplen = skb->len - hdrlen;
94 struct udphdr _hdr, *hdr;
95
96 /* Header is too small? */
97 hdr = skb_header_pointer(skb, hdrlen, sizeof(_hdr), &_hdr);
98 if (hdr == NULL) {
99 if (LOG_INVALID(IPPROTO_UDP))
100 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
101 "ip_ct_udp: short packet ");
102 return -NF_ACCEPT;
103 }
104
105 /* Truncated/malformed packets */
106 if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
107 if (LOG_INVALID(IPPROTO_UDP))
108 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
109 "ip_ct_udp: truncated/malformed packet ");
110 return -NF_ACCEPT;
111 }
112
113 /* Packet with no checksum */
114 if (!hdr->check)
115 return NF_ACCEPT;
116
117 /* Checksum invalid? Ignore.
118 * We skip checking packets on the outgoing path
119 * because the checksum is assumed to be correct.
120 * FIXME: Source route IP option packets --RR */
121 if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
122 nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_UDP)) {
123 if (LOG_INVALID(IPPROTO_UDP))
124 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
125 "ip_ct_udp: bad UDP checksum ");
126 return -NF_ACCEPT;
127 }
128
129 return NF_ACCEPT;
130}
131
132struct ip_conntrack_protocol ip_conntrack_protocol_udp =
133{
134 .proto = IPPROTO_UDP,
135 .name = "udp",
136 .pkt_to_tuple = udp_pkt_to_tuple,
137 .invert_tuple = udp_invert_tuple,
138 .print_tuple = udp_print_tuple,
139 .print_conntrack = udp_print_conntrack,
140 .packet = udp_packet,
141 .new = udp_new,
142 .error = udp_error,
143#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
144 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
145 .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
146 .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
147#endif
148};
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
deleted file mode 100644
index 7363e2a5cea4..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ /dev/null
@@ -1,520 +0,0 @@
1/* SIP extension for IP connection tracking.
2 *
3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
4 * based on RR's ip_conntrack_ftp.c and other modules.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/ctype.h>
13#include <linux/skbuff.h>
14#include <linux/in.h>
15#include <linux/ip.h>
16#include <linux/udp.h>
17
18#include <linux/netfilter.h>
19#include <linux/netfilter_ipv4.h>
20#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
21#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
22
23#if 0
24#define DEBUGP printk
25#else
26#define DEBUGP(format, args...)
27#endif
28
29MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
31MODULE_DESCRIPTION("SIP connection tracking helper");
32
33#define MAX_PORTS 8
34static unsigned short ports[MAX_PORTS];
35static int ports_c;
36module_param_array(ports, ushort, &ports_c, 0400);
37MODULE_PARM_DESC(ports, "port numbers of sip servers");
38
39static unsigned int sip_timeout = SIP_TIMEOUT;
40module_param(sip_timeout, uint, 0600);
41MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
42
43unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
44 enum ip_conntrack_info ctinfo,
45 struct ip_conntrack *ct,
46 const char **dptr);
47EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
48
49unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
50 enum ip_conntrack_info ctinfo,
51 struct ip_conntrack_expect *exp,
52 const char *dptr);
53EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
54
55static int digits_len(const char *dptr, const char *limit, int *shift);
56static int epaddr_len(const char *dptr, const char *limit, int *shift);
57static int skp_digits_len(const char *dptr, const char *limit, int *shift);
58static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
59
60struct sip_header_nfo {
61 const char *lname;
62 const char *sname;
63 const char *ln_str;
64 size_t lnlen;
65 size_t snlen;
66 size_t ln_strlen;
67 int case_sensitive;
68 int (*match_len)(const char *, const char *, int *);
69};
70
71static struct sip_header_nfo ct_sip_hdrs[] = {
72 [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */
73 .lname = "sip:",
74 .lnlen = sizeof("sip:") - 1,
75 .ln_str = ":",
76 .ln_strlen = sizeof(":") - 1,
77 .match_len = epaddr_len
78 },
79 [POS_REQ_URI] = { /* SIP request URI */
80 .lname = "sip:",
81 .lnlen = sizeof("sip:") - 1,
82 .ln_str = "@",
83 .ln_strlen = sizeof("@") - 1,
84 .match_len = epaddr_len
85 },
86 [POS_FROM] = { /* SIP From header */
87 .lname = "From:",
88 .lnlen = sizeof("From:") - 1,
89 .sname = "\r\nf:",
90 .snlen = sizeof("\r\nf:") - 1,
91 .ln_str = "sip:",
92 .ln_strlen = sizeof("sip:") - 1,
93 .match_len = skp_epaddr_len,
94 },
95 [POS_TO] = { /* SIP To header */
96 .lname = "To:",
97 .lnlen = sizeof("To:") - 1,
98 .sname = "\r\nt:",
99 .snlen = sizeof("\r\nt:") - 1,
100 .ln_str = "sip:",
101 .ln_strlen = sizeof("sip:") - 1,
102 .match_len = skp_epaddr_len,
103 },
104 [POS_VIA] = { /* SIP Via header */
105 .lname = "Via:",
106 .lnlen = sizeof("Via:") - 1,
107 .sname = "\r\nv:",
108 .snlen = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
109 .ln_str = "UDP ",
110 .ln_strlen = sizeof("UDP ") - 1,
111 .match_len = epaddr_len,
112 },
113 [POS_CONTACT] = { /* SIP Contact header */
114 .lname = "Contact:",
115 .lnlen = sizeof("Contact:") - 1,
116 .sname = "\r\nm:",
117 .snlen = sizeof("\r\nm:") - 1,
118 .ln_str = "sip:",
119 .ln_strlen = sizeof("sip:") - 1,
120 .match_len = skp_epaddr_len
121 },
122 [POS_CONTENT] = { /* SIP Content length header */
123 .lname = "Content-Length:",
124 .lnlen = sizeof("Content-Length:") - 1,
125 .sname = "\r\nl:",
126 .snlen = sizeof("\r\nl:") - 1,
127 .ln_str = ":",
128 .ln_strlen = sizeof(":") - 1,
129 .match_len = skp_digits_len
130 },
131 [POS_MEDIA] = { /* SDP media info */
132 .case_sensitive = 1,
133 .lname = "\nm=",
134 .lnlen = sizeof("\nm=") - 1,
135 .sname = "\rm=",
136 .snlen = sizeof("\rm=") - 1,
137 .ln_str = "audio ",
138 .ln_strlen = sizeof("audio ") - 1,
139 .match_len = digits_len
140 },
141 [POS_OWNER] = { /* SDP owner address*/
142 .case_sensitive = 1,
143 .lname = "\no=",
144 .lnlen = sizeof("\no=") - 1,
145 .sname = "\ro=",
146 .snlen = sizeof("\ro=") - 1,
147 .ln_str = "IN IP4 ",
148 .ln_strlen = sizeof("IN IP4 ") - 1,
149 .match_len = epaddr_len
150 },
151 [POS_CONNECTION] = { /* SDP connection info */
152 .case_sensitive = 1,
153 .lname = "\nc=",
154 .lnlen = sizeof("\nc=") - 1,
155 .sname = "\rc=",
156 .snlen = sizeof("\rc=") - 1,
157 .ln_str = "IN IP4 ",
158 .ln_strlen = sizeof("IN IP4 ") - 1,
159 .match_len = epaddr_len
160 },
161 [POS_SDP_HEADER] = { /* SDP version header */
162 .case_sensitive = 1,
163 .lname = "\nv=",
164 .lnlen = sizeof("\nv=") - 1,
165 .sname = "\rv=",
166 .snlen = sizeof("\rv=") - 1,
167 .ln_str = "=",
168 .ln_strlen = sizeof("=") - 1,
169 .match_len = digits_len
170 }
171};
172
173/* get line lenght until first CR or LF seen. */
174int ct_sip_lnlen(const char *line, const char *limit)
175{
176 const char *k = line;
177
178 while ((line <= limit) && (*line == '\r' || *line == '\n'))
179 line++;
180
181 while (line <= limit) {
182 if (*line == '\r' || *line == '\n')
183 break;
184 line++;
185 }
186 return line - k;
187}
188EXPORT_SYMBOL_GPL(ct_sip_lnlen);
189
190/* Linear string search, case sensitive. */
191const char *ct_sip_search(const char *needle, const char *haystack,
192 size_t needle_len, size_t haystack_len,
193 int case_sensitive)
194{
195 const char *limit = haystack + (haystack_len - needle_len);
196
197 while (haystack <= limit) {
198 if (case_sensitive) {
199 if (strncmp(haystack, needle, needle_len) == 0)
200 return haystack;
201 } else {
202 if (strnicmp(haystack, needle, needle_len) == 0)
203 return haystack;
204 }
205 haystack++;
206 }
207 return NULL;
208}
209EXPORT_SYMBOL_GPL(ct_sip_search);
210
211static int digits_len(const char *dptr, const char *limit, int *shift)
212{
213 int len = 0;
214 while (dptr <= limit && isdigit(*dptr)) {
215 dptr++;
216 len++;
217 }
218 return len;
219}
220
221/* get digits lenght, skiping blank spaces. */
222static int skp_digits_len(const char *dptr, const char *limit, int *shift)
223{
224 for (; dptr <= limit && *dptr == ' '; dptr++)
225 (*shift)++;
226
227 return digits_len(dptr, limit, shift);
228}
229
230/* Simple ipaddr parser.. */
231static int parse_ipaddr(const char *cp, const char **endp,
232 __be32 *ipaddr, const char *limit)
233{
234 unsigned long int val;
235 int i, digit = 0;
236
237 for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
238 digit = 0;
239 if (!isdigit(*cp))
240 break;
241
242 val = simple_strtoul(cp, (char **)&cp, 10);
243 if (val > 0xFF)
244 return -1;
245
246 ((u_int8_t *)ipaddr)[i] = val;
247 digit = 1;
248
249 if (*cp != '.')
250 break;
251 cp++;
252 }
253 if (!digit)
254 return -1;
255
256 if (endp)
257 *endp = cp;
258
259 return 0;
260}
261
262/* skip ip address. returns it lenght. */
263static int epaddr_len(const char *dptr, const char *limit, int *shift)
264{
265 const char *aux = dptr;
266 __be32 ip;
267
268 if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
269 DEBUGP("ip: %s parse failed.!\n", dptr);
270 return 0;
271 }
272
273 /* Port number */
274 if (*dptr == ':') {
275 dptr++;
276 dptr += digits_len(dptr, limit, shift);
277 }
278 return dptr - aux;
279}
280
281/* get address length, skiping user info. */
282static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
283{
284 int s = *shift;
285
286 /* Search for @, but stop at the end of the line.
287 * We are inside a sip: URI, so we don't need to worry about
288 * continuation lines. */
289 while (dptr <= limit &&
290 *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
291 (*shift)++;
292 dptr++;
293 }
294
295 if (dptr <= limit && *dptr == '@') {
296 dptr++;
297 (*shift)++;
298 } else
299 *shift = s;
300
301 return epaddr_len(dptr, limit, shift);
302}
303
304/* Returns 0 if not found, -1 error parsing. */
305int ct_sip_get_info(const char *dptr, size_t dlen,
306 unsigned int *matchoff,
307 unsigned int *matchlen,
308 enum sip_header_pos pos)
309{
310 struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
311 const char *limit, *aux, *k = dptr;
312 int shift = 0;
313
314 limit = dptr + (dlen - hnfo->lnlen);
315
316 while (dptr <= limit) {
317 if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
318 (hnfo->sname == NULL ||
319 strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
320 dptr++;
321 continue;
322 }
323 aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
324 ct_sip_lnlen(dptr, limit),
325 hnfo->case_sensitive);
326 if (!aux) {
327 DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
328 hnfo->lname);
329 return -1;
330 }
331 aux += hnfo->ln_strlen;
332
333 *matchlen = hnfo->match_len(aux, limit, &shift);
334 if (!*matchlen)
335 return -1;
336
337 *matchoff = (aux - k) + shift;
338
339 DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
340 *matchlen);
341 return 1;
342 }
343 DEBUGP("%s header not found.\n", hnfo->lname);
344 return 0;
345}
346EXPORT_SYMBOL_GPL(ct_sip_get_info);
347
348static int set_expected_rtp(struct sk_buff **pskb,
349 struct ip_conntrack *ct,
350 enum ip_conntrack_info ctinfo,
351 __be32 ipaddr, u_int16_t port,
352 const char *dptr)
353{
354 struct ip_conntrack_expect *exp;
355 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
356 int ret;
357 typeof(ip_nat_sdp_hook) ip_nat_sdp;
358
359 exp = ip_conntrack_expect_alloc(ct);
360 if (exp == NULL)
361 return NF_DROP;
362
363 exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
364 exp->tuple.src.u.udp.port = 0;
365 exp->tuple.dst.ip = ipaddr;
366 exp->tuple.dst.u.udp.port = htons(port);
367 exp->tuple.dst.protonum = IPPROTO_UDP;
368
369 exp->mask.src.ip = htonl(0xFFFFFFFF);
370 exp->mask.src.u.udp.port = 0;
371 exp->mask.dst.ip = htonl(0xFFFFFFFF);
372 exp->mask.dst.u.udp.port = htons(0xFFFF);
373 exp->mask.dst.protonum = 0xFF;
374
375 exp->expectfn = NULL;
376 exp->flags = 0;
377
378 ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook);
379 if (ip_nat_sdp)
380 ret = ip_nat_sdp(pskb, ctinfo, exp, dptr);
381 else {
382 if (ip_conntrack_expect_related(exp) != 0)
383 ret = NF_DROP;
384 else
385 ret = NF_ACCEPT;
386 }
387 ip_conntrack_expect_put(exp);
388
389 return ret;
390}
391
392static int sip_help(struct sk_buff **pskb,
393 struct ip_conntrack *ct,
394 enum ip_conntrack_info ctinfo)
395{
396 unsigned int dataoff, datalen;
397 const char *dptr;
398 int ret = NF_ACCEPT;
399 int matchoff, matchlen;
400 __be32 ipaddr;
401 u_int16_t port;
402 typeof(ip_nat_sip_hook) ip_nat_sip;
403
404 /* No Data ? */
405 dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
406 if (dataoff >= (*pskb)->len) {
407 DEBUGP("skb->len = %u\n", (*pskb)->len);
408 return NF_ACCEPT;
409 }
410
411 ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
412
413 if (!skb_is_nonlinear(*pskb))
414 dptr = (*pskb)->data + dataoff;
415 else {
416 DEBUGP("Copy of skbuff not supported yet.\n");
417 goto out;
418 }
419
420 ip_nat_sip = rcu_dereference(ip_nat_sip_hook);
421 if (ip_nat_sip) {
422 if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) {
423 ret = NF_DROP;
424 goto out;
425 }
426 }
427
428 /* After this point NAT, could have mangled skb, so
429 we need to recalculate payload lenght. */
430 datalen = (*pskb)->len - dataoff;
431
432 if (datalen < (sizeof("SIP/2.0 200") - 1))
433 goto out;
434
435 /* RTP info only in some SDP pkts */
436 if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
437 memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
438 goto out;
439 }
440 /* Get ip and port address from SDP packet. */
441 if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
442 POS_CONNECTION) > 0) {
443
444 /* We'll drop only if there are parse problems. */
445 if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
446 dptr + datalen) < 0) {
447 ret = NF_DROP;
448 goto out;
449 }
450 if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
451 POS_MEDIA) > 0) {
452
453 port = simple_strtoul(dptr + matchoff, NULL, 10);
454 if (port < 1024) {
455 ret = NF_DROP;
456 goto out;
457 }
458 ret = set_expected_rtp(pskb, ct, ctinfo,
459 ipaddr, port, dptr);
460 }
461 }
462out:
463 return ret;
464}
465
466static struct ip_conntrack_helper sip[MAX_PORTS];
467static char sip_names[MAX_PORTS][10];
468
469static void fini(void)
470{
471 int i;
472 for (i = 0; i < ports_c; i++) {
473 DEBUGP("unregistering helper for port %d\n", ports[i]);
474 ip_conntrack_helper_unregister(&sip[i]);
475 }
476}
477
478static int __init init(void)
479{
480 int i, ret;
481 char *tmpname;
482
483 if (ports_c == 0)
484 ports[ports_c++] = SIP_PORT;
485
486 for (i = 0; i < ports_c; i++) {
487 /* Create helper structure */
488 memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
489
490 sip[i].tuple.dst.protonum = IPPROTO_UDP;
491 sip[i].tuple.src.u.udp.port = htons(ports[i]);
492 sip[i].mask.src.u.udp.port = htons(0xFFFF);
493 sip[i].mask.dst.protonum = 0xFF;
494 sip[i].max_expected = 2;
495 sip[i].timeout = 3 * 60; /* 3 minutes */
496 sip[i].me = THIS_MODULE;
497 sip[i].help = sip_help;
498
499 tmpname = &sip_names[i][0];
500 if (ports[i] == SIP_PORT)
501 sprintf(tmpname, "sip");
502 else
503 sprintf(tmpname, "sip-%d", i);
504 sip[i].name = tmpname;
505
506 DEBUGP("port #%d: %d\n", i, ports[i]);
507
508 ret = ip_conntrack_helper_register(&sip[i]);
509 if (ret) {
510 printk("ERROR registering helper for port %d\n",
511 ports[i]);
512 fini();
513 return ret;
514 }
515 }
516 return 0;
517}
518
519module_init(init);
520module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
deleted file mode 100644
index c32200153d62..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ /dev/null
@@ -1,962 +0,0 @@
1/* This file contains all the functions required for the standalone
2 ip_conntrack module.
3
4 These are not required by the compatibility layer.
5*/
6
7/* (C) 1999-2001 Paul `Rusty' Russell
8 * (C) 2002-2005 Netfilter Core Team <coreteam@netfilter.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/types.h>
16#include <linux/ip.h>
17#include <linux/netfilter.h>
18#include <linux/netfilter_ipv4.h>
19#include <linux/module.h>
20#include <linux/skbuff.h>
21#include <linux/proc_fs.h>
22#include <linux/seq_file.h>
23#include <linux/percpu.h>
24#ifdef CONFIG_SYSCTL
25#include <linux/sysctl.h>
26#endif
27#include <net/checksum.h>
28#include <net/ip.h>
29#include <net/route.h>
30
31#include <linux/netfilter_ipv4/ip_conntrack.h>
32#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
33#include <linux/netfilter_ipv4/ip_conntrack_core.h>
34#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
35
36#if 0
37#define DEBUGP printk
38#else
39#define DEBUGP(format, args...)
40#endif
41
42MODULE_LICENSE("GPL");
43
44extern atomic_t ip_conntrack_count;
45DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
46
47static int kill_proto(struct ip_conntrack *i, void *data)
48{
49 return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
50 *((u_int8_t *) data));
51}
52
53#ifdef CONFIG_PROC_FS
54static int
55print_tuple(struct seq_file *s, const struct ip_conntrack_tuple *tuple,
56 struct ip_conntrack_protocol *proto)
57{
58 seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
59 NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
60 return proto->print_tuple(s, tuple);
61}
62
63#ifdef CONFIG_IP_NF_CT_ACCT
64static unsigned int
65seq_print_counters(struct seq_file *s,
66 const struct ip_conntrack_counter *counter)
67{
68 return seq_printf(s, "packets=%llu bytes=%llu ",
69 (unsigned long long)counter->packets,
70 (unsigned long long)counter->bytes);
71}
72#else
73#define seq_print_counters(x, y) 0
74#endif
75
76struct ct_iter_state {
77 unsigned int bucket;
78};
79
80static struct list_head *ct_get_first(struct seq_file *seq)
81{
82 struct ct_iter_state *st = seq->private;
83
84 for (st->bucket = 0;
85 st->bucket < ip_conntrack_htable_size;
86 st->bucket++) {
87 if (!list_empty(&ip_conntrack_hash[st->bucket]))
88 return ip_conntrack_hash[st->bucket].next;
89 }
90 return NULL;
91}
92
93static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
94{
95 struct ct_iter_state *st = seq->private;
96
97 head = head->next;
98 while (head == &ip_conntrack_hash[st->bucket]) {
99 if (++st->bucket >= ip_conntrack_htable_size)
100 return NULL;
101 head = ip_conntrack_hash[st->bucket].next;
102 }
103 return head;
104}
105
106static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
107{
108 struct list_head *head = ct_get_first(seq);
109
110 if (head)
111 while (pos && (head = ct_get_next(seq, head)))
112 pos--;
113 return pos ? NULL : head;
114}
115
116static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
117{
118 read_lock_bh(&ip_conntrack_lock);
119 return ct_get_idx(seq, *pos);
120}
121
122static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
123{
124 (*pos)++;
125 return ct_get_next(s, v);
126}
127
128static void ct_seq_stop(struct seq_file *s, void *v)
129{
130 read_unlock_bh(&ip_conntrack_lock);
131}
132
133static int ct_seq_show(struct seq_file *s, void *v)
134{
135 const struct ip_conntrack_tuple_hash *hash = v;
136 const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
137 struct ip_conntrack_protocol *proto;
138
139 IP_NF_ASSERT(conntrack);
140
141 /* we only want to print DIR_ORIGINAL */
142 if (DIRECTION(hash))
143 return 0;
144
145 proto = __ip_conntrack_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
146 IP_NF_ASSERT(proto);
147
148 if (seq_printf(s, "%-8s %u %ld ",
149 proto->name,
150 conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
151 timer_pending(&conntrack->timeout)
152 ? (long)(conntrack->timeout.expires - jiffies)/HZ
153 : 0) != 0)
154 return -ENOSPC;
155
156 if (proto->print_conntrack(s, conntrack))
157 return -ENOSPC;
158
159 if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
160 proto))
161 return -ENOSPC;
162
163 if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
164 return -ENOSPC;
165
166 if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
167 if (seq_printf(s, "[UNREPLIED] "))
168 return -ENOSPC;
169
170 if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
171 proto))
172 return -ENOSPC;
173
174 if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
175 return -ENOSPC;
176
177 if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
178 if (seq_printf(s, "[ASSURED] "))
179 return -ENOSPC;
180
181#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
182 if (seq_printf(s, "mark=%u ", conntrack->mark))
183 return -ENOSPC;
184#endif
185
186#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
187 if (seq_printf(s, "secmark=%u ", conntrack->secmark))
188 return -ENOSPC;
189#endif
190
191 if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
192 return -ENOSPC;
193
194 return 0;
195}
196
197static struct seq_operations ct_seq_ops = {
198 .start = ct_seq_start,
199 .next = ct_seq_next,
200 .stop = ct_seq_stop,
201 .show = ct_seq_show
202};
203
204static int ct_open(struct inode *inode, struct file *file)
205{
206 struct seq_file *seq;
207 struct ct_iter_state *st;
208 int ret;
209
210 st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
211 if (st == NULL)
212 return -ENOMEM;
213 ret = seq_open(file, &ct_seq_ops);
214 if (ret)
215 goto out_free;
216 seq = file->private_data;
217 seq->private = st;
218 memset(st, 0, sizeof(struct ct_iter_state));
219 return ret;
220out_free:
221 kfree(st);
222 return ret;
223}
224
225static const struct file_operations ct_file_ops = {
226 .owner = THIS_MODULE,
227 .open = ct_open,
228 .read = seq_read,
229 .llseek = seq_lseek,
230 .release = seq_release_private,
231};
232
233/* expects */
234static void *exp_seq_start(struct seq_file *s, loff_t *pos)
235{
236 struct list_head *e = &ip_conntrack_expect_list;
237 loff_t i;
238
239 /* strange seq_file api calls stop even if we fail,
240 * thus we need to grab lock since stop unlocks */
241 read_lock_bh(&ip_conntrack_lock);
242
243 if (list_empty(e))
244 return NULL;
245
246 for (i = 0; i <= *pos; i++) {
247 e = e->next;
248 if (e == &ip_conntrack_expect_list)
249 return NULL;
250 }
251 return e;
252}
253
254static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
255{
256 struct list_head *e = v;
257
258 ++*pos;
259 e = e->next;
260
261 if (e == &ip_conntrack_expect_list)
262 return NULL;
263
264 return e;
265}
266
267static void exp_seq_stop(struct seq_file *s, void *v)
268{
269 read_unlock_bh(&ip_conntrack_lock);
270}
271
272static int exp_seq_show(struct seq_file *s, void *v)
273{
274 struct ip_conntrack_expect *expect = v;
275
276 if (expect->timeout.function)
277 seq_printf(s, "%ld ", timer_pending(&expect->timeout)
278 ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
279 else
280 seq_printf(s, "- ");
281
282 seq_printf(s, "proto=%u ", expect->tuple.dst.protonum);
283
284 print_tuple(s, &expect->tuple,
285 __ip_conntrack_proto_find(expect->tuple.dst.protonum));
286 return seq_putc(s, '\n');
287}
288
289static struct seq_operations exp_seq_ops = {
290 .start = exp_seq_start,
291 .next = exp_seq_next,
292 .stop = exp_seq_stop,
293 .show = exp_seq_show
294};
295
296static int exp_open(struct inode *inode, struct file *file)
297{
298 return seq_open(file, &exp_seq_ops);
299}
300
301static const struct file_operations exp_file_ops = {
302 .owner = THIS_MODULE,
303 .open = exp_open,
304 .read = seq_read,
305 .llseek = seq_lseek,
306 .release = seq_release
307};
308
309static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
310{
311 int cpu;
312
313 if (*pos == 0)
314 return SEQ_START_TOKEN;
315
316 for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
317 if (!cpu_possible(cpu))
318 continue;
319 *pos = cpu+1;
320 return &per_cpu(ip_conntrack_stat, cpu);
321 }
322
323 return NULL;
324}
325
326static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
327{
328 int cpu;
329
330 for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
331 if (!cpu_possible(cpu))
332 continue;
333 *pos = cpu+1;
334 return &per_cpu(ip_conntrack_stat, cpu);
335 }
336
337 return NULL;
338}
339
340static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
341{
342}
343
344static int ct_cpu_seq_show(struct seq_file *seq, void *v)
345{
346 unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);
347 struct ip_conntrack_stat *st = v;
348
349 if (v == SEQ_START_TOKEN) {
350 seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n");
351 return 0;
352 }
353
354 seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x "
355 "%08x %08x %08x %08x %08x %08x %08x %08x \n",
356 nr_conntracks,
357 st->searched,
358 st->found,
359 st->new,
360 st->invalid,
361 st->ignore,
362 st->delete,
363 st->delete_list,
364 st->insert,
365 st->insert_failed,
366 st->drop,
367 st->early_drop,
368 st->error,
369
370 st->expect_new,
371 st->expect_create,
372 st->expect_delete
373 );
374 return 0;
375}
376
377static struct seq_operations ct_cpu_seq_ops = {
378 .start = ct_cpu_seq_start,
379 .next = ct_cpu_seq_next,
380 .stop = ct_cpu_seq_stop,
381 .show = ct_cpu_seq_show,
382};
383
384static int ct_cpu_seq_open(struct inode *inode, struct file *file)
385{
386 return seq_open(file, &ct_cpu_seq_ops);
387}
388
389static const struct file_operations ct_cpu_seq_fops = {
390 .owner = THIS_MODULE,
391 .open = ct_cpu_seq_open,
392 .read = seq_read,
393 .llseek = seq_lseek,
394 .release = seq_release_private,
395};
396#endif
397
398static unsigned int ip_confirm(unsigned int hooknum,
399 struct sk_buff **pskb,
400 const struct net_device *in,
401 const struct net_device *out,
402 int (*okfn)(struct sk_buff *))
403{
404 /* We've seen it coming out the other side: confirm it */
405 return ip_conntrack_confirm(pskb);
406}
407
408static unsigned int ip_conntrack_help(unsigned int hooknum,
409 struct sk_buff **pskb,
410 const struct net_device *in,
411 const struct net_device *out,
412 int (*okfn)(struct sk_buff *))
413{
414 struct ip_conntrack *ct;
415 enum ip_conntrack_info ctinfo;
416
417 /* This is where we call the helper: as the packet goes out. */
418 ct = ip_conntrack_get(*pskb, &ctinfo);
419 if (ct && ct->helper && ctinfo != IP_CT_RELATED + IP_CT_IS_REPLY) {
420 unsigned int ret;
421 ret = ct->helper->help(pskb, ct, ctinfo);
422 if (ret != NF_ACCEPT)
423 return ret;
424 }
425 return NF_ACCEPT;
426}
427
428static unsigned int ip_conntrack_defrag(unsigned int hooknum,
429 struct sk_buff **pskb,
430 const struct net_device *in,
431 const struct net_device *out,
432 int (*okfn)(struct sk_buff *))
433{
434#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
435 /* Previously seen (loopback)? Ignore. Do this before
436 fragment check. */
437 if ((*pskb)->nfct)
438 return NF_ACCEPT;
439#endif
440
441 /* Gather fragments. */
442 if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
443 *pskb = ip_ct_gather_frags(*pskb,
444 hooknum == NF_IP_PRE_ROUTING ?
445 IP_DEFRAG_CONNTRACK_IN :
446 IP_DEFRAG_CONNTRACK_OUT);
447 if (!*pskb)
448 return NF_STOLEN;
449 }
450 return NF_ACCEPT;
451}
452
453static unsigned int ip_conntrack_local(unsigned int hooknum,
454 struct sk_buff **pskb,
455 const struct net_device *in,
456 const struct net_device *out,
457 int (*okfn)(struct sk_buff *))
458{
459 /* root is playing with raw sockets. */
460 if ((*pskb)->len < sizeof(struct iphdr)
461 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
462 if (net_ratelimit())
463 printk("ipt_hook: happy cracking.\n");
464 return NF_ACCEPT;
465 }
466 return ip_conntrack_in(hooknum, pskb, in, out, okfn);
467}
468
469/* Connection tracking may drop packets, but never alters them, so
470 make it the first hook. */
471static struct nf_hook_ops ip_conntrack_ops[] = {
472 {
473 .hook = ip_conntrack_defrag,
474 .owner = THIS_MODULE,
475 .pf = PF_INET,
476 .hooknum = NF_IP_PRE_ROUTING,
477 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
478 },
479 {
480 .hook = ip_conntrack_in,
481 .owner = THIS_MODULE,
482 .pf = PF_INET,
483 .hooknum = NF_IP_PRE_ROUTING,
484 .priority = NF_IP_PRI_CONNTRACK,
485 },
486 {
487 .hook = ip_conntrack_defrag,
488 .owner = THIS_MODULE,
489 .pf = PF_INET,
490 .hooknum = NF_IP_LOCAL_OUT,
491 .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
492 },
493 {
494 .hook = ip_conntrack_local,
495 .owner = THIS_MODULE,
496 .pf = PF_INET,
497 .hooknum = NF_IP_LOCAL_OUT,
498 .priority = NF_IP_PRI_CONNTRACK,
499 },
500 {
501 .hook = ip_conntrack_help,
502 .owner = THIS_MODULE,
503 .pf = PF_INET,
504 .hooknum = NF_IP_POST_ROUTING,
505 .priority = NF_IP_PRI_CONNTRACK_HELPER,
506 },
507 {
508 .hook = ip_conntrack_help,
509 .owner = THIS_MODULE,
510 .pf = PF_INET,
511 .hooknum = NF_IP_LOCAL_IN,
512 .priority = NF_IP_PRI_CONNTRACK_HELPER,
513 },
514 {
515 .hook = ip_confirm,
516 .owner = THIS_MODULE,
517 .pf = PF_INET,
518 .hooknum = NF_IP_POST_ROUTING,
519 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
520 },
521 {
522 .hook = ip_confirm,
523 .owner = THIS_MODULE,
524 .pf = PF_INET,
525 .hooknum = NF_IP_LOCAL_IN,
526 .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
527 },
528};
529
530/* Sysctl support */
531
532int ip_conntrack_checksum __read_mostly = 1;
533
534#ifdef CONFIG_SYSCTL
535
536/* From ip_conntrack_core.c */
537extern int ip_conntrack_max;
538extern unsigned int ip_conntrack_htable_size;
539
540/* From ip_conntrack_proto_tcp.c */
541extern unsigned int ip_ct_tcp_timeout_syn_sent;
542extern unsigned int ip_ct_tcp_timeout_syn_recv;
543extern unsigned int ip_ct_tcp_timeout_established;
544extern unsigned int ip_ct_tcp_timeout_fin_wait;
545extern unsigned int ip_ct_tcp_timeout_close_wait;
546extern unsigned int ip_ct_tcp_timeout_last_ack;
547extern unsigned int ip_ct_tcp_timeout_time_wait;
548extern unsigned int ip_ct_tcp_timeout_close;
549extern unsigned int ip_ct_tcp_timeout_max_retrans;
550extern int ip_ct_tcp_loose;
551extern int ip_ct_tcp_be_liberal;
552extern int ip_ct_tcp_max_retrans;
553
554/* From ip_conntrack_proto_udp.c */
555extern unsigned int ip_ct_udp_timeout;
556extern unsigned int ip_ct_udp_timeout_stream;
557
558/* From ip_conntrack_proto_icmp.c */
559extern unsigned int ip_ct_icmp_timeout;
560
561/* From ip_conntrack_proto_generic.c */
562extern unsigned int ip_ct_generic_timeout;
563
564/* Log invalid packets of a given protocol */
565static int log_invalid_proto_min = 0;
566static int log_invalid_proto_max = 255;
567
568static struct ctl_table_header *ip_ct_sysctl_header;
569
570static ctl_table ip_ct_sysctl_table[] = {
571 {
572 .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
573 .procname = "ip_conntrack_max",
574 .data = &ip_conntrack_max,
575 .maxlen = sizeof(int),
576 .mode = 0644,
577 .proc_handler = &proc_dointvec,
578 },
579 {
580 .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
581 .procname = "ip_conntrack_count",
582 .data = &ip_conntrack_count,
583 .maxlen = sizeof(int),
584 .mode = 0444,
585 .proc_handler = &proc_dointvec,
586 },
587 {
588 .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
589 .procname = "ip_conntrack_buckets",
590 .data = &ip_conntrack_htable_size,
591 .maxlen = sizeof(unsigned int),
592 .mode = 0444,
593 .proc_handler = &proc_dointvec,
594 },
595 {
596 .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM,
597 .procname = "ip_conntrack_checksum",
598 .data = &ip_conntrack_checksum,
599 .maxlen = sizeof(int),
600 .mode = 0644,
601 .proc_handler = &proc_dointvec,
602 },
603 {
604 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
605 .procname = "ip_conntrack_tcp_timeout_syn_sent",
606 .data = &ip_ct_tcp_timeout_syn_sent,
607 .maxlen = sizeof(unsigned int),
608 .mode = 0644,
609 .proc_handler = &proc_dointvec_jiffies,
610 },
611 {
612 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
613 .procname = "ip_conntrack_tcp_timeout_syn_recv",
614 .data = &ip_ct_tcp_timeout_syn_recv,
615 .maxlen = sizeof(unsigned int),
616 .mode = 0644,
617 .proc_handler = &proc_dointvec_jiffies,
618 },
619 {
620 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
621 .procname = "ip_conntrack_tcp_timeout_established",
622 .data = &ip_ct_tcp_timeout_established,
623 .maxlen = sizeof(unsigned int),
624 .mode = 0644,
625 .proc_handler = &proc_dointvec_jiffies,
626 },
627 {
628 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
629 .procname = "ip_conntrack_tcp_timeout_fin_wait",
630 .data = &ip_ct_tcp_timeout_fin_wait,
631 .maxlen = sizeof(unsigned int),
632 .mode = 0644,
633 .proc_handler = &proc_dointvec_jiffies,
634 },
635 {
636 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
637 .procname = "ip_conntrack_tcp_timeout_close_wait",
638 .data = &ip_ct_tcp_timeout_close_wait,
639 .maxlen = sizeof(unsigned int),
640 .mode = 0644,
641 .proc_handler = &proc_dointvec_jiffies,
642 },
643 {
644 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
645 .procname = "ip_conntrack_tcp_timeout_last_ack",
646 .data = &ip_ct_tcp_timeout_last_ack,
647 .maxlen = sizeof(unsigned int),
648 .mode = 0644,
649 .proc_handler = &proc_dointvec_jiffies,
650 },
651 {
652 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
653 .procname = "ip_conntrack_tcp_timeout_time_wait",
654 .data = &ip_ct_tcp_timeout_time_wait,
655 .maxlen = sizeof(unsigned int),
656 .mode = 0644,
657 .proc_handler = &proc_dointvec_jiffies,
658 },
659 {
660 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
661 .procname = "ip_conntrack_tcp_timeout_close",
662 .data = &ip_ct_tcp_timeout_close,
663 .maxlen = sizeof(unsigned int),
664 .mode = 0644,
665 .proc_handler = &proc_dointvec_jiffies,
666 },
667 {
668 .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
669 .procname = "ip_conntrack_udp_timeout",
670 .data = &ip_ct_udp_timeout,
671 .maxlen = sizeof(unsigned int),
672 .mode = 0644,
673 .proc_handler = &proc_dointvec_jiffies,
674 },
675 {
676 .ctl_name = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
677 .procname = "ip_conntrack_udp_timeout_stream",
678 .data = &ip_ct_udp_timeout_stream,
679 .maxlen = sizeof(unsigned int),
680 .mode = 0644,
681 .proc_handler = &proc_dointvec_jiffies,
682 },
683 {
684 .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
685 .procname = "ip_conntrack_icmp_timeout",
686 .data = &ip_ct_icmp_timeout,
687 .maxlen = sizeof(unsigned int),
688 .mode = 0644,
689 .proc_handler = &proc_dointvec_jiffies,
690 },
691 {
692 .ctl_name = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
693 .procname = "ip_conntrack_generic_timeout",
694 .data = &ip_ct_generic_timeout,
695 .maxlen = sizeof(unsigned int),
696 .mode = 0644,
697 .proc_handler = &proc_dointvec_jiffies,
698 },
699 {
700 .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
701 .procname = "ip_conntrack_log_invalid",
702 .data = &ip_ct_log_invalid,
703 .maxlen = sizeof(unsigned int),
704 .mode = 0644,
705 .proc_handler = &proc_dointvec_minmax,
706 .strategy = &sysctl_intvec,
707 .extra1 = &log_invalid_proto_min,
708 .extra2 = &log_invalid_proto_max,
709 },
710 {
711 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
712 .procname = "ip_conntrack_tcp_timeout_max_retrans",
713 .data = &ip_ct_tcp_timeout_max_retrans,
714 .maxlen = sizeof(unsigned int),
715 .mode = 0644,
716 .proc_handler = &proc_dointvec_jiffies,
717 },
718 {
719 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
720 .procname = "ip_conntrack_tcp_loose",
721 .data = &ip_ct_tcp_loose,
722 .maxlen = sizeof(unsigned int),
723 .mode = 0644,
724 .proc_handler = &proc_dointvec,
725 },
726 {
727 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
728 .procname = "ip_conntrack_tcp_be_liberal",
729 .data = &ip_ct_tcp_be_liberal,
730 .maxlen = sizeof(unsigned int),
731 .mode = 0644,
732 .proc_handler = &proc_dointvec,
733 },
734 {
735 .ctl_name = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
736 .procname = "ip_conntrack_tcp_max_retrans",
737 .data = &ip_ct_tcp_max_retrans,
738 .maxlen = sizeof(unsigned int),
739 .mode = 0644,
740 .proc_handler = &proc_dointvec,
741 },
742 { .ctl_name = 0 }
743};
744
745#define NET_IP_CONNTRACK_MAX 2089
746
747static ctl_table ip_ct_netfilter_table[] = {
748 {
749 .ctl_name = NET_IPV4_NETFILTER,
750 .procname = "netfilter",
751 .mode = 0555,
752 .child = ip_ct_sysctl_table,
753 },
754 {
755 .ctl_name = NET_IP_CONNTRACK_MAX,
756 .procname = "ip_conntrack_max",
757 .data = &ip_conntrack_max,
758 .maxlen = sizeof(int),
759 .mode = 0644,
760 .proc_handler = &proc_dointvec
761 },
762 { .ctl_name = 0 }
763};
764
765static ctl_table ip_ct_ipv4_table[] = {
766 {
767 .ctl_name = NET_IPV4,
768 .procname = "ipv4",
769 .mode = 0555,
770 .child = ip_ct_netfilter_table,
771 },
772 { .ctl_name = 0 }
773};
774
775static ctl_table ip_ct_net_table[] = {
776 {
777 .ctl_name = CTL_NET,
778 .procname = "net",
779 .mode = 0555,
780 .child = ip_ct_ipv4_table,
781 },
782 { .ctl_name = 0 }
783};
784
785EXPORT_SYMBOL(ip_ct_log_invalid);
786#endif /* CONFIG_SYSCTL */
787
788/* FIXME: Allow NULL functions and sub in pointers to generic for
789 them. --RR */
790int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
791{
792 int ret = 0;
793
794 write_lock_bh(&ip_conntrack_lock);
795 if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
796 ret = -EBUSY;
797 goto out;
798 }
799 rcu_assign_pointer(ip_ct_protos[proto->proto], proto);
800 out:
801 write_unlock_bh(&ip_conntrack_lock);
802 return ret;
803}
804
805void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
806{
807 write_lock_bh(&ip_conntrack_lock);
808 rcu_assign_pointer(ip_ct_protos[proto->proto],
809 &ip_conntrack_generic_protocol);
810 write_unlock_bh(&ip_conntrack_lock);
811 synchronize_rcu();
812
813 /* Remove all contrack entries for this protocol */
814 ip_ct_iterate_cleanup(kill_proto, &proto->proto);
815}
816
817static int __init ip_conntrack_standalone_init(void)
818{
819#ifdef CONFIG_PROC_FS
820 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
821#endif
822 int ret = 0;
823
824 ret = ip_conntrack_init();
825 if (ret < 0)
826 return ret;
827
828#ifdef CONFIG_PROC_FS
829 ret = -ENOMEM;
830 proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
831 if (!proc) goto cleanup_init;
832
833 proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
834 &exp_file_ops);
835 if (!proc_exp) goto cleanup_proc;
836
837 proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
838 if (!proc_stat)
839 goto cleanup_proc_exp;
840
841 proc_stat->proc_fops = &ct_cpu_seq_fops;
842 proc_stat->owner = THIS_MODULE;
843#endif
844
845 ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
846 if (ret < 0) {
847 printk("ip_conntrack: can't register hooks.\n");
848 goto cleanup_proc_stat;
849 }
850#ifdef CONFIG_SYSCTL
851 ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table);
852 if (ip_ct_sysctl_header == NULL) {
853 printk("ip_conntrack: can't register to sysctl.\n");
854 ret = -ENOMEM;
855 goto cleanup_hooks;
856 }
857#endif
858 return ret;
859
860#ifdef CONFIG_SYSCTL
861 cleanup_hooks:
862 nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
863#endif
864 cleanup_proc_stat:
865#ifdef CONFIG_PROC_FS
866 remove_proc_entry("ip_conntrack", proc_net_stat);
867 cleanup_proc_exp:
868 proc_net_remove("ip_conntrack_expect");
869 cleanup_proc:
870 proc_net_remove("ip_conntrack");
871 cleanup_init:
872#endif /* CONFIG_PROC_FS */
873 ip_conntrack_cleanup();
874 return ret;
875}
876
877static void __exit ip_conntrack_standalone_fini(void)
878{
879 synchronize_net();
880#ifdef CONFIG_SYSCTL
881 unregister_sysctl_table(ip_ct_sysctl_header);
882#endif
883 nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
884#ifdef CONFIG_PROC_FS
885 remove_proc_entry("ip_conntrack", proc_net_stat);
886 proc_net_remove("ip_conntrack_expect");
887 proc_net_remove("ip_conntrack");
888#endif /* CONFIG_PROC_FS */
889 ip_conntrack_cleanup();
890}
891
892module_init(ip_conntrack_standalone_init);
893module_exit(ip_conntrack_standalone_fini);
894
895/* Some modules need us, but don't depend directly on any symbol.
896 They should call this. */
897void need_conntrack(void)
898{
899}
900
901#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
902EXPORT_SYMBOL_GPL(ip_conntrack_chain);
903EXPORT_SYMBOL_GPL(ip_conntrack_expect_chain);
904EXPORT_SYMBOL_GPL(ip_conntrack_register_notifier);
905EXPORT_SYMBOL_GPL(ip_conntrack_unregister_notifier);
906EXPORT_SYMBOL_GPL(__ip_ct_event_cache_init);
907EXPORT_PER_CPU_SYMBOL_GPL(ip_conntrack_ecache);
908#endif
909EXPORT_SYMBOL(ip_conntrack_protocol_register);
910EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
911EXPORT_SYMBOL(ip_ct_get_tuple);
912EXPORT_SYMBOL(invert_tuplepr);
913EXPORT_SYMBOL(ip_conntrack_alter_reply);
914EXPORT_SYMBOL(ip_conntrack_destroyed);
915EXPORT_SYMBOL(need_conntrack);
916EXPORT_SYMBOL(ip_conntrack_helper_register);
917EXPORT_SYMBOL(ip_conntrack_helper_unregister);
918EXPORT_SYMBOL(ip_ct_iterate_cleanup);
919EXPORT_SYMBOL(__ip_ct_refresh_acct);
920
921EXPORT_SYMBOL(ip_conntrack_expect_alloc);
922EXPORT_SYMBOL(ip_conntrack_expect_put);
923EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
924EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
925EXPORT_SYMBOL(ip_conntrack_expect_related);
926EXPORT_SYMBOL(ip_conntrack_unexpect_related);
927EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
928EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
929
930EXPORT_SYMBOL(ip_conntrack_tuple_taken);
931EXPORT_SYMBOL(ip_ct_gather_frags);
932EXPORT_SYMBOL(ip_conntrack_htable_size);
933EXPORT_SYMBOL(ip_conntrack_lock);
934EXPORT_SYMBOL(ip_conntrack_hash);
935EXPORT_SYMBOL(ip_conntrack_untracked);
936EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
937#ifdef CONFIG_IP_NF_NAT_NEEDED
938EXPORT_SYMBOL(ip_conntrack_tcp_update);
939#endif
940
941EXPORT_SYMBOL_GPL(ip_conntrack_flush);
942EXPORT_SYMBOL_GPL(__ip_conntrack_find);
943
944EXPORT_SYMBOL_GPL(ip_conntrack_alloc);
945EXPORT_SYMBOL_GPL(ip_conntrack_free);
946EXPORT_SYMBOL_GPL(ip_conntrack_hash_insert);
947
948EXPORT_SYMBOL_GPL(ip_ct_remove_expectations);
949
950EXPORT_SYMBOL_GPL(ip_conntrack_helper_find_get);
951EXPORT_SYMBOL_GPL(ip_conntrack_helper_put);
952EXPORT_SYMBOL_GPL(__ip_conntrack_helper_find_byname);
953
954EXPORT_SYMBOL_GPL(ip_conntrack_proto_find_get);
955EXPORT_SYMBOL_GPL(ip_conntrack_proto_put);
956EXPORT_SYMBOL_GPL(__ip_conntrack_proto_find);
957EXPORT_SYMBOL_GPL(ip_conntrack_checksum);
958#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
959 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
960EXPORT_SYMBOL_GPL(ip_ct_port_tuple_to_nfattr);
961EXPORT_SYMBOL_GPL(ip_ct_port_nfattr_to_tuple);
962#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
deleted file mode 100644
index afc6809a3888..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ /dev/null
@@ -1,161 +0,0 @@
1/* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 *
7 * Version: 0.0.7
8 *
9 * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
10 * - port to newnat API
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/ip.h>
16#include <linux/udp.h>
17
18#include <linux/netfilter.h>
19#include <linux/netfilter_ipv4/ip_tables.h>
20#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
21#include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
22#include <linux/moduleparam.h>
23
24MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
25MODULE_DESCRIPTION("tftp connection tracking helper");
26MODULE_LICENSE("GPL");
27
28#define MAX_PORTS 8
29static unsigned short ports[MAX_PORTS];
30static int ports_c;
31module_param_array(ports, ushort, &ports_c, 0400);
32MODULE_PARM_DESC(ports, "port numbers of tftp servers");
33
34#if 0
35#define DEBUGP(format, args...) printk("%s:%s:" format, \
36 __FILE__, __FUNCTION__ , ## args)
37#else
38#define DEBUGP(format, args...)
39#endif
40
41unsigned int (*ip_nat_tftp_hook)(struct sk_buff **pskb,
42 enum ip_conntrack_info ctinfo,
43 struct ip_conntrack_expect *exp);
44EXPORT_SYMBOL_GPL(ip_nat_tftp_hook);
45
46static int tftp_help(struct sk_buff **pskb,
47 struct ip_conntrack *ct,
48 enum ip_conntrack_info ctinfo)
49{
50 struct tftphdr _tftph, *tfh;
51 struct ip_conntrack_expect *exp;
52 unsigned int ret = NF_ACCEPT;
53 typeof(ip_nat_tftp_hook) ip_nat_tftp;
54
55 tfh = skb_header_pointer(*pskb,
56 ip_hdrlen(*pskb) + sizeof(struct udphdr),
57 sizeof(_tftph), &_tftph);
58 if (tfh == NULL)
59 return NF_ACCEPT;
60
61 switch (ntohs(tfh->opcode)) {
62 /* RRQ and WRQ works the same way */
63 case TFTP_OPCODE_READ:
64 case TFTP_OPCODE_WRITE:
65 DEBUGP("");
66 DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
67 DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
68
69 exp = ip_conntrack_expect_alloc(ct);
70 if (exp == NULL)
71 return NF_DROP;
72
73 exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
74 exp->mask.src.ip = htonl(0xffffffff);
75 exp->mask.src.u.udp.port = 0;
76 exp->mask.dst.ip = htonl(0xffffffff);
77 exp->mask.dst.u.udp.port = htons(0xffff);
78 exp->mask.dst.protonum = 0xff;
79 exp->expectfn = NULL;
80 exp->flags = 0;
81
82 DEBUGP("expect: ");
83 DUMP_TUPLE(&exp->tuple);
84 DUMP_TUPLE(&exp->mask);
85 ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook);
86 if (ip_nat_tftp)
87 ret = ip_nat_tftp(pskb, ctinfo, exp);
88 else if (ip_conntrack_expect_related(exp) != 0)
89 ret = NF_DROP;
90 ip_conntrack_expect_put(exp);
91 break;
92 case TFTP_OPCODE_DATA:
93 case TFTP_OPCODE_ACK:
94 DEBUGP("Data/ACK opcode\n");
95 break;
96 case TFTP_OPCODE_ERROR:
97 DEBUGP("Error opcode\n");
98 break;
99 default:
100 DEBUGP("Unknown opcode\n");
101 }
102 return NF_ACCEPT;
103}
104
105static struct ip_conntrack_helper tftp[MAX_PORTS];
106static char tftp_names[MAX_PORTS][sizeof("tftp-65535")];
107
108static void ip_conntrack_tftp_fini(void)
109{
110 int i;
111
112 for (i = 0 ; i < ports_c; i++) {
113 DEBUGP("unregistering helper for port %d\n",
114 ports[i]);
115 ip_conntrack_helper_unregister(&tftp[i]);
116 }
117}
118
119static int __init ip_conntrack_tftp_init(void)
120{
121 int i, ret;
122 char *tmpname;
123
124 if (ports_c == 0)
125 ports[ports_c++] = TFTP_PORT;
126
127 for (i = 0; i < ports_c; i++) {
128 /* Create helper structure */
129 memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
130
131 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
132 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
133 tftp[i].mask.dst.protonum = 0xFF;
134 tftp[i].mask.src.u.udp.port = htons(0xFFFF);
135 tftp[i].max_expected = 1;
136 tftp[i].timeout = 5 * 60; /* 5 minutes */
137 tftp[i].me = THIS_MODULE;
138 tftp[i].help = tftp_help;
139
140 tmpname = &tftp_names[i][0];
141 if (ports[i] == TFTP_PORT)
142 sprintf(tmpname, "tftp");
143 else
144 sprintf(tmpname, "tftp-%d", i);
145 tftp[i].name = tmpname;
146
147 DEBUGP("port #%d: %d\n", i, ports[i]);
148
149 ret=ip_conntrack_helper_register(&tftp[i]);
150 if (ret) {
151 printk("ERROR registering helper for port %d\n",
152 ports[i]);
153 ip_conntrack_tftp_fini();
154 return(ret);
155 }
156 }
157 return(0);
158}
159
160module_init(ip_conntrack_tftp_init);
161module_exit(ip_conntrack_tftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
deleted file mode 100644
index 85df1a9aed33..000000000000
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ /dev/null
@@ -1,85 +0,0 @@
1/* Amanda extension for TCP NAT alteration.
2 * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
3 * based on a copy of HW's ip_nat_irc.c as well as other modules
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 * Module load syntax:
11 * insmod ip_nat_amanda.o
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/netfilter.h>
17#include <linux/skbuff.h>
18#include <linux/ip.h>
19#include <linux/udp.h>
20#include <net/tcp.h>
21#include <net/udp.h>
22
23#include <linux/netfilter_ipv4.h>
24#include <linux/netfilter_ipv4/ip_nat.h>
25#include <linux/netfilter_ipv4/ip_nat_helper.h>
26#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
27#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
28
29
30MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
31MODULE_DESCRIPTION("Amanda NAT helper");
32MODULE_LICENSE("GPL");
33
34static unsigned int help(struct sk_buff **pskb,
35 enum ip_conntrack_info ctinfo,
36 unsigned int matchoff,
37 unsigned int matchlen,
38 struct ip_conntrack_expect *exp)
39{
40 char buffer[sizeof("65535")];
41 u_int16_t port;
42 unsigned int ret;
43
44 /* Connection comes from client. */
45 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
46 exp->dir = IP_CT_DIR_ORIGINAL;
47
48 /* When you see the packet, we need to NAT it the same as the
49 * this one (ie. same IP: it will be TCP and master is UDP). */
50 exp->expectfn = ip_nat_follow_master;
51
52 /* Try to get same port: if not, try to change it. */
53 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
54 exp->tuple.dst.u.tcp.port = htons(port);
55 if (ip_conntrack_expect_related(exp) == 0)
56 break;
57 }
58
59 if (port == 0)
60 return NF_DROP;
61
62 sprintf(buffer, "%u", port);
63 ret = ip_nat_mangle_udp_packet(pskb, exp->master, ctinfo,
64 matchoff, matchlen,
65 buffer, strlen(buffer));
66 if (ret != NF_ACCEPT)
67 ip_conntrack_unexpect_related(exp);
68 return ret;
69}
70
71static void __exit ip_nat_amanda_fini(void)
72{
73 rcu_assign_pointer(ip_nat_amanda_hook, NULL);
74 synchronize_rcu();
75}
76
77static int __init ip_nat_amanda_init(void)
78{
79 BUG_ON(rcu_dereference(ip_nat_amanda_hook));
80 rcu_assign_pointer(ip_nat_amanda_hook, help);
81 return 0;
82}
83
84module_init(ip_nat_amanda_init);
85module_exit(ip_nat_amanda_fini);
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
deleted file mode 100644
index cf46930606f2..000000000000
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ /dev/null
@@ -1,633 +0,0 @@
1/* NAT for netfilter; shared with compatibility layer. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/timer.h>
14#include <linux/skbuff.h>
15#include <linux/netfilter_ipv4.h>
16#include <linux/vmalloc.h>
17#include <net/checksum.h>
18#include <net/icmp.h>
19#include <net/ip.h>
20#include <net/tcp.h> /* For tcp_prot in getorigdst */
21#include <linux/icmp.h>
22#include <linux/udp.h>
23#include <linux/jhash.h>
24
25#include <linux/netfilter_ipv4/ip_conntrack.h>
26#include <linux/netfilter_ipv4/ip_conntrack_core.h>
27#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
28#include <linux/netfilter_ipv4/ip_nat.h>
29#include <linux/netfilter_ipv4/ip_nat_protocol.h>
30#include <linux/netfilter_ipv4/ip_nat_core.h>
31#include <linux/netfilter_ipv4/ip_nat_helper.h>
32#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
33
34#if 0
35#define DEBUGP printk
36#else
37#define DEBUGP(format, args...)
38#endif
39
40DEFINE_RWLOCK(ip_nat_lock);
41
42/* Calculated at init based on memory size */
43static unsigned int ip_nat_htable_size;
44
45static struct list_head *bysource;
46
47#define MAX_IP_NAT_PROTO 256
48static struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
49
50static inline struct ip_nat_protocol *
51__ip_nat_proto_find(u_int8_t protonum)
52{
53 return rcu_dereference(ip_nat_protos[protonum]);
54}
55
56struct ip_nat_protocol *
57ip_nat_proto_find_get(u_int8_t protonum)
58{
59 struct ip_nat_protocol *p;
60
61 rcu_read_lock();
62 p = __ip_nat_proto_find(protonum);
63 if (!try_module_get(p->me))
64 p = &ip_nat_unknown_protocol;
65 rcu_read_unlock();
66
67 return p;
68}
69EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
70
71void
72ip_nat_proto_put(struct ip_nat_protocol *p)
73{
74 module_put(p->me);
75}
76EXPORT_SYMBOL_GPL(ip_nat_proto_put);
77
78/* We keep an extra hash for each conntrack, for fast searching. */
79static inline unsigned int
80hash_by_src(const struct ip_conntrack_tuple *tuple)
81{
82 /* Original src, to ensure we map it consistently if poss. */
83 return jhash_3words((__force u32)tuple->src.ip, tuple->src.u.all,
84 tuple->dst.protonum, 0) % ip_nat_htable_size;
85}
86
87/* Noone using conntrack by the time this called. */
88static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
89{
90 if (!(conn->status & IPS_NAT_DONE_MASK))
91 return;
92
93 write_lock_bh(&ip_nat_lock);
94 list_del(&conn->nat.info.bysource);
95 write_unlock_bh(&ip_nat_lock);
96}
97
98/* Is this tuple already taken? (not by us) */
99int
100ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
101 const struct ip_conntrack *ignored_conntrack)
102{
103 /* Conntrack tracking doesn't keep track of outgoing tuples; only
104 incoming ones. NAT means they don't have a fixed mapping,
105 so we invert the tuple and look for the incoming reply.
106
107 We could keep a separate hash if this proves too slow. */
108 struct ip_conntrack_tuple reply;
109
110 invert_tuplepr(&reply, tuple);
111 return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
112}
113EXPORT_SYMBOL(ip_nat_used_tuple);
114
115/* If we source map this tuple so reply looks like reply_tuple, will
116 * that meet the constraints of range. */
117static int
118in_range(const struct ip_conntrack_tuple *tuple,
119 const struct ip_nat_range *range)
120{
121 struct ip_nat_protocol *proto;
122 int ret = 0;
123
124 /* If we are supposed to map IPs, then we must be in the
125 range specified, otherwise let this drag us onto a new src IP. */
126 if (range->flags & IP_NAT_RANGE_MAP_IPS) {
127 if (ntohl(tuple->src.ip) < ntohl(range->min_ip)
128 || ntohl(tuple->src.ip) > ntohl(range->max_ip))
129 return 0;
130 }
131
132 rcu_read_lock();
133 proto = __ip_nat_proto_find(tuple->dst.protonum);
134 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
135 || proto->in_range(tuple, IP_NAT_MANIP_SRC,
136 &range->min, &range->max))
137 ret = 1;
138 rcu_read_unlock();
139
140 return ret;
141}
142
143static inline int
144same_src(const struct ip_conntrack *ct,
145 const struct ip_conntrack_tuple *tuple)
146{
147 return (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
148 == tuple->dst.protonum
149 && ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
150 == tuple->src.ip
151 && ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
152 == tuple->src.u.all);
153}
154
155/* Only called for SRC manip */
156static int
157find_appropriate_src(const struct ip_conntrack_tuple *tuple,
158 struct ip_conntrack_tuple *result,
159 const struct ip_nat_range *range)
160{
161 unsigned int h = hash_by_src(tuple);
162 struct ip_conntrack *ct;
163
164 read_lock_bh(&ip_nat_lock);
165 list_for_each_entry(ct, &bysource[h], nat.info.bysource) {
166 if (same_src(ct, tuple)) {
167 /* Copy source part from reply tuple. */
168 invert_tuplepr(result,
169 &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
170 result->dst = tuple->dst;
171
172 if (in_range(result, range)) {
173 read_unlock_bh(&ip_nat_lock);
174 return 1;
175 }
176 }
177 }
178 read_unlock_bh(&ip_nat_lock);
179 return 0;
180}
181
182/* For [FUTURE] fragmentation handling, we want the least-used
183 src-ip/dst-ip/proto triple. Fairness doesn't come into it. Thus
184 if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports
185 1-65535, we don't do pro-rata allocation based on ports; we choose
186 the ip with the lowest src-ip/dst-ip/proto usage.
187*/
188static void
189find_best_ips_proto(struct ip_conntrack_tuple *tuple,
190 const struct ip_nat_range *range,
191 const struct ip_conntrack *conntrack,
192 enum ip_nat_manip_type maniptype)
193{
194 __be32 *var_ipp;
195 /* Host order */
196 u_int32_t minip, maxip, j;
197
198 /* No IP mapping? Do nothing. */
199 if (!(range->flags & IP_NAT_RANGE_MAP_IPS))
200 return;
201
202 if (maniptype == IP_NAT_MANIP_SRC)
203 var_ipp = &tuple->src.ip;
204 else
205 var_ipp = &tuple->dst.ip;
206
207 /* Fast path: only one choice. */
208 if (range->min_ip == range->max_ip) {
209 *var_ipp = range->min_ip;
210 return;
211 }
212
213 /* Hashing source and destination IPs gives a fairly even
214 * spread in practice (if there are a small number of IPs
215 * involved, there usually aren't that many connections
216 * anyway). The consistency means that servers see the same
217 * client coming from the same IP (some Internet Banking sites
218 * like this), even across reboots. */
219 minip = ntohl(range->min_ip);
220 maxip = ntohl(range->max_ip);
221 j = jhash_2words((__force u32)tuple->src.ip, (__force u32)tuple->dst.ip, 0);
222 *var_ipp = htonl(minip + j % (maxip - minip + 1));
223}
224
225/* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING,
226 * we change the source to map into the range. For NF_IP_PRE_ROUTING
227 * and NF_IP_LOCAL_OUT, we change the destination to map into the
228 * range. It might not be possible to get a unique tuple, but we try.
229 * At worst (or if we race), we will end up with a final duplicate in
230 * __ip_conntrack_confirm and drop the packet. */
231static void
232get_unique_tuple(struct ip_conntrack_tuple *tuple,
233 const struct ip_conntrack_tuple *orig_tuple,
234 const struct ip_nat_range *range,
235 struct ip_conntrack *conntrack,
236 enum ip_nat_manip_type maniptype)
237{
238 struct ip_nat_protocol *proto;
239
240 /* 1) If this srcip/proto/src-proto-part is currently mapped,
241 and that same mapping gives a unique tuple within the given
242 range, use that.
243
244 This is only required for source (ie. NAT/masq) mappings.
245 So far, we don't do local source mappings, so multiple
246 manips not an issue. */
247 if (maniptype == IP_NAT_MANIP_SRC) {
248 if (find_appropriate_src(orig_tuple, tuple, range)) {
249 DEBUGP("get_unique_tuple: Found current src map\n");
250 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
251 if (!ip_nat_used_tuple(tuple, conntrack))
252 return;
253 }
254 }
255
256 /* 2) Select the least-used IP/proto combination in the given
257 range. */
258 *tuple = *orig_tuple;
259 find_best_ips_proto(tuple, range, conntrack, maniptype);
260
261 /* 3) The per-protocol part of the manip is made to map into
262 the range to make a unique tuple. */
263
264 rcu_read_lock();
265 proto = __ip_nat_proto_find(orig_tuple->dst.protonum);
266
267 /* Change protocol info to have some randomization */
268 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
269 proto->unique_tuple(tuple, range, maniptype, conntrack);
270 goto out;
271 }
272
273 /* Only bother mapping if it's not already in range and unique */
274 if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
275 || proto->in_range(tuple, maniptype, &range->min, &range->max))
276 && !ip_nat_used_tuple(tuple, conntrack))
277 goto out;
278
279 /* Last change: get protocol to try to obtain unique tuple. */
280 proto->unique_tuple(tuple, range, maniptype, conntrack);
281out:
282 rcu_read_unlock();
283}
284
285unsigned int
286ip_nat_setup_info(struct ip_conntrack *conntrack,
287 const struct ip_nat_range *range,
288 unsigned int hooknum)
289{
290 struct ip_conntrack_tuple curr_tuple, new_tuple;
291 struct ip_nat_info *info = &conntrack->nat.info;
292 int have_to_hash = !(conntrack->status & IPS_NAT_DONE_MASK);
293 enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum);
294
295 IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
296 || hooknum == NF_IP_POST_ROUTING
297 || hooknum == NF_IP_LOCAL_IN
298 || hooknum == NF_IP_LOCAL_OUT);
299 BUG_ON(ip_nat_initialized(conntrack, maniptype));
300
301 /* What we've got will look like inverse of reply. Normally
302 this is what is in the conntrack, except for prior
303 manipulations (future optimization: if num_manips == 0,
304 orig_tp =
305 conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */
306 invert_tuplepr(&curr_tuple,
307 &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple);
308
309 get_unique_tuple(&new_tuple, &curr_tuple, range, conntrack, maniptype);
310
311 if (!ip_ct_tuple_equal(&new_tuple, &curr_tuple)) {
312 struct ip_conntrack_tuple reply;
313
314 /* Alter conntrack table so will recognize replies. */
315 invert_tuplepr(&reply, &new_tuple);
316 ip_conntrack_alter_reply(conntrack, &reply);
317
318 /* Non-atomic: we own this at the moment. */
319 if (maniptype == IP_NAT_MANIP_SRC)
320 conntrack->status |= IPS_SRC_NAT;
321 else
322 conntrack->status |= IPS_DST_NAT;
323 }
324
325 /* Place in source hash if this is the first time. */
326 if (have_to_hash) {
327 unsigned int srchash
328 = hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
329 .tuple);
330 write_lock_bh(&ip_nat_lock);
331 list_add(&info->bysource, &bysource[srchash]);
332 write_unlock_bh(&ip_nat_lock);
333 }
334
335 /* It's done. */
336 if (maniptype == IP_NAT_MANIP_DST)
337 set_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status);
338 else
339 set_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status);
340
341 return NF_ACCEPT;
342}
343EXPORT_SYMBOL(ip_nat_setup_info);
344
345/* Returns true if succeeded. */
346static int
347manip_pkt(u_int16_t proto,
348 struct sk_buff **pskb,
349 unsigned int iphdroff,
350 const struct ip_conntrack_tuple *target,
351 enum ip_nat_manip_type maniptype)
352{
353 struct iphdr *iph;
354 struct ip_nat_protocol *p;
355
356 if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))
357 return 0;
358
359 iph = (void *)(*pskb)->data + iphdroff;
360
361 /* Manipulate protcol part. */
362
363 /* rcu_read_lock()ed by nf_hook_slow */
364 p = __ip_nat_proto_find(proto);
365 if (!p->manip_pkt(pskb, iphdroff, target, maniptype))
366 return 0;
367
368 iph = (void *)(*pskb)->data + iphdroff;
369
370 if (maniptype == IP_NAT_MANIP_SRC) {
371 nf_csum_replace4(&iph->check, iph->saddr, target->src.ip);
372 iph->saddr = target->src.ip;
373 } else {
374 nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip);
375 iph->daddr = target->dst.ip;
376 }
377 return 1;
378}
379
380/* Do packet manipulations according to ip_nat_setup_info. */
381unsigned int ip_nat_packet(struct ip_conntrack *ct,
382 enum ip_conntrack_info ctinfo,
383 unsigned int hooknum,
384 struct sk_buff **pskb)
385{
386 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
387 unsigned long statusbit;
388 enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum);
389
390 if (mtype == IP_NAT_MANIP_SRC)
391 statusbit = IPS_SRC_NAT;
392 else
393 statusbit = IPS_DST_NAT;
394
395 /* Invert if this is reply dir. */
396 if (dir == IP_CT_DIR_REPLY)
397 statusbit ^= IPS_NAT_MASK;
398
399 /* Non-atomic: these bits don't change. */
400 if (ct->status & statusbit) {
401 struct ip_conntrack_tuple target;
402
403 /* We are aiming to look like inverse of other direction. */
404 invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
405
406 if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype))
407 return NF_DROP;
408 }
409 return NF_ACCEPT;
410}
411EXPORT_SYMBOL_GPL(ip_nat_packet);
412
413/* Dir is direction ICMP is coming from (opposite to packet it contains) */
414int ip_nat_icmp_reply_translation(struct ip_conntrack *ct,
415 enum ip_conntrack_info ctinfo,
416 unsigned int hooknum,
417 struct sk_buff **pskb)
418{
419 struct {
420 struct icmphdr icmp;
421 struct iphdr ip;
422 } *inside;
423 struct ip_conntrack_protocol *proto;
424 struct ip_conntrack_tuple inner, target;
425 int hdrlen = ip_hdrlen(*pskb);
426 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
427 unsigned long statusbit;
428 enum ip_nat_manip_type manip = HOOK2MANIP(hooknum);
429
430 if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
431 return 0;
432
433 inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
434
435 /* We're actually going to mangle it beyond trivial checksum
436 adjustment, so make sure the current checksum is correct. */
437 if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0))
438 return 0;
439
440 /* Must be RELATED */
441 IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
442 (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
443
444 /* Redirects on non-null nats must be dropped, else they'll
445 start talking to each other without our translation, and be
446 confused... --RR */
447 if (inside->icmp.type == ICMP_REDIRECT) {
448 /* If NAT isn't finished, assume it and drop. */
449 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
450 return 0;
451
452 if (ct->status & IPS_NAT_MASK)
453 return 0;
454 }
455
456 DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
457 *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
458
459 /* rcu_read_lock()ed by nf_hook_slow */
460 proto = __ip_conntrack_proto_find(inside->ip.protocol);
461 if (!ip_ct_get_tuple(&inside->ip, *pskb, ip_hdrlen(*pskb) +
462 sizeof(struct icmphdr) + inside->ip.ihl*4,
463 &inner, proto))
464 return 0;
465
466 /* Change inner back to look like incoming packet. We do the
467 opposite manip on this hook to normal, because it might not
468 pass all hooks (locally-generated ICMP). Consider incoming
469 packet: PREROUTING (DST manip), routing produces ICMP, goes
470 through POSTROUTING (which must correct the DST manip). */
471 if (!manip_pkt(inside->ip.protocol, pskb,
472 ip_hdrlen(*pskb) + sizeof(inside->icmp),
473 &ct->tuplehash[!dir].tuple,
474 !manip))
475 return 0;
476
477 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
478 /* Reloading "inside" here since manip_pkt inner. */
479 inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
480 inside->icmp.checksum = 0;
481 inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,
482 (*pskb)->len - hdrlen,
483 0));
484 }
485
486 /* Change outer to look the reply to an incoming packet
487 * (proto 0 means don't invert per-proto part). */
488 if (manip == IP_NAT_MANIP_SRC)
489 statusbit = IPS_SRC_NAT;
490 else
491 statusbit = IPS_DST_NAT;
492
493 /* Invert if this is reply dir. */
494 if (dir == IP_CT_DIR_REPLY)
495 statusbit ^= IPS_NAT_MASK;
496
497 if (ct->status & statusbit) {
498 invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
499 if (!manip_pkt(0, pskb, 0, &target, manip))
500 return 0;
501 }
502
503 return 1;
504}
505EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);
506
507/* Protocol registration. */
508int ip_nat_protocol_register(struct ip_nat_protocol *proto)
509{
510 int ret = 0;
511
512 write_lock_bh(&ip_nat_lock);
513 if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {
514 ret = -EBUSY;
515 goto out;
516 }
517 rcu_assign_pointer(ip_nat_protos[proto->protonum], proto);
518 out:
519 write_unlock_bh(&ip_nat_lock);
520 return ret;
521}
522EXPORT_SYMBOL(ip_nat_protocol_register);
523
524/* Noone stores the protocol anywhere; simply delete it. */
525void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
526{
527 write_lock_bh(&ip_nat_lock);
528 rcu_assign_pointer(ip_nat_protos[proto->protonum],
529 &ip_nat_unknown_protocol);
530 write_unlock_bh(&ip_nat_lock);
531 synchronize_rcu();
532}
533EXPORT_SYMBOL(ip_nat_protocol_unregister);
534
535#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
536 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
537int
538ip_nat_port_range_to_nfattr(struct sk_buff *skb,
539 const struct ip_nat_range *range)
540{
541 NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16),
542 &range->min.tcp.port);
543 NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(__be16),
544 &range->max.tcp.port);
545
546 return 0;
547
548nfattr_failure:
549 return -1;
550}
551
552int
553ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
554{
555 int ret = 0;
556
557 /* we have to return whether we actually parsed something or not */
558
559 if (tb[CTA_PROTONAT_PORT_MIN-1]) {
560 ret = 1;
561 range->min.tcp.port =
562 *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
563 }
564
565 if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
566 if (ret)
567 range->max.tcp.port = range->min.tcp.port;
568 } else {
569 ret = 1;
570 range->max.tcp.port =
571 *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
572 }
573
574 return ret;
575}
576EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
577EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
578#endif
579
580static int __init ip_nat_init(void)
581{
582 size_t i;
583
584 /* Leave them the same for the moment. */
585 ip_nat_htable_size = ip_conntrack_htable_size;
586
587 /* One vmalloc for both hash tables */
588 bysource = vmalloc(sizeof(struct list_head) * ip_nat_htable_size);
589 if (!bysource)
590 return -ENOMEM;
591
592 /* Sew in builtin protocols. */
593 write_lock_bh(&ip_nat_lock);
594 for (i = 0; i < MAX_IP_NAT_PROTO; i++)
595 rcu_assign_pointer(ip_nat_protos[i], &ip_nat_unknown_protocol);
596 rcu_assign_pointer(ip_nat_protos[IPPROTO_TCP], &ip_nat_protocol_tcp);
597 rcu_assign_pointer(ip_nat_protos[IPPROTO_UDP], &ip_nat_protocol_udp);
598 rcu_assign_pointer(ip_nat_protos[IPPROTO_ICMP], &ip_nat_protocol_icmp);
599 write_unlock_bh(&ip_nat_lock);
600
601 for (i = 0; i < ip_nat_htable_size; i++) {
602 INIT_LIST_HEAD(&bysource[i]);
603 }
604
605 /* FIXME: Man, this is a hack. <SIGH> */
606 IP_NF_ASSERT(rcu_dereference(ip_conntrack_destroyed) == NULL);
607 rcu_assign_pointer(ip_conntrack_destroyed, ip_nat_cleanup_conntrack);
608
609 /* Initialize fake conntrack so that NAT will skip it */
610 ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
611 return 0;
612}
613
614/* Clear NAT section of all conntracks, in case we're loaded again. */
615static int clean_nat(struct ip_conntrack *i, void *data)
616{
617 memset(&i->nat, 0, sizeof(i->nat));
618 i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
619 return 0;
620}
621
622static void __exit ip_nat_cleanup(void)
623{
624 ip_ct_iterate_cleanup(&clean_nat, NULL);
625 rcu_assign_pointer(ip_conntrack_destroyed, NULL);
626 synchronize_rcu();
627 vfree(bysource);
628}
629
630MODULE_LICENSE("GPL");
631
632module_init(ip_nat_init);
633module_exit(ip_nat_cleanup);
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
deleted file mode 100644
index 32e01d8dffcb..000000000000
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ /dev/null
@@ -1,180 +0,0 @@
1/* FTP extension for TCP NAT alteration. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/netfilter_ipv4.h>
13#include <linux/ip.h>
14#include <linux/tcp.h>
15#include <linux/moduleparam.h>
16#include <net/tcp.h>
17#include <linux/netfilter_ipv4/ip_nat.h>
18#include <linux/netfilter_ipv4/ip_nat_helper.h>
19#include <linux/netfilter_ipv4/ip_nat_rule.h>
20#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
21#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
25MODULE_DESCRIPTION("ftp NAT helper");
26
27#if 0
28#define DEBUGP printk
29#else
30#define DEBUGP(format, args...)
31#endif
32
33/* FIXME: Time out? --RR */
34
35static int
36mangle_rfc959_packet(struct sk_buff **pskb,
37 __be32 newip,
38 u_int16_t port,
39 unsigned int matchoff,
40 unsigned int matchlen,
41 struct ip_conntrack *ct,
42 enum ip_conntrack_info ctinfo,
43 u32 *seq)
44{
45 char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
46
47 sprintf(buffer, "%u,%u,%u,%u,%u,%u",
48 NIPQUAD(newip), port>>8, port&0xFF);
49
50 DEBUGP("calling ip_nat_mangle_tcp_packet\n");
51
52 *seq += strlen(buffer) - matchlen;
53 return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
54 matchlen, buffer, strlen(buffer));
55}
56
57/* |1|132.235.1.2|6275| */
58static int
59mangle_eprt_packet(struct sk_buff **pskb,
60 __be32 newip,
61 u_int16_t port,
62 unsigned int matchoff,
63 unsigned int matchlen,
64 struct ip_conntrack *ct,
65 enum ip_conntrack_info ctinfo,
66 u32 *seq)
67{
68 char buffer[sizeof("|1|255.255.255.255|65535|")];
69
70 sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
71
72 DEBUGP("calling ip_nat_mangle_tcp_packet\n");
73
74 *seq += strlen(buffer) - matchlen;
75 return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
76 matchlen, buffer, strlen(buffer));
77}
78
79/* |1|132.235.1.2|6275| */
80static int
81mangle_epsv_packet(struct sk_buff **pskb,
82 __be32 newip,
83 u_int16_t port,
84 unsigned int matchoff,
85 unsigned int matchlen,
86 struct ip_conntrack *ct,
87 enum ip_conntrack_info ctinfo,
88 u32 *seq)
89{
90 char buffer[sizeof("|||65535|")];
91
92 sprintf(buffer, "|||%u|", port);
93
94 DEBUGP("calling ip_nat_mangle_tcp_packet\n");
95
96 *seq += strlen(buffer) - matchlen;
97 return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
98 matchlen, buffer, strlen(buffer));
99}
100
101static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
102 unsigned int,
103 unsigned int,
104 struct ip_conntrack *,
105 enum ip_conntrack_info,
106 u32 *seq)
107= { [IP_CT_FTP_PORT] = mangle_rfc959_packet,
108 [IP_CT_FTP_PASV] = mangle_rfc959_packet,
109 [IP_CT_FTP_EPRT] = mangle_eprt_packet,
110 [IP_CT_FTP_EPSV] = mangle_epsv_packet
111};
112
113/* So, this packet has hit the connection tracking matching code.
114 Mangle it, and change the expectation to match the new version. */
115static unsigned int ip_nat_ftp(struct sk_buff **pskb,
116 enum ip_conntrack_info ctinfo,
117 enum ip_ct_ftp_type type,
118 unsigned int matchoff,
119 unsigned int matchlen,
120 struct ip_conntrack_expect *exp,
121 u32 *seq)
122{
123 __be32 newip;
124 u_int16_t port;
125 int dir = CTINFO2DIR(ctinfo);
126 struct ip_conntrack *ct = exp->master;
127
128 DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
129
130 /* Connection will come from wherever this packet goes, hence !dir */
131 newip = ct->tuplehash[!dir].tuple.dst.ip;
132 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
133 exp->dir = !dir;
134
135 /* When you see the packet, we need to NAT it the same as the
136 * this one. */
137 exp->expectfn = ip_nat_follow_master;
138
139 /* Try to get same port: if not, try to change it. */
140 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
141 exp->tuple.dst.u.tcp.port = htons(port);
142 if (ip_conntrack_expect_related(exp) == 0)
143 break;
144 }
145
146 if (port == 0)
147 return NF_DROP;
148
149 if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo,
150 seq)) {
151 ip_conntrack_unexpect_related(exp);
152 return NF_DROP;
153 }
154 return NF_ACCEPT;
155}
156
157static void __exit ip_nat_ftp_fini(void)
158{
159 rcu_assign_pointer(ip_nat_ftp_hook, NULL);
160 synchronize_rcu();
161}
162
163static int __init ip_nat_ftp_init(void)
164{
165 BUG_ON(rcu_dereference(ip_nat_ftp_hook));
166 rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp);
167 return 0;
168}
169
170/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
171static int warn_set(const char *val, struct kernel_param *kp)
172{
173 printk(KERN_INFO KBUILD_MODNAME
174 ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
175 return 0;
176}
177module_param_call(ports, warn_set, NULL, NULL, 0);
178
179module_init(ip_nat_ftp_init);
180module_exit(ip_nat_ftp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
deleted file mode 100644
index 4cddc2951744..000000000000
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ /dev/null
@@ -1,436 +0,0 @@
1/* ip_nat_helper.c - generic support functions for NAT helpers
2 *
3 * (C) 2000-2002 Harald Welte <laforge@netfilter.org>
4 * (C) 2003-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 14 Jan 2002 Harald Welte <laforge@gnumonks.org>:
11 * - add support for SACK adjustment
12 * 14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
13 * - merge SACK support into newnat API
14 * 16 Aug 2002 Brian J. Murrell <netfilter@interlinx.bc.ca>:
15 * - make ip_nat_resize_packet more generic (TCP and UDP)
16 * - add ip_nat_mangle_udp_packet
17 */
18#include <linux/module.h>
19#include <linux/kmod.h>
20#include <linux/types.h>
21#include <linux/timer.h>
22#include <linux/skbuff.h>
23#include <linux/netfilter_ipv4.h>
24#include <net/checksum.h>
25#include <net/icmp.h>
26#include <net/ip.h>
27#include <net/tcp.h>
28#include <net/udp.h>
29
30#include <linux/netfilter_ipv4/ip_conntrack.h>
31#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
32#include <linux/netfilter_ipv4/ip_nat.h>
33#include <linux/netfilter_ipv4/ip_nat_protocol.h>
34#include <linux/netfilter_ipv4/ip_nat_core.h>
35#include <linux/netfilter_ipv4/ip_nat_helper.h>
36
37#if 0
38#define DEBUGP printk
39#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
40#else
41#define DEBUGP(format, args...)
42#define DUMP_OFFSET(x)
43#endif
44
45static DEFINE_SPINLOCK(ip_nat_seqofs_lock);
46
47/* Setup TCP sequence correction given this change at this sequence */
48static inline void
49adjust_tcp_sequence(u32 seq,
50 int sizediff,
51 struct ip_conntrack *ct,
52 enum ip_conntrack_info ctinfo)
53{
54 int dir;
55 struct ip_nat_seq *this_way, *other_way;
56
57 DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n",
58 (*skb)->len, new_size);
59
60 dir = CTINFO2DIR(ctinfo);
61
62 this_way = &ct->nat.info.seq[dir];
63 other_way = &ct->nat.info.seq[!dir];
64
65 DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
66 DUMP_OFFSET(this_way);
67
68 spin_lock_bh(&ip_nat_seqofs_lock);
69
70 /* SYN adjust. If it's uninitialized, or this is after last
71 * correction, record it: we don't handle more than one
72 * adjustment in the window, but do deal with common case of a
73 * retransmit */
74 if (this_way->offset_before == this_way->offset_after
75 || before(this_way->correction_pos, seq)) {
76 this_way->correction_pos = seq;
77 this_way->offset_before = this_way->offset_after;
78 this_way->offset_after += sizediff;
79 }
80 spin_unlock_bh(&ip_nat_seqofs_lock);
81
82 DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
83 DUMP_OFFSET(this_way);
84}
85
86/* Frobs data inside this packet, which is linear. */
87static void mangle_contents(struct sk_buff *skb,
88 unsigned int dataoff,
89 unsigned int match_offset,
90 unsigned int match_len,
91 const char *rep_buffer,
92 unsigned int rep_len)
93{
94 unsigned char *data;
95
96 BUG_ON(skb_is_nonlinear(skb));
97 data = skb_network_header(skb) + dataoff;
98
99 /* move post-replacement */
100 memmove(data + match_offset + rep_len,
101 data + match_offset + match_len,
102 skb->tail - (data + match_offset + match_len));
103
104 /* insert data from buffer */
105 memcpy(data + match_offset, rep_buffer, rep_len);
106
107 /* update skb info */
108 if (rep_len > match_len) {
109 DEBUGP("ip_nat_mangle_packet: Extending packet by "
110 "%u from %u bytes\n", rep_len - match_len,
111 skb->len);
112 skb_put(skb, rep_len - match_len);
113 } else {
114 DEBUGP("ip_nat_mangle_packet: Shrinking packet from "
115 "%u from %u bytes\n", match_len - rep_len,
116 skb->len);
117 __skb_trim(skb, skb->len + rep_len - match_len);
118 }
119
120 /* fix IP hdr checksum information */
121 ip_hdr(skb)->tot_len = htons(skb->len);
122 ip_send_check(ip_hdr(skb));
123}
124
125/* Unusual, but possible case. */
126static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
127{
128 struct sk_buff *nskb;
129
130 if ((*pskb)->len + extra > 65535)
131 return 0;
132
133 nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
134 if (!nskb)
135 return 0;
136
137 /* Transfer socket to new skb. */
138 if ((*pskb)->sk)
139 skb_set_owner_w(nskb, (*pskb)->sk);
140 kfree_skb(*pskb);
141 *pskb = nskb;
142 return 1;
143}
144
145/* Generic function for mangling variable-length address changes inside
146 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
147 * command in FTP).
148 *
149 * Takes care about all the nasty sequence number changes, checksumming,
150 * skb enlargement, ...
151 *
152 * */
153int
154ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
155 struct ip_conntrack *ct,
156 enum ip_conntrack_info ctinfo,
157 unsigned int match_offset,
158 unsigned int match_len,
159 const char *rep_buffer,
160 unsigned int rep_len)
161{
162 struct iphdr *iph;
163 struct tcphdr *tcph;
164 int oldlen, datalen;
165
166 if (!skb_make_writable(pskb, (*pskb)->len))
167 return 0;
168
169 if (rep_len > match_len
170 && rep_len - match_len > skb_tailroom(*pskb)
171 && !enlarge_skb(pskb, rep_len - match_len))
172 return 0;
173
174 SKB_LINEAR_ASSERT(*pskb);
175
176 iph = ip_hdr(*pskb);
177 tcph = (void *)iph + iph->ihl*4;
178
179 oldlen = (*pskb)->len - iph->ihl*4;
180 mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
181 match_offset, match_len, rep_buffer, rep_len);
182
183 datalen = (*pskb)->len - iph->ihl*4;
184 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
185 tcph->check = 0;
186 tcph->check = tcp_v4_check(datalen,
187 iph->saddr, iph->daddr,
188 csum_partial((char *)tcph,
189 datalen, 0));
190 } else
191 nf_proto_csum_replace2(&tcph->check, *pskb,
192 htons(oldlen), htons(datalen), 1);
193
194 if (rep_len != match_len) {
195 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
196 adjust_tcp_sequence(ntohl(tcph->seq),
197 (int)rep_len - (int)match_len,
198 ct, ctinfo);
199 /* Tell TCP window tracking about seq change */
200 ip_conntrack_tcp_update(*pskb, ct, CTINFO2DIR(ctinfo));
201 }
202 return 1;
203}
204EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
205
206/* Generic function for mangling variable-length address changes inside
207 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
208 * command in the Amanda protocol)
209 *
210 * Takes care about all the nasty sequence number changes, checksumming,
211 * skb enlargement, ...
212 *
213 * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
214 * should be fairly easy to do.
215 */
216int
217ip_nat_mangle_udp_packet(struct sk_buff **pskb,
218 struct ip_conntrack *ct,
219 enum ip_conntrack_info ctinfo,
220 unsigned int match_offset,
221 unsigned int match_len,
222 const char *rep_buffer,
223 unsigned int rep_len)
224{
225 struct iphdr *iph;
226 struct udphdr *udph;
227 int datalen, oldlen;
228
229 /* UDP helpers might accidentally mangle the wrong packet */
230 iph = ip_hdr(*pskb);
231 if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
232 match_offset + match_len)
233 return 0;
234
235 if (!skb_make_writable(pskb, (*pskb)->len))
236 return 0;
237
238 if (rep_len > match_len
239 && rep_len - match_len > skb_tailroom(*pskb)
240 && !enlarge_skb(pskb, rep_len - match_len))
241 return 0;
242
243 iph = ip_hdr(*pskb);
244 udph = (void *)iph + iph->ihl*4;
245
246 oldlen = (*pskb)->len - iph->ihl*4;
247 mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
248 match_offset, match_len, rep_buffer, rep_len);
249
250 /* update the length of the UDP packet */
251 datalen = (*pskb)->len - iph->ihl*4;
252 udph->len = htons(datalen);
253
254 /* fix udp checksum if udp checksum was previously calculated */
255 if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
256 return 1;
257
258 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
259 udph->check = 0;
260 udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
261 datalen, IPPROTO_UDP,
262 csum_partial((char *)udph,
263 datalen, 0));
264 if (!udph->check)
265 udph->check = CSUM_MANGLED_0;
266 } else
267 nf_proto_csum_replace2(&udph->check, *pskb,
268 htons(oldlen), htons(datalen), 1);
269 return 1;
270}
271EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
272
273/* Adjust one found SACK option including checksum correction */
274static void
275sack_adjust(struct sk_buff *skb,
276 struct tcphdr *tcph,
277 unsigned int sackoff,
278 unsigned int sackend,
279 struct ip_nat_seq *natseq)
280{
281 while (sackoff < sackend) {
282 struct tcp_sack_block_wire *sack;
283 __be32 new_start_seq, new_end_seq;
284
285 sack = (void *)skb->data + sackoff;
286 if (after(ntohl(sack->start_seq) - natseq->offset_before,
287 natseq->correction_pos))
288 new_start_seq = htonl(ntohl(sack->start_seq)
289 - natseq->offset_after);
290 else
291 new_start_seq = htonl(ntohl(sack->start_seq)
292 - natseq->offset_before);
293
294 if (after(ntohl(sack->end_seq) - natseq->offset_before,
295 natseq->correction_pos))
296 new_end_seq = htonl(ntohl(sack->end_seq)
297 - natseq->offset_after);
298 else
299 new_end_seq = htonl(ntohl(sack->end_seq)
300 - natseq->offset_before);
301
302 DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
303 ntohl(sack->start_seq), new_start_seq,
304 ntohl(sack->end_seq), new_end_seq);
305
306 nf_proto_csum_replace4(&tcph->check, skb,
307 sack->start_seq, new_start_seq, 0);
308 nf_proto_csum_replace4(&tcph->check, skb,
309 sack->end_seq, new_end_seq, 0);
310 sack->start_seq = new_start_seq;
311 sack->end_seq = new_end_seq;
312 sackoff += sizeof(*sack);
313 }
314}
315
316/* TCP SACK sequence number adjustment */
317static inline unsigned int
318ip_nat_sack_adjust(struct sk_buff **pskb,
319 struct tcphdr *tcph,
320 struct ip_conntrack *ct,
321 enum ip_conntrack_info ctinfo)
322{
323 unsigned int dir, optoff, optend;
324
325 optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr);
326 optend = ip_hdrlen(*pskb) + tcph->doff * 4;
327
328 if (!skb_make_writable(pskb, optend))
329 return 0;
330
331 dir = CTINFO2DIR(ctinfo);
332
333 while (optoff < optend) {
334 /* Usually: option, length. */
335 unsigned char *op = (*pskb)->data + optoff;
336
337 switch (op[0]) {
338 case TCPOPT_EOL:
339 return 1;
340 case TCPOPT_NOP:
341 optoff++;
342 continue;
343 default:
344 /* no partial options */
345 if (optoff + 1 == optend
346 || optoff + op[1] > optend
347 || op[1] < 2)
348 return 0;
349 if (op[0] == TCPOPT_SACK
350 && op[1] >= 2+TCPOLEN_SACK_PERBLOCK
351 && ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
352 sack_adjust(*pskb, tcph, optoff+2,
353 optoff+op[1],
354 &ct->nat.info.seq[!dir]);
355 optoff += op[1];
356 }
357 }
358 return 1;
359}
360
361/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */
362int
363ip_nat_seq_adjust(struct sk_buff **pskb,
364 struct ip_conntrack *ct,
365 enum ip_conntrack_info ctinfo)
366{
367 struct tcphdr *tcph;
368 int dir;
369 __be32 newseq, newack;
370 struct ip_nat_seq *this_way, *other_way;
371
372 dir = CTINFO2DIR(ctinfo);
373
374 this_way = &ct->nat.info.seq[dir];
375 other_way = &ct->nat.info.seq[!dir];
376
377 if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
378 return 0;
379
380 tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb);
381 if (after(ntohl(tcph->seq), this_way->correction_pos))
382 newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
383 else
384 newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);
385
386 if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
387 other_way->correction_pos))
388 newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
389 else
390 newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
391
392 nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
393 nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
394
395 DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
396 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
397 ntohl(newack));
398
399 tcph->seq = newseq;
400 tcph->ack_seq = newack;
401
402 if (!ip_nat_sack_adjust(pskb, tcph, ct, ctinfo))
403 return 0;
404
405 ip_conntrack_tcp_update(*pskb, ct, dir);
406
407 return 1;
408}
409EXPORT_SYMBOL(ip_nat_seq_adjust);
410
411/* Setup NAT on this expected conntrack so it follows master. */
412/* If we fail to get a free NAT slot, we'll get dropped on confirm */
413void ip_nat_follow_master(struct ip_conntrack *ct,
414 struct ip_conntrack_expect *exp)
415{
416 struct ip_nat_range range;
417
418 /* This must be a fresh one. */
419 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
420
421 /* Change src to where master sends to */
422 range.flags = IP_NAT_RANGE_MAP_IPS;
423 range.min_ip = range.max_ip
424 = ct->master->tuplehash[!exp->dir].tuple.dst.ip;
425 /* hook doesn't matter, but it has to do source manip */
426 ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
427
428 /* For DST manip, map port here to where it's expected. */
429 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
430 range.min = range.max = exp->saved_proto;
431 range.min_ip = range.max_ip
432 = ct->master->tuplehash[!exp->dir].tuple.src.ip;
433 /* hook doesn't matter, but it has to do destination manip */
434 ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
435}
436EXPORT_SYMBOL(ip_nat_follow_master);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
deleted file mode 100644
index 0d9444f9236b..000000000000
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ /dev/null
@@ -1,611 +0,0 @@
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/netfilter_ipv4.h>
14#include <linux/netfilter.h>
15#include <linux/ip.h>
16#include <linux/tcp.h>
17#include <linux/moduleparam.h>
18#include <net/tcp.h>
19#include <linux/netfilter_ipv4/ip_nat.h>
20#include <linux/netfilter_ipv4/ip_nat_helper.h>
21#include <linux/netfilter_ipv4/ip_nat_rule.h>
22#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
23#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
24#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
25
26#if 0
27#define DEBUGP printk
28#else
29#define DEBUGP(format, args...)
30#endif
31
32/****************************************************************************/
33static int set_addr(struct sk_buff **pskb,
34 unsigned char **data, int dataoff,
35 unsigned int addroff, __be32 ip, u_int16_t port)
36{
37 enum ip_conntrack_info ctinfo;
38 struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
39 struct {
40 __be32 ip;
41 __be16 port;
42 } __attribute__ ((__packed__)) buf;
43 struct tcphdr _tcph, *th;
44
45 buf.ip = ip;
46 buf.port = htons(port);
47 addroff += dataoff;
48
49 if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) {
50 if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
51 addroff, sizeof(buf),
52 (char *) &buf, sizeof(buf))) {
53 if (net_ratelimit())
54 printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
55 " error\n");
56 return -1;
57 }
58
59 /* Relocate data pointer */
60 th = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
61 sizeof(_tcph), &_tcph);
62 if (th == NULL)
63 return -1;
64 *data = (*pskb)->data + ip_hdrlen(*pskb) +
65 th->doff * 4 + dataoff;
66 } else {
67 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
68 addroff, sizeof(buf),
69 (char *) &buf, sizeof(buf))) {
70 if (net_ratelimit())
71 printk("ip_nat_h323: ip_nat_mangle_udp_packet"
72 " error\n");
73 return -1;
74 }
75 /* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
76 * or pull everything in a linear buffer, so we can safely
77 * use the skb pointers now */
78 *data = ((*pskb)->data + ip_hdrlen(*pskb) +
79 sizeof(struct udphdr));
80 }
81
82 return 0;
83}
84
85/****************************************************************************/
86static int set_h225_addr(struct sk_buff **pskb,
87 unsigned char **data, int dataoff,
88 TransportAddress * addr,
89 __be32 ip, u_int16_t port)
90{
91 return set_addr(pskb, data, dataoff, addr->ipAddress.ip, ip, port);
92}
93
94/****************************************************************************/
95static int set_h245_addr(struct sk_buff **pskb,
96 unsigned char **data, int dataoff,
97 H245_TransportAddress * addr,
98 __be32 ip, u_int16_t port)
99{
100 return set_addr(pskb, data, dataoff,
101 addr->unicastAddress.iPAddress.network, ip, port);
102}
103
104/****************************************************************************/
105static int set_sig_addr(struct sk_buff **pskb, struct ip_conntrack *ct,
106 enum ip_conntrack_info ctinfo,
107 unsigned char **data,
108 TransportAddress * addr, int count)
109{
110 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
111 int dir = CTINFO2DIR(ctinfo);
112 int i;
113 __be32 ip;
114 u_int16_t port;
115
116 for (i = 0; i < count; i++) {
117 if (get_h225_addr(*data, &addr[i], &ip, &port)) {
118 if (ip == ct->tuplehash[dir].tuple.src.ip &&
119 port == info->sig_port[dir]) {
120 /* GW->GK */
121
122 /* Fix for Gnomemeeting */
123 if (i > 0 &&
124 get_h225_addr(*data, &addr[0],
125 &ip, &port) &&
126 (ntohl(ip) & 0xff000000) == 0x7f000000)
127 i = 0;
128
129 DEBUGP
130 ("ip_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, &addr[i],
136 ct->tuplehash[!dir].
137 tuple.dst.ip,
138 info->sig_port[!dir]);
139 } else if (ip == ct->tuplehash[dir].tuple.dst.ip &&
140 port == info->sig_port[dir]) {
141 /* GK->GW */
142 DEBUGP
143 ("ip_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, &addr[i],
149 ct->tuplehash[!dir].
150 tuple.src.ip,
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 ip_conntrack *ct,
161 enum ip_conntrack_info ctinfo,
162 unsigned char **data,
163 TransportAddress * addr, int count)
164{
165 int dir = CTINFO2DIR(ctinfo);
166 int i;
167 __be32 ip;
168 u_int16_t port;
169
170 for (i = 0; i < count; i++) {
171 if (get_h225_addr(*data, &addr[i], &ip, &port) &&
172 ip == ct->tuplehash[dir].tuple.src.ip &&
173 port == ntohs(ct->tuplehash[dir].tuple.src.u.udp.port)) {
174 DEBUGP("ip_nat_ras: set rasAddress "
175 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
176 NIPQUAD(ip), port,
177 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
178 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
179 port));
180 return set_h225_addr(pskb, data, 0, &addr[i],
181 ct->tuplehash[!dir].tuple.dst.ip,
182 ntohs(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 ip_conntrack *ct,
192 enum ip_conntrack_info ctinfo,
193 unsigned char **data, int dataoff,
194 H245_TransportAddress * addr,
195 u_int16_t port, u_int16_t rtp_port,
196 struct ip_conntrack_expect *rtp_exp,
197 struct ip_conntrack_expect *rtcp_exp)
198{
199 struct ip_ct_h323_master *info = &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 = ip_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 = ip_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 =
220 htons(info->rtp_port[i][dir]);
221 rtcp_exp->tuple.dst.u.udp.port =
222 htons(info->rtp_port[i][dir] + 1);
223 break;
224 } else if (info->rtp_port[i][dir] == 0) {
225 /* Not expected */
226 break;
227 }
228 }
229
230 /* Run out of expectations */
231 if (i >= H323_RTP_CHANNEL_MAX) {
232 if (net_ratelimit())
233 printk("ip_nat_h323: out of expectations\n");
234 return 0;
235 }
236
237 /* Try to get a pair of ports. */
238 for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
239 nated_port != 0; nated_port += 2) {
240 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
241 if (ip_conntrack_expect_related(rtp_exp) == 0) {
242 rtcp_exp->tuple.dst.u.udp.port =
243 htons(nated_port + 1);
244 if (ip_conntrack_expect_related(rtcp_exp) == 0)
245 break;
246 ip_conntrack_unexpect_related(rtp_exp);
247 }
248 }
249
250 if (nated_port == 0) { /* No port available */
251 if (net_ratelimit())
252 printk("ip_nat_h323: out of RTP ports\n");
253 return 0;
254 }
255
256 /* Modify signal */
257 if (set_h245_addr(pskb, data, dataoff, addr,
258 ct->tuplehash[!dir].tuple.dst.ip,
259 (port & 1) ? nated_port + 1 : nated_port) == 0) {
260 /* Save ports */
261 info->rtp_port[i][dir] = rtp_port;
262 info->rtp_port[i][!dir] = nated_port;
263 } else {
264 ip_conntrack_unexpect_related(rtp_exp);
265 ip_conntrack_unexpect_related(rtcp_exp);
266 return -1;
267 }
268
269 /* Success */
270 DEBUGP("ip_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("ip_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 ip_conntrack *ct,
286 enum ip_conntrack_info ctinfo,
287 unsigned char **data, int dataoff,
288 H245_TransportAddress * addr, u_int16_t port,
289 struct ip_conntrack_expect *exp)
290{
291 int dir = CTINFO2DIR(ctinfo);
292 u_int16_t nated_port = port;
293
294 /* Set expectations for NAT */
295 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
296 exp->expectfn = ip_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 (ip_conntrack_expect_related(exp) == 0)
303 break;
304 }
305
306 if (nated_port == 0) { /* No port available */
307 if (net_ratelimit())
308 printk("ip_nat_h323: out of TCP ports\n");
309 return 0;
310 }
311
312 /* Modify signal */
313 if (set_h245_addr(pskb, data, dataoff, addr,
314 ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) {
315 ip_conntrack_unexpect_related(exp);
316 return -1;
317 }
318
319 DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
320 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
321 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
322
323 return 0;
324}
325
326/****************************************************************************
327 * This conntrack expect function replaces ip_conntrack_h245_expect()
328 * which was set by ip_conntrack_helper_h323.c. It calls both
329 * ip_nat_follow_master() and ip_conntrack_h245_expect()
330 ****************************************************************************/
331static void ip_nat_h245_expect(struct ip_conntrack *new,
332 struct ip_conntrack_expect *this)
333{
334 ip_nat_follow_master(new, this);
335 ip_conntrack_h245_expect(new, this);
336}
337
338/****************************************************************************/
339static int nat_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
340 enum ip_conntrack_info ctinfo,
341 unsigned char **data, int dataoff,
342 TransportAddress * addr, u_int16_t port,
343 struct ip_conntrack_expect *exp)
344{
345 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
346 int dir = CTINFO2DIR(ctinfo);
347 u_int16_t nated_port = port;
348
349 /* Set expectations for NAT */
350 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
351 exp->expectfn = ip_nat_h245_expect;
352 exp->dir = !dir;
353
354 /* Check existing expects */
355 if (info->sig_port[dir] == port)
356 nated_port = info->sig_port[!dir];
357
358 /* Try to get same port: if not, try to change it. */
359 for (; nated_port != 0; nated_port++) {
360 exp->tuple.dst.u.tcp.port = htons(nated_port);
361 if (ip_conntrack_expect_related(exp) == 0)
362 break;
363 }
364
365 if (nated_port == 0) { /* No port available */
366 if (net_ratelimit())
367 printk("ip_nat_q931: out of TCP ports\n");
368 return 0;
369 }
370
371 /* Modify signal */
372 if (set_h225_addr(pskb, data, dataoff, addr,
373 ct->tuplehash[!dir].tuple.dst.ip,
374 nated_port) == 0) {
375 /* Save ports */
376 info->sig_port[dir] = port;
377 info->sig_port[!dir] = nated_port;
378 } else {
379 ip_conntrack_unexpect_related(exp);
380 return -1;
381 }
382
383 DEBUGP("ip_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
384 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
385 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
386
387 return 0;
388}
389
390/****************************************************************************
391 * This conntrack expect function replaces ip_conntrack_q931_expect()
392 * which was set by ip_conntrack_helper_h323.c.
393 ****************************************************************************/
394static void ip_nat_q931_expect(struct ip_conntrack *new,
395 struct ip_conntrack_expect *this)
396{
397 struct ip_nat_range range;
398
399 if (this->tuple.src.ip != 0) { /* Only accept calls from GK */
400 ip_nat_follow_master(new, this);
401 goto out;
402 }
403
404 /* This must be a fresh one. */
405 BUG_ON(new->status & IPS_NAT_DONE_MASK);
406
407 /* Change src to where master sends to */
408 range.flags = IP_NAT_RANGE_MAP_IPS;
409 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
410
411 /* hook doesn't matter, but it has to do source manip */
412 ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
413
414 /* For DST manip, map port here to where it's expected. */
415 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
416 range.min = range.max = this->saved_proto;
417 range.min_ip = range.max_ip =
418 new->master->tuplehash[!this->dir].tuple.src.ip;
419
420 /* hook doesn't matter, but it has to do destination manip */
421 ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
422
423 out:
424 ip_conntrack_q931_expect(new, this);
425}
426
427/****************************************************************************/
428static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
429 enum ip_conntrack_info ctinfo,
430 unsigned char **data, TransportAddress * addr, int idx,
431 u_int16_t port, struct ip_conntrack_expect *exp)
432{
433 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
434 int dir = CTINFO2DIR(ctinfo);
435 u_int16_t nated_port = port;
436 __be32 ip;
437
438 /* Set expectations for NAT */
439 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
440 exp->expectfn = ip_nat_q931_expect;
441 exp->dir = !dir;
442
443 /* Check existing expects */
444 if (info->sig_port[dir] == port)
445 nated_port = info->sig_port[!dir];
446
447 /* Try to get same port: if not, try to change it. */
448 for (; nated_port != 0; nated_port++) {
449 exp->tuple.dst.u.tcp.port = htons(nated_port);
450 if (ip_conntrack_expect_related(exp) == 0)
451 break;
452 }
453
454 if (nated_port == 0) { /* No port available */
455 if (net_ratelimit())
456 printk("ip_nat_ras: out of TCP ports\n");
457 return 0;
458 }
459
460 /* Modify signal */
461 if (set_h225_addr(pskb, data, 0, &addr[idx],
462 ct->tuplehash[!dir].tuple.dst.ip,
463 nated_port) == 0) {
464 /* Save ports */
465 info->sig_port[dir] = port;
466 info->sig_port[!dir] = nated_port;
467
468 /* Fix for Gnomemeeting */
469 if (idx > 0 &&
470 get_h225_addr(*data, &addr[0], &ip, &port) &&
471 (ntohl(ip) & 0xff000000) == 0x7f000000) {
472 set_h225_addr_hook(pskb, data, 0, &addr[0],
473 ct->tuplehash[!dir].tuple.dst.ip,
474 info->sig_port[!dir]);
475 }
476 } else {
477 ip_conntrack_unexpect_related(exp);
478 return -1;
479 }
480
481 /* Success */
482 DEBUGP("ip_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
483 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
484 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
485
486 return 0;
487}
488
489/****************************************************************************/
490static void ip_nat_callforwarding_expect(struct ip_conntrack *new,
491 struct ip_conntrack_expect *this)
492{
493 struct ip_nat_range range;
494
495 /* This must be a fresh one. */
496 BUG_ON(new->status & IPS_NAT_DONE_MASK);
497
498 /* Change src to where master sends to */
499 range.flags = IP_NAT_RANGE_MAP_IPS;
500 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
501
502 /* hook doesn't matter, but it has to do source manip */
503 ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
504
505 /* For DST manip, map port here to where it's expected. */
506 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
507 range.min = range.max = this->saved_proto;
508 range.min_ip = range.max_ip = this->saved_ip;
509
510 /* hook doesn't matter, but it has to do destination manip */
511 ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
512
513 ip_conntrack_q931_expect(new, this);
514}
515
516/****************************************************************************/
517static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
518 enum ip_conntrack_info ctinfo,
519 unsigned char **data, int dataoff,
520 TransportAddress * addr, u_int16_t port,
521 struct ip_conntrack_expect *exp)
522{
523 int dir = CTINFO2DIR(ctinfo);
524 u_int16_t nated_port;
525
526 /* Set expectations for NAT */
527 exp->saved_ip = exp->tuple.dst.ip;
528 exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
529 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
530 exp->expectfn = ip_nat_callforwarding_expect;
531 exp->dir = !dir;
532
533 /* Try to get same port: if not, try to change it. */
534 for (nated_port = port; nated_port != 0; nated_port++) {
535 exp->tuple.dst.u.tcp.port = htons(nated_port);
536 if (ip_conntrack_expect_related(exp) == 0)
537 break;
538 }
539
540 if (nated_port == 0) { /* No port available */
541 if (net_ratelimit())
542 printk("ip_nat_q931: out of TCP ports\n");
543 return 0;
544 }
545
546 /* Modify signal */
547 if (!set_h225_addr(pskb, data, dataoff, addr,
548 ct->tuplehash[!dir].tuple.dst.ip,
549 nated_port) == 0) {
550 ip_conntrack_unexpect_related(exp);
551 return -1;
552 }
553
554 /* Success */
555 DEBUGP("ip_nat_q931: expect Call Forwarding "
556 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
557 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
558 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
559
560 return 0;
561}
562
563/****************************************************************************/
564static int __init init(void)
565{
566 BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
567 BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
568 BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
569 BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
570 BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
571 BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
572 BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
573 BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
574 BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
575
576 rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
577 rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
578 rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
579 rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
580 rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
581 rcu_assign_pointer(nat_t120_hook, nat_t120);
582 rcu_assign_pointer(nat_h245_hook, nat_h245);
583 rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
584 rcu_assign_pointer(nat_q931_hook, nat_q931);
585
586 DEBUGP("ip_nat_h323: init success\n");
587 return 0;
588}
589
590/****************************************************************************/
591static void __exit fini(void)
592{
593 rcu_assign_pointer(set_h245_addr_hook, NULL);
594 rcu_assign_pointer(set_h225_addr_hook, NULL);
595 rcu_assign_pointer(set_sig_addr_hook, NULL);
596 rcu_assign_pointer(set_ras_addr_hook, NULL);
597 rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
598 rcu_assign_pointer(nat_t120_hook, NULL);
599 rcu_assign_pointer(nat_h245_hook, NULL);
600 rcu_assign_pointer(nat_callforwarding_hook, NULL);
601 rcu_assign_pointer(nat_q931_hook, NULL);
602 synchronize_rcu();
603}
604
605/****************************************************************************/
606module_init(init);
607module_exit(fini);
608
609MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
610MODULE_DESCRIPTION("H.323 NAT helper");
611MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
deleted file mode 100644
index 24ce4a5023d7..000000000000
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ /dev/null
@@ -1,350 +0,0 @@
1/*
2 * ip_nat_pptp.c - Version 3.0
3 *
4 * NAT support for PPTP (Point to Point Tunneling Protocol).
5 * PPTP is a a protocol for creating virtual private networks.
6 * It is a specification defined by Microsoft and some vendors
7 * working with Microsoft. PPTP is built on top of a modified
8 * version of the Internet Generic Routing Encapsulation Protocol.
9 * GRE is defined in RFC 1701 and RFC 1702. Documentation of
10 * PPTP can be found in RFC 2637
11 *
12 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
13 *
14 * Development of this code funded by Astaro AG (http://www.astaro.com/)
15 *
16 * TODO: - NAT to a unique tuple, not to TCP source port
17 * (needs netfilter tuple reservation)
18 *
19 * Changes:
20 * 2002-02-10 - Version 1.3
21 * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
22 * in local connections (Philip Craig <philipc@snapgear.com>)
23 * - add checks for magicCookie and pptp version
24 * - make argument list of pptp_{out,in}bound_packet() shorter
25 * - move to C99 style initializers
26 * - print version number at module loadtime
27 * 2003-09-22 - Version 1.5
28 * - use SNATed tcp sourceport as callid, since we get called before
29 * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
30 * 2004-10-22 - Version 2.0
31 * - kernel 2.6.x version
32 * 2005-06-10 - Version 3.0
33 * - kernel >= 2.6.11 version,
34 * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
35 *
36 */
37
38#include <linux/module.h>
39#include <linux/ip.h>
40#include <linux/tcp.h>
41#include <net/tcp.h>
42
43#include <linux/netfilter_ipv4/ip_nat.h>
44#include <linux/netfilter_ipv4/ip_nat_rule.h>
45#include <linux/netfilter_ipv4/ip_nat_helper.h>
46#include <linux/netfilter_ipv4/ip_nat_pptp.h>
47#include <linux/netfilter_ipv4/ip_conntrack_core.h>
48#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
49#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
50#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
51
52#define IP_NAT_PPTP_VERSION "3.0"
53
54#define REQ_CID(req, off) (*(__be16 *)((char *)(req) + (off)))
55
56MODULE_LICENSE("GPL");
57MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
58MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
59
60
61#if 0
62extern const char *pptp_msg_name[];
63#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
64 __FUNCTION__, ## args)
65#else
66#define DEBUGP(format, args...)
67#endif
68
69static void pptp_nat_expected(struct ip_conntrack *ct,
70 struct ip_conntrack_expect *exp)
71{
72 struct ip_conntrack *master = ct->master;
73 struct ip_conntrack_expect *other_exp;
74 struct ip_conntrack_tuple t;
75 struct ip_ct_pptp_master *ct_pptp_info;
76 struct ip_nat_pptp *nat_pptp_info;
77 struct ip_nat_range range;
78
79 ct_pptp_info = &master->help.ct_pptp_info;
80 nat_pptp_info = &master->nat.help.nat_pptp_info;
81
82 /* And here goes the grand finale of corrosion... */
83
84 if (exp->dir == IP_CT_DIR_ORIGINAL) {
85 DEBUGP("we are PNS->PAC\n");
86 /* therefore, build tuple for PAC->PNS */
87 t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
88 t.src.u.gre.key = master->help.ct_pptp_info.pac_call_id;
89 t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
90 t.dst.u.gre.key = master->help.ct_pptp_info.pns_call_id;
91 t.dst.protonum = IPPROTO_GRE;
92 } else {
93 DEBUGP("we are PAC->PNS\n");
94 /* build tuple for PNS->PAC */
95 t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
96 t.src.u.gre.key = master->nat.help.nat_pptp_info.pns_call_id;
97 t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
98 t.dst.u.gre.key = master->nat.help.nat_pptp_info.pac_call_id;
99 t.dst.protonum = IPPROTO_GRE;
100 }
101
102 DEBUGP("trying to unexpect other dir: ");
103 DUMP_TUPLE(&t);
104 other_exp = ip_conntrack_expect_find_get(&t);
105 if (other_exp) {
106 ip_conntrack_unexpect_related(other_exp);
107 ip_conntrack_expect_put(other_exp);
108 DEBUGP("success\n");
109 } else {
110 DEBUGP("not found!\n");
111 }
112
113 /* This must be a fresh one. */
114 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
115
116 /* Change src to where master sends to */
117 range.flags = IP_NAT_RANGE_MAP_IPS;
118 range.min_ip = range.max_ip
119 = ct->master->tuplehash[!exp->dir].tuple.dst.ip;
120 if (exp->dir == IP_CT_DIR_ORIGINAL) {
121 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
122 range.min = range.max = exp->saved_proto;
123 }
124 /* hook doesn't matter, but it has to do source manip */
125 ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
126
127 /* For DST manip, map port here to where it's expected. */
128 range.flags = IP_NAT_RANGE_MAP_IPS;
129 range.min_ip = range.max_ip
130 = ct->master->tuplehash[!exp->dir].tuple.src.ip;
131 if (exp->dir == IP_CT_DIR_REPLY) {
132 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
133 range.min = range.max = exp->saved_proto;
134 }
135 /* hook doesn't matter, but it has to do destination manip */
136 ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
137}
138
139/* outbound packets == from PNS to PAC */
140static int
141pptp_outbound_pkt(struct sk_buff **pskb,
142 struct ip_conntrack *ct,
143 enum ip_conntrack_info ctinfo,
144 struct PptpControlHeader *ctlh,
145 union pptp_ctrl_union *pptpReq)
146
147{
148 struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
149 struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
150 u_int16_t msg;
151 __be16 new_callid;
152 unsigned int cid_off;
153
154 new_callid = ct_pptp_info->pns_call_id;
155
156 switch (msg = ntohs(ctlh->messageType)) {
157 case PPTP_OUT_CALL_REQUEST:
158 cid_off = offsetof(union pptp_ctrl_union, ocreq.callID);
159 /* FIXME: ideally we would want to reserve a call ID
160 * here. current netfilter NAT core is not able to do
161 * this :( For now we use TCP source port. This breaks
162 * multiple calls within one control session */
163
164 /* save original call ID in nat_info */
165 nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
166
167 /* don't use tcph->source since we are at a DSTmanip
168 * hook (e.g. PREROUTING) and pkt is not mangled yet */
169 new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
170
171 /* save new call ID in ct info */
172 ct_pptp_info->pns_call_id = new_callid;
173 break;
174 case PPTP_IN_CALL_REPLY:
175 cid_off = offsetof(union pptp_ctrl_union, icack.callID);
176 break;
177 case PPTP_CALL_CLEAR_REQUEST:
178 cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
179 break;
180 default:
181 DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
182 (msg <= PPTP_MSG_MAX)?
183 pptp_msg_name[msg]:pptp_msg_name[0]);
184 /* fall through */
185
186 case PPTP_SET_LINK_INFO:
187 /* only need to NAT in case PAC is behind NAT box */
188 case PPTP_START_SESSION_REQUEST:
189 case PPTP_START_SESSION_REPLY:
190 case PPTP_STOP_SESSION_REQUEST:
191 case PPTP_STOP_SESSION_REPLY:
192 case PPTP_ECHO_REQUEST:
193 case PPTP_ECHO_REPLY:
194 /* no need to alter packet */
195 return NF_ACCEPT;
196 }
197
198 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
199 * down to here */
200 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
201 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
202
203 /* mangle packet */
204 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
205 cid_off + sizeof(struct pptp_pkt_hdr) +
206 sizeof(struct PptpControlHeader),
207 sizeof(new_callid), (char *)&new_callid,
208 sizeof(new_callid)) == 0)
209 return NF_DROP;
210
211 return NF_ACCEPT;
212}
213
214static void
215pptp_exp_gre(struct ip_conntrack_expect *expect_orig,
216 struct ip_conntrack_expect *expect_reply)
217{
218 struct ip_conntrack *ct = expect_orig->master;
219 struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
220 struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
221
222 /* save original PAC call ID in nat_info */
223 nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
224
225 /* alter expectation for PNS->PAC direction */
226 expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
227 expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
228 expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
229 expect_orig->dir = IP_CT_DIR_ORIGINAL;
230
231 /* alter expectation for PAC->PNS direction */
232 expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
233 expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
234 expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
235 expect_reply->dir = IP_CT_DIR_REPLY;
236}
237
238/* inbound packets == from PAC to PNS */
239static int
240pptp_inbound_pkt(struct sk_buff **pskb,
241 struct ip_conntrack *ct,
242 enum ip_conntrack_info ctinfo,
243 struct PptpControlHeader *ctlh,
244 union pptp_ctrl_union *pptpReq)
245{
246 struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
247 u_int16_t msg;
248 __be16 new_pcid;
249 unsigned int pcid_off;
250
251 new_pcid = nat_pptp_info->pns_call_id;
252
253 switch (msg = ntohs(ctlh->messageType)) {
254 case PPTP_OUT_CALL_REPLY:
255 pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID);
256 break;
257 case PPTP_IN_CALL_CONNECT:
258 pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID);
259 break;
260 case PPTP_IN_CALL_REQUEST:
261 /* only need to nat in case PAC is behind NAT box */
262 return NF_ACCEPT;
263 case PPTP_WAN_ERROR_NOTIFY:
264 pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID);
265 break;
266 case PPTP_CALL_DISCONNECT_NOTIFY:
267 pcid_off = offsetof(union pptp_ctrl_union, disc.callID);
268 break;
269 case PPTP_SET_LINK_INFO:
270 pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
271 break;
272
273 default:
274 DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
275 pptp_msg_name[msg]:pptp_msg_name[0]);
276 /* fall through */
277
278 case PPTP_START_SESSION_REQUEST:
279 case PPTP_START_SESSION_REPLY:
280 case PPTP_STOP_SESSION_REQUEST:
281 case PPTP_STOP_SESSION_REPLY:
282 case PPTP_ECHO_REQUEST:
283 case PPTP_ECHO_REPLY:
284 /* no need to alter packet */
285 return NF_ACCEPT;
286 }
287
288 /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
289 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
290
291 /* mangle packet */
292 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
293 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
294
295 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
296 pcid_off + sizeof(struct pptp_pkt_hdr) +
297 sizeof(struct PptpControlHeader),
298 sizeof(new_pcid), (char *)&new_pcid,
299 sizeof(new_pcid)) == 0)
300 return NF_DROP;
301 return NF_ACCEPT;
302}
303
304
305extern int __init ip_nat_proto_gre_init(void);
306extern void __exit ip_nat_proto_gre_fini(void);
307
308static int __init ip_nat_helper_pptp_init(void)
309{
310 int ret;
311
312 DEBUGP("%s: registering NAT helper\n", __FILE__);
313
314 ret = ip_nat_proto_gre_init();
315 if (ret < 0)
316 return ret;
317
318 BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound));
319 rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt);
320
321 BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound));
322 rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt);
323
324 BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre));
325 rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre);
326
327 BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn));
328 rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected);
329
330 printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
331 return 0;
332}
333
334static void __exit ip_nat_helper_pptp_fini(void)
335{
336 DEBUGP("cleanup_module\n" );
337
338 rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL);
339 rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL);
340 rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL);
341 rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL);
342 synchronize_rcu();
343
344 ip_nat_proto_gre_fini();
345
346 printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
347}
348
349module_init(ip_nat_helper_pptp_init);
350module_exit(ip_nat_helper_pptp_fini);
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
deleted file mode 100644
index cfaeea38314f..000000000000
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ /dev/null
@@ -1,122 +0,0 @@
1/* IRC extension for TCP NAT alteration.
2 * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
3 * (C) 2004 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
4 * based on a copy of RR's ip_nat_ftp.c
5 *
6 * ip_nat_irc.c,v 1.16 2001/12/06 07:42:10 laforge Exp
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/netfilter_ipv4.h>
16#include <linux/ip.h>
17#include <linux/tcp.h>
18#include <linux/kernel.h>
19#include <net/tcp.h>
20#include <linux/netfilter_ipv4/ip_nat.h>
21#include <linux/netfilter_ipv4/ip_nat_helper.h>
22#include <linux/netfilter_ipv4/ip_nat_rule.h>
23#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
24#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
25#include <linux/moduleparam.h>
26
27#if 0
28#define DEBUGP printk
29#else
30#define DEBUGP(format, args...)
31#endif
32
33MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
34MODULE_DESCRIPTION("IRC (DCC) NAT helper");
35MODULE_LICENSE("GPL");
36
37static unsigned int help(struct sk_buff **pskb,
38 enum ip_conntrack_info ctinfo,
39 unsigned int matchoff,
40 unsigned int matchlen,
41 struct ip_conntrack_expect *exp)
42{
43 u_int16_t port;
44 unsigned int ret;
45
46 /* "4294967296 65635 " */
47 char buffer[18];
48
49 DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
50 expect->seq, exp_irc_info->len,
51 ntohl(tcph->seq));
52
53 /* Reply comes from server. */
54 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
55 exp->dir = IP_CT_DIR_REPLY;
56
57 /* When you see the packet, we need to NAT it the same as the
58 * this one. */
59 exp->expectfn = ip_nat_follow_master;
60
61 /* Try to get same port: if not, try to change it. */
62 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
63 exp->tuple.dst.u.tcp.port = htons(port);
64 if (ip_conntrack_expect_related(exp) == 0)
65 break;
66 }
67
68 if (port == 0)
69 return NF_DROP;
70
71 /* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
72 * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
73 * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
74 * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
75 * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
76 * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
77 * 255.255.255.255==4294967296, 10 digits)
78 * P: bound port (min 1 d, max 5d (65635))
79 * F: filename (min 1 d )
80 * S: size (min 1 d )
81 * 0x01, \n: terminators
82 */
83
84 /* AAA = "us", ie. where server normally talks to. */
85 sprintf(buffer, "%u %u",
86 ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
87 port);
88 DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n",
89 buffer, NIPQUAD(exp->tuple.src.ip), port);
90
91 ret = ip_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
92 matchoff, matchlen, buffer,
93 strlen(buffer));
94 if (ret != NF_ACCEPT)
95 ip_conntrack_unexpect_related(exp);
96 return ret;
97}
98
99static void __exit ip_nat_irc_fini(void)
100{
101 rcu_assign_pointer(ip_nat_irc_hook, NULL);
102 synchronize_rcu();
103}
104
105static int __init ip_nat_irc_init(void)
106{
107 BUG_ON(rcu_dereference(ip_nat_irc_hook));
108 rcu_assign_pointer(ip_nat_irc_hook, help);
109 return 0;
110}
111
112/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
113static int warn_set(const char *val, struct kernel_param *kp)
114{
115 printk(KERN_INFO KBUILD_MODNAME
116 ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
117 return 0;
118}
119module_param_call(ports, warn_set, NULL, NULL, 0);
120
121module_init(ip_nat_irc_init);
122module_exit(ip_nat_irc_fini);
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
deleted file mode 100644
index 95810202d849..000000000000
--- a/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ /dev/null
@@ -1,174 +0,0 @@
1/*
2 * ip_nat_proto_gre.c - Version 2.0
3 *
4 * NAT protocol helper module for GRE.
5 *
6 * GRE is a generic encapsulation protocol, which is generally not very
7 * suited for NAT, as it has no protocol-specific part as port numbers.
8 *
9 * It has an optional key field, which may help us distinguishing two
10 * connections between the same two hosts.
11 *
12 * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
13 *
14 * PPTP is built on top of a modified version of GRE, and has a mandatory
15 * field called "CallID", which serves us for the same purpose as the key
16 * field in plain GRE.
17 *
18 * Documentation about PPTP can be found in RFC 2637
19 *
20 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
21 *
22 * Development of this code funded by Astaro AG (http://www.astaro.com/)
23 *
24 */
25
26#include <linux/module.h>
27#include <linux/ip.h>
28#include <linux/netfilter_ipv4/ip_nat.h>
29#include <linux/netfilter_ipv4/ip_nat_rule.h>
30#include <linux/netfilter_ipv4/ip_nat_protocol.h>
31#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
32
33MODULE_LICENSE("GPL");
34MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
35MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
36
37#if 0
38#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
39 __FUNCTION__, ## args)
40#else
41#define DEBUGP(x, args...)
42#endif
43
44/* is key in given range between min and max */
45static int
46gre_in_range(const struct ip_conntrack_tuple *tuple,
47 enum ip_nat_manip_type maniptype,
48 const union ip_conntrack_manip_proto *min,
49 const union ip_conntrack_manip_proto *max)
50{
51 __be16 key;
52
53 if (maniptype == IP_NAT_MANIP_SRC)
54 key = tuple->src.u.gre.key;
55 else
56 key = tuple->dst.u.gre.key;
57
58 return ntohs(key) >= ntohs(min->gre.key)
59 && ntohs(key) <= ntohs(max->gre.key);
60}
61
62/* generate unique tuple ... */
63static int
64gre_unique_tuple(struct ip_conntrack_tuple *tuple,
65 const struct ip_nat_range *range,
66 enum ip_nat_manip_type maniptype,
67 const struct ip_conntrack *conntrack)
68{
69 static u_int16_t key;
70 __be16 *keyptr;
71 unsigned int min, i, range_size;
72
73 if (maniptype == IP_NAT_MANIP_SRC)
74 keyptr = &tuple->src.u.gre.key;
75 else
76 keyptr = &tuple->dst.u.gre.key;
77
78 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
79 DEBUGP("%p: NATing GRE PPTP\n", conntrack);
80 min = 1;
81 range_size = 0xffff;
82 } else {
83 min = ntohs(range->min.gre.key);
84 range_size = ntohs(range->max.gre.key) - min + 1;
85 }
86
87 DEBUGP("min = %u, range_size = %u\n", min, range_size);
88
89 for (i = 0; i < range_size; i++, key++) {
90 *keyptr = htons(min + key % range_size);
91 if (!ip_nat_used_tuple(tuple, conntrack))
92 return 1;
93 }
94
95 DEBUGP("%p: no NAT mapping\n", conntrack);
96
97 return 0;
98}
99
100/* manipulate a GRE packet according to maniptype */
101static int
102gre_manip_pkt(struct sk_buff **pskb,
103 unsigned int iphdroff,
104 const struct ip_conntrack_tuple *tuple,
105 enum ip_nat_manip_type maniptype)
106{
107 struct gre_hdr *greh;
108 struct gre_hdr_pptp *pgreh;
109 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
110 unsigned int hdroff = iphdroff + iph->ihl*4;
111
112 /* pgreh includes two optional 32bit fields which are not required
113 * to be there. That's where the magic '8' comes from */
114 if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8))
115 return 0;
116
117 greh = (void *)(*pskb)->data + hdroff;
118 pgreh = (struct gre_hdr_pptp *) greh;
119
120 /* we only have destination manip of a packet, since 'source key'
121 * is not present in the packet itself */
122 if (maniptype == IP_NAT_MANIP_DST) {
123 /* key manipulation is always dest */
124 switch (greh->version) {
125 case 0:
126 if (!greh->key) {
127 DEBUGP("can't nat GRE w/o key\n");
128 break;
129 }
130 if (greh->csum) {
131 /* FIXME: Never tested this code... */
132 nf_proto_csum_replace4(gre_csum(greh), *pskb,
133 *(gre_key(greh)),
134 tuple->dst.u.gre.key, 0);
135 }
136 *(gre_key(greh)) = tuple->dst.u.gre.key;
137 break;
138 case GRE_VERSION_PPTP:
139 DEBUGP("call_id -> 0x%04x\n",
140 ntohs(tuple->dst.u.gre.key));
141 pgreh->call_id = tuple->dst.u.gre.key;
142 break;
143 default:
144 DEBUGP("can't nat unknown GRE version\n");
145 return 0;
146 break;
147 }
148 }
149 return 1;
150}
151
152/* nat helper struct */
153static struct ip_nat_protocol gre = {
154 .name = "GRE",
155 .protonum = IPPROTO_GRE,
156 .manip_pkt = gre_manip_pkt,
157 .in_range = gre_in_range,
158 .unique_tuple = gre_unique_tuple,
159#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
160 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
161 .range_to_nfattr = ip_nat_port_range_to_nfattr,
162 .nfattr_to_range = ip_nat_port_nfattr_to_range,
163#endif
164};
165
166int __init ip_nat_proto_gre_init(void)
167{
168 return ip_nat_protocol_register(&gre);
169}
170
171void __exit ip_nat_proto_gre_fini(void)
172{
173 ip_nat_protocol_unregister(&gre);
174}
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
deleted file mode 100644
index 22a528ae0380..000000000000
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ /dev/null
@@ -1,87 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/netfilter.h>
12#include <linux/ip.h>
13#include <linux/icmp.h>
14#include <linux/if.h>
15
16#include <linux/netfilter_ipv4/ip_nat.h>
17#include <linux/netfilter_ipv4/ip_nat_core.h>
18#include <linux/netfilter_ipv4/ip_nat_rule.h>
19#include <linux/netfilter_ipv4/ip_nat_protocol.h>
20
21static int
22icmp_in_range(const struct ip_conntrack_tuple *tuple,
23 enum ip_nat_manip_type maniptype,
24 const union ip_conntrack_manip_proto *min,
25 const union ip_conntrack_manip_proto *max)
26{
27 return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
28 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
29}
30
31static int
32icmp_unique_tuple(struct ip_conntrack_tuple *tuple,
33 const struct ip_nat_range *range,
34 enum ip_nat_manip_type maniptype,
35 const struct ip_conntrack *conntrack)
36{
37 static u_int16_t id;
38 unsigned int range_size;
39 unsigned int i;
40
41 range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1;
42 /* If no range specified... */
43 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED))
44 range_size = 0xFFFF;
45
46 for (i = 0; i < range_size; i++, id++) {
47 tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
48 (id % range_size));
49 if (!ip_nat_used_tuple(tuple, conntrack))
50 return 1;
51 }
52 return 0;
53}
54
55static int
56icmp_manip_pkt(struct sk_buff **pskb,
57 unsigned int iphdroff,
58 const struct ip_conntrack_tuple *tuple,
59 enum ip_nat_manip_type maniptype)
60{
61 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
62 struct icmphdr *hdr;
63 unsigned int hdroff = iphdroff + iph->ihl*4;
64
65 if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
66 return 0;
67
68 hdr = (struct icmphdr *)((*pskb)->data + hdroff);
69 nf_proto_csum_replace2(&hdr->checksum, *pskb,
70 hdr->un.echo.id, tuple->src.u.icmp.id, 0);
71 hdr->un.echo.id = tuple->src.u.icmp.id;
72 return 1;
73}
74
75struct ip_nat_protocol ip_nat_protocol_icmp = {
76 .name = "ICMP",
77 .protonum = IPPROTO_ICMP,
78 .me = THIS_MODULE,
79 .manip_pkt = icmp_manip_pkt,
80 .in_range = icmp_in_range,
81 .unique_tuple = icmp_unique_tuple,
82#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
83 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
84 .range_to_nfattr = ip_nat_port_range_to_nfattr,
85 .nfattr_to_range = ip_nat_port_nfattr_to_range,
86#endif
87};
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
deleted file mode 100644
index 14ff24f53a7a..000000000000
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/random.h>
12#include <linux/netfilter.h>
13#include <linux/ip.h>
14#include <linux/tcp.h>
15#include <linux/if.h>
16#include <linux/netfilter/nfnetlink_conntrack.h>
17#include <linux/netfilter_ipv4/ip_nat.h>
18#include <linux/netfilter_ipv4/ip_nat_rule.h>
19#include <linux/netfilter_ipv4/ip_nat_protocol.h>
20#include <linux/netfilter_ipv4/ip_nat_core.h>
21
22static int
23tcp_in_range(const struct ip_conntrack_tuple *tuple,
24 enum ip_nat_manip_type maniptype,
25 const union ip_conntrack_manip_proto *min,
26 const union ip_conntrack_manip_proto *max)
27{
28 __be16 port;
29
30 if (maniptype == IP_NAT_MANIP_SRC)
31 port = tuple->src.u.tcp.port;
32 else
33 port = tuple->dst.u.tcp.port;
34
35 return ntohs(port) >= ntohs(min->tcp.port)
36 && ntohs(port) <= ntohs(max->tcp.port);
37}
38
39static int
40tcp_unique_tuple(struct ip_conntrack_tuple *tuple,
41 const struct ip_nat_range *range,
42 enum ip_nat_manip_type maniptype,
43 const struct ip_conntrack *conntrack)
44{
45 static u_int16_t port;
46 __be16 *portptr;
47 unsigned int range_size, min, i;
48
49 if (maniptype == IP_NAT_MANIP_SRC)
50 portptr = &tuple->src.u.tcp.port;
51 else
52 portptr = &tuple->dst.u.tcp.port;
53
54 /* If no range specified... */
55 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
56 /* If it's dst rewrite, can't change port */
57 if (maniptype == IP_NAT_MANIP_DST)
58 return 0;
59
60 /* Map privileged onto privileged. */
61 if (ntohs(*portptr) < 1024) {
62 /* Loose convention: >> 512 is credential passing */
63 if (ntohs(*portptr)<512) {
64 min = 1;
65 range_size = 511 - min + 1;
66 } else {
67 min = 600;
68 range_size = 1023 - min + 1;
69 }
70 } else {
71 min = 1024;
72 range_size = 65535 - 1024 + 1;
73 }
74 } else {
75 min = ntohs(range->min.tcp.port);
76 range_size = ntohs(range->max.tcp.port) - min + 1;
77 }
78
79 /* Start from random port to avoid prediction */
80 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
81 port = net_random();
82
83 for (i = 0; i < range_size; i++, port++) {
84 *portptr = htons(min + port % range_size);
85 if (!ip_nat_used_tuple(tuple, conntrack)) {
86 return 1;
87 }
88 }
89 return 0;
90}
91
92static int
93tcp_manip_pkt(struct sk_buff **pskb,
94 unsigned int iphdroff,
95 const struct ip_conntrack_tuple *tuple,
96 enum ip_nat_manip_type maniptype)
97{
98 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
99 struct tcphdr *hdr;
100 unsigned int hdroff = iphdroff + iph->ihl*4;
101 __be32 oldip, newip;
102 __be16 *portptr, newport, oldport;
103 int hdrsize = 8; /* TCP connection tracking guarantees this much */
104
105 /* this could be a inner header returned in icmp packet; in such
106 cases we cannot update the checksum field since it is outside of
107 the 8 bytes of transport layer headers we are guaranteed */
108 if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
109 hdrsize = sizeof(struct tcphdr);
110
111 if (!skb_make_writable(pskb, hdroff + hdrsize))
112 return 0;
113
114 iph = (struct iphdr *)((*pskb)->data + iphdroff);
115 hdr = (struct tcphdr *)((*pskb)->data + hdroff);
116
117 if (maniptype == IP_NAT_MANIP_SRC) {
118 /* Get rid of src ip and src pt */
119 oldip = iph->saddr;
120 newip = tuple->src.ip;
121 newport = tuple->src.u.tcp.port;
122 portptr = &hdr->source;
123 } else {
124 /* Get rid of dst ip and dst pt */
125 oldip = iph->daddr;
126 newip = tuple->dst.ip;
127 newport = tuple->dst.u.tcp.port;
128 portptr = &hdr->dest;
129 }
130
131 oldport = *portptr;
132 *portptr = newport;
133
134 if (hdrsize < sizeof(*hdr))
135 return 1;
136
137 nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
138 nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
139 return 1;
140}
141
142struct ip_nat_protocol ip_nat_protocol_tcp = {
143 .name = "TCP",
144 .protonum = IPPROTO_TCP,
145 .me = THIS_MODULE,
146 .manip_pkt = tcp_manip_pkt,
147 .in_range = tcp_in_range,
148 .unique_tuple = tcp_unique_tuple,
149#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
150 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
151 .range_to_nfattr = ip_nat_port_range_to_nfattr,
152 .nfattr_to_range = ip_nat_port_nfattr_to_range,
153#endif
154};
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
deleted file mode 100644
index dfd521672891..000000000000
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ /dev/null
@@ -1,144 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/random.h>
12#include <linux/netfilter.h>
13#include <linux/ip.h>
14#include <linux/udp.h>
15#include <linux/if.h>
16
17#include <linux/netfilter_ipv4/ip_nat.h>
18#include <linux/netfilter_ipv4/ip_nat_core.h>
19#include <linux/netfilter_ipv4/ip_nat_rule.h>
20#include <linux/netfilter_ipv4/ip_nat_protocol.h>
21
22static int
23udp_in_range(const struct ip_conntrack_tuple *tuple,
24 enum ip_nat_manip_type maniptype,
25 const union ip_conntrack_manip_proto *min,
26 const union ip_conntrack_manip_proto *max)
27{
28 __be16 port;
29
30 if (maniptype == IP_NAT_MANIP_SRC)
31 port = tuple->src.u.udp.port;
32 else
33 port = tuple->dst.u.udp.port;
34
35 return ntohs(port) >= ntohs(min->udp.port)
36 && ntohs(port) <= ntohs(max->udp.port);
37}
38
39static int
40udp_unique_tuple(struct ip_conntrack_tuple *tuple,
41 const struct ip_nat_range *range,
42 enum ip_nat_manip_type maniptype,
43 const struct ip_conntrack *conntrack)
44{
45 static u_int16_t port;
46 __be16 *portptr;
47 unsigned int range_size, min, i;
48
49 if (maniptype == IP_NAT_MANIP_SRC)
50 portptr = &tuple->src.u.udp.port;
51 else
52 portptr = &tuple->dst.u.udp.port;
53
54 /* If no range specified... */
55 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
56 /* If it's dst rewrite, can't change port */
57 if (maniptype == IP_NAT_MANIP_DST)
58 return 0;
59
60 if (ntohs(*portptr) < 1024) {
61 /* Loose convention: >> 512 is credential passing */
62 if (ntohs(*portptr)<512) {
63 min = 1;
64 range_size = 511 - min + 1;
65 } else {
66 min = 600;
67 range_size = 1023 - min + 1;
68 }
69 } else {
70 min = 1024;
71 range_size = 65535 - 1024 + 1;
72 }
73 } else {
74 min = ntohs(range->min.udp.port);
75 range_size = ntohs(range->max.udp.port) - min + 1;
76 }
77
78 /* Start from random port to avoid prediction */
79 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
80 port = net_random();
81
82 for (i = 0; i < range_size; i++, port++) {
83 *portptr = htons(min + port % range_size);
84 if (!ip_nat_used_tuple(tuple, conntrack))
85 return 1;
86 }
87 return 0;
88}
89
90static int
91udp_manip_pkt(struct sk_buff **pskb,
92 unsigned int iphdroff,
93 const struct ip_conntrack_tuple *tuple,
94 enum ip_nat_manip_type maniptype)
95{
96 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
97 struct udphdr *hdr;
98 unsigned int hdroff = iphdroff + iph->ihl*4;
99 __be32 oldip, newip;
100 __be16 *portptr, newport;
101
102 if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
103 return 0;
104
105 iph = (struct iphdr *)((*pskb)->data + iphdroff);
106 hdr = (struct udphdr *)((*pskb)->data + hdroff);
107
108 if (maniptype == IP_NAT_MANIP_SRC) {
109 /* Get rid of src ip and src pt */
110 oldip = iph->saddr;
111 newip = tuple->src.ip;
112 newport = tuple->src.u.udp.port;
113 portptr = &hdr->source;
114 } else {
115 /* Get rid of dst ip and dst pt */
116 oldip = iph->daddr;
117 newip = tuple->dst.ip;
118 newport = tuple->dst.u.udp.port;
119 portptr = &hdr->dest;
120 }
121
122 if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
123 nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
124 nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0);
125 if (!hdr->check)
126 hdr->check = CSUM_MANGLED_0;
127 }
128 *portptr = newport;
129 return 1;
130}
131
132struct ip_nat_protocol ip_nat_protocol_udp = {
133 .name = "UDP",
134 .protonum = IPPROTO_UDP,
135 .me = THIS_MODULE,
136 .manip_pkt = udp_manip_pkt,
137 .in_range = udp_in_range,
138 .unique_tuple = udp_unique_tuple,
139#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
140 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
141 .range_to_nfattr = ip_nat_port_range_to_nfattr,
142 .nfattr_to_range = ip_nat_port_nfattr_to_range,
143#endif
144};
diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
deleted file mode 100644
index 3bf049517246..000000000000
--- a/net/ipv4/netfilter/ip_nat_proto_unknown.c
+++ /dev/null
@@ -1,55 +0,0 @@
1/* The "unknown" protocol. This is what is used for protocols we
2 * don't understand. It's returned by ip_ct_find_proto().
3 */
4
5/* (C) 1999-2001 Paul `Rusty' Russell
6 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/types.h>
14#include <linux/init.h>
15#include <linux/netfilter.h>
16#include <linux/if.h>
17
18#include <linux/netfilter_ipv4/ip_nat.h>
19#include <linux/netfilter_ipv4/ip_nat_rule.h>
20#include <linux/netfilter_ipv4/ip_nat_protocol.h>
21
22static int unknown_in_range(const struct ip_conntrack_tuple *tuple,
23 enum ip_nat_manip_type manip_type,
24 const union ip_conntrack_manip_proto *min,
25 const union ip_conntrack_manip_proto *max)
26{
27 return 1;
28}
29
30static int unknown_unique_tuple(struct ip_conntrack_tuple *tuple,
31 const struct ip_nat_range *range,
32 enum ip_nat_manip_type maniptype,
33 const struct ip_conntrack *conntrack)
34{
35 /* Sorry: we can't help you; if it's not unique, we can't frob
36 anything. */
37 return 0;
38}
39
40static int
41unknown_manip_pkt(struct sk_buff **pskb,
42 unsigned int iphdroff,
43 const struct ip_conntrack_tuple *tuple,
44 enum ip_nat_manip_type maniptype)
45{
46 return 1;
47}
48
49struct ip_nat_protocol ip_nat_unknown_protocol = {
50 .name = "unknown",
51 /* .me isn't set: getting a ref to this cannot fail. */
52 .manip_pkt = unknown_manip_pkt,
53 .in_range = unknown_in_range,
54 .unique_tuple = unknown_unique_tuple,
55};
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
deleted file mode 100644
index 25415a91e023..000000000000
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ /dev/null
@@ -1,314 +0,0 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9/* Everything about the rules for NAT. */
10#include <linux/types.h>
11#include <linux/ip.h>
12#include <linux/netfilter.h>
13#include <linux/netfilter_ipv4.h>
14#include <linux/module.h>
15#include <linux/kmod.h>
16#include <linux/skbuff.h>
17#include <linux/proc_fs.h>
18#include <net/checksum.h>
19#include <net/route.h>
20#include <linux/bitops.h>
21
22#include <linux/netfilter_ipv4/ip_tables.h>
23#include <linux/netfilter_ipv4/ip_nat.h>
24#include <linux/netfilter_ipv4/ip_nat_core.h>
25#include <linux/netfilter_ipv4/ip_nat_rule.h>
26
27#if 0
28#define DEBUGP printk
29#else
30#define DEBUGP(format, args...)
31#endif
32
33#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
34
35static struct
36{
37 struct ipt_replace repl;
38 struct ipt_standard entries[3];
39 struct ipt_error term;
40} nat_initial_table __initdata
41= { { "nat", NAT_VALID_HOOKS, 4,
42 sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
43 { [NF_IP_PRE_ROUTING] = 0,
44 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
45 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
46 { [NF_IP_PRE_ROUTING] = 0,
47 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
48 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
49 0, NULL, { } },
50 {
51 /* PRE_ROUTING */
52 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
53 0,
54 sizeof(struct ipt_entry),
55 sizeof(struct ipt_standard),
56 0, { 0, 0 }, { } },
57 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
58 -NF_ACCEPT - 1 } },
59 /* POST_ROUTING */
60 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
61 0,
62 sizeof(struct ipt_entry),
63 sizeof(struct ipt_standard),
64 0, { 0, 0 }, { } },
65 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
66 -NF_ACCEPT - 1 } },
67 /* LOCAL_OUT */
68 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
69 0,
70 sizeof(struct ipt_entry),
71 sizeof(struct ipt_standard),
72 0, { 0, 0 }, { } },
73 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
74 -NF_ACCEPT - 1 } }
75 },
76 /* ERROR */
77 { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
78 0,
79 sizeof(struct ipt_entry),
80 sizeof(struct ipt_error),
81 0, { 0, 0 }, { } },
82 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
83 { } },
84 "ERROR"
85 }
86 }
87};
88
89static struct xt_table nat_table = {
90 .name = "nat",
91 .valid_hooks = NAT_VALID_HOOKS,
92 .lock = RW_LOCK_UNLOCKED,
93 .me = THIS_MODULE,
94 .af = AF_INET,
95};
96
97/* Source NAT */
98static unsigned int ipt_snat_target(struct sk_buff **pskb,
99 const struct net_device *in,
100 const struct net_device *out,
101 unsigned int hooknum,
102 const struct xt_target *target,
103 const void *targinfo)
104{
105 struct ip_conntrack *ct;
106 enum ip_conntrack_info ctinfo;
107 const struct ip_nat_multi_range_compat *mr = targinfo;
108
109 IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
110
111 ct = ip_conntrack_get(*pskb, &ctinfo);
112
113 /* Connection must be valid and new. */
114 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
115 || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
116 IP_NF_ASSERT(out);
117
118 return ip_nat_setup_info(ct, &mr->range[0], hooknum);
119}
120
121/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
122static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
123{
124 static int warned = 0;
125 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
126 struct rtable *rt;
127
128 if (ip_route_output_key(&rt, &fl) != 0)
129 return;
130
131 if (rt->rt_src != srcip && !warned) {
132 printk("NAT: no longer support implicit source local NAT\n");
133 printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n",
134 NIPQUAD(srcip), NIPQUAD(dstip));
135 warned = 1;
136 }
137 ip_rt_put(rt);
138}
139
140static unsigned int ipt_dnat_target(struct sk_buff **pskb,
141 const struct net_device *in,
142 const struct net_device *out,
143 unsigned int hooknum,
144 const struct xt_target *target,
145 const void *targinfo)
146{
147 struct ip_conntrack *ct;
148 enum ip_conntrack_info ctinfo;
149 const struct ip_nat_multi_range_compat *mr = targinfo;
150
151 IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
152 || hooknum == NF_IP_LOCAL_OUT);
153
154 ct = ip_conntrack_get(*pskb, &ctinfo);
155
156 /* Connection must be valid and new. */
157 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
158
159 if (hooknum == NF_IP_LOCAL_OUT
160 && mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
161 warn_if_extra_mangle(ip_hdr(*pskb)->daddr,
162 mr->range[0].min_ip);
163
164 return ip_nat_setup_info(ct, &mr->range[0], hooknum);
165}
166
167static int ipt_snat_checkentry(const char *tablename,
168 const void *entry,
169 const struct xt_target *target,
170 void *targinfo,
171 unsigned int hook_mask)
172{
173 struct ip_nat_multi_range_compat *mr = targinfo;
174
175 /* Must be a valid range */
176 if (mr->rangesize != 1) {
177 printk("SNAT: multiple ranges no longer supported\n");
178 return 0;
179 }
180 return 1;
181}
182
183static int ipt_dnat_checkentry(const char *tablename,
184 const void *entry,
185 const struct xt_target *target,
186 void *targinfo,
187 unsigned int hook_mask)
188{
189 struct ip_nat_multi_range_compat *mr = targinfo;
190
191 /* Must be a valid range */
192 if (mr->rangesize != 1) {
193 printk("DNAT: multiple ranges no longer supported\n");
194 return 0;
195 }
196 if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
197 printk("DNAT: port randomization not supported\n");
198 return 0;
199 }
200 return 1;
201}
202
203inline unsigned int
204alloc_null_binding(struct ip_conntrack *conntrack,
205 struct ip_nat_info *info,
206 unsigned int hooknum)
207{
208 /* Force range to this IP; let proto decide mapping for
209 per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
210 Use reply in case it's already been mangled (eg local packet).
211 */
212 __be32 ip
213 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
214 ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
215 : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
216 struct ip_nat_range range
217 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
218
219 DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", conntrack,
220 NIPQUAD(ip));
221 return ip_nat_setup_info(conntrack, &range, hooknum);
222}
223
224unsigned int
225alloc_null_binding_confirmed(struct ip_conntrack *conntrack,
226 struct ip_nat_info *info,
227 unsigned int hooknum)
228{
229 __be32 ip
230 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
231 ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip
232 : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
233 u_int16_t all
234 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
235 ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
236 : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
237 struct ip_nat_range range
238 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
239
240 DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
241 conntrack, NIPQUAD(ip));
242 return ip_nat_setup_info(conntrack, &range, hooknum);
243}
244
245int ip_nat_rule_find(struct sk_buff **pskb,
246 unsigned int hooknum,
247 const struct net_device *in,
248 const struct net_device *out,
249 struct ip_conntrack *ct,
250 struct ip_nat_info *info)
251{
252 int ret;
253
254 ret = ipt_do_table(pskb, hooknum, in, out, &nat_table);
255
256 if (ret == NF_ACCEPT) {
257 if (!ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
258 /* NUL mapping */
259 ret = alloc_null_binding(ct, info, hooknum);
260 }
261 return ret;
262}
263
264static struct xt_target ipt_snat_reg = {
265 .name = "SNAT",
266 .family = AF_INET,
267 .target = ipt_snat_target,
268 .targetsize = sizeof(struct ip_nat_multi_range_compat),
269 .table = "nat",
270 .hooks = 1 << NF_IP_POST_ROUTING,
271 .checkentry = ipt_snat_checkentry,
272};
273
274static struct xt_target ipt_dnat_reg = {
275 .name = "DNAT",
276 .family = AF_INET,
277 .target = ipt_dnat_target,
278 .targetsize = sizeof(struct ip_nat_multi_range_compat),
279 .table = "nat",
280 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
281 .checkentry = ipt_dnat_checkentry,
282};
283
284int __init ip_nat_rule_init(void)
285{
286 int ret;
287
288 ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
289 if (ret != 0)
290 return ret;
291 ret = xt_register_target(&ipt_snat_reg);
292 if (ret != 0)
293 goto unregister_table;
294
295 ret = xt_register_target(&ipt_dnat_reg);
296 if (ret != 0)
297 goto unregister_snat;
298
299 return ret;
300
301 unregister_snat:
302 xt_unregister_target(&ipt_snat_reg);
303 unregister_table:
304 xt_unregister_table(&nat_table);
305
306 return ret;
307}
308
309void ip_nat_rule_cleanup(void)
310{
311 xt_unregister_target(&ipt_dnat_reg);
312 xt_unregister_target(&ipt_snat_reg);
313 ipt_unregister_table(&nat_table);
314}
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
deleted file mode 100644
index 84953601762d..000000000000
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ /dev/null
@@ -1,282 +0,0 @@
1/* SIP extension for UDP NAT alteration.
2 *
3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
4 * based on RR's ip_nat_ftp.c and other modules.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/ip.h>
14#include <linux/udp.h>
15
16#include <linux/netfilter_ipv4.h>
17#include <linux/netfilter_ipv4/ip_nat.h>
18#include <linux/netfilter_ipv4/ip_nat_helper.h>
19#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
20#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
21
22MODULE_LICENSE("GPL");
23MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
24MODULE_DESCRIPTION("SIP NAT helper");
25
26#if 0
27#define DEBUGP printk
28#else
29#define DEBUGP(format, args...)
30#endif
31
32struct addr_map {
33 struct {
34 char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
35 char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
36 unsigned int srclen, srciplen;
37 unsigned int dstlen, dstiplen;
38 } addr[IP_CT_DIR_MAX];
39};
40
41static void addr_map_init(struct ip_conntrack *ct, struct addr_map *map)
42{
43 struct ip_conntrack_tuple *t;
44 enum ip_conntrack_dir dir;
45 unsigned int n;
46
47 for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
48 t = &ct->tuplehash[dir].tuple;
49
50 n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
51 NIPQUAD(t->src.ip));
52 map->addr[dir].srciplen = n;
53 n += sprintf(map->addr[dir].src + n, ":%u",
54 ntohs(t->src.u.udp.port));
55 map->addr[dir].srclen = n;
56
57 n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
58 NIPQUAD(t->dst.ip));
59 map->addr[dir].dstiplen = n;
60 n += sprintf(map->addr[dir].dst + n, ":%u",
61 ntohs(t->dst.u.udp.port));
62 map->addr[dir].dstlen = n;
63 }
64}
65
66static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
67 struct ip_conntrack *ct, const char **dptr, size_t dlen,
68 enum sip_header_pos pos, struct addr_map *map)
69{
70 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
71 unsigned int matchlen, matchoff, addrlen;
72 char *addr;
73
74 if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
75 return 1;
76
77 if ((matchlen == map->addr[dir].srciplen ||
78 matchlen == map->addr[dir].srclen) &&
79 memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
80 addr = map->addr[!dir].dst;
81 addrlen = map->addr[!dir].dstlen;
82 } else if ((matchlen == map->addr[dir].dstiplen ||
83 matchlen == map->addr[dir].dstlen) &&
84 memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
85 addr = map->addr[!dir].src;
86 addrlen = map->addr[!dir].srclen;
87 } else
88 return 1;
89
90 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
91 matchoff, matchlen, addr, addrlen))
92 return 0;
93 *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr);
94 return 1;
95
96}
97
98static unsigned int ip_nat_sip(struct sk_buff **pskb,
99 enum ip_conntrack_info ctinfo,
100 struct ip_conntrack *ct,
101 const char **dptr)
102{
103 enum sip_header_pos pos;
104 struct addr_map map;
105 int dataoff, datalen;
106
107 dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
108 datalen = (*pskb)->len - dataoff;
109 if (datalen < sizeof("SIP/2.0") - 1)
110 return NF_DROP;
111
112 addr_map_init(ct, &map);
113
114 /* Basic rules: requests and responses. */
115 if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
116 /* 10.2: Constructing the REGISTER Request:
117 *
118 * The "userinfo" and "@" components of the SIP URI MUST NOT
119 * be present.
120 */
121 if (datalen >= sizeof("REGISTER") - 1 &&
122 strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
123 pos = POS_REG_REQ_URI;
124 else
125 pos = POS_REQ_URI;
126
127 if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
128 return NF_DROP;
129 }
130
131 if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
132 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
133 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
134 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
135 return NF_DROP;
136 return NF_ACCEPT;
137}
138
139static unsigned int mangle_sip_packet(struct sk_buff **pskb,
140 enum ip_conntrack_info ctinfo,
141 struct ip_conntrack *ct,
142 const char **dptr, size_t dlen,
143 char *buffer, int bufflen,
144 enum sip_header_pos pos)
145{
146 unsigned int matchlen, matchoff;
147
148 if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
149 return 0;
150
151 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
152 matchoff, matchlen, buffer, bufflen))
153 return 0;
154
155 /* We need to reload this. Thanks Patrick. */
156 *dptr = (*pskb)->data + ip_hdrlen(*pskb) + sizeof(struct udphdr);
157 return 1;
158}
159
160static int mangle_content_len(struct sk_buff **pskb,
161 enum ip_conntrack_info ctinfo,
162 struct ip_conntrack *ct,
163 const char *dptr)
164{
165 unsigned int dataoff, matchoff, matchlen;
166 char buffer[sizeof("65536")];
167 int bufflen;
168
169 dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
170
171 /* Get actual SDP lenght */
172 if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
173 &matchlen, POS_SDP_HEADER) > 0) {
174
175 /* since ct_sip_get_info() give us a pointer passing 'v='
176 we need to add 2 bytes in this count. */
177 int c_len = (*pskb)->len - dataoff - matchoff + 2;
178
179 /* Now, update SDP lenght */
180 if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
181 &matchlen, POS_CONTENT) > 0) {
182
183 bufflen = sprintf(buffer, "%u", c_len);
184
185 return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
186 matchoff, matchlen,
187 buffer, bufflen);
188 }
189 }
190 return 0;
191}
192
193static unsigned int mangle_sdp(struct sk_buff **pskb,
194 enum ip_conntrack_info ctinfo,
195 struct ip_conntrack *ct,
196 __be32 newip, u_int16_t port,
197 const char *dptr)
198{
199 char buffer[sizeof("nnn.nnn.nnn.nnn")];
200 unsigned int dataoff, bufflen;
201
202 dataoff = ip_hdrlen(*pskb) + sizeof(struct udphdr);
203
204 /* Mangle owner and contact info. */
205 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
206 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
207 buffer, bufflen, POS_OWNER))
208 return 0;
209
210 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
211 buffer, bufflen, POS_CONNECTION))
212 return 0;
213
214 /* Mangle media port. */
215 bufflen = sprintf(buffer, "%u", port);
216 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
217 buffer, bufflen, POS_MEDIA))
218 return 0;
219
220 return mangle_content_len(pskb, ctinfo, ct, dptr);
221}
222
223/* So, this packet has hit the connection tracking matching code.
224 Mangle it, and change the expectation to match the new version. */
225static unsigned int ip_nat_sdp(struct sk_buff **pskb,
226 enum ip_conntrack_info ctinfo,
227 struct ip_conntrack_expect *exp,
228 const char *dptr)
229{
230 struct ip_conntrack *ct = exp->master;
231 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
232 __be32 newip;
233 u_int16_t port;
234
235 DEBUGP("ip_nat_sdp():\n");
236
237 /* Connection will come from reply */
238 newip = ct->tuplehash[!dir].tuple.dst.ip;
239
240 exp->tuple.dst.ip = newip;
241 exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
242 exp->dir = !dir;
243
244 /* When you see the packet, we need to NAT it the same as the
245 this one. */
246 exp->expectfn = ip_nat_follow_master;
247
248 /* Try to get same port: if not, try to change it. */
249 for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
250 exp->tuple.dst.u.udp.port = htons(port);
251 if (ip_conntrack_expect_related(exp) == 0)
252 break;
253 }
254
255 if (port == 0)
256 return NF_DROP;
257
258 if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
259 ip_conntrack_unexpect_related(exp);
260 return NF_DROP;
261 }
262 return NF_ACCEPT;
263}
264
265static void __exit fini(void)
266{
267 rcu_assign_pointer(ip_nat_sip_hook, NULL);
268 rcu_assign_pointer(ip_nat_sdp_hook, NULL);
269 synchronize_rcu();
270}
271
272static int __init init(void)
273{
274 BUG_ON(rcu_dereference(ip_nat_sip_hook));
275 BUG_ON(rcu_dereference(ip_nat_sdp_hook));
276 rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip);
277 rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp);
278 return 0;
279}
280
281module_init(init);
282module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
deleted file mode 100644
index 025e04587789..000000000000
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ /dev/null
@@ -1,1333 +0,0 @@
1/*
2 * ip_nat_snmp_basic.c
3 *
4 * Basic SNMP Application Layer Gateway
5 *
6 * This IP NAT module is intended for use with SNMP network
7 * discovery and monitoring applications where target networks use
8 * conflicting private address realms.
9 *
10 * Static NAT is used to remap the networks from the view of the network
11 * management system at the IP layer, and this module remaps some application
12 * layer addresses to match.
13 *
14 * The simplest form of ALG is performed, where only tagged IP addresses
15 * are modified. The module does not need to be MIB aware and only scans
16 * messages at the ASN.1/BER level.
17 *
18 * Currently, only SNMPv1 and SNMPv2 are supported.
19 *
20 * More information on ALG and associated issues can be found in
21 * RFC 2962
22 *
23 * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
24 * McLean & Jochen Friedrich, stripped down for use in the kernel.
25 *
26 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 * Author: James Morris <jmorris@intercode.com.au>
41 *
42 * Updates:
43 * 2000-08-06: Convert to new helper API (Harald Welte).
44 *
45 */
46#include <linux/in.h>
47#include <linux/module.h>
48#include <linux/types.h>
49#include <linux/kernel.h>
50#include <linux/moduleparam.h>
51#include <linux/netfilter_ipv4.h>
52#include <linux/netfilter_ipv4/ip_nat.h>
53#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
54#include <linux/netfilter_ipv4/ip_nat_helper.h>
55#include <linux/ip.h>
56#include <linux/udp.h>
57#include <net/checksum.h>
58#include <net/udp.h>
59#include <asm/uaccess.h>
60
61MODULE_LICENSE("GPL");
62MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
63MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
64
65#define SNMP_PORT 161
66#define SNMP_TRAP_PORT 162
67#define NOCT1(n) (*(u8 *)n)
68
69static int debug;
70static DEFINE_SPINLOCK(snmp_lock);
71
72/*
73 * Application layer address mapping mimics the NAT mapping, but
74 * only for the first octet in this case (a more flexible system
75 * can be implemented if needed).
76 */
77struct oct1_map
78{
79 u_int8_t from;
80 u_int8_t to;
81};
82
83
84/*****************************************************************************
85 *
86 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
87 *
88 *****************************************************************************/
89
90/* Class */
91#define ASN1_UNI 0 /* Universal */
92#define ASN1_APL 1 /* Application */
93#define ASN1_CTX 2 /* Context */
94#define ASN1_PRV 3 /* Private */
95
96/* Tag */
97#define ASN1_EOC 0 /* End Of Contents */
98#define ASN1_BOL 1 /* Boolean */
99#define ASN1_INT 2 /* Integer */
100#define ASN1_BTS 3 /* Bit String */
101#define ASN1_OTS 4 /* Octet String */
102#define ASN1_NUL 5 /* Null */
103#define ASN1_OJI 6 /* Object Identifier */
104#define ASN1_OJD 7 /* Object Description */
105#define ASN1_EXT 8 /* External */
106#define ASN1_SEQ 16 /* Sequence */
107#define ASN1_SET 17 /* Set */
108#define ASN1_NUMSTR 18 /* Numerical String */
109#define ASN1_PRNSTR 19 /* Printable String */
110#define ASN1_TEXSTR 20 /* Teletext String */
111#define ASN1_VIDSTR 21 /* Video String */
112#define ASN1_IA5STR 22 /* IA5 String */
113#define ASN1_UNITIM 23 /* Universal Time */
114#define ASN1_GENTIM 24 /* General Time */
115#define ASN1_GRASTR 25 /* Graphical String */
116#define ASN1_VISSTR 26 /* Visible String */
117#define ASN1_GENSTR 27 /* General String */
118
119/* Primitive / Constructed methods*/
120#define ASN1_PRI 0 /* Primitive */
121#define ASN1_CON 1 /* Constructed */
122
123/*
124 * Error codes.
125 */
126#define ASN1_ERR_NOERROR 0
127#define ASN1_ERR_DEC_EMPTY 2
128#define ASN1_ERR_DEC_EOC_MISMATCH 3
129#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
130#define ASN1_ERR_DEC_BADVALUE 5
131
132/*
133 * ASN.1 context.
134 */
135struct asn1_ctx
136{
137 int error; /* Error condition */
138 unsigned char *pointer; /* Octet just to be decoded */
139 unsigned char *begin; /* First octet */
140 unsigned char *end; /* Octet after last octet */
141};
142
143/*
144 * Octet string (not null terminated)
145 */
146struct asn1_octstr
147{
148 unsigned char *data;
149 unsigned int len;
150};
151
152static void asn1_open(struct asn1_ctx *ctx,
153 unsigned char *buf,
154 unsigned int len)
155{
156 ctx->begin = buf;
157 ctx->end = buf + len;
158 ctx->pointer = buf;
159 ctx->error = ASN1_ERR_NOERROR;
160}
161
162static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
163{
164 if (ctx->pointer >= ctx->end) {
165 ctx->error = ASN1_ERR_DEC_EMPTY;
166 return 0;
167 }
168 *ch = *(ctx->pointer)++;
169 return 1;
170}
171
172static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
173{
174 unsigned char ch;
175
176 *tag = 0;
177
178 do
179 {
180 if (!asn1_octet_decode(ctx, &ch))
181 return 0;
182 *tag <<= 7;
183 *tag |= ch & 0x7F;
184 } while ((ch & 0x80) == 0x80);
185 return 1;
186}
187
188static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
189 unsigned int *cls,
190 unsigned int *con,
191 unsigned int *tag)
192{
193 unsigned char ch;
194
195 if (!asn1_octet_decode(ctx, &ch))
196 return 0;
197
198 *cls = (ch & 0xC0) >> 6;
199 *con = (ch & 0x20) >> 5;
200 *tag = (ch & 0x1F);
201
202 if (*tag == 0x1F) {
203 if (!asn1_tag_decode(ctx, tag))
204 return 0;
205 }
206 return 1;
207}
208
209static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
210 unsigned int *def,
211 unsigned int *len)
212{
213 unsigned char ch, cnt;
214
215 if (!asn1_octet_decode(ctx, &ch))
216 return 0;
217
218 if (ch == 0x80)
219 *def = 0;
220 else {
221 *def = 1;
222
223 if (ch < 0x80)
224 *len = ch;
225 else {
226 cnt = (unsigned char) (ch & 0x7F);
227 *len = 0;
228
229 while (cnt > 0) {
230 if (!asn1_octet_decode(ctx, &ch))
231 return 0;
232 *len <<= 8;
233 *len |= ch;
234 cnt--;
235 }
236 }
237 }
238 return 1;
239}
240
241static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
242 unsigned char **eoc,
243 unsigned int *cls,
244 unsigned int *con,
245 unsigned int *tag)
246{
247 unsigned int def, len;
248
249 if (!asn1_id_decode(ctx, cls, con, tag))
250 return 0;
251
252 def = len = 0;
253 if (!asn1_length_decode(ctx, &def, &len))
254 return 0;
255
256 if (def)
257 *eoc = ctx->pointer + len;
258 else
259 *eoc = NULL;
260 return 1;
261}
262
263static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
264{
265 unsigned char ch;
266
267 if (eoc == 0) {
268 if (!asn1_octet_decode(ctx, &ch))
269 return 0;
270
271 if (ch != 0x00) {
272 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
273 return 0;
274 }
275
276 if (!asn1_octet_decode(ctx, &ch))
277 return 0;
278
279 if (ch != 0x00) {
280 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
281 return 0;
282 }
283 return 1;
284 } else {
285 if (ctx->pointer != eoc) {
286 ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
287 return 0;
288 }
289 return 1;
290 }
291}
292
293static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
294{
295 ctx->pointer = eoc;
296 return 1;
297}
298
299static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
300 unsigned char *eoc,
301 long *integer)
302{
303 unsigned char ch;
304 unsigned int len;
305
306 if (!asn1_octet_decode(ctx, &ch))
307 return 0;
308
309 *integer = (signed char) ch;
310 len = 1;
311
312 while (ctx->pointer < eoc) {
313 if (++len > sizeof (long)) {
314 ctx->error = ASN1_ERR_DEC_BADVALUE;
315 return 0;
316 }
317
318 if (!asn1_octet_decode(ctx, &ch))
319 return 0;
320
321 *integer <<= 8;
322 *integer |= ch;
323 }
324 return 1;
325}
326
327static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
328 unsigned char *eoc,
329 unsigned int *integer)
330{
331 unsigned char ch;
332 unsigned int len;
333
334 if (!asn1_octet_decode(ctx, &ch))
335 return 0;
336
337 *integer = ch;
338 if (ch == 0) len = 0;
339 else len = 1;
340
341 while (ctx->pointer < eoc) {
342 if (++len > sizeof (unsigned int)) {
343 ctx->error = ASN1_ERR_DEC_BADVALUE;
344 return 0;
345 }
346
347 if (!asn1_octet_decode(ctx, &ch))
348 return 0;
349
350 *integer <<= 8;
351 *integer |= ch;
352 }
353 return 1;
354}
355
356static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
357 unsigned char *eoc,
358 unsigned long *integer)
359{
360 unsigned char ch;
361 unsigned int len;
362
363 if (!asn1_octet_decode(ctx, &ch))
364 return 0;
365
366 *integer = ch;
367 if (ch == 0) len = 0;
368 else len = 1;
369
370 while (ctx->pointer < eoc) {
371 if (++len > sizeof (unsigned long)) {
372 ctx->error = ASN1_ERR_DEC_BADVALUE;
373 return 0;
374 }
375
376 if (!asn1_octet_decode(ctx, &ch))
377 return 0;
378
379 *integer <<= 8;
380 *integer |= ch;
381 }
382 return 1;
383}
384
385static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
386 unsigned char *eoc,
387 unsigned char **octets,
388 unsigned int *len)
389{
390 unsigned char *ptr;
391
392 *len = 0;
393
394 *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
395 if (*octets == NULL) {
396 if (net_ratelimit())
397 printk("OOM in bsalg (%d)\n", __LINE__);
398 return 0;
399 }
400
401 ptr = *octets;
402 while (ctx->pointer < eoc) {
403 if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) {
404 kfree(*octets);
405 *octets = NULL;
406 return 0;
407 }
408 (*len)++;
409 }
410 return 1;
411}
412
413static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
414 unsigned long *subid)
415{
416 unsigned char ch;
417
418 *subid = 0;
419
420 do {
421 if (!asn1_octet_decode(ctx, &ch))
422 return 0;
423
424 *subid <<= 7;
425 *subid |= ch & 0x7F;
426 } while ((ch & 0x80) == 0x80);
427 return 1;
428}
429
430static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
431 unsigned char *eoc,
432 unsigned long **oid,
433 unsigned int *len)
434{
435 unsigned long subid;
436 unsigned int size;
437 unsigned long *optr;
438
439 size = eoc - ctx->pointer + 1;
440 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
441 if (*oid == NULL) {
442 if (net_ratelimit())
443 printk("OOM in bsalg (%d)\n", __LINE__);
444 return 0;
445 }
446
447 optr = *oid;
448
449 if (!asn1_subid_decode(ctx, &subid)) {
450 kfree(*oid);
451 *oid = NULL;
452 return 0;
453 }
454
455 if (subid < 40) {
456 optr [0] = 0;
457 optr [1] = subid;
458 } else if (subid < 80) {
459 optr [0] = 1;
460 optr [1] = subid - 40;
461 } else {
462 optr [0] = 2;
463 optr [1] = subid - 80;
464 }
465
466 *len = 2;
467 optr += 2;
468
469 while (ctx->pointer < eoc) {
470 if (++(*len) > size) {
471 ctx->error = ASN1_ERR_DEC_BADVALUE;
472 kfree(*oid);
473 *oid = NULL;
474 return 0;
475 }
476
477 if (!asn1_subid_decode(ctx, optr++)) {
478 kfree(*oid);
479 *oid = NULL;
480 return 0;
481 }
482 }
483 return 1;
484}
485
486/*****************************************************************************
487 *
488 * SNMP decoding routines (gxsnmp author Dirk Wisse)
489 *
490 *****************************************************************************/
491
492/* SNMP Versions */
493#define SNMP_V1 0
494#define SNMP_V2C 1
495#define SNMP_V2 2
496#define SNMP_V3 3
497
498/* Default Sizes */
499#define SNMP_SIZE_COMM 256
500#define SNMP_SIZE_OBJECTID 128
501#define SNMP_SIZE_BUFCHR 256
502#define SNMP_SIZE_BUFINT 128
503#define SNMP_SIZE_SMALLOBJECTID 16
504
505/* Requests */
506#define SNMP_PDU_GET 0
507#define SNMP_PDU_NEXT 1
508#define SNMP_PDU_RESPONSE 2
509#define SNMP_PDU_SET 3
510#define SNMP_PDU_TRAP1 4
511#define SNMP_PDU_BULK 5
512#define SNMP_PDU_INFORM 6
513#define SNMP_PDU_TRAP2 7
514
515/* Errors */
516#define SNMP_NOERROR 0
517#define SNMP_TOOBIG 1
518#define SNMP_NOSUCHNAME 2
519#define SNMP_BADVALUE 3
520#define SNMP_READONLY 4
521#define SNMP_GENERROR 5
522#define SNMP_NOACCESS 6
523#define SNMP_WRONGTYPE 7
524#define SNMP_WRONGLENGTH 8
525#define SNMP_WRONGENCODING 9
526#define SNMP_WRONGVALUE 10
527#define SNMP_NOCREATION 11
528#define SNMP_INCONSISTENTVALUE 12
529#define SNMP_RESOURCEUNAVAILABLE 13
530#define SNMP_COMMITFAILED 14
531#define SNMP_UNDOFAILED 15
532#define SNMP_AUTHORIZATIONERROR 16
533#define SNMP_NOTWRITABLE 17
534#define SNMP_INCONSISTENTNAME 18
535
536/* General SNMP V1 Traps */
537#define SNMP_TRAP_COLDSTART 0
538#define SNMP_TRAP_WARMSTART 1
539#define SNMP_TRAP_LINKDOWN 2
540#define SNMP_TRAP_LINKUP 3
541#define SNMP_TRAP_AUTFAILURE 4
542#define SNMP_TRAP_EQPNEIGHBORLOSS 5
543#define SNMP_TRAP_ENTSPECIFIC 6
544
545/* SNMPv1 Types */
546#define SNMP_NULL 0
547#define SNMP_INTEGER 1 /* l */
548#define SNMP_OCTETSTR 2 /* c */
549#define SNMP_DISPLAYSTR 2 /* c */
550#define SNMP_OBJECTID 3 /* ul */
551#define SNMP_IPADDR 4 /* uc */
552#define SNMP_COUNTER 5 /* ul */
553#define SNMP_GAUGE 6 /* ul */
554#define SNMP_TIMETICKS 7 /* ul */
555#define SNMP_OPAQUE 8 /* c */
556
557/* Additional SNMPv2 Types */
558#define SNMP_UINTEGER 5 /* ul */
559#define SNMP_BITSTR 9 /* uc */
560#define SNMP_NSAP 10 /* uc */
561#define SNMP_COUNTER64 11 /* ul */
562#define SNMP_NOSUCHOBJECT 12
563#define SNMP_NOSUCHINSTANCE 13
564#define SNMP_ENDOFMIBVIEW 14
565
566union snmp_syntax
567{
568 unsigned char uc[0]; /* 8 bit unsigned */
569 char c[0]; /* 8 bit signed */
570 unsigned long ul[0]; /* 32 bit unsigned */
571 long l[0]; /* 32 bit signed */
572};
573
574struct snmp_object
575{
576 unsigned long *id;
577 unsigned int id_len;
578 unsigned short type;
579 unsigned int syntax_len;
580 union snmp_syntax syntax;
581};
582
583struct snmp_request
584{
585 unsigned long id;
586 unsigned int error_status;
587 unsigned int error_index;
588};
589
590struct snmp_v1_trap
591{
592 unsigned long *id;
593 unsigned int id_len;
594 unsigned long ip_address; /* pointer */
595 unsigned int general;
596 unsigned int specific;
597 unsigned long time;
598};
599
600/* SNMP types */
601#define SNMP_IPA 0
602#define SNMP_CNT 1
603#define SNMP_GGE 2
604#define SNMP_TIT 3
605#define SNMP_OPQ 4
606#define SNMP_C64 6
607
608/* SNMP errors */
609#define SERR_NSO 0
610#define SERR_NSI 1
611#define SERR_EOM 2
612
613static inline void mangle_address(unsigned char *begin,
614 unsigned char *addr,
615 const struct oct1_map *map,
616 __sum16 *check);
617struct snmp_cnv
618{
619 unsigned int class;
620 unsigned int tag;
621 int syntax;
622};
623
624static struct snmp_cnv snmp_conv [] =
625{
626 {ASN1_UNI, ASN1_NUL, SNMP_NULL},
627 {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
628 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
629 {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR},
630 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID},
631 {ASN1_APL, SNMP_IPA, SNMP_IPADDR},
632 {ASN1_APL, SNMP_CNT, SNMP_COUNTER}, /* Counter32 */
633 {ASN1_APL, SNMP_GGE, SNMP_GAUGE}, /* Gauge32 == Unsigned32 */
634 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},
635 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},
636
637 /* SNMPv2 data types and errors */
638 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR},
639 {ASN1_APL, SNMP_C64, SNMP_COUNTER64},
640 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT},
641 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE},
642 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW},
643 {0, 0, -1}
644};
645
646static unsigned char snmp_tag_cls2syntax(unsigned int tag,
647 unsigned int cls,
648 unsigned short *syntax)
649{
650 struct snmp_cnv *cnv;
651
652 cnv = snmp_conv;
653
654 while (cnv->syntax != -1) {
655 if (cnv->tag == tag && cnv->class == cls) {
656 *syntax = cnv->syntax;
657 return 1;
658 }
659 cnv++;
660 }
661 return 0;
662}
663
664static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
665 struct snmp_object **obj)
666{
667 unsigned int cls, con, tag, len, idlen;
668 unsigned short type;
669 unsigned char *eoc, *end, *p;
670 unsigned long *lp, *id;
671 unsigned long ul;
672 long l;
673
674 *obj = NULL;
675 id = NULL;
676
677 if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag))
678 return 0;
679
680 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
681 return 0;
682
683 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
684 return 0;
685
686 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
687 return 0;
688
689 if (!asn1_oid_decode(ctx, end, &id, &idlen))
690 return 0;
691
692 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) {
693 kfree(id);
694 return 0;
695 }
696
697 if (con != ASN1_PRI) {
698 kfree(id);
699 return 0;
700 }
701
702 type = 0;
703 if (!snmp_tag_cls2syntax(tag, cls, &type)) {
704 kfree(id);
705 return 0;
706 }
707
708 l = 0;
709 switch (type) {
710 case SNMP_INTEGER:
711 len = sizeof(long);
712 if (!asn1_long_decode(ctx, end, &l)) {
713 kfree(id);
714 return 0;
715 }
716 *obj = kmalloc(sizeof(struct snmp_object) + len,
717 GFP_ATOMIC);
718 if (*obj == NULL) {
719 kfree(id);
720 if (net_ratelimit())
721 printk("OOM in bsalg (%d)\n", __LINE__);
722 return 0;
723 }
724 (*obj)->syntax.l[0] = l;
725 break;
726 case SNMP_OCTETSTR:
727 case SNMP_OPAQUE:
728 if (!asn1_octets_decode(ctx, end, &p, &len)) {
729 kfree(id);
730 return 0;
731 }
732 *obj = kmalloc(sizeof(struct snmp_object) + len,
733 GFP_ATOMIC);
734 if (*obj == NULL) {
735 kfree(id);
736 if (net_ratelimit())
737 printk("OOM in bsalg (%d)\n", __LINE__);
738 return 0;
739 }
740 memcpy((*obj)->syntax.c, p, len);
741 kfree(p);
742 break;
743 case SNMP_NULL:
744 case SNMP_NOSUCHOBJECT:
745 case SNMP_NOSUCHINSTANCE:
746 case SNMP_ENDOFMIBVIEW:
747 len = 0;
748 *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
749 if (*obj == NULL) {
750 kfree(id);
751 if (net_ratelimit())
752 printk("OOM in bsalg (%d)\n", __LINE__);
753 return 0;
754 }
755 if (!asn1_null_decode(ctx, end)) {
756 kfree(id);
757 kfree(*obj);
758 *obj = NULL;
759 return 0;
760 }
761 break;
762 case SNMP_OBJECTID:
763 if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
764 kfree(id);
765 return 0;
766 }
767 len *= sizeof(unsigned long);
768 *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
769 if (*obj == NULL) {
770 kfree(lp);
771 kfree(id);
772 if (net_ratelimit())
773 printk("OOM in bsalg (%d)\n", __LINE__);
774 return 0;
775 }
776 memcpy((*obj)->syntax.ul, lp, len);
777 kfree(lp);
778 break;
779 case SNMP_IPADDR:
780 if (!asn1_octets_decode(ctx, end, &p, &len)) {
781 kfree(id);
782 return 0;
783 }
784 if (len != 4) {
785 kfree(p);
786 kfree(id);
787 return 0;
788 }
789 *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
790 if (*obj == NULL) {
791 kfree(p);
792 kfree(id);
793 if (net_ratelimit())
794 printk("OOM in bsalg (%d)\n", __LINE__);
795 return 0;
796 }
797 memcpy((*obj)->syntax.uc, p, len);
798 kfree(p);
799 break;
800 case SNMP_COUNTER:
801 case SNMP_GAUGE:
802 case SNMP_TIMETICKS:
803 len = sizeof(unsigned long);
804 if (!asn1_ulong_decode(ctx, end, &ul)) {
805 kfree(id);
806 return 0;
807 }
808 *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
809 if (*obj == NULL) {
810 kfree(id);
811 if (net_ratelimit())
812 printk("OOM in bsalg (%d)\n", __LINE__);
813 return 0;
814 }
815 (*obj)->syntax.ul[0] = ul;
816 break;
817 default:
818 kfree(id);
819 return 0;
820 }
821
822 (*obj)->syntax_len = len;
823 (*obj)->type = type;
824 (*obj)->id = id;
825 (*obj)->id_len = idlen;
826
827 if (!asn1_eoc_decode(ctx, eoc)) {
828 kfree(id);
829 kfree(*obj);
830 *obj = NULL;
831 return 0;
832 }
833 return 1;
834}
835
836static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
837 struct snmp_request *request)
838{
839 unsigned int cls, con, tag;
840 unsigned char *end;
841
842 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
843 return 0;
844
845 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
846 return 0;
847
848 if (!asn1_ulong_decode(ctx, end, &request->id))
849 return 0;
850
851 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
852 return 0;
853
854 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
855 return 0;
856
857 if (!asn1_uint_decode(ctx, end, &request->error_status))
858 return 0;
859
860 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
861 return 0;
862
863 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
864 return 0;
865
866 if (!asn1_uint_decode(ctx, end, &request->error_index))
867 return 0;
868
869 return 1;
870}
871
872/*
873 * Fast checksum update for possibly oddly-aligned UDP byte, from the
874 * code example in the draft.
875 */
876static void fast_csum(__sum16 *csum,
877 const unsigned char *optr,
878 const unsigned char *nptr,
879 int offset)
880{
881 unsigned char s[4];
882
883 if (offset & 1) {
884 s[0] = s[2] = 0;
885 s[1] = ~*optr;
886 s[3] = *nptr;
887 } else {
888 s[1] = s[3] = 0;
889 s[0] = ~*optr;
890 s[2] = *nptr;
891 }
892
893 *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
894}
895
896/*
897 * Mangle IP address.
898 * - begin points to the start of the snmp messgae
899 * - addr points to the start of the address
900 */
901static inline void mangle_address(unsigned char *begin,
902 unsigned char *addr,
903 const struct oct1_map *map,
904 __sum16 *check)
905{
906 if (map->from == NOCT1(addr)) {
907 u_int32_t old;
908
909 if (debug)
910 memcpy(&old, (unsigned char *)addr, sizeof(old));
911
912 *addr = map->to;
913
914 /* Update UDP checksum if being used */
915 if (*check) {
916 fast_csum(check,
917 &map->from, &map->to, addr - begin);
918 }
919
920 if (debug)
921 printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
922 "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
923 }
924}
925
926static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
927 struct snmp_v1_trap *trap,
928 const struct oct1_map *map,
929 __sum16 *check)
930{
931 unsigned int cls, con, tag, len;
932 unsigned char *end;
933
934 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
935 return 0;
936
937 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
938 return 0;
939
940 if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
941 return 0;
942
943 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
944 goto err_id_free;
945
946 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
947 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
948 goto err_id_free;
949
950 if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
951 goto err_id_free;
952
953 /* IPv4 only */
954 if (len != 4)
955 goto err_addr_free;
956
957 mangle_address(ctx->begin, ctx->pointer - 4, map, check);
958
959 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
960 goto err_addr_free;
961
962 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
963 goto err_addr_free;
964
965 if (!asn1_uint_decode(ctx, end, &trap->general))
966 goto err_addr_free;
967
968 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
969 goto err_addr_free;
970
971 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
972 goto err_addr_free;
973
974 if (!asn1_uint_decode(ctx, end, &trap->specific))
975 goto err_addr_free;
976
977 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
978 goto err_addr_free;
979
980 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
981 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
982 goto err_addr_free;
983
984 if (!asn1_ulong_decode(ctx, end, &trap->time))
985 goto err_addr_free;
986
987 return 1;
988
989err_addr_free:
990 kfree((unsigned long *)trap->ip_address);
991
992err_id_free:
993 kfree(trap->id);
994
995 return 0;
996}
997
998/*****************************************************************************
999 *
1000 * Misc. routines
1001 *
1002 *****************************************************************************/
1003
1004static void hex_dump(unsigned char *buf, size_t len)
1005{
1006 size_t i;
1007
1008 for (i = 0; i < len; i++) {
1009 if (i && !(i % 16))
1010 printk("\n");
1011 printk("%02x ", *(buf + i));
1012 }
1013 printk("\n");
1014}
1015
1016/*
1017 * Parse and mangle SNMP message according to mapping.
1018 * (And this is the fucking 'basic' method).
1019 */
1020static int snmp_parse_mangle(unsigned char *msg,
1021 u_int16_t len,
1022 const struct oct1_map *map,
1023 __sum16 *check)
1024{
1025 unsigned char *eoc, *end;
1026 unsigned int cls, con, tag, vers, pdutype;
1027 struct asn1_ctx ctx;
1028 struct asn1_octstr comm;
1029 struct snmp_object **obj;
1030
1031 if (debug > 1)
1032 hex_dump(msg, len);
1033
1034 asn1_open(&ctx, msg, len);
1035
1036 /*
1037 * Start of SNMP message.
1038 */
1039 if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1040 return 0;
1041 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1042 return 0;
1043
1044 /*
1045 * Version 1 or 2 handled.
1046 */
1047 if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
1048 return 0;
1049 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
1050 return 0;
1051 if (!asn1_uint_decode (&ctx, end, &vers))
1052 return 0;
1053 if (debug > 1)
1054 printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);
1055 if (vers > 1)
1056 return 1;
1057
1058 /*
1059 * Community.
1060 */
1061 if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))
1062 return 0;
1063 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
1064 return 0;
1065 if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))
1066 return 0;
1067 if (debug > 1) {
1068 unsigned int i;
1069
1070 printk(KERN_DEBUG "bsalg: community: ");
1071 for (i = 0; i < comm.len; i++)
1072 printk("%c", comm.data[i]);
1073 printk("\n");
1074 }
1075 kfree(comm.data);
1076
1077 /*
1078 * PDU type
1079 */
1080 if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))
1081 return 0;
1082 if (cls != ASN1_CTX || con != ASN1_CON)
1083 return 0;
1084 if (debug > 1) {
1085 unsigned char *pdus[] = {
1086 [SNMP_PDU_GET] = "get",
1087 [SNMP_PDU_NEXT] = "get-next",
1088 [SNMP_PDU_RESPONSE] = "response",
1089 [SNMP_PDU_SET] = "set",
1090 [SNMP_PDU_TRAP1] = "trapv1",
1091 [SNMP_PDU_BULK] = "bulk",
1092 [SNMP_PDU_INFORM] = "inform",
1093 [SNMP_PDU_TRAP2] = "trapv2"
1094 };
1095
1096 if (pdutype > SNMP_PDU_TRAP2)
1097 printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);
1098 else
1099 printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]);
1100 }
1101 if (pdutype != SNMP_PDU_RESPONSE &&
1102 pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
1103 return 1;
1104
1105 /*
1106 * Request header or v1 trap
1107 */
1108 if (pdutype == SNMP_PDU_TRAP1) {
1109 struct snmp_v1_trap trap;
1110 unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
1111
1112 if (ret) {
1113 kfree(trap.id);
1114 kfree((unsigned long *)trap.ip_address);
1115 } else
1116 return ret;
1117
1118 } else {
1119 struct snmp_request req;
1120
1121 if (!snmp_request_decode(&ctx, &req))
1122 return 0;
1123
1124 if (debug > 1)
1125 printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "
1126 "error_index=%u\n", req.id, req.error_status,
1127 req.error_index);
1128 }
1129
1130 /*
1131 * Loop through objects, look for IP addresses to mangle.
1132 */
1133 if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1134 return 0;
1135
1136 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1137 return 0;
1138
1139 obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
1140 if (obj == NULL) {
1141 if (net_ratelimit())
1142 printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
1143 return 0;
1144 }
1145
1146 while (!asn1_eoc_decode(&ctx, eoc)) {
1147 unsigned int i;
1148
1149 if (!snmp_object_decode(&ctx, obj)) {
1150 if (*obj) {
1151 kfree((*obj)->id);
1152 kfree(*obj);
1153 }
1154 kfree(obj);
1155 return 0;
1156 }
1157
1158 if (debug > 1) {
1159 printk(KERN_DEBUG "bsalg: object: ");
1160 for (i = 0; i < (*obj)->id_len; i++) {
1161 if (i > 0)
1162 printk(".");
1163 printk("%lu", (*obj)->id[i]);
1164 }
1165 printk(": type=%u\n", (*obj)->type);
1166
1167 }
1168
1169 if ((*obj)->type == SNMP_IPADDR)
1170 mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
1171
1172 kfree((*obj)->id);
1173 kfree(*obj);
1174 }
1175 kfree(obj);
1176
1177 if (!asn1_eoc_decode(&ctx, eoc))
1178 return 0;
1179
1180 return 1;
1181}
1182
1183/*****************************************************************************
1184 *
1185 * NAT routines.
1186 *
1187 *****************************************************************************/
1188
1189/*
1190 * SNMP translation routine.
1191 */
1192static int snmp_translate(struct ip_conntrack *ct,
1193 enum ip_conntrack_info ctinfo,
1194 struct sk_buff **pskb)
1195{
1196 struct iphdr *iph = ip_hdr(*pskb);
1197 struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1198 u_int16_t udplen = ntohs(udph->len);
1199 u_int16_t paylen = udplen - sizeof(struct udphdr);
1200 int dir = CTINFO2DIR(ctinfo);
1201 struct oct1_map map;
1202
1203 /*
1204 * Determine mappping for application layer addresses based
1205 * on NAT manipulations for the packet.
1206 */
1207 if (dir == IP_CT_DIR_ORIGINAL) {
1208 /* SNAT traps */
1209 map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip);
1210 map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip);
1211 } else {
1212 /* DNAT replies */
1213 map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
1214 map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);
1215 }
1216
1217 if (map.from == map.to)
1218 return NF_ACCEPT;
1219
1220 if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
1221 paylen, &map, &udph->check)) {
1222 if (net_ratelimit())
1223 printk(KERN_WARNING "bsalg: parser failed\n");
1224 return NF_DROP;
1225 }
1226 return NF_ACCEPT;
1227}
1228
1229/* We don't actually set up expectations, just adjust internal IP
1230 * addresses if this is being NATted */
1231static int help(struct sk_buff **pskb,
1232 struct ip_conntrack *ct,
1233 enum ip_conntrack_info ctinfo)
1234{
1235 int dir = CTINFO2DIR(ctinfo);
1236 unsigned int ret;
1237 struct iphdr *iph = ip_hdr(*pskb);
1238 struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
1239
1240 /* SNMP replies and originating SNMP traps get mangled */
1241 if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
1242 return NF_ACCEPT;
1243 if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
1244 return NF_ACCEPT;
1245
1246 /* No NAT? */
1247 if (!(ct->status & IPS_NAT_MASK))
1248 return NF_ACCEPT;
1249
1250 /*
1251 * Make sure the packet length is ok. So far, we were only guaranteed
1252 * to have a valid length IP header plus 8 bytes, which means we have
1253 * enough room for a UDP header. Just verify the UDP length field so we
1254 * can mess around with the payload.
1255 */
1256 if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
1257 if (net_ratelimit())
1258 printk(KERN_WARNING "SNMP: dropping malformed packet "
1259 "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
1260 NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
1261 return NF_DROP;
1262 }
1263
1264 if (!skb_make_writable(pskb, (*pskb)->len))
1265 return NF_DROP;
1266
1267 spin_lock_bh(&snmp_lock);
1268 ret = snmp_translate(ct, ctinfo, pskb);
1269 spin_unlock_bh(&snmp_lock);
1270 return ret;
1271}
1272
1273static struct ip_conntrack_helper snmp_helper = {
1274 .max_expected = 0,
1275 .timeout = 180,
1276 .me = THIS_MODULE,
1277 .help = help,
1278 .name = "snmp",
1279
1280 .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_PORT)}}},
1281 .dst = {.protonum = IPPROTO_UDP},
1282 },
1283 .mask = {.src = {.u = {0xFFFF}},
1284 .dst = {.protonum = 0xFF},
1285 },
1286};
1287
1288static struct ip_conntrack_helper snmp_trap_helper = {
1289 .max_expected = 0,
1290 .timeout = 180,
1291 .me = THIS_MODULE,
1292 .help = help,
1293 .name = "snmp_trap",
1294
1295 .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_TRAP_PORT)}}},
1296 .dst = {.protonum = IPPROTO_UDP},
1297 },
1298 .mask = {.src = {.u = {0xFFFF}},
1299 .dst = {.protonum = 0xFF},
1300 },
1301};
1302
1303/*****************************************************************************
1304 *
1305 * Module stuff.
1306 *
1307 *****************************************************************************/
1308
1309static int __init ip_nat_snmp_basic_init(void)
1310{
1311 int ret = 0;
1312
1313 ret = ip_conntrack_helper_register(&snmp_helper);
1314 if (ret < 0)
1315 return ret;
1316 ret = ip_conntrack_helper_register(&snmp_trap_helper);
1317 if (ret < 0) {
1318 ip_conntrack_helper_unregister(&snmp_helper);
1319 return ret;
1320 }
1321 return ret;
1322}
1323
1324static void __exit ip_nat_snmp_basic_fini(void)
1325{
1326 ip_conntrack_helper_unregister(&snmp_helper);
1327 ip_conntrack_helper_unregister(&snmp_trap_helper);
1328}
1329
1330module_init(ip_nat_snmp_basic_init);
1331module_exit(ip_nat_snmp_basic_fini);
1332
1333module_param(debug, int, 0600);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
deleted file mode 100644
index 32f7bf661fc8..000000000000
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ /dev/null
@@ -1,387 +0,0 @@
1/* This file contains all the functions required for the standalone
2 ip_nat module.
3
4 These are not required by the compatibility layer.
5*/
6
7/* (C) 1999-2001 Paul `Rusty' Russell
8 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15/*
16 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
17 * - new API and handling of conntrack/nat helpers
18 * - now capable of multiple expectations for one master
19 * */
20
21#include <linux/types.h>
22#include <linux/icmp.h>
23#include <linux/ip.h>
24#include <linux/netfilter.h>
25#include <linux/netfilter_ipv4.h>
26#include <linux/module.h>
27#include <linux/skbuff.h>
28#include <linux/proc_fs.h>
29#include <net/ip.h>
30#include <net/checksum.h>
31#include <linux/spinlock.h>
32
33#include <linux/netfilter_ipv4/ip_nat.h>
34#include <linux/netfilter_ipv4/ip_nat_rule.h>
35#include <linux/netfilter_ipv4/ip_nat_protocol.h>
36#include <linux/netfilter_ipv4/ip_nat_core.h>
37#include <linux/netfilter_ipv4/ip_nat_helper.h>
38#include <linux/netfilter_ipv4/ip_tables.h>
39#include <linux/netfilter_ipv4/ip_conntrack_core.h>
40
41#if 0
42#define DEBUGP printk
43#else
44#define DEBUGP(format, args...)
45#endif
46
47#ifdef CONFIG_XFRM
48static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
49{
50 struct ip_conntrack *ct;
51 struct ip_conntrack_tuple *t;
52 enum ip_conntrack_info ctinfo;
53 enum ip_conntrack_dir dir;
54 unsigned long statusbit;
55
56 ct = ip_conntrack_get(skb, &ctinfo);
57 if (ct == NULL)
58 return;
59 dir = CTINFO2DIR(ctinfo);
60 t = &ct->tuplehash[dir].tuple;
61
62 if (dir == IP_CT_DIR_ORIGINAL)
63 statusbit = IPS_DST_NAT;
64 else
65 statusbit = IPS_SRC_NAT;
66
67 if (ct->status & statusbit) {
68 fl->fl4_dst = t->dst.ip;
69 if (t->dst.protonum == IPPROTO_TCP ||
70 t->dst.protonum == IPPROTO_UDP)
71 fl->fl_ip_dport = t->dst.u.tcp.port;
72 }
73
74 statusbit ^= IPS_NAT_MASK;
75
76 if (ct->status & statusbit) {
77 fl->fl4_src = t->src.ip;
78 if (t->dst.protonum == IPPROTO_TCP ||
79 t->dst.protonum == IPPROTO_UDP)
80 fl->fl_ip_sport = t->src.u.tcp.port;
81 }
82}
83#endif
84
85static unsigned int
86ip_nat_fn(unsigned int hooknum,
87 struct sk_buff **pskb,
88 const struct net_device *in,
89 const struct net_device *out,
90 int (*okfn)(struct sk_buff *))
91{
92 struct ip_conntrack *ct;
93 enum ip_conntrack_info ctinfo;
94 struct ip_nat_info *info;
95 /* maniptype == SRC for postrouting. */
96 enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum);
97
98 /* We never see fragments: conntrack defrags on pre-routing
99 and local-out, and ip_nat_out protects post-routing. */
100 IP_NF_ASSERT(!(ip_hdr(*pskb)->frag_off
101 & htons(IP_MF|IP_OFFSET)));
102
103 ct = ip_conntrack_get(*pskb, &ctinfo);
104 /* Can't track? It's not due to stress, or conntrack would
105 have dropped it. Hence it's the user's responsibilty to
106 packet filter it out, or implement conntrack/NAT for that
107 protocol. 8) --RR */
108 if (!ct) {
109 /* Exception: ICMP redirect to new connection (not in
110 hash table yet). We must not let this through, in
111 case we're doing NAT to the same network. */
112 if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
113 struct icmphdr _hdr, *hp;
114
115 hp = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
116 sizeof(_hdr), &_hdr);
117 if (hp != NULL &&
118 hp->type == ICMP_REDIRECT)
119 return NF_DROP;
120 }
121 return NF_ACCEPT;
122 }
123
124 /* Don't try to NAT if this packet is not conntracked */
125 if (ct == &ip_conntrack_untracked)
126 return NF_ACCEPT;
127
128 switch (ctinfo) {
129 case IP_CT_RELATED:
130 case IP_CT_RELATED+IP_CT_IS_REPLY:
131 if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
132 if (!ip_nat_icmp_reply_translation(ct, ctinfo,
133 hooknum, pskb))
134 return NF_DROP;
135 else
136 return NF_ACCEPT;
137 }
138 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
139 case IP_CT_NEW:
140 info = &ct->nat.info;
141
142 /* Seen it before? This can happen for loopback, retrans,
143 or local packets.. */
144 if (!ip_nat_initialized(ct, maniptype)) {
145 unsigned int ret;
146
147 if (unlikely(is_confirmed(ct)))
148 /* NAT module was loaded late */
149 ret = alloc_null_binding_confirmed(ct, info,
150 hooknum);
151 else if (hooknum == NF_IP_LOCAL_IN)
152 /* LOCAL_IN hook doesn't have a chain! */
153 ret = alloc_null_binding(ct, info, hooknum);
154 else
155 ret = ip_nat_rule_find(pskb, hooknum,
156 in, out, ct,
157 info);
158
159 if (ret != NF_ACCEPT) {
160 return ret;
161 }
162 } else
163 DEBUGP("Already setup manip %s for ct %p\n",
164 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
165 ct);
166 break;
167
168 default:
169 /* ESTABLISHED */
170 IP_NF_ASSERT(ctinfo == IP_CT_ESTABLISHED
171 || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
172 info = &ct->nat.info;
173 }
174
175 IP_NF_ASSERT(info);
176 return ip_nat_packet(ct, ctinfo, hooknum, pskb);
177}
178
179static unsigned int
180ip_nat_in(unsigned int hooknum,
181 struct sk_buff **pskb,
182 const struct net_device *in,
183 const struct net_device *out,
184 int (*okfn)(struct sk_buff *))
185{
186 unsigned int ret;
187 __be32 daddr = ip_hdr(*pskb)->daddr;
188
189 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
190 if (ret != NF_DROP && ret != NF_STOLEN
191 && daddr != ip_hdr(*pskb)->daddr) {
192 dst_release((*pskb)->dst);
193 (*pskb)->dst = NULL;
194 }
195 return ret;
196}
197
198static unsigned int
199ip_nat_out(unsigned int hooknum,
200 struct sk_buff **pskb,
201 const struct net_device *in,
202 const struct net_device *out,
203 int (*okfn)(struct sk_buff *))
204{
205#ifdef CONFIG_XFRM
206 struct ip_conntrack *ct;
207 enum ip_conntrack_info ctinfo;
208#endif
209 unsigned int ret;
210
211 /* root is playing with raw sockets. */
212 if ((*pskb)->len < sizeof(struct iphdr)
213 || ip_hdrlen(*pskb) < sizeof(struct iphdr))
214 return NF_ACCEPT;
215
216 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
217#ifdef CONFIG_XFRM
218 if (ret != NF_DROP && ret != NF_STOLEN
219 && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
220 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
221
222 if (ct->tuplehash[dir].tuple.src.ip !=
223 ct->tuplehash[!dir].tuple.dst.ip
224 || ct->tuplehash[dir].tuple.src.u.all !=
225 ct->tuplehash[!dir].tuple.dst.u.all
226 )
227 return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
228 }
229#endif
230 return ret;
231}
232
233static unsigned int
234ip_nat_local_fn(unsigned int hooknum,
235 struct sk_buff **pskb,
236 const struct net_device *in,
237 const struct net_device *out,
238 int (*okfn)(struct sk_buff *))
239{
240 struct ip_conntrack *ct;
241 enum ip_conntrack_info ctinfo;
242 unsigned int ret;
243
244 /* root is playing with raw sockets. */
245 if ((*pskb)->len < sizeof(struct iphdr)
246 || ip_hdrlen(*pskb) < sizeof(struct iphdr))
247 return NF_ACCEPT;
248
249 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
250 if (ret != NF_DROP && ret != NF_STOLEN
251 && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
252 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
253
254 if (ct->tuplehash[dir].tuple.dst.ip !=
255 ct->tuplehash[!dir].tuple.src.ip) {
256 if (ip_route_me_harder(pskb, RTN_UNSPEC))
257 ret = NF_DROP;
258 }
259#ifdef CONFIG_XFRM
260 else if (ct->tuplehash[dir].tuple.dst.u.all !=
261 ct->tuplehash[!dir].tuple.src.u.all)
262 if (ip_xfrm_me_harder(pskb))
263 ret = NF_DROP;
264#endif
265
266 }
267 return ret;
268}
269
270static unsigned int
271ip_nat_adjust(unsigned int hooknum,
272 struct sk_buff **pskb,
273 const struct net_device *in,
274 const struct net_device *out,
275 int (*okfn)(struct sk_buff *))
276{
277 struct ip_conntrack *ct;
278 enum ip_conntrack_info ctinfo;
279
280 ct = ip_conntrack_get(*pskb, &ctinfo);
281 if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
282 DEBUGP("ip_nat_standalone: adjusting sequence number\n");
283 if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
284 return NF_DROP;
285 }
286 return NF_ACCEPT;
287}
288
289/* We must be after connection tracking and before packet filtering. */
290
291static struct nf_hook_ops ip_nat_ops[] = {
292 /* Before packet filtering, change destination */
293 {
294 .hook = ip_nat_in,
295 .owner = THIS_MODULE,
296 .pf = PF_INET,
297 .hooknum = NF_IP_PRE_ROUTING,
298 .priority = NF_IP_PRI_NAT_DST,
299 },
300 /* After packet filtering, change source */
301 {
302 .hook = ip_nat_out,
303 .owner = THIS_MODULE,
304 .pf = PF_INET,
305 .hooknum = NF_IP_POST_ROUTING,
306 .priority = NF_IP_PRI_NAT_SRC,
307 },
308 /* After conntrack, adjust sequence number */
309 {
310 .hook = ip_nat_adjust,
311 .owner = THIS_MODULE,
312 .pf = PF_INET,
313 .hooknum = NF_IP_POST_ROUTING,
314 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
315 },
316 /* Before packet filtering, change destination */
317 {
318 .hook = ip_nat_local_fn,
319 .owner = THIS_MODULE,
320 .pf = PF_INET,
321 .hooknum = NF_IP_LOCAL_OUT,
322 .priority = NF_IP_PRI_NAT_DST,
323 },
324 /* After packet filtering, change source */
325 {
326 .hook = ip_nat_fn,
327 .owner = THIS_MODULE,
328 .pf = PF_INET,
329 .hooknum = NF_IP_LOCAL_IN,
330 .priority = NF_IP_PRI_NAT_SRC,
331 },
332 /* After conntrack, adjust sequence number */
333 {
334 .hook = ip_nat_adjust,
335 .owner = THIS_MODULE,
336 .pf = PF_INET,
337 .hooknum = NF_IP_LOCAL_IN,
338 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
339 },
340};
341
342static int __init ip_nat_standalone_init(void)
343{
344 int ret = 0;
345
346 need_conntrack();
347
348#ifdef CONFIG_XFRM
349 BUG_ON(ip_nat_decode_session != NULL);
350 ip_nat_decode_session = nat_decode_session;
351#endif
352 ret = ip_nat_rule_init();
353 if (ret < 0) {
354 printk("ip_nat_init: can't setup rules.\n");
355 goto cleanup_decode_session;
356 }
357 ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
358 if (ret < 0) {
359 printk("ip_nat_init: can't register hooks.\n");
360 goto cleanup_rule_init;
361 }
362 return ret;
363
364 cleanup_rule_init:
365 ip_nat_rule_cleanup();
366 cleanup_decode_session:
367#ifdef CONFIG_XFRM
368 ip_nat_decode_session = NULL;
369 synchronize_net();
370#endif
371 return ret;
372}
373
374static void __exit ip_nat_standalone_fini(void)
375{
376 nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
377 ip_nat_rule_cleanup();
378#ifdef CONFIG_XFRM
379 ip_nat_decode_session = NULL;
380 synchronize_net();
381#endif
382}
383
384module_init(ip_nat_standalone_init);
385module_exit(ip_nat_standalone_fini);
386
387MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
deleted file mode 100644
index 604793536fc1..000000000000
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 *
7 * Version: 0.0.7
8 *
9 * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
10 * - Port to newnat API
11 *
12 * This module currently supports DNAT:
13 * iptables -t nat -A PREROUTING -d x.x.x.x -j DNAT --to-dest x.x.x.y
14 *
15 * and SNAT:
16 * iptables -t nat -A POSTROUTING { -j MASQUERADE , -j SNAT --to-source x.x.x.x }
17 *
18 * It has not been tested with
19 * -j SNAT --to-source x.x.x.x-x.x.x.y since I only have one external ip
20 * If you do test this please let me know if it works or not.
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/netfilter_ipv4.h>
26#include <linux/ip.h>
27#include <linux/udp.h>
28
29#include <linux/netfilter.h>
30#include <linux/netfilter_ipv4/ip_tables.h>
31#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
32#include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
33#include <linux/netfilter_ipv4/ip_nat_helper.h>
34#include <linux/netfilter_ipv4/ip_nat_rule.h>
35#include <linux/moduleparam.h>
36
37MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
38MODULE_DESCRIPTION("tftp NAT helper");
39MODULE_LICENSE("GPL");
40
41static unsigned int help(struct sk_buff **pskb,
42 enum ip_conntrack_info ctinfo,
43 struct ip_conntrack_expect *exp)
44{
45 struct ip_conntrack *ct = exp->master;
46
47 exp->saved_proto.udp.port
48 = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
49 exp->dir = IP_CT_DIR_REPLY;
50 exp->expectfn = ip_nat_follow_master;
51 if (ip_conntrack_expect_related(exp) != 0)
52 return NF_DROP;
53 return NF_ACCEPT;
54}
55
56static void __exit ip_nat_tftp_fini(void)
57{
58 rcu_assign_pointer(ip_nat_tftp_hook, NULL);
59 synchronize_rcu();
60}
61
62static int __init ip_nat_tftp_init(void)
63{
64 BUG_ON(rcu_dereference(ip_nat_tftp_hook));
65 rcu_assign_pointer(ip_nat_tftp_hook, help);
66 return 0;
67}
68
69module_init(ip_nat_tftp_init);
70module_exit(ip_nat_tftp_fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index d3b16817a991..40e273421398 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -21,15 +21,12 @@
21#include <linux/if_arp.h> 21#include <linux/if_arp.h>
22#include <linux/proc_fs.h> 22#include <linux/proc_fs.h>
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24
25#include <net/checksum.h>
26
27#include <linux/netfilter_arp.h> 24#include <linux/netfilter_arp.h>
28
29#include <linux/netfilter/x_tables.h> 25#include <linux/netfilter/x_tables.h>
30#include <linux/netfilter_ipv4/ip_tables.h> 26#include <linux/netfilter_ipv4/ip_tables.h>
31#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> 27#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
32#include <net/netfilter/nf_conntrack_compat.h> 28#include <net/netfilter/nf_conntrack.h>
29#include <net/checksum.h>
33 30
34#define CLUSTERIP_VERSION "0.8" 31#define CLUSTERIP_VERSION "0.8"
35 32
@@ -310,15 +307,16 @@ target(struct sk_buff **pskb,
310 const void *targinfo) 307 const void *targinfo)
311{ 308{
312 const struct ipt_clusterip_tgt_info *cipinfo = targinfo; 309 const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
310 struct nf_conn *ct;
313 enum ip_conntrack_info ctinfo; 311 enum ip_conntrack_info ctinfo;
314 u_int32_t *mark, hash; 312 u_int32_t hash;
315 313
316 /* don't need to clusterip_config_get() here, since refcount 314 /* don't need to clusterip_config_get() here, since refcount
317 * is only decremented by destroy() - and ip_tables guarantees 315 * is only decremented by destroy() - and ip_tables guarantees
318 * that the ->target() function isn't called after ->destroy() */ 316 * that the ->target() function isn't called after ->destroy() */
319 317
320 mark = nf_ct_get_mark((*pskb), &ctinfo); 318 ct = nf_ct_get(*pskb, &ctinfo);
321 if (mark == NULL) { 319 if (ct == NULL) {
322 printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); 320 printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
323 /* FIXME: need to drop invalid ones, since replies 321 /* FIXME: need to drop invalid ones, since replies
324 * to outgoing connections of other nodes will be 322 * to outgoing connections of other nodes will be
@@ -341,7 +339,7 @@ target(struct sk_buff **pskb,
341 339
342 switch (ctinfo) { 340 switch (ctinfo) {
343 case IP_CT_NEW: 341 case IP_CT_NEW:
344 *mark = hash; 342 ct->mark = hash;
345 break; 343 break;
346 case IP_CT_RELATED: 344 case IP_CT_RELATED:
347 case IP_CT_RELATED+IP_CT_IS_REPLY: 345 case IP_CT_RELATED+IP_CT_IS_REPLY:
@@ -358,7 +356,7 @@ target(struct sk_buff **pskb,
358#ifdef DEBUG_CLUSTERP 356#ifdef DEBUG_CLUSTERP
359 DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 357 DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
360#endif 358#endif
361 DEBUGP("hash=%u ct_hash=%u ", hash, *mark); 359 DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark);
362 if (!clusterip_responsible(cipinfo->config, hash)) { 360 if (!clusterip_responsible(cipinfo->config, hash)) {
363 DEBUGP("not responsible\n"); 361 DEBUGP("not responsible\n");
364 return NF_DROP; 362 return NF_DROP;
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index b5955f3a3f8f..d4f2d7775330 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -19,12 +19,8 @@
19#include <net/ip.h> 19#include <net/ip.h>
20#include <net/checksum.h> 20#include <net/checksum.h>
21#include <net/route.h> 21#include <net/route.h>
22#include <linux/netfilter_ipv4.h>
23#ifdef CONFIG_NF_NAT_NEEDED
24#include <net/netfilter/nf_nat_rule.h> 22#include <net/netfilter/nf_nat_rule.h>
25#else 23#include <linux/netfilter_ipv4.h>
26#include <linux/netfilter_ipv4/ip_nat_rule.h>
27#endif
28#include <linux/netfilter/x_tables.h> 24#include <linux/netfilter/x_tables.h>
29 25
30MODULE_LICENSE("GPL"); 26MODULE_LICENSE("GPL");
@@ -48,7 +44,7 @@ masquerade_check(const char *tablename,
48 void *targinfo, 44 void *targinfo,
49 unsigned int hook_mask) 45 unsigned int hook_mask)
50{ 46{
51 const struct ip_nat_multi_range_compat *mr = targinfo; 47 const struct nf_nat_multi_range_compat *mr = targinfo;
52 48
53 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 49 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
54 DEBUGP("masquerade_check: bad MAP_IPS.\n"); 50 DEBUGP("masquerade_check: bad MAP_IPS.\n");
@@ -69,33 +65,26 @@ masquerade_target(struct sk_buff **pskb,
69 const struct xt_target *target, 65 const struct xt_target *target,
70 const void *targinfo) 66 const void *targinfo)
71{ 67{
72#ifdef CONFIG_NF_NAT_NEEDED 68 struct nf_conn *ct;
73 struct nf_conn_nat *nat; 69 struct nf_conn_nat *nat;
74#endif
75 struct ip_conntrack *ct;
76 enum ip_conntrack_info ctinfo; 70 enum ip_conntrack_info ctinfo;
77 struct ip_nat_range newrange; 71 struct nf_nat_range newrange;
78 const struct ip_nat_multi_range_compat *mr; 72 const struct nf_nat_multi_range_compat *mr;
79 struct rtable *rt; 73 struct rtable *rt;
80 __be32 newsrc; 74 __be32 newsrc;
81 75
82 IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); 76 NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
83 77
84 ct = ip_conntrack_get(*pskb, &ctinfo); 78 ct = nf_ct_get(*pskb, &ctinfo);
85#ifdef CONFIG_NF_NAT_NEEDED
86 nat = nfct_nat(ct); 79 nat = nfct_nat(ct);
87#endif 80
88 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED 81 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
89 || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); 82 || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
90 83
91 /* Source address is 0.0.0.0 - locally generated packet that is 84 /* Source address is 0.0.0.0 - locally generated packet that is
92 * probably not supposed to be masqueraded. 85 * probably not supposed to be masqueraded.
93 */ 86 */
94#ifdef CONFIG_NF_NAT_NEEDED
95 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0) 87 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
96#else
97 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
98#endif
99 return NF_ACCEPT; 88 return NF_ACCEPT;
100 89
101 mr = targinfo; 90 mr = targinfo;
@@ -107,40 +96,30 @@ masquerade_target(struct sk_buff **pskb,
107 } 96 }
108 97
109 write_lock_bh(&masq_lock); 98 write_lock_bh(&masq_lock);
110#ifdef CONFIG_NF_NAT_NEEDED
111 nat->masq_index = out->ifindex; 99 nat->masq_index = out->ifindex;
112#else
113 ct->nat.masq_index = out->ifindex;
114#endif
115 write_unlock_bh(&masq_lock); 100 write_unlock_bh(&masq_lock);
116 101
117 /* Transfer from original range. */ 102 /* Transfer from original range. */
118 newrange = ((struct ip_nat_range) 103 newrange = ((struct nf_nat_range)
119 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, 104 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
120 newsrc, newsrc, 105 newsrc, newsrc,
121 mr->range[0].min, mr->range[0].max }); 106 mr->range[0].min, mr->range[0].max });
122 107
123 /* Hand modified range to generic setup. */ 108 /* Hand modified range to generic setup. */
124 return ip_nat_setup_info(ct, &newrange, hooknum); 109 return nf_nat_setup_info(ct, &newrange, hooknum);
125} 110}
126 111
127static inline int 112static inline int
128device_cmp(struct ip_conntrack *i, void *ifindex) 113device_cmp(struct nf_conn *i, void *ifindex)
129{ 114{
130 int ret;
131#ifdef CONFIG_NF_NAT_NEEDED
132 struct nf_conn_nat *nat = nfct_nat(i); 115 struct nf_conn_nat *nat = nfct_nat(i);
116 int ret;
133 117
134 if (!nat) 118 if (!nat)
135 return 0; 119 return 0;
136#endif
137 120
138 read_lock_bh(&masq_lock); 121 read_lock_bh(&masq_lock);
139#ifdef CONFIG_NF_NAT_NEEDED
140 ret = (nat->masq_index == (int)(long)ifindex); 122 ret = (nat->masq_index == (int)(long)ifindex);
141#else
142 ret = (i->nat.masq_index == (int)(long)ifindex);
143#endif
144 read_unlock_bh(&masq_lock); 123 read_unlock_bh(&masq_lock);
145 124
146 return ret; 125 return ret;
@@ -156,9 +135,9 @@ static int masq_device_event(struct notifier_block *this,
156 /* Device was downed. Search entire table for 135 /* Device was downed. Search entire table for
157 conntracks which were associated with that device, 136 conntracks which were associated with that device,
158 and forget them. */ 137 and forget them. */
159 IP_NF_ASSERT(dev->ifindex != 0); 138 NF_CT_ASSERT(dev->ifindex != 0);
160 139
161 ip_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex); 140 nf_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
162 } 141 }
163 142
164 return NOTIFY_DONE; 143 return NOTIFY_DONE;
@@ -174,9 +153,9 @@ static int masq_inet_event(struct notifier_block *this,
174 /* IP address was deleted. Search entire table for 153 /* IP address was deleted. Search entire table for
175 conntracks which were associated with that device, 154 conntracks which were associated with that device,
176 and forget them. */ 155 and forget them. */
177 IP_NF_ASSERT(dev->ifindex != 0); 156 NF_CT_ASSERT(dev->ifindex != 0);
178 157
179 ip_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex); 158 nf_ct_iterate_cleanup(device_cmp, (void *)(long)dev->ifindex);
180 } 159 }
181 160
182 return NOTIFY_DONE; 161 return NOTIFY_DONE;
@@ -194,7 +173,7 @@ static struct xt_target masquerade = {
194 .name = "MASQUERADE", 173 .name = "MASQUERADE",
195 .family = AF_INET, 174 .family = AF_INET,
196 .target = masquerade_target, 175 .target = masquerade_target,
197 .targetsize = sizeof(struct ip_nat_multi_range_compat), 176 .targetsize = sizeof(struct nf_nat_multi_range_compat),
198 .table = "nat", 177 .table = "nat",
199 .hooks = 1 << NF_IP_POST_ROUTING, 178 .hooks = 1 << NF_IP_POST_ROUTING,
200 .checkentry = masquerade_check, 179 .checkentry = masquerade_check,
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index d03f165722da..068c69bce30e 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -16,11 +16,7 @@
16#include <linux/netfilter.h> 16#include <linux/netfilter.h>
17#include <linux/netfilter_ipv4.h> 17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter/x_tables.h> 18#include <linux/netfilter/x_tables.h>
19#ifdef CONFIG_NF_NAT_NEEDED
20#include <net/netfilter/nf_nat_rule.h> 19#include <net/netfilter/nf_nat_rule.h>
21#else
22#include <linux/netfilter_ipv4/ip_nat_rule.h>
23#endif
24 20
25#define MODULENAME "NETMAP" 21#define MODULENAME "NETMAP"
26MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
@@ -40,7 +36,7 @@ check(const char *tablename,
40 void *targinfo, 36 void *targinfo,
41 unsigned int hook_mask) 37 unsigned int hook_mask)
42{ 38{
43 const struct ip_nat_multi_range_compat *mr = targinfo; 39 const struct nf_nat_multi_range_compat *mr = targinfo;
44 40
45 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { 41 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
46 DEBUGP(MODULENAME":check: bad MAP_IPS.\n"); 42 DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
@@ -61,16 +57,16 @@ target(struct sk_buff **pskb,
61 const struct xt_target *target, 57 const struct xt_target *target,
62 const void *targinfo) 58 const void *targinfo)
63{ 59{
64 struct ip_conntrack *ct; 60 struct nf_conn *ct;
65 enum ip_conntrack_info ctinfo; 61 enum ip_conntrack_info ctinfo;
66 __be32 new_ip, netmask; 62 __be32 new_ip, netmask;
67 const struct ip_nat_multi_range_compat *mr = targinfo; 63 const struct nf_nat_multi_range_compat *mr = targinfo;
68 struct ip_nat_range newrange; 64 struct nf_nat_range newrange;
69 65
70 IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING 66 NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
71 || hooknum == NF_IP_POST_ROUTING 67 || hooknum == NF_IP_POST_ROUTING
72 || hooknum == NF_IP_LOCAL_OUT); 68 || hooknum == NF_IP_LOCAL_OUT);
73 ct = ip_conntrack_get(*pskb, &ctinfo); 69 ct = nf_ct_get(*pskb, &ctinfo);
74 70
75 netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip); 71 netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
76 72
@@ -80,20 +76,20 @@ target(struct sk_buff **pskb,
80 new_ip = ip_hdr(*pskb)->saddr & ~netmask; 76 new_ip = ip_hdr(*pskb)->saddr & ~netmask;
81 new_ip |= mr->range[0].min_ip & netmask; 77 new_ip |= mr->range[0].min_ip & netmask;
82 78
83 newrange = ((struct ip_nat_range) 79 newrange = ((struct nf_nat_range)
84 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, 80 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
85 new_ip, new_ip, 81 new_ip, new_ip,
86 mr->range[0].min, mr->range[0].max }); 82 mr->range[0].min, mr->range[0].max });
87 83
88 /* Hand modified range to generic setup. */ 84 /* Hand modified range to generic setup. */
89 return ip_nat_setup_info(ct, &newrange, hooknum); 85 return nf_nat_setup_info(ct, &newrange, hooknum);
90} 86}
91 87
92static struct xt_target target_module = { 88static struct xt_target target_module = {
93 .name = MODULENAME, 89 .name = MODULENAME,
94 .family = AF_INET, 90 .family = AF_INET,
95 .target = target, 91 .target = target,
96 .targetsize = sizeof(struct ip_nat_multi_range_compat), 92 .targetsize = sizeof(struct nf_nat_multi_range_compat),
97 .table = "nat", 93 .table = "nat",
98 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) | 94 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING) |
99 (1 << NF_IP_LOCAL_OUT), 95 (1 << NF_IP_LOCAL_OUT),
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index c2b6b80670f8..68cc76a198eb 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -19,11 +19,7 @@
19#include <net/checksum.h> 19#include <net/checksum.h>
20#include <linux/netfilter_ipv4.h> 20#include <linux/netfilter_ipv4.h>
21#include <linux/netfilter/x_tables.h> 21#include <linux/netfilter/x_tables.h>
22#ifdef CONFIG_NF_NAT_NEEDED
23#include <net/netfilter/nf_nat_rule.h> 22#include <net/netfilter/nf_nat_rule.h>
24#else
25#include <linux/netfilter_ipv4/ip_nat_rule.h>
26#endif
27 23
28MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 25MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -43,7 +39,7 @@ redirect_check(const char *tablename,
43 void *targinfo, 39 void *targinfo,
44 unsigned int hook_mask) 40 unsigned int hook_mask)
45{ 41{
46 const struct ip_nat_multi_range_compat *mr = targinfo; 42 const struct nf_nat_multi_range_compat *mr = targinfo;
47 43
48 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 44 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
49 DEBUGP("redirect_check: bad MAP_IPS.\n"); 45 DEBUGP("redirect_check: bad MAP_IPS.\n");
@@ -64,17 +60,17 @@ redirect_target(struct sk_buff **pskb,
64 const struct xt_target *target, 60 const struct xt_target *target,
65 const void *targinfo) 61 const void *targinfo)
66{ 62{
67 struct ip_conntrack *ct; 63 struct nf_conn *ct;
68 enum ip_conntrack_info ctinfo; 64 enum ip_conntrack_info ctinfo;
69 __be32 newdst; 65 __be32 newdst;
70 const struct ip_nat_multi_range_compat *mr = targinfo; 66 const struct nf_nat_multi_range_compat *mr = targinfo;
71 struct ip_nat_range newrange; 67 struct nf_nat_range newrange;
72 68
73 IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING 69 NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING
74 || hooknum == NF_IP_LOCAL_OUT); 70 || hooknum == NF_IP_LOCAL_OUT);
75 71
76 ct = ip_conntrack_get(*pskb, &ctinfo); 72 ct = nf_ct_get(*pskb, &ctinfo);
77 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); 73 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
78 74
79 /* Local packets: make them go to loopback */ 75 /* Local packets: make them go to loopback */
80 if (hooknum == NF_IP_LOCAL_OUT) 76 if (hooknum == NF_IP_LOCAL_OUT)
@@ -96,20 +92,20 @@ redirect_target(struct sk_buff **pskb,
96 } 92 }
97 93
98 /* Transfer from original range. */ 94 /* Transfer from original range. */
99 newrange = ((struct ip_nat_range) 95 newrange = ((struct nf_nat_range)
100 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, 96 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
101 newdst, newdst, 97 newdst, newdst,
102 mr->range[0].min, mr->range[0].max }); 98 mr->range[0].min, mr->range[0].max });
103 99
104 /* Hand modified range to generic setup. */ 100 /* Hand modified range to generic setup. */
105 return ip_nat_setup_info(ct, &newrange, hooknum); 101 return nf_nat_setup_info(ct, &newrange, hooknum);
106} 102}
107 103
108static struct xt_target redirect_reg = { 104static struct xt_target redirect_reg = {
109 .name = "REDIRECT", 105 .name = "REDIRECT",
110 .family = AF_INET, 106 .family = AF_INET,
111 .target = redirect_target, 107 .target = redirect_target,
112 .targetsize = sizeof(struct ip_nat_multi_range_compat), 108 .targetsize = sizeof(struct nf_nat_multi_range_compat),
113 .table = "nat", 109 .table = "nat",
114 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT), 110 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
115 .checkentry = redirect_check, 111 .checkentry = redirect_check,
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index bd4404e5c688..fe76ffc0caed 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -35,11 +35,7 @@
35#include <net/checksum.h> 35#include <net/checksum.h>
36#include <linux/netfilter_ipv4.h> 36#include <linux/netfilter_ipv4.h>
37#include <linux/netfilter/x_tables.h> 37#include <linux/netfilter/x_tables.h>
38#ifdef CONFIG_NF_NAT_NEEDED
39#include <net/netfilter/nf_nat_rule.h> 38#include <net/netfilter/nf_nat_rule.h>
40#else
41#include <linux/netfilter_ipv4/ip_nat_rule.h>
42#endif
43#include <linux/netfilter_ipv4/ipt_SAME.h> 39#include <linux/netfilter_ipv4/ipt_SAME.h>
44 40
45MODULE_LICENSE("GPL"); 41MODULE_LICENSE("GPL");
@@ -138,17 +134,17 @@ same_target(struct sk_buff **pskb,
138 const struct xt_target *target, 134 const struct xt_target *target,
139 const void *targinfo) 135 const void *targinfo)
140{ 136{
141 struct ip_conntrack *ct; 137 struct nf_conn *ct;
142 enum ip_conntrack_info ctinfo; 138 enum ip_conntrack_info ctinfo;
143 u_int32_t tmpip, aindex; 139 u_int32_t tmpip, aindex;
144 __be32 new_ip; 140 __be32 new_ip;
145 const struct ipt_same_info *same = targinfo; 141 const struct ipt_same_info *same = targinfo;
146 struct ip_nat_range newrange; 142 struct nf_nat_range newrange;
147 const struct ip_conntrack_tuple *t; 143 const struct nf_conntrack_tuple *t;
148 144
149 IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || 145 NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
150 hooknum == NF_IP_POST_ROUTING); 146 hooknum == NF_IP_POST_ROUTING);
151 ct = ip_conntrack_get(*pskb, &ctinfo); 147 ct = nf_ct_get(*pskb, &ctinfo);
152 148
153 t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 149 t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
154 150
@@ -157,17 +153,10 @@ same_target(struct sk_buff **pskb,
157 Here we calculate the index in same->iparray which 153 Here we calculate the index in same->iparray which
158 holds the ipaddress we should use */ 154 holds the ipaddress we should use */
159 155
160#ifdef CONFIG_NF_NAT_NEEDED
161 tmpip = ntohl(t->src.u3.ip); 156 tmpip = ntohl(t->src.u3.ip);
162 157
163 if (!(same->info & IPT_SAME_NODST)) 158 if (!(same->info & IPT_SAME_NODST))
164 tmpip += ntohl(t->dst.u3.ip); 159 tmpip += ntohl(t->dst.u3.ip);
165#else
166 tmpip = ntohl(t->src.ip);
167
168 if (!(same->info & IPT_SAME_NODST))
169 tmpip += ntohl(t->dst.ip);
170#endif
171 aindex = tmpip % same->ipnum; 160 aindex = tmpip % same->ipnum;
172 161
173 new_ip = htonl(same->iparray[aindex]); 162 new_ip = htonl(same->iparray[aindex]);
@@ -178,13 +167,13 @@ same_target(struct sk_buff **pskb,
178 NIPQUAD(new_ip)); 167 NIPQUAD(new_ip));
179 168
180 /* Transfer from original range. */ 169 /* Transfer from original range. */
181 newrange = ((struct ip_nat_range) 170 newrange = ((struct nf_nat_range)
182 { same->range[0].flags, new_ip, new_ip, 171 { same->range[0].flags, new_ip, new_ip,
183 /* FIXME: Use ports from correct range! */ 172 /* FIXME: Use ports from correct range! */
184 same->range[0].min, same->range[0].max }); 173 same->range[0].min, same->range[0].max });
185 174
186 /* Hand modified range to generic setup. */ 175 /* Hand modified range to generic setup. */
187 return ip_nat_setup_info(ct, &newrange, hooknum); 176 return nf_nat_setup_info(ct, &newrange, hooknum);
188} 177}
189 178
190static struct xt_target same_reg = { 179static struct xt_target same_reg = {
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 3c58fea0d391..fcebc968d37f 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -33,7 +33,7 @@ static int set_addr(struct sk_buff **pskb,
33 unsigned int addroff, __be32 ip, __be16 port) 33 unsigned int addroff, __be32 ip, __be16 port)
34{ 34{
35 enum ip_conntrack_info ctinfo; 35 enum ip_conntrack_info ctinfo;
36 struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo); 36 struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo);
37 struct { 37 struct {
38 __be32 ip; 38 __be32 ip;
39 __be16 port; 39 __be16 port;
@@ -383,7 +383,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
383static void ip_nat_q931_expect(struct nf_conn *new, 383static void ip_nat_q931_expect(struct nf_conn *new,
384 struct nf_conntrack_expect *this) 384 struct nf_conntrack_expect *this)
385{ 385{
386 struct ip_nat_range range; 386 struct nf_nat_range range;
387 387
388 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ 388 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
389 nf_nat_follow_master(new, this); 389 nf_nat_follow_master(new, this);
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 7ba341c22eaa..a66888749ceb 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -53,7 +53,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
53 struct nf_conntrack_tuple t; 53 struct nf_conntrack_tuple t;
54 struct nf_ct_pptp_master *ct_pptp_info; 54 struct nf_ct_pptp_master *ct_pptp_info;
55 struct nf_nat_pptp *nat_pptp_info; 55 struct nf_nat_pptp *nat_pptp_info;
56 struct ip_nat_range range; 56 struct nf_nat_range range;
57 57
58 ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; 58 ct_pptp_info = &nfct_help(master)->help.ct_pptp_info;
59 nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; 59 nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 54698af6d0af..c558f3214255 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -25,6 +25,7 @@ config NETFILTER_NETLINK_LOG
25 and is also scheduled to replace the old syslog-based ipt_LOG 25 and is also scheduled to replace the old syslog-based ipt_LOG
26 and ip6t_LOG modules. 26 and ip6t_LOG modules.
27 27
28# Rename this to NF_CONNTRACK in a 2.6.25
28config NF_CONNTRACK_ENABLED 29config NF_CONNTRACK_ENABLED
29 tristate "Netfilter connection tracking support" 30 tristate "Netfilter connection tracking support"
30 help 31 help
@@ -39,42 +40,9 @@ config NF_CONNTRACK_ENABLED
39 40
40 To compile it as a module, choose M here. If unsure, say N. 41 To compile it as a module, choose M here. If unsure, say N.
41 42
42choice
43 prompt "Netfilter connection tracking support"
44 depends on NF_CONNTRACK_ENABLED
45
46config NF_CONNTRACK_SUPPORT
47 bool "Layer 3 Independent Connection tracking"
48 help
49 Layer 3 independent connection tracking is experimental scheme
50 which generalize ip_conntrack to support other layer 3 protocols.
51
52 This is required to do Masquerading or other kinds of Network
53 Address Translation (except for Fast NAT). It can also be used to
54 enhance packet filtering (see `Connection state match support'
55 below).
56
57config IP_NF_CONNTRACK_SUPPORT
58 bool "Layer 3 Dependent Connection tracking (OBSOLETE)"
59 help
60 The old, Layer 3 dependent ip_conntrack subsystem of netfilter.
61
62 This is required to do Masquerading or other kinds of Network
63 Address Translation (except for Fast NAT). It can also be used to
64 enhance packet filtering (see `Connection state match support'
65 below).
66
67endchoice
68
69config NF_CONNTRACK 43config NF_CONNTRACK
70 tristate 44 tristate
71 default m if NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=m 45 default NF_CONNTRACK_ENABLED
72 default y if NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=y
73
74config IP_NF_CONNTRACK
75 tristate
76 default m if IP_NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=m
77 default y if IP_NF_CONNTRACK_SUPPORT && NF_CONNTRACK_ENABLED=y
78 46
79config NF_CT_ACCT 47config NF_CT_ACCT
80 bool "Connection tracking flow accounting" 48 bool "Connection tracking flow accounting"
@@ -303,9 +271,8 @@ config NETFILTER_XT_TARGET_CONNMARK
303 tristate '"CONNMARK" target support' 271 tristate '"CONNMARK" target support'
304 depends on NETFILTER_XTABLES 272 depends on NETFILTER_XTABLES
305 depends on IP_NF_MANGLE || IP6_NF_MANGLE 273 depends on IP_NF_MANGLE || IP6_NF_MANGLE
306 depends on IP_NF_CONNTRACK || NF_CONNTRACK 274 depends on NF_CONNTRACK
307 select IP_NF_CONNTRACK_MARK if IP_NF_CONNTRACK 275 select NF_CONNTRACK_MARK
308 select NF_CONNTRACK_MARK if NF_CONNTRACK
309 help 276 help
310 This option adds a `CONNMARK' target, which allows one to manipulate 277 This option adds a `CONNMARK' target, which allows one to manipulate
311 the connection mark value. Similar to the MARK target, but 278 the connection mark value. Similar to the MARK target, but
@@ -366,7 +333,7 @@ config NETFILTER_XT_TARGET_NOTRACK
366 tristate '"NOTRACK" target support' 333 tristate '"NOTRACK" target support'
367 depends on NETFILTER_XTABLES 334 depends on NETFILTER_XTABLES
368 depends on IP_NF_RAW || IP6_NF_RAW 335 depends on IP_NF_RAW || IP6_NF_RAW
369 depends on IP_NF_CONNTRACK || NF_CONNTRACK 336 depends on NF_CONNTRACK
370 help 337 help
371 The NOTRACK target allows a select rule to specify 338 The NOTRACK target allows a select rule to specify
372 which packets *not* to enter the conntrack/NAT 339 which packets *not* to enter the conntrack/NAT
@@ -387,9 +354,7 @@ config NETFILTER_XT_TARGET_SECMARK
387 354
388config NETFILTER_XT_TARGET_CONNSECMARK 355config NETFILTER_XT_TARGET_CONNSECMARK
389 tristate '"CONNSECMARK" target support' 356 tristate '"CONNSECMARK" target support'
390 depends on NETFILTER_XTABLES && \ 357 depends on NETFILTER_XTABLES && NF_CONNTRACK && NF_CONNTRACK_SECMARK
391 ((NF_CONNTRACK && NF_CONNTRACK_SECMARK) || \
392 (IP_NF_CONNTRACK && IP_NF_CONNTRACK_SECMARK))
393 help 358 help
394 The CONNSECMARK target copies security markings from packets 359 The CONNSECMARK target copies security markings from packets
395 to connections, and restores security markings from connections 360 to connections, and restores security markings from connections
@@ -437,9 +402,8 @@ config NETFILTER_XT_MATCH_COMMENT
437config NETFILTER_XT_MATCH_CONNBYTES 402config NETFILTER_XT_MATCH_CONNBYTES
438 tristate '"connbytes" per-connection counter match support' 403 tristate '"connbytes" per-connection counter match support'
439 depends on NETFILTER_XTABLES 404 depends on NETFILTER_XTABLES
440 depends on IP_NF_CONNTRACK || NF_CONNTRACK 405 depends on NF_CONNTRACK
441 select IP_NF_CT_ACCT if IP_NF_CONNTRACK 406 select NF_CT_ACCT
442 select NF_CT_ACCT if NF_CONNTRACK
443 help 407 help
444 This option adds a `connbytes' match, which allows you to match the 408 This option adds a `connbytes' match, which allows you to match the
445 number of bytes and/or packets for each direction within a connection. 409 number of bytes and/or packets for each direction within a connection.
@@ -450,9 +414,8 @@ config NETFILTER_XT_MATCH_CONNBYTES
450config NETFILTER_XT_MATCH_CONNMARK 414config NETFILTER_XT_MATCH_CONNMARK
451 tristate '"connmark" connection mark match support' 415 tristate '"connmark" connection mark match support'
452 depends on NETFILTER_XTABLES 416 depends on NETFILTER_XTABLES
453 depends on IP_NF_CONNTRACK || NF_CONNTRACK 417 depends on NF_CONNTRACK
454 select IP_NF_CONNTRACK_MARK if IP_NF_CONNTRACK 418 select NF_CONNTRACK_MARK
455 select NF_CONNTRACK_MARK if NF_CONNTRACK
456 help 419 help
457 This option adds a `connmark' match, which allows you to match the 420 This option adds a `connmark' match, which allows you to match the
458 connection mark value previously set for the session by `CONNMARK'. 421 connection mark value previously set for the session by `CONNMARK'.
@@ -464,7 +427,7 @@ config NETFILTER_XT_MATCH_CONNMARK
464config NETFILTER_XT_MATCH_CONNTRACK 427config NETFILTER_XT_MATCH_CONNTRACK
465 tristate '"conntrack" connection tracking match support' 428 tristate '"conntrack" connection tracking match support'
466 depends on NETFILTER_XTABLES 429 depends on NETFILTER_XTABLES
467 depends on IP_NF_CONNTRACK || NF_CONNTRACK 430 depends on NF_CONNTRACK
468 help 431 help
469 This is a general conntrack match module, a superset of the state match. 432 This is a general conntrack match module, a superset of the state match.
470 433
@@ -508,7 +471,7 @@ config NETFILTER_XT_MATCH_ESP
508config NETFILTER_XT_MATCH_HELPER 471config NETFILTER_XT_MATCH_HELPER
509 tristate '"helper" match support' 472 tristate '"helper" match support'
510 depends on NETFILTER_XTABLES 473 depends on NETFILTER_XTABLES
511 depends on IP_NF_CONNTRACK || NF_CONNTRACK 474 depends on NF_CONNTRACK
512 help 475 help
513 Helper matching allows you to match packets in dynamic connections 476 Helper matching allows you to match packets in dynamic connections
514 tracked by a conntrack-helper, ie. ip_conntrack_ftp 477 tracked by a conntrack-helper, ie. ip_conntrack_ftp
@@ -632,7 +595,7 @@ config NETFILTER_XT_MATCH_SCTP
632config NETFILTER_XT_MATCH_STATE 595config NETFILTER_XT_MATCH_STATE
633 tristate '"state" match support' 596 tristate '"state" match support'
634 depends on NETFILTER_XTABLES 597 depends on NETFILTER_XTABLES
635 depends on IP_NF_CONNTRACK || NF_CONNTRACK 598 depends on NF_CONNTRACK
636 help 599 help
637 Connection state matching allows you to match packets based on their 600 Connection state matching allows you to match packets based on their
638 relationship to a tracked connection (ie. previous packets). This 601 relationship to a tracked connection (ie. previous packets). This
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 795c058b16a5..b03ce009d0bf 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -30,10 +30,7 @@ MODULE_ALIAS("ipt_CONNMARK");
30 30
31#include <linux/netfilter/x_tables.h> 31#include <linux/netfilter/x_tables.h>
32#include <linux/netfilter/xt_CONNMARK.h> 32#include <linux/netfilter/xt_CONNMARK.h>
33#include <net/netfilter/nf_conntrack_compat.h>
34#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
35#include <net/netfilter/nf_conntrack_ecache.h> 33#include <net/netfilter/nf_conntrack_ecache.h>
36#endif
37 34
38static unsigned int 35static unsigned int
39target(struct sk_buff **pskb, 36target(struct sk_buff **pskb,
@@ -44,40 +41,33 @@ target(struct sk_buff **pskb,
44 const void *targinfo) 41 const void *targinfo)
45{ 42{
46 const struct xt_connmark_target_info *markinfo = targinfo; 43 const struct xt_connmark_target_info *markinfo = targinfo;
44 struct nf_conn *ct;
45 enum ip_conntrack_info ctinfo;
47 u_int32_t diff; 46 u_int32_t diff;
48 u_int32_t mark; 47 u_int32_t mark;
49 u_int32_t newmark; 48 u_int32_t newmark;
50 u_int32_t ctinfo;
51 u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
52 49
53 if (ctmark) { 50 ct = nf_ct_get(*pskb, &ctinfo);
51 if (ct) {
54 switch(markinfo->mode) { 52 switch(markinfo->mode) {
55 case XT_CONNMARK_SET: 53 case XT_CONNMARK_SET:
56 newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; 54 newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
57 if (newmark != *ctmark) { 55 if (newmark != ct->mark) {
58 *ctmark = newmark; 56 ct->mark = newmark;
59#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
60 ip_conntrack_event_cache(IPCT_MARK, *pskb);
61#else
62 nf_conntrack_event_cache(IPCT_MARK, *pskb); 57 nf_conntrack_event_cache(IPCT_MARK, *pskb);
63#endif
64 } 58 }
65 break; 59 break;
66 case XT_CONNMARK_SAVE: 60 case XT_CONNMARK_SAVE:
67 newmark = (*ctmark & ~markinfo->mask) | 61 newmark = (ct->mark & ~markinfo->mask) |
68 ((*pskb)->mark & markinfo->mask); 62 ((*pskb)->mark & markinfo->mask);
69 if (*ctmark != newmark) { 63 if (ct->mark != newmark) {
70 *ctmark = newmark; 64 ct->mark = newmark;
71#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
72 ip_conntrack_event_cache(IPCT_MARK, *pskb);
73#else
74 nf_conntrack_event_cache(IPCT_MARK, *pskb); 65 nf_conntrack_event_cache(IPCT_MARK, *pskb);
75#endif
76 } 66 }
77 break; 67 break;
78 case XT_CONNMARK_RESTORE: 68 case XT_CONNMARK_RESTORE:
79 mark = (*pskb)->mark; 69 mark = (*pskb)->mark;
80 diff = (*ctmark ^ mark) & markinfo->mask; 70 diff = (ct->mark ^ mark) & markinfo->mask;
81 (*pskb)->mark = mark ^ diff; 71 (*pskb)->mark = mark ^ diff;
82 break; 72 break;
83 } 73 }
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 1ab0db641f96..81c0c58bab47 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -19,7 +19,7 @@
19#include <linux/skbuff.h> 19#include <linux/skbuff.h>
20#include <linux/netfilter/x_tables.h> 20#include <linux/netfilter/x_tables.h>
21#include <linux/netfilter/xt_CONNSECMARK.h> 21#include <linux/netfilter/xt_CONNSECMARK.h>
22#include <net/netfilter/nf_conntrack_compat.h> 22#include <net/netfilter/nf_conntrack.h>
23 23
24#define PFX "CONNSECMARK: " 24#define PFX "CONNSECMARK: "
25 25
@@ -36,12 +36,12 @@ MODULE_ALIAS("ip6t_CONNSECMARK");
36static void secmark_save(struct sk_buff *skb) 36static void secmark_save(struct sk_buff *skb)
37{ 37{
38 if (skb->secmark) { 38 if (skb->secmark) {
39 u32 *connsecmark; 39 struct nf_conn *ct;
40 enum ip_conntrack_info ctinfo; 40 enum ip_conntrack_info ctinfo;
41 41
42 connsecmark = nf_ct_get_secmark(skb, &ctinfo); 42 ct = nf_ct_get(skb, &ctinfo);
43 if (connsecmark && !*connsecmark) 43 if (ct && !ct->secmark)
44 *connsecmark = skb->secmark; 44 ct->secmark = skb->secmark;
45 } 45 }
46} 46}
47 47
@@ -52,12 +52,12 @@ static void secmark_save(struct sk_buff *skb)
52static void secmark_restore(struct sk_buff *skb) 52static void secmark_restore(struct sk_buff *skb)
53{ 53{
54 if (!skb->secmark) { 54 if (!skb->secmark) {
55 u32 *connsecmark; 55 struct nf_conn *ct;
56 enum ip_conntrack_info ctinfo; 56 enum ip_conntrack_info ctinfo;
57 57
58 connsecmark = nf_ct_get_secmark(skb, &ctinfo); 58 ct = nf_ct_get(skb, &ctinfo);
59 if (connsecmark && *connsecmark) 59 if (ct && ct->secmark)
60 skb->secmark = *connsecmark; 60 skb->secmark = ct->secmark;
61 } 61 }
62} 62}
63 63
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index b874a2008b2b..5085fb3d1e2d 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -5,7 +5,7 @@
5#include <linux/skbuff.h> 5#include <linux/skbuff.h>
6 6
7#include <linux/netfilter/x_tables.h> 7#include <linux/netfilter/x_tables.h>
8#include <net/netfilter/nf_conntrack_compat.h> 8#include <net/netfilter/nf_conntrack.h>
9 9
10MODULE_LICENSE("GPL"); 10MODULE_LICENSE("GPL");
11MODULE_ALIAS("ipt_NOTRACK"); 11MODULE_ALIAS("ipt_NOTRACK");
@@ -26,7 +26,7 @@ target(struct sk_buff **pskb,
26 If there is a real ct entry correspondig to this packet, 26 If there is a real ct entry correspondig to this packet,
27 it'll hang aroun till timing out. We don't deal with it 27 it'll hang aroun till timing out. We don't deal with it
28 for performance reasons. JK */ 28 for performance reasons. JK */
29 nf_ct_untrack(*pskb); 29 (*pskb)->nfct = &nf_conntrack_untracked.ct_general;
30 (*pskb)->nfctinfo = IP_CT_NEW; 30 (*pskb)->nfctinfo = IP_CT_NEW;
31 nf_conntrack_get((*pskb)->nfct); 31 nf_conntrack_get((*pskb)->nfct);
32 32
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 302043bc41b2..fec9316a1e10 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -12,9 +12,9 @@
12 */ 12 */
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <net/netfilter/nf_conntrack_compat.h>
16#include <linux/netfilter/x_tables.h> 15#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_connbytes.h> 16#include <linux/netfilter/xt_connbytes.h>
17#include <net/netfilter/nf_conntrack.h>
18 18
19#include <asm/div64.h> 19#include <asm/div64.h>
20#include <asm/bitops.h> 20#include <asm/bitops.h>
@@ -35,13 +35,17 @@ match(const struct sk_buff *skb,
35 int *hotdrop) 35 int *hotdrop)
36{ 36{
37 const struct xt_connbytes_info *sinfo = matchinfo; 37 const struct xt_connbytes_info *sinfo = matchinfo;
38 struct nf_conn *ct;
39 enum ip_conntrack_info ctinfo;
38 u_int64_t what = 0; /* initialize to make gcc happy */ 40 u_int64_t what = 0; /* initialize to make gcc happy */
39 u_int64_t bytes = 0; 41 u_int64_t bytes = 0;
40 u_int64_t pkts = 0; 42 u_int64_t pkts = 0;
41 const struct ip_conntrack_counter *counters; 43 const struct ip_conntrack_counter *counters;
42 44
43 if (!(counters = nf_ct_get_counters(skb))) 45 ct = nf_ct_get(skb, &ctinfo);
44 return 0; /* no match */ 46 if (!ct)
47 return 0;
48 counters = ct->counters;
45 49
46 switch (sinfo->what) { 50 switch (sinfo->what) {
47 case XT_CONNBYTES_PKTS: 51 case XT_CONNBYTES_PKTS:
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 36c2defff238..e1803256c792 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -21,16 +21,15 @@
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/skbuff.h> 23#include <linux/skbuff.h>
24#include <net/netfilter/nf_conntrack.h>
25#include <linux/netfilter/x_tables.h>
26#include <linux/netfilter/xt_connmark.h>
24 27
25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 28MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
26MODULE_DESCRIPTION("IP tables connmark match module"); 29MODULE_DESCRIPTION("IP tables connmark match module");
27MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
28MODULE_ALIAS("ipt_connmark"); 31MODULE_ALIAS("ipt_connmark");
29 32
30#include <linux/netfilter/x_tables.h>
31#include <linux/netfilter/xt_connmark.h>
32#include <net/netfilter/nf_conntrack_compat.h>
33
34static int 33static int
35match(const struct sk_buff *skb, 34match(const struct sk_buff *skb,
36 const struct net_device *in, 35 const struct net_device *in,
@@ -42,12 +41,14 @@ match(const struct sk_buff *skb,
42 int *hotdrop) 41 int *hotdrop)
43{ 42{
44 const struct xt_connmark_info *info = matchinfo; 43 const struct xt_connmark_info *info = matchinfo;
45 u_int32_t ctinfo; 44 struct nf_conn *ct;
46 const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); 45 enum ip_conntrack_info ctinfo;
47 if (!ctmark) 46
47 ct = nf_ct_get(skb, &ctinfo);
48 if (!ct)
48 return 0; 49 return 0;
49 50
50 return (((*ctmark) & info->mask) == info->mark) ^ info->invert; 51 return (((ct->mark) & info->mask) == info->mark) ^ info->invert;
51} 52}
52 53
53static int 54static int
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 2885c378288e..f4ea8fe07a53 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -10,121 +10,15 @@
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13
14#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
15#include <linux/netfilter_ipv4/ip_conntrack.h>
16#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
17#else
18#include <net/netfilter/nf_conntrack.h>
19#endif
20
21#include <linux/netfilter/x_tables.h> 13#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter/xt_conntrack.h> 14#include <linux/netfilter/xt_conntrack.h>
23#include <net/netfilter/nf_conntrack_compat.h> 15#include <net/netfilter/nf_conntrack.h>
24 16
25MODULE_LICENSE("GPL"); 17MODULE_LICENSE("GPL");
26MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 18MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
27MODULE_DESCRIPTION("iptables connection tracking match module"); 19MODULE_DESCRIPTION("iptables connection tracking match module");
28MODULE_ALIAS("ipt_conntrack"); 20MODULE_ALIAS("ipt_conntrack");
29 21
30#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
31
32static int
33match(const struct sk_buff *skb,
34 const struct net_device *in,
35 const struct net_device *out,
36 const struct xt_match *match,
37 const void *matchinfo,
38 int offset,
39 unsigned int protoff,
40 int *hotdrop)
41{
42 const struct xt_conntrack_info *sinfo = matchinfo;
43 struct ip_conntrack *ct;
44 enum ip_conntrack_info ctinfo;
45 unsigned int statebit;
46
47 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
48
49#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & invflg))
50
51 if (ct == &ip_conntrack_untracked)
52 statebit = XT_CONNTRACK_STATE_UNTRACKED;
53 else if (ct)
54 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
55 else
56 statebit = XT_CONNTRACK_STATE_INVALID;
57
58 if (sinfo->flags & XT_CONNTRACK_STATE) {
59 if (ct) {
60 if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
61 statebit |= XT_CONNTRACK_STATE_SNAT;
62 if (test_bit(IPS_DST_NAT_BIT, &ct->status))
63 statebit |= XT_CONNTRACK_STATE_DNAT;
64 }
65 if (FWINV((statebit & sinfo->statemask) == 0,
66 XT_CONNTRACK_STATE))
67 return 0;
68 }
69
70 if (ct == NULL) {
71 if (sinfo->flags & ~XT_CONNTRACK_STATE)
72 return 0;
73 return 1;
74 }
75
76 if (sinfo->flags & XT_CONNTRACK_PROTO &&
77 FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
78 sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
79 XT_CONNTRACK_PROTO))
80 return 0;
81
82 if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
83 FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip &
84 sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
85 sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
86 XT_CONNTRACK_ORIGSRC))
87 return 0;
88
89 if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
90 FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip &
91 sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
92 sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
93 XT_CONNTRACK_ORIGDST))
94 return 0;
95
96 if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
97 FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip &
98 sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
99 sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
100 XT_CONNTRACK_REPLSRC))
101 return 0;
102
103 if (sinfo->flags & XT_CONNTRACK_REPLDST &&
104 FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip &
105 sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
106 sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
107 XT_CONNTRACK_REPLDST))
108 return 0;
109
110 if (sinfo->flags & XT_CONNTRACK_STATUS &&
111 FWINV((ct->status & sinfo->statusmask) == 0,
112 XT_CONNTRACK_STATUS))
113 return 0;
114
115 if (sinfo->flags & XT_CONNTRACK_EXPIRES) {
116 unsigned long expires = timer_pending(&ct->timeout) ?
117 (ct->timeout.expires - jiffies)/HZ : 0;
118
119 if (FWINV(!(expires >= sinfo->expires_min &&
120 expires <= sinfo->expires_max),
121 XT_CONNTRACK_EXPIRES))
122 return 0;
123 }
124 return 1;
125}
126
127#else /* CONFIG_IP_NF_CONNTRACK */
128static int 22static int
129match(const struct sk_buff *skb, 23match(const struct sk_buff *skb,
130 const struct net_device *in, 24 const struct net_device *in,
@@ -220,8 +114,6 @@ match(const struct sk_buff *skb,
220 return 1; 114 return 1;
221} 115}
222 116
223#endif /* CONFIG_NF_IP_CONNTRACK */
224
225static int 117static int
226checkentry(const char *tablename, 118checkentry(const char *tablename,
227 const void *ip, 119 const void *ip,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 407d1d5da8a1..bc70b26ba5b4 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -13,18 +13,11 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/skbuff.h> 14#include <linux/skbuff.h>
15#include <linux/netfilter.h> 15#include <linux/netfilter.h>
16#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
17#include <linux/netfilter_ipv4/ip_conntrack.h>
18#include <linux/netfilter_ipv4/ip_conntrack_core.h>
19#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
20#else
21#include <net/netfilter/nf_conntrack.h> 16#include <net/netfilter/nf_conntrack.h>
22#include <net/netfilter/nf_conntrack_core.h> 17#include <net/netfilter/nf_conntrack_core.h>
23#include <net/netfilter/nf_conntrack_helper.h> 18#include <net/netfilter/nf_conntrack_helper.h>
24#endif
25#include <linux/netfilter/x_tables.h> 19#include <linux/netfilter/x_tables.h>
26#include <linux/netfilter/xt_helper.h> 20#include <linux/netfilter/xt_helper.h>
27#include <net/netfilter/nf_conntrack_compat.h>
28 21
29MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); 23MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
@@ -38,55 +31,6 @@ MODULE_ALIAS("ip6t_helper");
38#define DEBUGP(format, args...) 31#define DEBUGP(format, args...)
39#endif 32#endif
40 33
41#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
42static int
43match(const struct sk_buff *skb,
44 const struct net_device *in,
45 const struct net_device *out,
46 const struct xt_match *match,
47 const void *matchinfo,
48 int offset,
49 unsigned int protoff,
50 int *hotdrop)
51{
52 const struct xt_helper_info *info = matchinfo;
53 struct ip_conntrack *ct;
54 enum ip_conntrack_info ctinfo;
55 int ret = info->invert;
56
57 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
58 if (!ct) {
59 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
60 return ret;
61 }
62
63 if (!ct->master) {
64 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
65 return ret;
66 }
67
68 read_lock_bh(&ip_conntrack_lock);
69 if (!ct->master->helper) {
70 DEBUGP("xt_helper: master ct %p has no helper\n",
71 exp->expectant);
72 goto out_unlock;
73 }
74
75 DEBUGP("master's name = %s , info->name = %s\n",
76 ct->master->helper->name, info->name);
77
78 if (info->name[0] == '\0')
79 ret ^= 1;
80 else
81 ret ^= !strncmp(ct->master->helper->name, info->name,
82 strlen(ct->master->helper->name));
83out_unlock:
84 read_unlock_bh(&ip_conntrack_lock);
85 return ret;
86}
87
88#else /* CONFIG_IP_NF_CONNTRACK */
89
90static int 34static int
91match(const struct sk_buff *skb, 35match(const struct sk_buff *skb,
92 const struct net_device *in, 36 const struct net_device *in,
@@ -134,7 +78,6 @@ out_unlock:
134 read_unlock_bh(&nf_conntrack_lock); 78 read_unlock_bh(&nf_conntrack_lock);
135 return ret; 79 return ret;
136} 80}
137#endif
138 81
139static int check(const char *tablename, 82static int check(const char *tablename,
140 const void *inf, 83 const void *inf,
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index df37b912163a..149294f7df71 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -10,7 +10,7 @@
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/skbuff.h> 12#include <linux/skbuff.h>
13#include <net/netfilter/nf_conntrack_compat.h> 13#include <net/netfilter/nf_conntrack.h>
14#include <linux/netfilter/x_tables.h> 14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter/xt_state.h> 15#include <linux/netfilter/xt_state.h>
16 16
@@ -36,7 +36,7 @@ match(const struct sk_buff *skb,
36 36
37 if (nf_ct_is_untracked(skb)) 37 if (nf_ct_is_untracked(skb))
38 statebit = XT_STATE_UNTRACKED; 38 statebit = XT_STATE_UNTRACKED;
39 else if (!nf_ct_get_ctinfo(skb, &ctinfo)) 39 else if (!nf_ct_get(skb, &ctinfo))
40 statebit = XT_STATE_INVALID; 40 statebit = XT_STATE_INVALID;
41 else 41 else
42 statebit = XT_STATE_BIT(ctinfo); 42 statebit = XT_STATE_BIT(ctinfo);