diff options
author | Harald Welte <laforge@netfilter.org> | 2005-08-09 22:28:03 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:31:24 -0400 |
commit | ac3247baf8ecadf168642e3898b0212c29c79715 (patch) | |
tree | f2b1c65f34c035491d921006efcf8b2e7a707785 /include | |
parent | abc3bc58047efa72ee9c2e208cbeb73d261ad703 (diff) |
[NETFILTER]: connection tracking event notifiers
This adds a notifier chain based event mechanism for ip_conntrack state
changes. As opposed to the previous implementations in patch-o-matic, we
do no longer need a field in the skb to achieve this.
Thanks to the valuable input from Patrick McHardy and Rusty on the idea
of a per_cpu implementation.
Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/netfilter_ipv4/ip_conntrack.h | 144 | ||||
-rw-r--r-- | include/linux/netfilter_ipv4/ip_conntrack_core.h | 17 |
2 files changed, 157 insertions, 4 deletions
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 4ed720f0c4cd..ae1270c97b50 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h | |||
@@ -65,6 +65,63 @@ enum ip_conntrack_status { | |||
65 | 65 | ||
66 | /* Both together */ | 66 | /* Both together */ |
67 | IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE), | 67 | IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE), |
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), | ||
68 | }; | 125 | }; |
69 | 126 | ||
70 | #ifdef __KERNEL__ | 127 | #ifdef __KERNEL__ |
@@ -280,6 +337,11 @@ static inline int is_confirmed(struct ip_conntrack *ct) | |||
280 | return test_bit(IPS_CONFIRMED_BIT, &ct->status); | 337 | return test_bit(IPS_CONFIRMED_BIT, &ct->status); |
281 | } | 338 | } |
282 | 339 | ||
340 | static inline int is_dying(struct ip_conntrack *ct) | ||
341 | { | ||
342 | return test_bit(IPS_DYING_BIT, &ct->status); | ||
343 | } | ||
344 | |||
283 | extern unsigned int ip_conntrack_htable_size; | 345 | extern unsigned int ip_conntrack_htable_size; |
284 | 346 | ||
285 | struct ip_conntrack_stat | 347 | struct ip_conntrack_stat |
@@ -303,6 +365,88 @@ struct ip_conntrack_stat | |||
303 | 365 | ||
304 | #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++) | 366 | #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++) |
305 | 367 | ||
368 | #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS | ||
369 | #include <linux/notifier.h> | ||
370 | |||
371 | struct ip_conntrack_ecache { | ||
372 | struct ip_conntrack *ct; | ||
373 | unsigned int events; | ||
374 | }; | ||
375 | DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); | ||
376 | |||
377 | #define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x) | ||
378 | |||
379 | extern struct notifier_block *ip_conntrack_chain; | ||
380 | extern struct notifier_block *ip_conntrack_expect_chain; | ||
381 | |||
382 | static inline int ip_conntrack_register_notifier(struct notifier_block *nb) | ||
383 | { | ||
384 | return notifier_chain_register(&ip_conntrack_chain, nb); | ||
385 | } | ||
386 | |||
387 | static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb) | ||
388 | { | ||
389 | return notifier_chain_unregister(&ip_conntrack_chain, nb); | ||
390 | } | ||
391 | |||
392 | static inline int | ||
393 | ip_conntrack_expect_register_notifier(struct notifier_block *nb) | ||
394 | { | ||
395 | return notifier_chain_register(&ip_conntrack_expect_chain, nb); | ||
396 | } | ||
397 | |||
398 | static inline int | ||
399 | ip_conntrack_expect_unregister_notifier(struct notifier_block *nb) | ||
400 | { | ||
401 | return notifier_chain_unregister(&ip_conntrack_expect_chain, nb); | ||
402 | } | ||
403 | |||
404 | static inline void | ||
405 | ip_conntrack_event_cache(enum ip_conntrack_events event, | ||
406 | const struct sk_buff *skb) | ||
407 | { | ||
408 | struct ip_conntrack_ecache *ecache = | ||
409 | &__get_cpu_var(ip_conntrack_ecache); | ||
410 | |||
411 | if (unlikely((struct ip_conntrack *) skb->nfct != ecache->ct)) { | ||
412 | if (net_ratelimit()) { | ||
413 | printk(KERN_ERR "ctevent: skb->ct != ecache->ct !!!\n"); | ||
414 | dump_stack(); | ||
415 | } | ||
416 | } | ||
417 | ecache->events |= event; | ||
418 | } | ||
419 | |||
420 | extern void | ||
421 | ip_conntrack_deliver_cached_events_for(const struct ip_conntrack *ct); | ||
422 | extern void ip_conntrack_event_cache_init(const struct sk_buff *skb); | ||
423 | |||
424 | static inline void ip_conntrack_event(enum ip_conntrack_events event, | ||
425 | struct ip_conntrack *ct) | ||
426 | { | ||
427 | if (is_confirmed(ct) && !is_dying(ct)) | ||
428 | notifier_call_chain(&ip_conntrack_chain, event, ct); | ||
429 | } | ||
430 | |||
431 | static inline void | ||
432 | ip_conntrack_expect_event(enum ip_conntrack_expect_events event, | ||
433 | struct ip_conntrack_expect *exp) | ||
434 | { | ||
435 | notifier_call_chain(&ip_conntrack_expect_chain, event, exp); | ||
436 | } | ||
437 | #else /* CONFIG_IP_NF_CONNTRACK_EVENTS */ | ||
438 | static inline void ip_conntrack_event_cache(enum ip_conntrack_events event, | ||
439 | const struct sk_buff *skb) {} | ||
440 | static inline void ip_conntrack_event(enum ip_conntrack_events event, | ||
441 | struct ip_conntrack *ct) {} | ||
442 | static inline void ip_conntrack_deliver_cached_events_for( | ||
443 | struct ip_conntrack *ct) {} | ||
444 | static inline void ip_conntrack_event_cache_init(const struct sk_buff *skb) {} | ||
445 | static inline void | ||
446 | ip_conntrack_expect_event(enum ip_conntrack_expect_events event, | ||
447 | struct ip_conntrack_expect *exp) {} | ||
448 | #endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */ | ||
449 | |||
306 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 450 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
307 | static inline int ip_nat_initialized(struct ip_conntrack *conntrack, | 451 | static inline int ip_nat_initialized(struct ip_conntrack *conntrack, |
308 | enum ip_nat_manip_type manip) | 452 | enum ip_nat_manip_type manip) |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h index 694aec9b4784..46eeea1e2733 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_core.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h | |||
@@ -38,12 +38,21 @@ extern int __ip_conntrack_confirm(struct sk_buff **pskb); | |||
38 | /* Confirm a connection: returns NF_DROP if packet must be dropped. */ | 38 | /* Confirm a connection: returns NF_DROP if packet must be dropped. */ |
39 | static inline int ip_conntrack_confirm(struct sk_buff **pskb) | 39 | static inline int ip_conntrack_confirm(struct sk_buff **pskb) |
40 | { | 40 | { |
41 | if ((*pskb)->nfct | 41 | struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct; |
42 | && !is_confirmed((struct ip_conntrack *)(*pskb)->nfct)) | 42 | int ret = NF_ACCEPT; |
43 | return __ip_conntrack_confirm(pskb); | 43 | |
44 | return NF_ACCEPT; | 44 | if (ct && !is_confirmed(ct)) |
45 | ret = __ip_conntrack_confirm(pskb); | ||
46 | ip_conntrack_deliver_cached_events_for(ct); | ||
47 | |||
48 | return ret; | ||
45 | } | 49 | } |
46 | 50 | ||
51 | #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS | ||
52 | struct ip_conntrack_ecache; | ||
53 | extern void __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ec); | ||
54 | #endif | ||
55 | |||
47 | extern struct list_head *ip_conntrack_hash; | 56 | extern struct list_head *ip_conntrack_hash; |
48 | extern struct list_head ip_conntrack_expect_list; | 57 | extern struct list_head ip_conntrack_expect_list; |
49 | extern rwlock_t ip_conntrack_lock; | 58 | extern rwlock_t ip_conntrack_lock; |