diff options
author | Patrick McHardy <kaber@trash.net> | 2010-06-28 08:16:08 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-06-28 08:16:08 -0400 |
commit | 7eb9282cd0efac08b8377cbd5037ba297c77e3f7 (patch) | |
tree | 7dcb6e149c96e27da69a75ff828de9681c6636f8 | |
parent | cf377eb4aeded926375d4d0fe0b66ba95f0521e1 (diff) |
netfilter: ipt_LOG/ip6t_LOG: add option to print decoded MAC header
The LOG targets print the entire MAC header as one long string, which is not
readable very well:
IN=eth0 OUT= MAC=00:15:f2:24:91:f8:00:1b:24:dc:61:e6:08:00 ...
Add an option to decode known header formats (currently just ARPHRD_ETHER devices)
in their individual fields:
IN=eth0 OUT= MACSRC=00:1b:24:dc:61:e6 MACDST=00:15:f2:24:91:f8 MACPROTO=0800 ...
IN=eth0 OUT= MACSRC=00:1b:24:dc:61:e6 MACDST=00:15:f2:24:91:f8 MACPROTO=86dd ...
The option needs to be explicitly enabled by userspace to avoid breaking
existing parsers.
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/linux/netfilter_ipv4/ipt_LOG.h | 3 | ||||
-rw-r--r-- | include/linux/netfilter_ipv6/ip6t_LOG.h | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_LOG.c | 54 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 81 |
4 files changed, 97 insertions, 44 deletions
diff --git a/include/linux/netfilter_ipv4/ipt_LOG.h b/include/linux/netfilter_ipv4/ipt_LOG.h index 90fa6525ef9c..dcdbadf9fd4a 100644 --- a/include/linux/netfilter_ipv4/ipt_LOG.h +++ b/include/linux/netfilter_ipv4/ipt_LOG.h | |||
@@ -7,7 +7,8 @@ | |||
7 | #define IPT_LOG_IPOPT 0x04 /* Log IP options */ | 7 | #define IPT_LOG_IPOPT 0x04 /* Log IP options */ |
8 | #define IPT_LOG_UID 0x08 /* Log UID owning local socket */ | 8 | #define IPT_LOG_UID 0x08 /* Log UID owning local socket */ |
9 | #define IPT_LOG_NFLOG 0x10 /* Unsupported, don't reuse */ | 9 | #define IPT_LOG_NFLOG 0x10 /* Unsupported, don't reuse */ |
10 | #define IPT_LOG_MASK 0x1f | 10 | #define IPT_LOG_MACDECODE 0x20 /* Decode MAC header */ |
11 | #define IPT_LOG_MASK 0x2f | ||
11 | 12 | ||
12 | struct ipt_log_info { | 13 | struct ipt_log_info { |
13 | unsigned char level; | 14 | unsigned char level; |
diff --git a/include/linux/netfilter_ipv6/ip6t_LOG.h b/include/linux/netfilter_ipv6/ip6t_LOG.h index 0d0119b0458c..9dd5579e02ec 100644 --- a/include/linux/netfilter_ipv6/ip6t_LOG.h +++ b/include/linux/netfilter_ipv6/ip6t_LOG.h | |||
@@ -7,7 +7,8 @@ | |||
7 | #define IP6T_LOG_IPOPT 0x04 /* Log IP options */ | 7 | #define IP6T_LOG_IPOPT 0x04 /* Log IP options */ |
8 | #define IP6T_LOG_UID 0x08 /* Log UID owning local socket */ | 8 | #define IP6T_LOG_UID 0x08 /* Log UID owning local socket */ |
9 | #define IP6T_LOG_NFLOG 0x10 /* Unsupported, don't use */ | 9 | #define IP6T_LOG_NFLOG 0x10 /* Unsupported, don't use */ |
10 | #define IP6T_LOG_MASK 0x1f | 10 | #define IP6T_LOG_MACDECODE 0x20 /* Decode MAC header */ |
11 | #define IP6T_LOG_MASK 0x2f | ||
11 | 12 | ||
12 | struct ip6t_log_info { | 13 | struct ip6t_log_info { |
13 | unsigned char level; | 14 | unsigned char level; |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 0a452a54adbe..915fc17d7ce2 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
16 | #include <linux/if_arp.h> | ||
16 | #include <linux/ip.h> | 17 | #include <linux/ip.h> |
17 | #include <net/icmp.h> | 18 | #include <net/icmp.h> |
18 | #include <net/udp.h> | 19 | #include <net/udp.h> |
@@ -363,6 +364,42 @@ static void dump_packet(const struct nf_loginfo *info, | |||
363 | /* maxlen = 230+ 91 + 230 + 252 = 803 */ | 364 | /* maxlen = 230+ 91 + 230 + 252 = 803 */ |
364 | } | 365 | } |
365 | 366 | ||
367 | static void dump_mac_header(const struct nf_loginfo *info, | ||
368 | const struct sk_buff *skb) | ||
369 | { | ||
370 | struct net_device *dev = skb->dev; | ||
371 | unsigned int logflags = 0; | ||
372 | |||
373 | if (info->type == NF_LOG_TYPE_LOG) | ||
374 | logflags = info->u.log.logflags; | ||
375 | |||
376 | if (!(logflags & IPT_LOG_MACDECODE)) | ||
377 | goto fallback; | ||
378 | |||
379 | switch (dev->type) { | ||
380 | case ARPHRD_ETHER: | ||
381 | printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
382 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
383 | ntohs(eth_hdr(skb)->h_proto)); | ||
384 | return; | ||
385 | default: | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | fallback: | ||
390 | printk("MAC="); | ||
391 | if (dev->hard_header_len && | ||
392 | skb->mac_header != skb->network_header) { | ||
393 | const unsigned char *p = skb_mac_header(skb); | ||
394 | unsigned int i; | ||
395 | |||
396 | printk("%02x", *p++); | ||
397 | for (i = 1; i < dev->hard_header_len; i++, p++) | ||
398 | printk(":%02x", *p); | ||
399 | } | ||
400 | printk(" "); | ||
401 | } | ||
402 | |||
366 | static struct nf_loginfo default_loginfo = { | 403 | static struct nf_loginfo default_loginfo = { |
367 | .type = NF_LOG_TYPE_LOG, | 404 | .type = NF_LOG_TYPE_LOG, |
368 | .u = { | 405 | .u = { |
@@ -404,20 +441,9 @@ ipt_log_packet(u_int8_t pf, | |||
404 | } | 441 | } |
405 | #endif | 442 | #endif |
406 | 443 | ||
407 | if (in && !out) { | 444 | /* MAC logging for input path only. */ |
408 | /* MAC logging for input chain only. */ | 445 | if (in && !out) |
409 | printk("MAC="); | 446 | dump_mac_header(loginfo, skb); |
410 | if (skb->dev && skb->dev->hard_header_len && | ||
411 | skb->mac_header != skb->network_header) { | ||
412 | int i; | ||
413 | const unsigned char *p = skb_mac_header(skb); | ||
414 | |||
415 | printk("%02x", *p++); | ||
416 | for (i = 1; i < skb->dev->hard_header_len; i++, p++) | ||
417 | printk(":%02x", *p); | ||
418 | } | ||
419 | printk(" "); | ||
420 | } | ||
421 | 447 | ||
422 | dump_packet(loginfo, skb, 0); | 448 | dump_packet(loginfo, skb, 0); |
423 | printk("\n"); | 449 | printk("\n"); |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 4c7ddac7c62b..0a07ae7b933f 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -373,6 +373,56 @@ static void dump_packet(const struct nf_loginfo *info, | |||
373 | printk("MARK=0x%x ", skb->mark); | 373 | printk("MARK=0x%x ", skb->mark); |
374 | } | 374 | } |
375 | 375 | ||
376 | static void dump_mac_header(const struct nf_loginfo *info, | ||
377 | const struct sk_buff *skb) | ||
378 | { | ||
379 | struct net_device *dev = skb->dev; | ||
380 | unsigned int logflags = 0; | ||
381 | |||
382 | if (info->type == NF_LOG_TYPE_LOG) | ||
383 | logflags = info->u.log.logflags; | ||
384 | |||
385 | if (!(logflags & IP6T_LOG_MACDECODE)) | ||
386 | goto fallback; | ||
387 | |||
388 | switch (dev->type) { | ||
389 | case ARPHRD_ETHER: | ||
390 | printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
392 | ntohs(eth_hdr(skb)->h_proto)); | ||
393 | return; | ||
394 | default: | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | fallback: | ||
399 | printk("MAC="); | ||
400 | if (dev->hard_header_len && | ||
401 | skb->mac_header != skb->network_header) { | ||
402 | const unsigned char *p = skb_mac_header(skb); | ||
403 | unsigned int len = dev->hard_header_len; | ||
404 | unsigned int i; | ||
405 | |||
406 | if (dev->type == ARPHRD_SIT && | ||
407 | (p -= ETH_HLEN) < skb->head) | ||
408 | p = NULL; | ||
409 | |||
410 | if (p != NULL) { | ||
411 | printk("%02x", *p++); | ||
412 | for (i = 1; i < len; i++) | ||
413 | printk(":%02x", p[i]); | ||
414 | } | ||
415 | printk(" "); | ||
416 | |||
417 | if (dev->type == ARPHRD_SIT) { | ||
418 | const struct iphdr *iph = | ||
419 | (struct iphdr *)skb_mac_header(skb); | ||
420 | printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); | ||
421 | } | ||
422 | } else | ||
423 | printk(" "); | ||
424 | } | ||
425 | |||
376 | static struct nf_loginfo default_loginfo = { | 426 | static struct nf_loginfo default_loginfo = { |
377 | .type = NF_LOG_TYPE_LOG, | 427 | .type = NF_LOG_TYPE_LOG, |
378 | .u = { | 428 | .u = { |
@@ -400,35 +450,10 @@ ip6t_log_packet(u_int8_t pf, | |||
400 | prefix, | 450 | prefix, |
401 | in ? in->name : "", | 451 | in ? in->name : "", |
402 | out ? out->name : ""); | 452 | out ? out->name : ""); |
403 | if (in && !out) { | ||
404 | unsigned int len; | ||
405 | /* MAC logging for input chain only. */ | ||
406 | printk("MAC="); | ||
407 | if (skb->dev && (len = skb->dev->hard_header_len) && | ||
408 | skb->mac_header != skb->network_header) { | ||
409 | const unsigned char *p = skb_mac_header(skb); | ||
410 | int i; | ||
411 | |||
412 | if (skb->dev->type == ARPHRD_SIT && | ||
413 | (p -= ETH_HLEN) < skb->head) | ||
414 | p = NULL; | ||
415 | |||
416 | if (p != NULL) { | ||
417 | printk("%02x", *p++); | ||
418 | for (i = 1; i < len; i++) | ||
419 | printk(":%02x", p[i]); | ||
420 | } | ||
421 | printk(" "); | ||
422 | 453 | ||
423 | if (skb->dev->type == ARPHRD_SIT) { | 454 | /* MAC logging for input path only. */ |
424 | const struct iphdr *iph = | 455 | if (in && !out) |
425 | (struct iphdr *)skb_mac_header(skb); | 456 | dump_mac_header(loginfo, skb); |
426 | printk("TUNNEL=%pI4->%pI4 ", | ||
427 | &iph->saddr, &iph->daddr); | ||
428 | } | ||
429 | } else | ||
430 | printk(" "); | ||
431 | } | ||
432 | 457 | ||
433 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); | 458 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); |
434 | printk("\n"); | 459 | printk("\n"); |