aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-08-09 22:28:03 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:31:24 -0400
commitac3247baf8ecadf168642e3898b0212c29c79715 (patch)
treef2b1c65f34c035491d921006efcf8b2e7a707785 /include
parentabc3bc58047efa72ee9c2e208cbeb73d261ad703 (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.h144
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_core.h17
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 */
75enum 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
122enum 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
340static inline int is_dying(struct ip_conntrack *ct)
341{
342 return test_bit(IPS_DYING_BIT, &ct->status);
343}
344
283extern unsigned int ip_conntrack_htable_size; 345extern unsigned int ip_conntrack_htable_size;
284 346
285struct ip_conntrack_stat 347struct 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
371struct ip_conntrack_ecache {
372 struct ip_conntrack *ct;
373 unsigned int events;
374};
375DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
376
377#define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x)
378
379extern struct notifier_block *ip_conntrack_chain;
380extern struct notifier_block *ip_conntrack_expect_chain;
381
382static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
383{
384 return notifier_chain_register(&ip_conntrack_chain, nb);
385}
386
387static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
388{
389 return notifier_chain_unregister(&ip_conntrack_chain, nb);
390}
391
392static inline int
393ip_conntrack_expect_register_notifier(struct notifier_block *nb)
394{
395 return notifier_chain_register(&ip_conntrack_expect_chain, nb);
396}
397
398static inline int
399ip_conntrack_expect_unregister_notifier(struct notifier_block *nb)
400{
401 return notifier_chain_unregister(&ip_conntrack_expect_chain, nb);
402}
403
404static inline void
405ip_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
420extern void
421ip_conntrack_deliver_cached_events_for(const struct ip_conntrack *ct);
422extern void ip_conntrack_event_cache_init(const struct sk_buff *skb);
423
424static 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
431static inline void
432ip_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 */
438static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
439 const struct sk_buff *skb) {}
440static inline void ip_conntrack_event(enum ip_conntrack_events event,
441 struct ip_conntrack *ct) {}
442static inline void ip_conntrack_deliver_cached_events_for(
443 struct ip_conntrack *ct) {}
444static inline void ip_conntrack_event_cache_init(const struct sk_buff *skb) {}
445static inline void
446ip_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
307static inline int ip_nat_initialized(struct ip_conntrack *conntrack, 451static 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. */
39static inline int ip_conntrack_confirm(struct sk_buff **pskb) 39static 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
52struct ip_conntrack_ecache;
53extern void __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ec);
54#endif
55
47extern struct list_head *ip_conntrack_hash; 56extern struct list_head *ip_conntrack_hash;
48extern struct list_head ip_conntrack_expect_list; 57extern struct list_head ip_conntrack_expect_list;
49extern rwlock_t ip_conntrack_lock; 58extern rwlock_t ip_conntrack_lock;