aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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/ipv4
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/ipv4')
-rw-r--r--net/ipv4/ip_output.c4
-rw-r--r--net/ipv4/netfilter/ip_tables.c127
2 files changed, 118 insertions, 13 deletions
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. */
208static inline int
209unconditional(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)
222static 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
230enum nf_ip_trace_comments {
231 NF_IP_TRACE_COMMENT_RULE,
232 NF_IP_TRACE_COMMENT_RETURN,
233 NF_IP_TRACE_COMMENT_POLICY,
234};
235
236static 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
242static 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
252static inline int
253get_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
283static 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. */
208unsigned int 314unsigned int
209ipt_do_table(struct sk_buff **pskb, 315ipt_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. */
345static inline int
346unconditional(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. */
359static int 460static int