diff options
author | Martin Josefsson <gandalf@wlug.westbo.se> | 2006-11-28 20:34:59 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:05 -0500 |
commit | 7e5d03bb9d2b96fdeab0cb0c98b93e6cf7130c96 (patch) | |
tree | 8214d124da1d3c098b3fcf67f46ef1ec7529cf5d | |
parent | 77ab9cff0f4112703df3ef7903c1a15adb967114 (diff) |
[NETFILTER]: nf_conntrack: split out helper handling
This patch splits out handling of helpers into its own file
nf_conntrack_helper.c
Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/net/netfilter/nf_conntrack_core.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_helper.h | 10 | ||||
-rw-r--r-- | net/netfilter/Makefile | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 120 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 151 |
5 files changed, 165 insertions, 120 deletions
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 84a8e01941fb..bf8d3008a381 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h | |||
@@ -80,4 +80,6 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, | |||
80 | extern struct list_head *nf_conntrack_hash; | 80 | extern struct list_head *nf_conntrack_hash; |
81 | extern struct list_head nf_conntrack_expect_list; | 81 | extern struct list_head nf_conntrack_expect_list; |
82 | extern rwlock_t nf_conntrack_lock ; | 82 | extern rwlock_t nf_conntrack_lock ; |
83 | extern struct list_head unconfirmed; | ||
84 | |||
83 | #endif /* _NF_CONNTRACK_CORE_H */ | 85 | #endif /* _NF_CONNTRACK_CORE_H */ |
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 3cbd13e22160..fbba9e8b95fc 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h | |||
@@ -37,6 +37,16 @@ struct nf_conntrack_helper | |||
37 | int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct); | 37 | int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct); |
38 | }; | 38 | }; |
39 | 39 | ||
40 | extern struct nf_conntrack_helper * | ||
41 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple); | ||
42 | |||
43 | extern struct nf_conntrack_helper * | ||
44 | nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple); | ||
45 | |||
46 | extern struct nf_conntrack_helper * | ||
47 | __nf_conntrack_helper_find_byname(const char *name); | ||
48 | |||
49 | extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); | ||
40 | extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); | 50 | extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); |
41 | extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); | 51 | extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); |
42 | 52 | ||
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index d33b9ac01aa7..236376483ef7 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o | 1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o |
2 | nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | 2 | nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o |
3 | 3 | ||
4 | obj-$(CONFIG_NETFILTER) = netfilter.o | 4 | obj-$(CONFIG_NETFILTER) = netfilter.o |
5 | 5 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 72fbae4e594c..cf6face67af4 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -75,13 +75,12 @@ atomic_t nf_conntrack_count = ATOMIC_INIT(0); | |||
75 | void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; | 75 | void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; |
76 | struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; | 76 | struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; |
77 | struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; | 77 | struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; |
78 | static LIST_HEAD(helpers); | ||
79 | unsigned int nf_conntrack_htable_size __read_mostly = 0; | 78 | unsigned int nf_conntrack_htable_size __read_mostly = 0; |
80 | int nf_conntrack_max __read_mostly; | 79 | int nf_conntrack_max __read_mostly; |
81 | struct list_head *nf_conntrack_hash __read_mostly; | 80 | struct list_head *nf_conntrack_hash __read_mostly; |
82 | struct nf_conn nf_conntrack_untracked; | 81 | struct nf_conn nf_conntrack_untracked; |
83 | unsigned int nf_ct_log_invalid __read_mostly; | 82 | unsigned int nf_ct_log_invalid __read_mostly; |
84 | static LIST_HEAD(unconfirmed); | 83 | LIST_HEAD(unconfirmed); |
85 | static int nf_conntrack_vmalloc __read_mostly; | 84 | static int nf_conntrack_vmalloc __read_mostly; |
86 | 85 | ||
87 | static unsigned int nf_conntrack_next_id; | 86 | static unsigned int nf_conntrack_next_id; |
@@ -696,46 +695,6 @@ static int early_drop(struct list_head *chain) | |||
696 | return dropped; | 695 | return dropped; |
697 | } | 696 | } |
698 | 697 | ||
699 | static struct nf_conntrack_helper * | ||
700 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) | ||
701 | { | ||
702 | struct nf_conntrack_helper *h; | ||
703 | |||
704 | list_for_each_entry(h, &helpers, list) { | ||
705 | if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) | ||
706 | return h; | ||
707 | } | ||
708 | return NULL; | ||
709 | } | ||
710 | |||
711 | struct nf_conntrack_helper * | ||
712 | nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) | ||
713 | { | ||
714 | struct nf_conntrack_helper *helper; | ||
715 | |||
716 | /* need nf_conntrack_lock to assure that helper exists until | ||
717 | * try_module_get() is called */ | ||
718 | read_lock_bh(&nf_conntrack_lock); | ||
719 | |||
720 | helper = __nf_ct_helper_find(tuple); | ||
721 | if (helper) { | ||
722 | /* need to increase module usage count to assure helper will | ||
723 | * not go away while the caller is e.g. busy putting a | ||
724 | * conntrack in the hash that uses the helper */ | ||
725 | if (!try_module_get(helper->me)) | ||
726 | helper = NULL; | ||
727 | } | ||
728 | |||
729 | read_unlock_bh(&nf_conntrack_lock); | ||
730 | |||
731 | return helper; | ||
732 | } | ||
733 | |||
734 | void nf_ct_helper_put(struct nf_conntrack_helper *helper) | ||
735 | { | ||
736 | module_put(helper->me); | ||
737 | } | ||
738 | |||
739 | static struct nf_conn * | 698 | static struct nf_conn * |
740 | __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, | 699 | __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, |
741 | const struct nf_conntrack_tuple *repl, | 700 | const struct nf_conntrack_tuple *repl, |
@@ -1035,83 +994,6 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, | |||
1035 | orig->dst.protonum)); | 994 | orig->dst.protonum)); |
1036 | } | 995 | } |
1037 | 996 | ||
1038 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) | ||
1039 | { | ||
1040 | int ret; | ||
1041 | BUG_ON(me->timeout == 0); | ||
1042 | |||
1043 | ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", | ||
1044 | sizeof(struct nf_conn) | ||
1045 | + sizeof(struct nf_conn_help) | ||
1046 | + __alignof__(struct nf_conn_help)); | ||
1047 | if (ret < 0) { | ||
1048 | printk(KERN_ERR "nf_conntrack_helper_reigster: Unable to create slab cache for conntracks\n"); | ||
1049 | return ret; | ||
1050 | } | ||
1051 | write_lock_bh(&nf_conntrack_lock); | ||
1052 | list_add(&me->list, &helpers); | ||
1053 | write_unlock_bh(&nf_conntrack_lock); | ||
1054 | |||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1058 | struct nf_conntrack_helper * | ||
1059 | __nf_conntrack_helper_find_byname(const char *name) | ||
1060 | { | ||
1061 | struct nf_conntrack_helper *h; | ||
1062 | |||
1063 | list_for_each_entry(h, &helpers, list) { | ||
1064 | if (!strcmp(h->name, name)) | ||
1065 | return h; | ||
1066 | } | ||
1067 | |||
1068 | return NULL; | ||
1069 | } | ||
1070 | |||
1071 | static inline void unhelp(struct nf_conntrack_tuple_hash *i, | ||
1072 | const struct nf_conntrack_helper *me) | ||
1073 | { | ||
1074 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); | ||
1075 | struct nf_conn_help *help = nfct_help(ct); | ||
1076 | |||
1077 | if (help && help->helper == me) { | ||
1078 | nf_conntrack_event(IPCT_HELPER, ct); | ||
1079 | help->helper = NULL; | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | ||
1084 | { | ||
1085 | unsigned int i; | ||
1086 | struct nf_conntrack_tuple_hash *h; | ||
1087 | struct nf_conntrack_expect *exp, *tmp; | ||
1088 | |||
1089 | /* Need write lock here, to delete helper. */ | ||
1090 | write_lock_bh(&nf_conntrack_lock); | ||
1091 | list_del(&me->list); | ||
1092 | |||
1093 | /* Get rid of expectations */ | ||
1094 | list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { | ||
1095 | struct nf_conn_help *help = nfct_help(exp->master); | ||
1096 | if (help->helper == me && del_timer(&exp->timeout)) { | ||
1097 | nf_ct_unlink_expect(exp); | ||
1098 | nf_conntrack_expect_put(exp); | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | /* Get rid of expecteds, set helpers to NULL. */ | ||
1103 | list_for_each_entry(h, &unconfirmed, list) | ||
1104 | unhelp(h, me); | ||
1105 | for (i = 0; i < nf_conntrack_htable_size; i++) { | ||
1106 | list_for_each_entry(h, &nf_conntrack_hash[i], list) | ||
1107 | unhelp(h, me); | ||
1108 | } | ||
1109 | write_unlock_bh(&nf_conntrack_lock); | ||
1110 | |||
1111 | /* Someone could be still looking at the helper in a bh. */ | ||
1112 | synchronize_net(); | ||
1113 | } | ||
1114 | |||
1115 | /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ | 997 | /* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ |
1116 | void __nf_ct_refresh_acct(struct nf_conn *ct, | 998 | void __nf_ct_refresh_acct(struct nf_conn *ct, |
1117 | enum ip_conntrack_info ctinfo, | 999 | enum ip_conntrack_info ctinfo, |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c new file mode 100644 index 000000000000..ca044875a561 --- /dev/null +++ b/net/netfilter/nf_conntrack_helper.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* Helper handling for netfilter. */ | ||
2 | |||
3 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
4 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
5 | * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> | ||
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 | #include <linux/types.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/vmalloc.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/random.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | |||
24 | #define ASSERT_READ_LOCK(x) | ||
25 | #define ASSERT_WRITE_LOCK(x) | ||
26 | |||
27 | #include <net/netfilter/nf_conntrack.h> | ||
28 | #include <net/netfilter/nf_conntrack_l3proto.h> | ||
29 | #include <net/netfilter/nf_conntrack_protocol.h> | ||
30 | #include <net/netfilter/nf_conntrack_helper.h> | ||
31 | #include <net/netfilter/nf_conntrack_core.h> | ||
32 | |||
33 | static LIST_HEAD(helpers); | ||
34 | |||
35 | struct nf_conntrack_helper * | ||
36 | __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) | ||
37 | { | ||
38 | struct nf_conntrack_helper *h; | ||
39 | |||
40 | list_for_each_entry(h, &helpers, list) { | ||
41 | if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) | ||
42 | return h; | ||
43 | } | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | struct nf_conntrack_helper * | ||
48 | nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple) | ||
49 | { | ||
50 | struct nf_conntrack_helper *helper; | ||
51 | |||
52 | /* need nf_conntrack_lock to assure that helper exists until | ||
53 | * try_module_get() is called */ | ||
54 | read_lock_bh(&nf_conntrack_lock); | ||
55 | |||
56 | helper = __nf_ct_helper_find(tuple); | ||
57 | if (helper) { | ||
58 | /* need to increase module usage count to assure helper will | ||
59 | * not go away while the caller is e.g. busy putting a | ||
60 | * conntrack in the hash that uses the helper */ | ||
61 | if (!try_module_get(helper->me)) | ||
62 | helper = NULL; | ||
63 | } | ||
64 | |||
65 | read_unlock_bh(&nf_conntrack_lock); | ||
66 | |||
67 | return helper; | ||
68 | } | ||
69 | |||
70 | void nf_ct_helper_put(struct nf_conntrack_helper *helper) | ||
71 | { | ||
72 | module_put(helper->me); | ||
73 | } | ||
74 | |||
75 | struct nf_conntrack_helper * | ||
76 | __nf_conntrack_helper_find_byname(const char *name) | ||
77 | { | ||
78 | struct nf_conntrack_helper *h; | ||
79 | |||
80 | list_for_each_entry(h, &helpers, list) { | ||
81 | if (!strcmp(h->name, name)) | ||
82 | return h; | ||
83 | } | ||
84 | |||
85 | return NULL; | ||
86 | } | ||
87 | |||
88 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, | ||
89 | const struct nf_conntrack_helper *me) | ||
90 | { | ||
91 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); | ||
92 | struct nf_conn_help *help = nfct_help(ct); | ||
93 | |||
94 | if (help && help->helper == me) { | ||
95 | nf_conntrack_event(IPCT_HELPER, ct); | ||
96 | help->helper = NULL; | ||
97 | } | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | int nf_conntrack_helper_register(struct nf_conntrack_helper *me) | ||
102 | { | ||
103 | int ret; | ||
104 | BUG_ON(me->timeout == 0); | ||
105 | |||
106 | ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help", | ||
107 | sizeof(struct nf_conn) | ||
108 | + sizeof(struct nf_conn_help) | ||
109 | + __alignof__(struct nf_conn_help)); | ||
110 | if (ret < 0) { | ||
111 | printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n"); | ||
112 | return ret; | ||
113 | } | ||
114 | write_lock_bh(&nf_conntrack_lock); | ||
115 | list_add(&me->list, &helpers); | ||
116 | write_unlock_bh(&nf_conntrack_lock); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | ||
122 | { | ||
123 | unsigned int i; | ||
124 | struct nf_conntrack_tuple_hash *h; | ||
125 | struct nf_conntrack_expect *exp, *tmp; | ||
126 | |||
127 | /* Need write lock here, to delete helper. */ | ||
128 | write_lock_bh(&nf_conntrack_lock); | ||
129 | list_del(&me->list); | ||
130 | |||
131 | /* Get rid of expectations */ | ||
132 | list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { | ||
133 | struct nf_conn_help *help = nfct_help(exp->master); | ||
134 | if (help->helper == me && del_timer(&exp->timeout)) { | ||
135 | nf_ct_unlink_expect(exp); | ||
136 | nf_conntrack_expect_put(exp); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | /* Get rid of expecteds, set helpers to NULL. */ | ||
141 | list_for_each_entry(h, &unconfirmed, list) | ||
142 | unhelp(h, me); | ||
143 | for (i = 0; i < nf_conntrack_htable_size; i++) { | ||
144 | list_for_each_entry(h, &nf_conntrack_hash[i], list) | ||
145 | unhelp(h, me); | ||
146 | } | ||
147 | write_unlock_bh(&nf_conntrack_lock); | ||
148 | |||
149 | /* Someone could be still looking at the helper in a bh. */ | ||
150 | synchronize_net(); | ||
151 | } | ||