2

Is there any way to receive data of a specific VLAN tagged frame? Currently I am receiving all VLAN tagged frames by giving htons(0x22f0) as input to socket() function like:

m_iSocketDesc = socket(AF_PACKET, SOCK_RAW, htons(0x22f0));
numBytes = recvfrom(m_iSocketDesc, message_data, 1522, 0, NULL, 0)
Avb Avb
  • 545
  • 2
  • 13
  • 25
  • I am trying to do the same, but haven't found a solution yet. I don't understand where you got the constant `0x22f0` from. I would have expected the proper value to use to be `ETH_P_8021Q` (which is 0x8100). I also couldn't get your code fragment to work. When I try your code, the `recvfrom` call blocks forever without receiving any packets. However using `tcpdump`, I can see that tagged packets are received by my network interface. – kasperd Jun 27 '14 at 22:44
  • http://stackoverflow.com/questions/10947286/how-to-initialize-raw-socket-for-vlan-sniffing might have some useful information. – kasperd Jun 27 '14 at 23:39
  • Another relevant link: http://seclists.org/tcpdump/2008/q3/35 – kasperd Jun 28 '14 at 08:03
  • This looks like the struct the kernel uses to track everything you could possibly configure on the socket: http://lxr.free-electrons.com/source/net/packet/internal.h#L92 I see a linked list of MAC addresses, but no VLAN tag information. – kasperd Jun 28 '14 at 08:28
  • One would have guessed `SO_ATTACH_FILTER` would be applicable. But it appears the filtering program only has access to a version of the frame where the VLAN tag has already been stripped. So it looks like the only way out may be to use the auxilary data as described in the seclists.org link and let user mode code just ignore packets for other VLANs. – kasperd Jun 28 '14 at 08:31
  • There is of course also the possibility to create a virtual network interface using a command like `vconfig add eth0 1234` and then bind your socket to `eth0.1234`. But this has the side effect of making the VLAN accessible to the rest of the network stack inside the kernel. I assume you want one user mode program to receive packets destined for that VLAN while letting everything else on the system keep behaving as if you weren't using that VLAN at all. – kasperd Jun 28 '14 at 08:39
  • Filtering by VLAN number in user mode would happen after the packet has been pulled out of the queue. Ideally you would want non-matching packets to be dropped before being put in the queue. The core part of that is `sk_receive_skb` http://lxr.free-electrons.com/source/net/core/sock.c#L485. As can be seen in this code, the only check is the `sk_filter`, which as best I can tell cannot be used for this task. So the best place to look for an answer is in the code, which calls `sk_receive_skb`. – kasperd Jun 29 '14 at 08:44

1 Answers1

2

I had a similar requirement. To receive packets with a specific VLAN, I created a VLAN interface and bound my raw socket to it. Now I can just send 802.3 frames, the kernel inserts/extracts VLAN tag.

  1. Create a VLAN interface, you should have root permission

    ip link add link <phyInterface> name <phyInterface.VLANID> type vlan id VLANID
    Eg: ip link add link eth0 name eth0.100 type vlan 100
    
  2. Use normal bind function in your application to bind to the VLAN interface. In the above example eth0.100.

You can refer to the below two links for sample code (I am NOT the owner of the code)

Sending: https://gist.github.com/austinmarton/1922600

Receiving: https://gist.github.com/austinmarton/2862515#file-recvraweth-c

The only change needed is that instead of binding to physical interface, bind to the virtual VLAN interface. Note that the Ethernet frames received are un-tagged frames. Any frames sent on this interface will automatically tagged with the VLANID.

Neo
  • 141
  • 5
  • 16