aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2007-07-08 01:21:23 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:17:14 -0400
commitba9dda3ab5a865542e69dfe01edb2436857c9420 (patch)
tree93f92442a8ad134d78b4d7cd8dc74e089baef3d7 /net/ipv6
parent1b50b8a371e90a5e110f466e4ac02cf6b5f681de (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>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_output.c4
-rw-r--r--net/ipv6/netfilter/ip6_tables.c128
2 files changed, 119 insertions, 13 deletions
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. */
245static inline int
246unconditional(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! */
260static 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
268enum nf_ip_trace_comments {
269 NF_IP6_TRACE_COMMENT_RULE,
270 NF_IP6_TRACE_COMMENT_RETURN,
271 NF_IP6_TRACE_COMMENT_POLICY,
272};
273
274static 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
280static 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
290static inline int
291get_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
321static 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. */
245unsigned int 352unsigned int
246ip6t_do_table(struct sk_buff **pskb, 353ip6t_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. */
381static inline int
382unconditional(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. */
395static int 497static int