Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _IP_CONNTRACK_H |
2 | #define _IP_CONNTRACK_H | |
3 | /* Connection state tracking for netfilter. This is separated from, | |
4 | but required by, the NAT layer; it can also be used by an iptables | |
5 | extension. */ | |
6 | enum ip_conntrack_info | |
7 | { | |
8 | /* Part of an established connection (either direction). */ | |
9 | IP_CT_ESTABLISHED, | |
10 | ||
11 | /* Like NEW, but related to an existing connection, or ICMP error | |
12 | (in either direction). */ | |
13 | IP_CT_RELATED, | |
14 | ||
15 | /* Started a new connection to track (only | |
16 | IP_CT_DIR_ORIGINAL); may be a retransmission. */ | |
17 | IP_CT_NEW, | |
18 | ||
19 | /* >= this indicates reply direction */ | |
20 | IP_CT_IS_REPLY, | |
21 | ||
22 | /* Number of distinct IP_CT types (no NEW in reply dirn). */ | |
23 | IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 | |
24 | }; | |
25 | ||
26 | /* Bitset representing status of connection. */ | |
27 | enum ip_conntrack_status { | |
28 | /* It's an expected connection: bit 0 set. This bit never changed */ | |
29 | IPS_EXPECTED_BIT = 0, | |
30 | IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), | |
31 | ||
32 | /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ | |
33 | IPS_SEEN_REPLY_BIT = 1, | |
34 | IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), | |
35 | ||
36 | /* Conntrack should never be early-expired. */ | |
37 | IPS_ASSURED_BIT = 2, | |
38 | IPS_ASSURED = (1 << IPS_ASSURED_BIT), | |
39 | ||
40 | /* Connection is confirmed: originating packet has left box */ | |
41 | IPS_CONFIRMED_BIT = 3, | |
42 | IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT), | |
43 | ||
44 | /* Connection needs src nat in orig dir. This bit never changed. */ | |
45 | IPS_SRC_NAT_BIT = 4, | |
46 | IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT), | |
47 | ||
48 | /* Connection needs dst nat in orig dir. This bit never changed. */ | |
49 | IPS_DST_NAT_BIT = 5, | |
50 | IPS_DST_NAT = (1 << IPS_DST_NAT_BIT), | |
51 | ||
52 | /* Both together. */ | |
53 | IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT), | |
54 | ||
55 | /* Connection needs TCP sequence adjusted. */ | |
56 | IPS_SEQ_ADJUST_BIT = 6, | |
57 | IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT), | |
58 | ||
59 | /* NAT initialization bits. */ | |
60 | IPS_SRC_NAT_DONE_BIT = 7, | |
61 | IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT), | |
62 | ||
63 | IPS_DST_NAT_DONE_BIT = 8, | |
64 | IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT), | |
65 | ||
66 | /* Both together */ | |
67 | IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE), | |
ac3247ba HW |
68 | |
69 | /* Connection is dying (removed from lists), can not be unset. */ | |
70 | IPS_DYING_BIT = 9, | |
71 | IPS_DYING = (1 << IPS_DYING_BIT), | |
72 | }; | |
73 | ||
74 | /* Connection tracking event bits */ | |
75 | enum ip_conntrack_events | |
76 | { | |
77 | /* New conntrack */ | |
78 | IPCT_NEW_BIT = 0, | |
79 | IPCT_NEW = (1 << IPCT_NEW_BIT), | |
80 | ||
81 | /* Expected connection */ | |
82 | IPCT_RELATED_BIT = 1, | |
83 | IPCT_RELATED = (1 << IPCT_RELATED_BIT), | |
84 | ||
85 | /* Destroyed conntrack */ | |
86 | IPCT_DESTROY_BIT = 2, | |
87 | IPCT_DESTROY = (1 << IPCT_DESTROY_BIT), | |
88 | ||
89 | /* Timer has been refreshed */ | |
90 | IPCT_REFRESH_BIT = 3, | |
91 | IPCT_REFRESH = (1 << IPCT_REFRESH_BIT), | |
92 | ||
93 | /* Status has changed */ | |
94 | IPCT_STATUS_BIT = 4, | |
95 | IPCT_STATUS = (1 << IPCT_STATUS_BIT), | |
96 | ||
97 | /* Update of protocol info */ | |
98 | IPCT_PROTOINFO_BIT = 5, | |
99 | IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT), | |
100 | ||
101 | /* Volatile protocol info */ | |
102 | IPCT_PROTOINFO_VOLATILE_BIT = 6, | |
103 | IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT), | |
104 | ||
105 | /* New helper for conntrack */ | |
106 | IPCT_HELPER_BIT = 7, | |
107 | IPCT_HELPER = (1 << IPCT_HELPER_BIT), | |
108 | ||
109 | /* Update of helper info */ | |
110 | IPCT_HELPINFO_BIT = 8, | |
111 | IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT), | |
112 | ||
113 | /* Volatile helper info */ | |
114 | IPCT_HELPINFO_VOLATILE_BIT = 9, | |
115 | IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT), | |
116 | ||
117 | /* NAT info */ | |
118 | IPCT_NATINFO_BIT = 10, | |
119 | IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), | |
120 | }; | |
121 | ||
122 | enum ip_conntrack_expect_events { | |
123 | IPEXP_NEW_BIT = 0, | |
124 | IPEXP_NEW = (1 << IPEXP_NEW_BIT), | |
1da177e4 LT |
125 | }; |
126 | ||
127 | #ifdef __KERNEL__ | |
128 | #include <linux/config.h> | |
129 | #include <linux/netfilter_ipv4/ip_conntrack_tuple.h> | |
130 | #include <linux/bitops.h> | |
131 | #include <linux/compiler.h> | |
132 | #include <asm/atomic.h> | |
133 | ||
134 | #include <linux/netfilter_ipv4/ip_conntrack_tcp.h> | |
135 | #include <linux/netfilter_ipv4/ip_conntrack_icmp.h> | |
136 | #include <linux/netfilter_ipv4/ip_conntrack_sctp.h> | |
137 | ||
138 | /* per conntrack: protocol private data */ | |
139 | union ip_conntrack_proto { | |
140 | /* insert conntrack proto private data here */ | |
141 | struct ip_ct_sctp sctp; | |
142 | struct ip_ct_tcp tcp; | |
143 | struct ip_ct_icmp icmp; | |
144 | }; | |
145 | ||
146 | union ip_conntrack_expect_proto { | |
147 | /* insert expect proto private data here */ | |
148 | }; | |
149 | ||
150 | /* Add protocol helper include file here */ | |
151 | #include <linux/netfilter_ipv4/ip_conntrack_amanda.h> | |
152 | #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> | |
153 | #include <linux/netfilter_ipv4/ip_conntrack_irc.h> | |
154 | ||
155 | /* per conntrack: application helper private data */ | |
156 | union ip_conntrack_help { | |
157 | /* insert conntrack helper private data (master) here */ | |
158 | struct ip_ct_ftp_master ct_ftp_info; | |
159 | struct ip_ct_irc_master ct_irc_info; | |
160 | }; | |
161 | ||
162 | #ifdef CONFIG_IP_NF_NAT_NEEDED | |
163 | #include <linux/netfilter_ipv4/ip_nat.h> | |
164 | #endif | |
165 | ||
166 | #include <linux/types.h> | |
167 | #include <linux/skbuff.h> | |
168 | ||
169 | #ifdef CONFIG_NETFILTER_DEBUG | |
170 | #define IP_NF_ASSERT(x) \ | |
171 | do { \ | |
172 | if (!(x)) \ | |
173 | /* Wooah! I'm tripping my conntrack in a frenzy of \ | |
174 | netplay... */ \ | |
175 | printk("NF_IP_ASSERT: %s:%i(%s)\n", \ | |
176 | __FILE__, __LINE__, __FUNCTION__); \ | |
177 | } while(0) | |
178 | #else | |
179 | #define IP_NF_ASSERT(x) | |
180 | #endif | |
181 | ||
182 | struct ip_conntrack_counter | |
183 | { | |
184 | u_int64_t packets; | |
185 | u_int64_t bytes; | |
186 | }; | |
187 | ||
188 | struct ip_conntrack_helper; | |
189 | ||
190 | struct ip_conntrack | |
191 | { | |
192 | /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, | |
193 | plus 1 for any connection(s) we are `master' for */ | |
194 | struct nf_conntrack ct_general; | |
195 | ||
196 | /* Have we seen traffic both ways yet? (bitset) */ | |
197 | unsigned long status; | |
198 | ||
199 | /* Timer function; drops refcnt when it goes off. */ | |
200 | struct timer_list timeout; | |
201 | ||
202 | #ifdef CONFIG_IP_NF_CT_ACCT | |
203 | /* Accounting Information (same cache line as other written members) */ | |
204 | struct ip_conntrack_counter counters[IP_CT_DIR_MAX]; | |
205 | #endif | |
206 | /* If we were expected by an expectation, this will be it */ | |
207 | struct ip_conntrack *master; | |
208 | ||
209 | /* Current number of expected connections */ | |
210 | unsigned int expecting; | |
211 | ||
080774a2 HW |
212 | /* Unique ID that identifies this conntrack*/ |
213 | unsigned int id; | |
214 | ||
1da177e4 LT |
215 | /* Helper, if any. */ |
216 | struct ip_conntrack_helper *helper; | |
217 | ||
218 | /* Storage reserved for other modules: */ | |
219 | union ip_conntrack_proto proto; | |
220 | ||
221 | union ip_conntrack_help help; | |
222 | ||
223 | #ifdef CONFIG_IP_NF_NAT_NEEDED | |
224 | struct { | |
225 | struct ip_nat_info info; | |
226 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ | |
227 | defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) | |
228 | int masq_index; | |
229 | #endif | |
230 | } nat; | |
231 | #endif /* CONFIG_IP_NF_NAT_NEEDED */ | |
232 | ||
233 | #if defined(CONFIG_IP_NF_CONNTRACK_MARK) | |
bf3a46aa | 234 | u_int32_t mark; |
1da177e4 LT |
235 | #endif |
236 | ||
237 | /* Traversed often, so hopefully in different cacheline to top */ | |
238 | /* These are my tuples; original and reply */ | |
239 | struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; | |
240 | }; | |
241 | ||
242 | struct ip_conntrack_expect | |
243 | { | |
244 | /* Internal linked list (global expectation list) */ | |
245 | struct list_head list; | |
246 | ||
247 | /* We expect this tuple, with the following mask */ | |
248 | struct ip_conntrack_tuple tuple, mask; | |
249 | ||
250 | /* Function to call after setup and insertion */ | |
251 | void (*expectfn)(struct ip_conntrack *new, | |
252 | struct ip_conntrack_expect *this); | |
253 | ||
254 | /* The conntrack of the master connection */ | |
255 | struct ip_conntrack *master; | |
256 | ||
257 | /* Timer function; deletes the expectation. */ | |
258 | struct timer_list timeout; | |
259 | ||
4acdbdbe RR |
260 | /* Usage count. */ |
261 | atomic_t use; | |
262 | ||
080774a2 HW |
263 | /* Unique ID */ |
264 | unsigned int id; | |
265 | ||
1da177e4 LT |
266 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
267 | /* This is the original per-proto part, used to map the | |
268 | * expected connection the way the recipient expects. */ | |
269 | union ip_conntrack_manip_proto saved_proto; | |
270 | /* Direction relative to the master connection. */ | |
271 | enum ip_conntrack_dir dir; | |
272 | #endif | |
273 | }; | |
274 | ||
275 | static inline struct ip_conntrack * | |
276 | tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash) | |
277 | { | |
278 | return container_of(hash, struct ip_conntrack, | |
279 | tuplehash[hash->tuple.dst.dir]); | |
280 | } | |
281 | ||
282 | /* get master conntrack via master expectation */ | |
283 | #define master_ct(conntr) (conntr->master) | |
284 | ||
285 | /* Alter reply tuple (maybe alter helper). */ | |
286 | extern void | |
287 | ip_conntrack_alter_reply(struct ip_conntrack *conntrack, | |
288 | const struct ip_conntrack_tuple *newreply); | |
289 | ||
290 | /* Is this tuple taken? (ignoring any belonging to the given | |
291 | conntrack). */ | |
292 | extern int | |
293 | ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple, | |
294 | const struct ip_conntrack *ignored_conntrack); | |
295 | ||
296 | /* Return conntrack_info and tuple hash for given skb. */ | |
297 | static inline struct ip_conntrack * | |
298 | ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo) | |
299 | { | |
300 | *ctinfo = skb->nfctinfo; | |
301 | return (struct ip_conntrack *)skb->nfct; | |
302 | } | |
303 | ||
304 | /* decrement reference count on a conntrack */ | |
080774a2 HW |
305 | static inline void |
306 | ip_conntrack_put(struct ip_conntrack *ct) | |
307 | { | |
308 | IP_NF_ASSERT(ct); | |
309 | nf_conntrack_put(&ct->ct_general); | |
310 | } | |
1da177e4 LT |
311 | |
312 | /* call to create an explicit dependency on ip_conntrack. */ | |
313 | extern void need_ip_conntrack(void); | |
314 | ||
315 | extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, | |
316 | const struct ip_conntrack_tuple *orig); | |
317 | ||
318 | /* Refresh conntrack for this many jiffies */ | |
319 | extern void ip_ct_refresh_acct(struct ip_conntrack *ct, | |
320 | enum ip_conntrack_info ctinfo, | |
321 | const struct sk_buff *skb, | |
322 | unsigned long extra_jiffies); | |
323 | ||
324 | /* These are for NAT. Icky. */ | |
325 | /* Update TCP window tracking data when NAT mangles the packet */ | |
326 | extern void ip_conntrack_tcp_update(struct sk_buff *skb, | |
327 | struct ip_conntrack *conntrack, | |
328 | enum ip_conntrack_dir dir); | |
329 | ||
330 | /* Call me when a conntrack is destroyed. */ | |
331 | extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); | |
332 | ||
333 | /* Fake conntrack entry for untracked connections */ | |
334 | extern struct ip_conntrack ip_conntrack_untracked; | |
335 | ||
336 | /* Returns new sk_buff, or NULL */ | |
337 | struct sk_buff * | |
338 | ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user); | |
339 | ||
340 | /* Iterate over all conntracks: if iter returns true, it's deleted. */ | |
341 | extern void | |
342 | ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *data), | |
343 | void *data); | |
344 | ||
080774a2 HW |
345 | extern struct ip_conntrack_helper * |
346 | __ip_conntrack_helper_find_byname(const char *); | |
347 | extern struct ip_conntrack_helper * | |
348 | ip_conntrack_helper_find_get(const struct ip_conntrack_tuple *tuple); | |
349 | extern void ip_conntrack_helper_put(struct ip_conntrack_helper *helper); | |
350 | ||
351 | extern struct ip_conntrack_protocol * | |
352 | __ip_conntrack_proto_find(u_int8_t protocol); | |
353 | extern struct ip_conntrack_protocol * | |
354 | ip_conntrack_proto_find_get(u_int8_t protocol); | |
355 | extern void ip_conntrack_proto_put(struct ip_conntrack_protocol *proto); | |
356 | ||
357 | extern void ip_ct_remove_expectations(struct ip_conntrack *ct); | |
358 | ||
359 | extern struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *, | |
360 | struct ip_conntrack_tuple *); | |
361 | ||
362 | extern void ip_conntrack_free(struct ip_conntrack *ct); | |
363 | ||
364 | extern void ip_conntrack_hash_insert(struct ip_conntrack *ct); | |
365 | ||
366 | extern struct ip_conntrack_expect * | |
367 | __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); | |
368 | ||
369 | extern struct ip_conntrack_expect * | |
370 | ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple); | |
371 | ||
372 | extern struct ip_conntrack_tuple_hash * | |
373 | __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, | |
374 | const struct ip_conntrack *ignored_conntrack); | |
375 | ||
376 | extern void ip_conntrack_flush(void); | |
377 | ||
1da177e4 LT |
378 | /* It's confirmed if it is, or has been in the hash table. */ |
379 | static inline int is_confirmed(struct ip_conntrack *ct) | |
380 | { | |
381 | return test_bit(IPS_CONFIRMED_BIT, &ct->status); | |
382 | } | |
383 | ||
ac3247ba HW |
384 | static inline int is_dying(struct ip_conntrack *ct) |
385 | { | |
386 | return test_bit(IPS_DYING_BIT, &ct->status); | |
387 | } | |
388 | ||
1da177e4 LT |
389 | extern unsigned int ip_conntrack_htable_size; |
390 | ||
391 | struct ip_conntrack_stat | |
392 | { | |
393 | unsigned int searched; | |
394 | unsigned int found; | |
395 | unsigned int new; | |
396 | unsigned int invalid; | |
397 | unsigned int ignore; | |
398 | unsigned int delete; | |
399 | unsigned int delete_list; | |
400 | unsigned int insert; | |
401 | unsigned int insert_failed; | |
402 | unsigned int drop; | |
403 | unsigned int early_drop; | |
404 | unsigned int error; | |
405 | unsigned int expect_new; | |
406 | unsigned int expect_create; | |
407 | unsigned int expect_delete; | |
408 | }; | |
409 | ||
410 | #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++) | |
411 | ||
ac3247ba HW |
412 | #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS |
413 | #include <linux/notifier.h> | |
a86888b9 | 414 | #include <linux/interrupt.h> |
ac3247ba HW |
415 | |
416 | struct ip_conntrack_ecache { | |
417 | struct ip_conntrack *ct; | |
418 | unsigned int events; | |
419 | }; | |
420 | DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); | |
421 | ||
422 | #define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x) | |
423 | ||
424 | extern struct notifier_block *ip_conntrack_chain; | |
425 | extern struct notifier_block *ip_conntrack_expect_chain; | |
426 | ||
427 | static inline int ip_conntrack_register_notifier(struct notifier_block *nb) | |
428 | { | |
429 | return notifier_chain_register(&ip_conntrack_chain, nb); | |
430 | } | |
431 | ||
432 | static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb) | |
433 | { | |
434 | return notifier_chain_unregister(&ip_conntrack_chain, nb); | |
435 | } | |
436 | ||
437 | static inline int | |
438 | ip_conntrack_expect_register_notifier(struct notifier_block *nb) | |
439 | { | |
440 | return notifier_chain_register(&ip_conntrack_expect_chain, nb); | |
441 | } | |
442 | ||
443 | static inline int | |
444 | ip_conntrack_expect_unregister_notifier(struct notifier_block *nb) | |
445 | { | |
446 | return notifier_chain_unregister(&ip_conntrack_expect_chain, nb); | |
447 | } | |
448 | ||
a86888b9 PM |
449 | extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct); |
450 | extern void __ip_ct_event_cache_init(struct ip_conntrack *ct); | |
451 | ||
ac3247ba HW |
452 | static inline void |
453 | ip_conntrack_event_cache(enum ip_conntrack_events event, | |
454 | const struct sk_buff *skb) | |
455 | { | |
a86888b9 PM |
456 | struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct; |
457 | struct ip_conntrack_ecache *ecache; | |
458 | ||
459 | local_bh_disable(); | |
460 | ecache = &__get_cpu_var(ip_conntrack_ecache); | |
461 | if (ct != ecache->ct) | |
462 | __ip_ct_event_cache_init(ct); | |
ac3247ba | 463 | ecache->events |= event; |
a86888b9 | 464 | local_bh_enable(); |
ac3247ba HW |
465 | } |
466 | ||
ac3247ba HW |
467 | static inline void ip_conntrack_event(enum ip_conntrack_events event, |
468 | struct ip_conntrack *ct) | |
469 | { | |
470 | if (is_confirmed(ct) && !is_dying(ct)) | |
471 | notifier_call_chain(&ip_conntrack_chain, event, ct); | |
472 | } | |
473 | ||
474 | static inline void | |
475 | ip_conntrack_expect_event(enum ip_conntrack_expect_events event, | |
476 | struct ip_conntrack_expect *exp) | |
477 | { | |
478 | notifier_call_chain(&ip_conntrack_expect_chain, event, exp); | |
479 | } | |
480 | #else /* CONFIG_IP_NF_CONNTRACK_EVENTS */ | |
481 | static inline void ip_conntrack_event_cache(enum ip_conntrack_events event, | |
482 | const struct sk_buff *skb) {} | |
483 | static inline void ip_conntrack_event(enum ip_conntrack_events event, | |
484 | struct ip_conntrack *ct) {} | |
a86888b9 | 485 | static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {} |
ac3247ba HW |
486 | static inline void |
487 | ip_conntrack_expect_event(enum ip_conntrack_expect_events event, | |
488 | struct ip_conntrack_expect *exp) {} | |
489 | #endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */ | |
490 | ||
1da177e4 LT |
491 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
492 | static inline int ip_nat_initialized(struct ip_conntrack *conntrack, | |
493 | enum ip_nat_manip_type manip) | |
494 | { | |
495 | if (manip == IP_NAT_MANIP_SRC) | |
496 | return test_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status); | |
497 | return test_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status); | |
498 | } | |
499 | #endif /* CONFIG_IP_NF_NAT_NEEDED */ | |
500 | ||
501 | #endif /* __KERNEL__ */ | |
502 | #endif /* _IP_CONNTRACK_H */ |