diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2007-07-08 01:21:23 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:17:14 -0400 |
commit | ba9dda3ab5a865542e69dfe01edb2436857c9420 (patch) | |
tree | 93f92442a8ad134d78b4d7cd8dc74e089baef3d7 | |
parent | 1b50b8a371e90a5e110f466e4ac02cf6b5f681de (diff) |
[NETFILTER]: x_tables: add TRACE target
The TRACE target can be used to follow IP and IPv6 packets through
the ruleset.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick NcHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/skbuff.h | 4 | ||||
-rw-r--r-- | net/core/skbuff.c | 8 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 127 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 128 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 12 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/xt_TRACE.c | 53 |
9 files changed, 314 insertions, 27 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2d6a14f5f2f1..625d73b07ab7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -227,6 +227,7 @@ typedef unsigned char *sk_buff_data_t; | |||
227 | * @mark: Generic packet mark | 227 | * @mark: Generic packet mark |
228 | * @nfct: Associated connection, if any | 228 | * @nfct: Associated connection, if any |
229 | * @ipvs_property: skbuff is owned by ipvs | 229 | * @ipvs_property: skbuff is owned by ipvs |
230 | * @nf_trace: netfilter packet trace flag | ||
230 | * @nfctinfo: Relationship of this skb to the connection | 231 | * @nfctinfo: Relationship of this skb to the connection |
231 | * @nfct_reasm: netfilter conntrack re-assembly pointer | 232 | * @nfct_reasm: netfilter conntrack re-assembly pointer |
232 | * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c | 233 | * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c |
@@ -278,7 +279,8 @@ struct sk_buff { | |||
278 | nfctinfo:3; | 279 | nfctinfo:3; |
279 | __u8 pkt_type:3, | 280 | __u8 pkt_type:3, |
280 | fclone:2, | 281 | fclone:2, |
281 | ipvs_property:1; | 282 | ipvs_property:1, |
283 | nf_trace:1; | ||
282 | __be16 protocol; | 284 | __be16 protocol; |
283 | 285 | ||
284 | void (*destructor)(struct sk_buff *skb); | 286 | void (*destructor)(struct sk_buff *skb); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6a41b96b3d37..0583e8498f13 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -428,6 +428,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
428 | n->destructor = NULL; | 428 | n->destructor = NULL; |
429 | C(mark); | 429 | C(mark); |
430 | __nf_copy(n, skb); | 430 | __nf_copy(n, skb); |
431 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
432 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
433 | C(nf_trace); | ||
434 | #endif | ||
431 | #ifdef CONFIG_NET_SCHED | 435 | #ifdef CONFIG_NET_SCHED |
432 | C(tc_index); | 436 | C(tc_index); |
433 | #ifdef CONFIG_NET_CLS_ACT | 437 | #ifdef CONFIG_NET_CLS_ACT |
@@ -485,6 +489,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
485 | new->destructor = NULL; | 489 | new->destructor = NULL; |
486 | new->mark = old->mark; | 490 | new->mark = old->mark; |
487 | __nf_copy(new, old); | 491 | __nf_copy(new, old); |
492 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
493 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
494 | new->nf_trace = old->nf_trace; | ||
495 | #endif | ||
488 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 496 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
489 | new->ipvs_property = old->ipvs_property; | 497 | new->ipvs_property = old->ipvs_property; |
490 | #endif | 498 | #endif |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index a7dd343d3a03..c9e2b5e6305e 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -399,6 +399,10 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
399 | to->tc_index = from->tc_index; | 399 | to->tc_index = from->tc_index; |
400 | #endif | 400 | #endif |
401 | nf_copy(to, from); | 401 | nf_copy(to, from); |
402 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
403 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
404 | to->nf_trace = from->nf_trace; | ||
405 | #endif | ||
402 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) | 406 | #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) |
403 | to->ipvs_property = from->ipvs_property; | 407 | to->ipvs_property = from->ipvs_property; |
404 | #endif | 408 | #endif |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 7962306df585..650ab52e9157 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -204,6 +204,112 @@ get_entry(void *base, unsigned int offset) | |||
204 | return (struct ipt_entry *)(base + offset); | 204 | return (struct ipt_entry *)(base + offset); |
205 | } | 205 | } |
206 | 206 | ||
207 | /* All zeroes == unconditional rule. */ | ||
208 | static inline int | ||
209 | unconditional(const struct ipt_ip *ip) | ||
210 | { | ||
211 | unsigned int i; | ||
212 | |||
213 | for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++) | ||
214 | if (((__u32 *)ip)[i]) | ||
215 | return 0; | ||
216 | |||
217 | return 1; | ||
218 | } | ||
219 | |||
220 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
221 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
222 | static const char *hooknames[] = { | ||
223 | [NF_IP_PRE_ROUTING] = "PREROUTING", | ||
224 | [NF_IP_LOCAL_IN] = "INPUT", | ||
225 | [NF_IP_FORWARD] = "FORWARD", | ||
226 | [NF_IP_LOCAL_OUT] = "OUTPUT", | ||
227 | [NF_IP_POST_ROUTING] = "POSTROUTING", | ||
228 | }; | ||
229 | |||
230 | enum nf_ip_trace_comments { | ||
231 | NF_IP_TRACE_COMMENT_RULE, | ||
232 | NF_IP_TRACE_COMMENT_RETURN, | ||
233 | NF_IP_TRACE_COMMENT_POLICY, | ||
234 | }; | ||
235 | |||
236 | static const char *comments[] = { | ||
237 | [NF_IP_TRACE_COMMENT_RULE] = "rule", | ||
238 | [NF_IP_TRACE_COMMENT_RETURN] = "return", | ||
239 | [NF_IP_TRACE_COMMENT_POLICY] = "policy", | ||
240 | }; | ||
241 | |||
242 | static struct nf_loginfo trace_loginfo = { | ||
243 | .type = NF_LOG_TYPE_LOG, | ||
244 | .u = { | ||
245 | .log = { | ||
246 | .level = 4, | ||
247 | .logflags = NF_LOG_MASK, | ||
248 | }, | ||
249 | }, | ||
250 | }; | ||
251 | |||
252 | static inline int | ||
253 | get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, | ||
254 | char *hookname, char **chainname, | ||
255 | char **comment, unsigned int *rulenum) | ||
256 | { | ||
257 | struct ipt_standard_target *t = (void *)ipt_get_target(s); | ||
258 | |||
259 | if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) { | ||
260 | /* Head of user chain: ERROR target with chainname */ | ||
261 | *chainname = t->target.data; | ||
262 | (*rulenum) = 0; | ||
263 | } else if (s == e) { | ||
264 | (*rulenum)++; | ||
265 | |||
266 | if (s->target_offset == sizeof(struct ipt_entry) | ||
267 | && strcmp(t->target.u.kernel.target->name, | ||
268 | IPT_STANDARD_TARGET) == 0 | ||
269 | && t->verdict < 0 | ||
270 | && unconditional(&s->ip)) { | ||
271 | /* Tail of chains: STANDARD target (return/policy) */ | ||
272 | *comment = *chainname == hookname | ||
273 | ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY] | ||
274 | : (char *)comments[NF_IP_TRACE_COMMENT_RETURN]; | ||
275 | } | ||
276 | return 1; | ||
277 | } else | ||
278 | (*rulenum)++; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static void trace_packet(struct sk_buff *skb, | ||
284 | unsigned int hook, | ||
285 | const struct net_device *in, | ||
286 | const struct net_device *out, | ||
287 | char *tablename, | ||
288 | struct xt_table_info *private, | ||
289 | struct ipt_entry *e) | ||
290 | { | ||
291 | void *table_base; | ||
292 | struct ipt_entry *root; | ||
293 | char *hookname, *chainname, *comment; | ||
294 | unsigned int rulenum = 0; | ||
295 | |||
296 | table_base = (void *)private->entries[smp_processor_id()]; | ||
297 | root = get_entry(table_base, private->hook_entry[hook]); | ||
298 | |||
299 | hookname = chainname = (char *)hooknames[hook]; | ||
300 | comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE]; | ||
301 | |||
302 | IPT_ENTRY_ITERATE(root, | ||
303 | private->size - private->hook_entry[hook], | ||
304 | get_chainname_rulenum, | ||
305 | e, hookname, &chainname, &comment, &rulenum); | ||
306 | |||
307 | nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, | ||
308 | "TRACE: %s:%s:%s:%u ", | ||
309 | tablename, chainname, comment, rulenum); | ||
310 | } | ||
311 | #endif | ||
312 | |||
207 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 313 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
208 | unsigned int | 314 | unsigned int |
209 | ipt_do_table(struct sk_buff **pskb, | 315 | ipt_do_table(struct sk_buff **pskb, |
@@ -261,6 +367,14 @@ ipt_do_table(struct sk_buff **pskb, | |||
261 | 367 | ||
262 | t = ipt_get_target(e); | 368 | t = ipt_get_target(e); |
263 | IP_NF_ASSERT(t->u.kernel.target); | 369 | IP_NF_ASSERT(t->u.kernel.target); |
370 | |||
371 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
372 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
373 | /* The packet is traced: log it */ | ||
374 | if (unlikely((*pskb)->nf_trace)) | ||
375 | trace_packet(*pskb, hook, in, out, | ||
376 | table->name, private, e); | ||
377 | #endif | ||
264 | /* Standard target? */ | 378 | /* Standard target? */ |
265 | if (!t->u.kernel.target->target) { | 379 | if (!t->u.kernel.target->target) { |
266 | int v; | 380 | int v; |
@@ -341,19 +455,6 @@ ipt_do_table(struct sk_buff **pskb, | |||
341 | #endif | 455 | #endif |
342 | } | 456 | } |
343 | 457 | ||
344 | /* All zeroes == unconditional rule. */ | ||
345 | static inline int | ||
346 | unconditional(const struct ipt_ip *ip) | ||
347 | { | ||
348 | unsigned int i; | ||
349 | |||
350 | for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++) | ||
351 | if (((__u32 *)ip)[i]) | ||
352 | return 0; | ||
353 | |||
354 | return 1; | ||
355 | } | ||
356 | |||
357 | /* Figures out from what hook each rule can be called: returns 0 if | 458 | /* Figures out from what hook each rule can be called: returns 0 if |
358 | there are loops. Puts hook bitmask in comefrom. */ | 459 | there are loops. Puts hook bitmask in comefrom. */ |
359 | static int | 460 | static int |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 31dafaf0b652..50d86e94d9ed 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -521,6 +521,10 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
521 | to->tc_index = from->tc_index; | 521 | to->tc_index = from->tc_index; |
522 | #endif | 522 | #endif |
523 | nf_copy(to, from); | 523 | nf_copy(to, from); |
524 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
525 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
526 | to->nf_trace = from->nf_trace; | ||
527 | #endif | ||
524 | skb_copy_secmark(to, from); | 528 | skb_copy_secmark(to, from); |
525 | } | 529 | } |
526 | 530 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 7fe4d29708cb..4f93b79163aa 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -241,6 +241,113 @@ get_entry(void *base, unsigned int offset) | |||
241 | return (struct ip6t_entry *)(base + offset); | 241 | return (struct ip6t_entry *)(base + offset); |
242 | } | 242 | } |
243 | 243 | ||
244 | /* All zeroes == unconditional rule. */ | ||
245 | static inline int | ||
246 | unconditional(const struct ip6t_ip6 *ipv6) | ||
247 | { | ||
248 | unsigned int i; | ||
249 | |||
250 | for (i = 0; i < sizeof(*ipv6); i++) | ||
251 | if (((char *)ipv6)[i]) | ||
252 | break; | ||
253 | |||
254 | return (i == sizeof(*ipv6)); | ||
255 | } | ||
256 | |||
257 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
258 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
259 | /* This cries for unification! */ | ||
260 | static const char *hooknames[] = { | ||
261 | [NF_IP6_PRE_ROUTING] = "PREROUTING", | ||
262 | [NF_IP6_LOCAL_IN] = "INPUT", | ||
263 | [NF_IP6_FORWARD] = "FORWARD", | ||
264 | [NF_IP6_LOCAL_OUT] = "OUTPUT", | ||
265 | [NF_IP6_POST_ROUTING] = "POSTROUTING", | ||
266 | }; | ||
267 | |||
268 | enum nf_ip_trace_comments { | ||
269 | NF_IP6_TRACE_COMMENT_RULE, | ||
270 | NF_IP6_TRACE_COMMENT_RETURN, | ||
271 | NF_IP6_TRACE_COMMENT_POLICY, | ||
272 | }; | ||
273 | |||
274 | static const char *comments[] = { | ||
275 | [NF_IP6_TRACE_COMMENT_RULE] = "rule", | ||
276 | [NF_IP6_TRACE_COMMENT_RETURN] = "return", | ||
277 | [NF_IP6_TRACE_COMMENT_POLICY] = "policy", | ||
278 | }; | ||
279 | |||
280 | static struct nf_loginfo trace_loginfo = { | ||
281 | .type = NF_LOG_TYPE_LOG, | ||
282 | .u = { | ||
283 | .log = { | ||
284 | .level = 4, | ||
285 | .logflags = NF_LOG_MASK, | ||
286 | }, | ||
287 | }, | ||
288 | }; | ||
289 | |||
290 | static inline int | ||
291 | get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | ||
292 | char *hookname, char **chainname, | ||
293 | char **comment, unsigned int *rulenum) | ||
294 | { | ||
295 | struct ip6t_standard_target *t = (void *)ip6t_get_target(s); | ||
296 | |||
297 | if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { | ||
298 | /* Head of user chain: ERROR target with chainname */ | ||
299 | *chainname = t->target.data; | ||
300 | (*rulenum) = 0; | ||
301 | } else if (s == e) { | ||
302 | (*rulenum)++; | ||
303 | |||
304 | if (s->target_offset == sizeof(struct ip6t_entry) | ||
305 | && strcmp(t->target.u.kernel.target->name, | ||
306 | IP6T_STANDARD_TARGET) == 0 | ||
307 | && t->verdict < 0 | ||
308 | && unconditional(&s->ipv6)) { | ||
309 | /* Tail of chains: STANDARD target (return/policy) */ | ||
310 | *comment = *chainname == hookname | ||
311 | ? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY] | ||
312 | : (char *)comments[NF_IP6_TRACE_COMMENT_RETURN]; | ||
313 | } | ||
314 | return 1; | ||
315 | } else | ||
316 | (*rulenum)++; | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static void trace_packet(struct sk_buff *skb, | ||
322 | unsigned int hook, | ||
323 | const struct net_device *in, | ||
324 | const struct net_device *out, | ||
325 | char *tablename, | ||
326 | struct xt_table_info *private, | ||
327 | struct ip6t_entry *e) | ||
328 | { | ||
329 | void *table_base; | ||
330 | struct ip6t_entry *root; | ||
331 | char *hookname, *chainname, *comment; | ||
332 | unsigned int rulenum = 0; | ||
333 | |||
334 | table_base = (void *)private->entries[smp_processor_id()]; | ||
335 | root = get_entry(table_base, private->hook_entry[hook]); | ||
336 | |||
337 | hookname = chainname = (char *)hooknames[hook]; | ||
338 | comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE]; | ||
339 | |||
340 | IP6T_ENTRY_ITERATE(root, | ||
341 | private->size - private->hook_entry[hook], | ||
342 | get_chainname_rulenum, | ||
343 | e, hookname, &chainname, &comment, &rulenum); | ||
344 | |||
345 | nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, | ||
346 | "TRACE: %s:%s:%s:%u ", | ||
347 | tablename, chainname, comment, rulenum); | ||
348 | } | ||
349 | #endif | ||
350 | |||
244 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ | 351 | /* Returns one of the generic firewall policies, like NF_ACCEPT. */ |
245 | unsigned int | 352 | unsigned int |
246 | ip6t_do_table(struct sk_buff **pskb, | 353 | ip6t_do_table(struct sk_buff **pskb, |
@@ -298,6 +405,14 @@ ip6t_do_table(struct sk_buff **pskb, | |||
298 | 405 | ||
299 | t = ip6t_get_target(e); | 406 | t = ip6t_get_target(e); |
300 | IP_NF_ASSERT(t->u.kernel.target); | 407 | IP_NF_ASSERT(t->u.kernel.target); |
408 | |||
409 | #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ | ||
410 | defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) | ||
411 | /* The packet is traced: log it */ | ||
412 | if (unlikely((*pskb)->nf_trace)) | ||
413 | trace_packet(*pskb, hook, in, out, | ||
414 | table->name, private, e); | ||
415 | #endif | ||
301 | /* Standard target? */ | 416 | /* Standard target? */ |
302 | if (!t->u.kernel.target->target) { | 417 | if (!t->u.kernel.target->target) { |
303 | int v; | 418 | int v; |
@@ -377,19 +492,6 @@ ip6t_do_table(struct sk_buff **pskb, | |||
377 | #endif | 492 | #endif |
378 | } | 493 | } |
379 | 494 | ||
380 | /* All zeroes == unconditional rule. */ | ||
381 | static inline int | ||
382 | unconditional(const struct ip6t_ip6 *ipv6) | ||
383 | { | ||
384 | unsigned int i; | ||
385 | |||
386 | for (i = 0; i < sizeof(*ipv6); i++) | ||
387 | if (((char *)ipv6)[i]) | ||
388 | break; | ||
389 | |||
390 | return (i == sizeof(*ipv6)); | ||
391 | } | ||
392 | |||
393 | /* Figures out from what hook each rule can be called: returns 0 if | 495 | /* Figures out from what hook each rule can be called: returns 0 if |
394 | there are loops. Puts hook bitmask in comefrom. */ | 496 | there are loops. Puts hook bitmask in comefrom. */ |
395 | static int | 497 | static int |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index aa567faa2a88..df5e8dab871d 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -343,6 +343,18 @@ config NETFILTER_XT_TARGET_NOTRACK | |||
343 | If you want to compile it as a module, say M here and read | 343 | If you want to compile it as a module, say M here and read |
344 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | 344 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. |
345 | 345 | ||
346 | config NETFILTER_XT_TARGET_TRACE | ||
347 | tristate '"TRACE" target support' | ||
348 | depends on NETFILTER_XTABLES | ||
349 | depends on IP_NF_RAW || IP6_NF_RAW | ||
350 | help | ||
351 | The TRACE target allows you to mark packets so that the kernel | ||
352 | will log every rule which match the packets as those traverse | ||
353 | the tables, chains, rules. | ||
354 | |||
355 | If you want to compile it as a module, say M here and read | ||
356 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
357 | |||
346 | config NETFILTER_XT_TARGET_SECMARK | 358 | config NETFILTER_XT_TARGET_SECMARK |
347 | tristate '"SECMARK" target support' | 359 | tristate '"SECMARK" target support' |
348 | depends on NETFILTER_XTABLES && NETWORK_SECMARK | 360 | depends on NETFILTER_XTABLES && NETWORK_SECMARK |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 3cf5b9cd6fe1..3b792687f001 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o | |||
44 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | 44 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o |
45 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | 45 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o |
46 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | 46 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o |
47 | obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o | ||
47 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | 48 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o |
48 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o | 49 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o |
49 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | 50 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o |
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c new file mode 100644 index 000000000000..b82fc4680344 --- /dev/null +++ b/net/netfilter/xt_TRACE.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* This is a module which is used to mark packets for tracing. | ||
2 | */ | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/skbuff.h> | ||
5 | |||
6 | #include <linux/netfilter/x_tables.h> | ||
7 | |||
8 | MODULE_LICENSE("GPL"); | ||
9 | MODULE_ALIAS("ipt_TRACE"); | ||
10 | MODULE_ALIAS("ip6t_TRACE"); | ||
11 | |||
12 | static unsigned int | ||
13 | target(struct sk_buff **pskb, | ||
14 | const struct net_device *in, | ||
15 | const struct net_device *out, | ||
16 | unsigned int hooknum, | ||
17 | const struct xt_target *target, | ||
18 | const void *targinfo) | ||
19 | { | ||
20 | (*pskb)->nf_trace = 1; | ||
21 | return XT_CONTINUE; | ||
22 | } | ||
23 | |||
24 | static struct xt_target xt_trace_target[] = { | ||
25 | { | ||
26 | .name = "TRACE", | ||
27 | .family = AF_INET, | ||
28 | .target = target, | ||
29 | .table = "raw", | ||
30 | .me = THIS_MODULE, | ||
31 | }, | ||
32 | { | ||
33 | .name = "TRACE", | ||
34 | .family = AF_INET6, | ||
35 | .target = target, | ||
36 | .table = "raw", | ||
37 | .me = THIS_MODULE, | ||
38 | }, | ||
39 | }; | ||
40 | |||
41 | static int __init xt_trace_init(void) | ||
42 | { | ||
43 | return xt_register_targets(xt_trace_target, | ||
44 | ARRAY_SIZE(xt_trace_target)); | ||
45 | } | ||
46 | |||
47 | static void __exit xt_trace_fini(void) | ||
48 | { | ||
49 | xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target)); | ||
50 | } | ||
51 | |||
52 | module_init(xt_trace_init); | ||
53 | module_exit(xt_trace_fini); | ||