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/netfilter_ipv4/ip_conntrack_tcp.h>
13#include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
14#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
15#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
16
17/* per conntrack: protocol private data */
18union ip_conntrack_proto {
19	/* insert conntrack proto private data here */
20	struct ip_ct_gre gre;
21	struct ip_ct_sctp sctp;
22	struct ip_ct_tcp tcp;
23	struct ip_ct_icmp icmp;
24};
25
26union ip_conntrack_expect_proto {
27	/* insert expect proto private data here */
28};
29
30/* Add protocol helper include file here */
31#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
32#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
33#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
34#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
35#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
36
37/* per conntrack: application helper private data */
38union ip_conntrack_help {
39	/* insert conntrack helper private data (master) here */
40	struct ip_ct_h323_master ct_h323_info;
41	struct ip_ct_pptp_master ct_pptp_info;
42	struct ip_ct_ftp_master ct_ftp_info;
43	struct ip_ct_irc_master ct_irc_info;
44};
45
46#ifdef CONFIG_IP_NF_NAT_NEEDED
47#include <linux/netfilter_ipv4/ip_nat.h>
48#include <linux/netfilter_ipv4/ip_nat_pptp.h>
49
50/* per conntrack: nat application helper private data */
51union ip_conntrack_nat_help {
52	/* insert nat helper private data here */
53	struct ip_nat_pptp nat_pptp_info;
54};
55#endif
56
57#include <linux/types.h>
58#include <linux/skbuff.h>
59
60#ifdef CONFIG_NETFILTER_DEBUG
61#define IP_NF_ASSERT(x)							\
62do {									\
63	if (!(x))							\
64		/* Wooah!  I'm tripping my conntrack in a frenzy of	\
65		   netplay... */					\
66		printk("NF_IP_ASSERT: %s:%i(%s)\n",			\
67		       __FILE__, __LINE__, __FUNCTION__);		\
68} while(0)
69#else
70#define IP_NF_ASSERT(x)
71#endif
72
73struct ip_conntrack_helper;
74
75struct ip_conntrack
76{
77	/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
78           plus 1 for any connection(s) we are `master' for */
79	struct nf_conntrack ct_general;
80
81	/* Have we seen traffic both ways yet? (bitset) */
82	unsigned long status;
83
84	/* Timer function; drops refcnt when it goes off. */
85	struct timer_list timeout;
86
87#ifdef CONFIG_IP_NF_CT_ACCT
88	/* Accounting Information (same cache line as other written members) */
89	struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
90#endif
91	/* If we were expected by an expectation, this will be it */
92	struct ip_conntrack *master;
93
94	/* Current number of expected connections */
95	unsigned int expecting;
96
97	/* Unique ID that identifies this conntrack*/
98	unsigned int id;
99
100	/* Helper, if any. */
101	struct ip_conntrack_helper *helper;
102
103	/* Storage reserved for other modules: */
104	union ip_conntrack_proto proto;
105
106	union ip_conntrack_help help;
107
108#ifdef CONFIG_IP_NF_NAT_NEEDED
109	struct {
110		struct ip_nat_info info;
111		union ip_conntrack_nat_help help;
112#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
113	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
114		int masq_index;
115#endif
116	} nat;
117#endif /* CONFIG_IP_NF_NAT_NEEDED */
118
119#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
120	u_int32_t mark;
121#endif
122
123#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
124	u_int32_t secmark;
125#endif
126
127	/* Traversed often, so hopefully in different cacheline to top */
128	/* These are my tuples; original and reply */
129	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
130};
131
132struct ip_conntrack_expect
133{
134	/* Internal linked list (global expectation list) */
135	struct list_head list;
136
137	/* We expect this tuple, with the following mask */
138	struct ip_conntrack_tuple tuple, mask;
139
140	/* Function to call after setup and insertion */
141	void (*expectfn)(struct ip_conntrack *new,
142			 struct ip_conntrack_expect *this);
143
144	/* The conntrack of the master connection */
145	struct ip_conntrack *master;
146
147	/* Timer function; deletes the expectation. */
148	struct timer_list timeout;
149
150	/* Usage count. */
151	atomic_t use;
152
153	/* Unique ID */
154	unsigned int id;
155
156	/* Flags */
157	unsigned int flags;
158
159#ifdef CONFIG_IP_NF_NAT_NEEDED
160	u_int32_t saved_ip;
161	/* This is the original per-proto part, used to map the
162	 * expected connection the way the recipient expects. */
163	union ip_conntrack_manip_proto saved_proto;
164	/* Direction relative to the master connection. */
165	enum ip_conntrack_dir dir;
166#endif
167};
168
169#define IP_CT_EXPECT_PERMANENT	0x1
170
171static inline struct ip_conntrack *
172tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash)
173{
174	return container_of(hash, struct ip_conntrack,
175			    tuplehash[hash->tuple.dst.dir]);
176}
177
178/* get master conntrack via master expectation */
179#define master_ct(conntr) (conntr->master)
180
181/* Alter reply tuple (maybe alter helper). */
182extern void
183ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
184			 const struct ip_conntrack_tuple *newreply);
185
186/* Is this tuple taken? (ignoring any belonging to the given
187   conntrack). */
188extern int
189ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
190			 const struct ip_conntrack *ignored_conntrack);
191
192/* Return conntrack_info and tuple hash for given skb. */
193static inline struct ip_conntrack *
194ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
195{
196	*ctinfo = skb->nfctinfo;
197	return (struct ip_conntrack *)skb->nfct;
198}
199
200/* decrement reference count on a conntrack */
201static inline void
202ip_conntrack_put(struct ip_conntrack *ct)
203{
204	IP_NF_ASSERT(ct);
205	nf_conntrack_put(&ct->ct_general);
206}
207
208extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
209			  const struct ip_conntrack_tuple *orig);
210
211extern void __ip_ct_refresh_acct(struct ip_conntrack *ct,
212			         enum ip_conntrack_info ctinfo,
213			         const struct sk_buff *skb,
214			         unsigned long extra_jiffies,
215				 int do_acct);
216
217/* Refresh conntrack for this many jiffies and do accounting */
218static inline void ip_ct_refresh_acct(struct ip_conntrack *ct,
219				      enum ip_conntrack_info ctinfo,
220				      const struct sk_buff *skb,
221				      unsigned long extra_jiffies)
222{
223	__ip_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
224}
225
226/* Refresh conntrack for this many jiffies */
227static inline void ip_ct_refresh(struct ip_conntrack *ct,
228				 const struct sk_buff *skb,
229				 unsigned long extra_jiffies)
230{
231	__ip_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
232}
233
234/* These are for NAT.  Icky. */
235/* Update TCP window tracking data when NAT mangles the packet */
236extern void ip_conntrack_tcp_update(struct sk_buff *skb,
237				    struct ip_conntrack *conntrack,
238				    enum ip_conntrack_dir dir);
239
240/* Call me when a conntrack is destroyed. */
241extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
242
243/* Fake conntrack entry for untracked connections */
244extern struct ip_conntrack ip_conntrack_untracked;
245
246/* Returns new sk_buff, or NULL */
247struct sk_buff *
248ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
249
250/* Iterate over all conntracks: if iter returns true, it's deleted. */
251extern void
252ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *data),
253		      void *data);
254
255extern struct ip_conntrack_helper *
256__ip_conntrack_helper_find_byname(const char *);
257extern struct ip_conntrack_helper *
258ip_conntrack_helper_find_get(const struct ip_conntrack_tuple *tuple);
259extern void ip_conntrack_helper_put(struct ip_conntrack_helper *helper);
260
261extern struct ip_conntrack_protocol *
262__ip_conntrack_proto_find(u_int8_t protocol);
263extern struct ip_conntrack_protocol *
264ip_conntrack_proto_find_get(u_int8_t protocol);
265extern void ip_conntrack_proto_put(struct ip_conntrack_protocol *proto);
266
267extern void ip_ct_remove_expectations(struct ip_conntrack *ct);
268
269extern struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *,
270					       struct ip_conntrack_tuple *);
271
272extern void ip_conntrack_free(struct ip_conntrack *ct);
273
274extern void ip_conntrack_hash_insert(struct ip_conntrack *ct);
275
276extern struct ip_conntrack_expect *
277__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
278
279extern struct ip_conntrack_expect *
280ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
281
282extern struct ip_conntrack_tuple_hash *
283__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
284                    const struct ip_conntrack *ignored_conntrack);
285
286extern void ip_conntrack_flush(void);
287
288/* It's confirmed if it is, or has been in the hash table. */
289static inline int is_confirmed(struct ip_conntrack *ct)
290{
291	return test_bit(IPS_CONFIRMED_BIT, &ct->status);
292}
293
294static inline int is_dying(struct ip_conntrack *ct)
295{
296	return test_bit(IPS_DYING_BIT, &ct->status);
297}
298
299extern unsigned int ip_conntrack_htable_size;
300extern int ip_conntrack_checksum;
301
302#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
303
304#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
305#include <linux/notifier.h>
306#include <linux/interrupt.h>
307
308struct ip_conntrack_ecache {
309	struct ip_conntrack *ct;
310	unsigned int events;
311};
312DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
313
314#define CONNTRACK_ECACHE(x)	(__get_cpu_var(ip_conntrack_ecache).x)
315
316extern struct atomic_notifier_head ip_conntrack_chain;
317extern struct atomic_notifier_head ip_conntrack_expect_chain;
318
319static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
320{
321	return atomic_notifier_chain_register(&ip_conntrack_chain, nb);
322}
323
324static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
325{
326	return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb);
327}
328
329static inline int
330ip_conntrack_expect_register_notifier(struct notifier_block *nb)
331{
332	return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb);
333}
334
335static inline int
336ip_conntrack_expect_unregister_notifier(struct notifier_block *nb)
337{
338	return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain,
339			nb);
340}
341
342extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
343extern void __ip_ct_event_cache_init(struct ip_conntrack *ct);
344
345static inline void
346ip_conntrack_event_cache(enum ip_conntrack_events event,
347			 const struct sk_buff *skb)
348{
349	struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct;
350	struct ip_conntrack_ecache *ecache;
351
352	local_bh_disable();
353	ecache = &__get_cpu_var(ip_conntrack_ecache);
354	if (ct != ecache->ct)
355		__ip_ct_event_cache_init(ct);
356	ecache->events |= event;
357	local_bh_enable();
358}
359
360static inline void ip_conntrack_event(enum ip_conntrack_events event,
361				      struct ip_conntrack *ct)
362{
363	if (is_confirmed(ct) && !is_dying(ct))
364		atomic_notifier_call_chain(&ip_conntrack_chain, event, ct);
365}
366
367static inline void
368ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
369			  struct ip_conntrack_expect *exp)
370{
371	atomic_notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
372}
373#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
374static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
375					    const struct sk_buff *skb) {}
376static inline void ip_conntrack_event(enum ip_conntrack_events event,
377				      struct ip_conntrack *ct) {}
378static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {}
379static inline void
380ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
381			  struct ip_conntrack_expect *exp) {}
382#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
383
384#ifdef CONFIG_IP_NF_NAT_NEEDED
385static inline int ip_nat_initialized(struct ip_conntrack *conntrack,
386				     enum ip_nat_manip_type manip)
387{
388	if (manip == IP_NAT_MANIP_SRC)
389		return test_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status);
390	return test_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status);
391}
392#endif /* CONFIG_IP_NF_NAT_NEEDED */
393
394#endif /* __KERNEL__ */
395#endif /* _IP_CONNTRACK_H */
396