[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <e06dbb47-2d1c-03ca-4cd7-cc958b6a939e@gmail.com>
Date: Wed, 14 Jun 2017 14:47:56 +0200
From: Jan Grashöfer <jan.grashoefer@...il.com>
To: netdev@...r.kernel.org
Cc: aeppert@...il.com
Subject: Receiving raw packets (incl. VLAN tags) on raw sockets
Hello,
trying to ingest packets to a network monitoring tool using AF_Packet, I
noticed that VLAN tags are stripped off even if VLAN offloading is
disabled. As described in [1] the tags are stripped that early in the
receive path that raw sockets do not receive the packets as seen on the
wire. However, the man pages [2] state:
> SOCK_RAW packets are passed to and from the device driver without any
> changes in the packet data.
So at least the docs are wrong here. While the VLAN information is
present in the tpacket_hdr, the packets themselves are manipulated by
the kernel. In my case, for example, I need to pass on each packet (in
form of a packet) and thus would have to reinsert the tag manually,
which is definitely undesirable.
As I am dealing with a monitoring application, the following patch that
disables untagging VLANs in promisc mode fixes the issue for me:
diff --git a/net/core/dev.c b/net/core/dev.c
index 54f8c16..ec5b1c5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4104,8 +4104,9 @@ static int __netif_receive_skb_core(struct sk_buff
*skb, bool pfmemalloc)
__this_cpu_inc(softnet_data.processed);
- if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
- skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
+ if ((skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
+ skb->protocol == cpu_to_be16(ETH_P_8021AD)) &&
+ skb->dev->promiscuity < 1) {
skb = skb_vlan_untag(skb);
if (unlikely(!skb))
goto out;
--
I tested the patch with tcpdump and suricata. As they are designed to
handle VLAN tags anyway, both work as expected. Still there are two
caveats regarding this patch: First, there might be software out there
that does not work as expected anymore. Second, the semantics of raw
sockets are even more cluttered than before. I could imagine the
following solutions:
1) Disable VLAN untagging done by the kernel or move it up the receive
path - probably least practicable.
2) Parse VLAN info into the tpacket_hdr but keep the packet as is (at
least in promisc mode) - still, seems clumsy and error-prone to me.
3) Introduce a new socket option to disable VLAN untagging for raw
sockets - maybe overkill.
I would be happy to receive some feedback!
Best regards,
Jan
[1] https://www.spinics.net/lists/netdev/msg244668.html
[2] http://man7.org/linux/man-pages/man7/ip.7.html
Powered by blists - more mailing lists