aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-08-27 20:53:14 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2012-09-03 07:32:48 -0400
commit236df005614bea6a2f9afa9867e3bdfc206c6291 (patch)
tree89bbe58ab9299a508589775f8ad184223889af7c
parent6703aa74ad1ba2e598bb49a37f7518da1195bacb (diff)
netfilter: xt_CT: refactorize xt_ct_tg_check
This patch adds xt_ct_set_helper and xt_ct_set_timeout to reduce the size of xt_ct_tg_check. This aims to improve code mantainability by splitting xt_ct_tg_check in smaller chunks. Suggested by Eric Dumazet. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/xt_CT.c262
1 files changed, 126 insertions, 136 deletions
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 116018560c60..16c712563860 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -72,14 +72,44 @@ static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
72 return 0; 72 return 0;
73} 73}
74 74
75static int
76xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
77 const struct xt_tgchk_param *par)
78{
79 struct nf_conntrack_helper *helper;
80 struct nf_conn_help *help;
81 u8 proto;
82
83 proto = xt_ct_find_proto(par);
84 if (!proto) {
85 pr_info("You must specify a L4 protocol, and not use "
86 "inversions on it.\n");
87 return -ENOENT;
88 }
89
90 helper = nf_conntrack_helper_try_module_get(helper_name, par->family,
91 proto);
92 if (helper == NULL) {
93 pr_info("No such helper \"%s\"\n", helper_name);
94 return -ENOENT;
95 }
96
97 help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
98 if (help == NULL) {
99 module_put(helper->me);
100 return -ENOMEM;
101 }
102
103 help->helper = helper;
104 return 0;
105}
106
75static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) 107static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
76{ 108{
77 struct xt_ct_target_info *info = par->targinfo; 109 struct xt_ct_target_info *info = par->targinfo;
78 struct nf_conntrack_tuple t; 110 struct nf_conntrack_tuple t;
79 struct nf_conn_help *help;
80 struct nf_conn *ct; 111 struct nf_conn *ct;
81 int ret = 0; 112 int ret;
82 u8 proto;
83 113
84 if (info->flags & ~XT_CT_NOTRACK) 114 if (info->flags & ~XT_CT_NOTRACK)
85 return -EINVAL; 115 return -EINVAL;
@@ -112,31 +142,9 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
112 goto err3; 142 goto err3;
113 143
114 if (info->helper[0]) { 144 if (info->helper[0]) {
115 struct nf_conntrack_helper *helper; 145 ret = xt_ct_set_helper(ct, info->helper, par);
116 146 if (ret < 0)
117 ret = -ENOENT;
118 proto = xt_ct_find_proto(par);
119 if (!proto) {
120 pr_info("You must specify a L4 protocol, "
121 "and not use inversions on it.\n");
122 goto err3;
123 }
124
125 ret = -ENOENT;
126 helper = nf_conntrack_helper_try_module_get(info->helper,
127 par->family,
128 proto);
129 if (helper == NULL) {
130 pr_info("No such helper \"%s\"\n", info->helper);
131 goto err3;
132 }
133
134 ret = -ENOMEM;
135 help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
136 if (help == NULL)
137 goto err3; 147 goto err3;
138
139 help->helper = helper;
140 } 148 }
141 149
142 __set_bit(IPS_TEMPLATE_BIT, &ct->status); 150 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
@@ -164,17 +172,77 @@ static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
164} 172}
165#endif 173#endif
166 174
175static int
176xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
177 const char *timeout_name)
178{
179#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
180 typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
181 struct ctnl_timeout *timeout;
182 struct nf_conn_timeout *timeout_ext;
183 const struct ipt_entry *e = par->entryinfo;
184 struct nf_conntrack_l4proto *l4proto;
185 int ret = 0;
186
187 rcu_read_lock();
188 timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
189 if (timeout_find_get == NULL) {
190 ret = -ENOENT;
191 pr_info("Timeout policy base is empty\n");
192 goto out;
193 }
194
195 if (e->ip.invflags & IPT_INV_PROTO) {
196 ret = -EINVAL;
197 pr_info("You cannot use inversion on L4 protocol\n");
198 goto out;
199 }
200
201 timeout = timeout_find_get(timeout_name);
202 if (timeout == NULL) {
203 ret = -ENOENT;
204 pr_info("No such timeout policy \"%s\"\n", timeout_name);
205 goto out;
206 }
207
208 if (timeout->l3num != par->family) {
209 ret = -EINVAL;
210 pr_info("Timeout policy `%s' can only be used by L3 protocol "
211 "number %d\n", timeout_name, timeout->l3num);
212 goto err_put_timeout;
213 }
214 /* Make sure the timeout policy matches any existing protocol tracker,
215 * otherwise default to generic.
216 */
217 l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto);
218 if (timeout->l4proto->l4proto != l4proto->l4proto) {
219 ret = -EINVAL;
220 pr_info("Timeout policy `%s' can only be used by L4 protocol "
221 "number %d\n",
222 timeout_name, timeout->l4proto->l4proto);
223 goto err_put_timeout;
224 }
225 timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
226 if (timeout_ext == NULL)
227 ret = -ENOMEM;
228
229err_put_timeout:
230 __xt_ct_tg_timeout_put(timeout);
231out:
232 rcu_read_unlock();
233 return ret;
234#else
235 return -EOPNOTSUPP;
236#endif
237}
238
167static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 239static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
168{ 240{
169 struct xt_ct_target_info_v1 *info = par->targinfo; 241 struct xt_ct_target_info_v1 *info = par->targinfo;
170 struct nf_conntrack_tuple t; 242 struct nf_conntrack_tuple t;
171 struct nf_conn_help *help;
172 struct nf_conn *ct; 243 struct nf_conn *ct;
173 int ret = 0; 244 int ret;
174 u8 proto; 245
175#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
176 struct ctnl_timeout *timeout;
177#endif
178 if (info->flags & ~XT_CT_NOTRACK) 246 if (info->flags & ~XT_CT_NOTRACK)
179 return -EINVAL; 247 return -EINVAL;
180 248
@@ -206,93 +274,16 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
206 goto err3; 274 goto err3;
207 275
208 if (info->helper[0]) { 276 if (info->helper[0]) {
209 struct nf_conntrack_helper *helper; 277 ret = xt_ct_set_helper(ct, info->helper, par);
210 278 if (ret < 0)
211 ret = -ENOENT;
212 proto = xt_ct_find_proto(par);
213 if (!proto) {
214 pr_info("You must specify a L4 protocol, "
215 "and not use inversions on it.\n");
216 goto err3;
217 }
218
219 ret = -ENOENT;
220 helper = nf_conntrack_helper_try_module_get(info->helper,
221 par->family,
222 proto);
223 if (helper == NULL) {
224 pr_info("No such helper \"%s\"\n", info->helper);
225 goto err3;
226 }
227
228 ret = -ENOMEM;
229 help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
230 if (help == NULL)
231 goto err3; 279 goto err3;
232
233 help->helper = helper;
234 } 280 }
235 281
236#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
237 if (info->timeout[0]) { 282 if (info->timeout[0]) {
238 typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 283 ret = xt_ct_set_timeout(ct, par, info->timeout);
239 struct nf_conn_timeout *timeout_ext; 284 if (ret < 0)
240 285 goto err3;
241 rcu_read_lock();
242 timeout_find_get =
243 rcu_dereference(nf_ct_timeout_find_get_hook);
244
245 if (timeout_find_get) {
246 const struct ipt_entry *e = par->entryinfo;
247 struct nf_conntrack_l4proto *l4proto;
248
249 if (e->ip.invflags & IPT_INV_PROTO) {
250 ret = -EINVAL;
251 pr_info("You cannot use inversion on "
252 "L4 protocol\n");
253 goto err4;
254 }
255 timeout = timeout_find_get(info->timeout);
256 if (timeout == NULL) {
257 ret = -ENOENT;
258 pr_info("No such timeout policy \"%s\"\n",
259 info->timeout);
260 goto err4;
261 }
262 if (timeout->l3num != par->family) {
263 ret = -EINVAL;
264 pr_info("Timeout policy `%s' can only be "
265 "used by L3 protocol number %d\n",
266 info->timeout, timeout->l3num);
267 goto err5;
268 }
269 /* Make sure the timeout policy matches any existing
270 * protocol tracker, otherwise default to generic.
271 */
272 l4proto = __nf_ct_l4proto_find(par->family,
273 e->ip.proto);
274 if (timeout->l4proto->l4proto != l4proto->l4proto) {
275 ret = -EINVAL;
276 pr_info("Timeout policy `%s' can only be "
277 "used by L4 protocol number %d\n",
278 info->timeout,
279 timeout->l4proto->l4proto);
280 goto err5;
281 }
282 timeout_ext = nf_ct_timeout_ext_add(ct, timeout,
283 GFP_ATOMIC);
284 if (timeout_ext == NULL) {
285 ret = -ENOMEM;
286 goto err5;
287 }
288 } else {
289 ret = -ENOENT;
290 pr_info("Timeout policy base is empty\n");
291 goto err4;
292 }
293 rcu_read_unlock();
294 } 286 }
295#endif
296 287
297 __set_bit(IPS_TEMPLATE_BIT, &ct->status); 288 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
298 __set_bit(IPS_CONFIRMED_BIT, &ct->status); 289 __set_bit(IPS_CONFIRMED_BIT, &ct->status);
@@ -300,12 +291,6 @@ out:
300 info->ct = ct; 291 info->ct = ct;
301 return 0; 292 return 0;
302 293
303#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
304err5:
305 __xt_ct_tg_timeout_put(timeout);
306err4:
307 rcu_read_unlock();
308#endif
309err3: 294err3:
310 nf_conntrack_free(ct); 295 nf_conntrack_free(ct);
311err2: 296err2:
@@ -330,15 +315,30 @@ static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
330 nf_ct_put(info->ct); 315 nf_ct_put(info->ct);
331} 316}
332 317
333static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) 318static void xt_ct_destroy_timeout(struct nf_conn *ct)
334{ 319{
335 struct xt_ct_target_info_v1 *info = par->targinfo;
336 struct nf_conn *ct = info->ct;
337 struct nf_conn_help *help;
338#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 320#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
339 struct nf_conn_timeout *timeout_ext; 321 struct nf_conn_timeout *timeout_ext;
340 typeof(nf_ct_timeout_put_hook) timeout_put; 322 typeof(nf_ct_timeout_put_hook) timeout_put;
323
324 rcu_read_lock();
325 timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
326
327 if (timeout_put) {
328 timeout_ext = nf_ct_timeout_find(ct);
329 if (timeout_ext)
330 timeout_put(timeout_ext->timeout);
331 }
332 rcu_read_unlock();
341#endif 333#endif
334}
335
336static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
337{
338 struct xt_ct_target_info_v1 *info = par->targinfo;
339 struct nf_conn *ct = info->ct;
340 struct nf_conn_help *help;
341
342 if (!nf_ct_is_untracked(ct)) { 342 if (!nf_ct_is_untracked(ct)) {
343 help = nfct_help(ct); 343 help = nfct_help(ct);
344 if (help) 344 if (help)
@@ -346,17 +346,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
346 346
347 nf_ct_l3proto_module_put(par->family); 347 nf_ct_l3proto_module_put(par->family);
348 348
349#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 349 xt_ct_destroy_timeout(ct);
350 rcu_read_lock();
351 timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
352
353 if (timeout_put) {
354 timeout_ext = nf_ct_timeout_find(ct);
355 if (timeout_ext)
356 timeout_put(timeout_ext->timeout);
357 }
358 rcu_read_unlock();
359#endif
360 } 350 }
361 nf_ct_put(info->ct); 351 nf_ct_put(info->ct);
362} 352}