Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7eb9282c authored by Patrick McHardy's avatar Patrick McHardy
Browse files

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: default avatarPatrick McHardy <kaber@trash.net>
parent cf377eb4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -7,7 +7,8 @@
#define IPT_LOG_IPOPT		0x04	/* Log IP options */
#define IPT_LOG_UID		0x08	/* Log UID owning local socket */
#define IPT_LOG_NFLOG		0x10	/* Unsupported, don't reuse */
#define IPT_LOG_MASK		0x1f
#define IPT_LOG_MACDECODE	0x20	/* Decode MAC header */
#define IPT_LOG_MASK		0x2f

struct ipt_log_info {
	unsigned char level;
+2 −1
Original line number Diff line number Diff line
@@ -7,7 +7,8 @@
#define IP6T_LOG_IPOPT		0x04	/* Log IP options */
#define IP6T_LOG_UID		0x08	/* Log UID owning local socket */
#define IP6T_LOG_NFLOG		0x10	/* Unsupported, don't use */
#define IP6T_LOG_MASK		0x1f
#define IP6T_LOG_MACDECODE	0x20	/* Decode MAC header */
#define IP6T_LOG_MASK		0x2f

struct ip6t_log_info {
	unsigned char level;
+40 −14
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ip.h>
#include <net/icmp.h>
#include <net/udp.h>
@@ -363,6 +364,42 @@ static void dump_packet(const struct nf_loginfo *info,
	/* maxlen = 230+   91  + 230 + 252 = 803 */
}

static void dump_mac_header(const struct nf_loginfo *info,
			    const struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	unsigned int logflags = 0;

	if (info->type == NF_LOG_TYPE_LOG)
		logflags = info->u.log.logflags;

	if (!(logflags & IPT_LOG_MACDECODE))
		goto fallback;

	switch (dev->type) {
	case ARPHRD_ETHER:
		printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
		       ntohs(eth_hdr(skb)->h_proto));
		return;
	default:
		break;
	}

fallback:
	printk("MAC=");
	if (dev->hard_header_len &&
	    skb->mac_header != skb->network_header) {
		const unsigned char *p = skb_mac_header(skb);
		unsigned int i;

		printk("%02x", *p++);
		for (i = 1; i < dev->hard_header_len; i++, p++)
			printk(":%02x", *p);
	}
	printk(" ");
}

static struct nf_loginfo default_loginfo = {
	.type	= NF_LOG_TYPE_LOG,
	.u = {
@@ -404,20 +441,9 @@ ipt_log_packet(u_int8_t pf,
	}
#endif

	if (in && !out) {
		/* MAC logging for input chain only. */
		printk("MAC=");
		if (skb->dev && skb->dev->hard_header_len &&
		    skb->mac_header != skb->network_header) {
			int i;
			const unsigned char *p = skb_mac_header(skb);

			printk("%02x", *p++);
			for (i = 1; i < skb->dev->hard_header_len; i++, p++)
				printk(":%02x", *p);
		}
		printk(" ");
	}
	/* MAC logging for input path only. */
	if (in && !out)
		dump_mac_header(loginfo, skb);

	dump_packet(loginfo, skb, 0);
	printk("\n");
+53 −28
Original line number Diff line number Diff line
@@ -373,6 +373,56 @@ static void dump_packet(const struct nf_loginfo *info,
		printk("MARK=0x%x ", skb->mark);
}

static void dump_mac_header(const struct nf_loginfo *info,
			    const struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	unsigned int logflags = 0;

	if (info->type == NF_LOG_TYPE_LOG)
		logflags = info->u.log.logflags;

	if (!(logflags & IP6T_LOG_MACDECODE))
		goto fallback;

	switch (dev->type) {
	case ARPHRD_ETHER:
		printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
		       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
		       ntohs(eth_hdr(skb)->h_proto));
		return;
	default:
		break;
	}

fallback:
	printk("MAC=");
	if (dev->hard_header_len &&
	    skb->mac_header != skb->network_header) {
		const unsigned char *p = skb_mac_header(skb);
		unsigned int len = dev->hard_header_len;
		unsigned int i;

		if (dev->type == ARPHRD_SIT &&
		    (p -= ETH_HLEN) < skb->head)
			p = NULL;

		if (p != NULL) {
			printk("%02x", *p++);
			for (i = 1; i < len; i++)
				printk(":%02x", p[i]);
		}
		printk(" ");

		if (dev->type == ARPHRD_SIT) {
			const struct iphdr *iph =
				(struct iphdr *)skb_mac_header(skb);
			printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr);
		}
	} else
		printk(" ");
}

static struct nf_loginfo default_loginfo = {
	.type	= NF_LOG_TYPE_LOG,
	.u = {
@@ -400,35 +450,10 @@ ip6t_log_packet(u_int8_t pf,
		prefix,
		in ? in->name : "",
		out ? out->name : "");
	if (in && !out) {
		unsigned int len;
		/* MAC logging for input chain only. */
		printk("MAC=");
		if (skb->dev && (len = skb->dev->hard_header_len) &&
		    skb->mac_header != skb->network_header) {
			const unsigned char *p = skb_mac_header(skb);
			int i;

			if (skb->dev->type == ARPHRD_SIT &&
			    (p -= ETH_HLEN) < skb->head)
				p = NULL;

			if (p != NULL) {
				printk("%02x", *p++);
				for (i = 1; i < len; i++)
					printk(":%02x", p[i]);
			}
			printk(" ");

			if (skb->dev->type == ARPHRD_SIT) {
				const struct iphdr *iph =
					(struct iphdr *)skb_mac_header(skb);
				printk("TUNNEL=%pI4->%pI4 ",
				       &iph->saddr, &iph->daddr);
			}
		} else
			printk(" ");
	}
	/* MAC logging for input path only. */
	if (in && !out)
		dump_mac_header(loginfo, skb);

	dump_packet(loginfo, skb, skb_network_offset(skb), 1);
	printk("\n");