On 2018/12/17 at 21:43

When playing with Linux netfilter, I was wondering why I can treat all packets as 802.3 packets and use eth_hdr to get L2 information even though the packet is a WLAN(802.11) packet. The 802.11 header is total differently from 802.3 header.

struct ethhdr {
    unsigned char   h_dest[ETH_ALEN];   /* destination eth addr */
    unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
    __be16      h_proto;        /* packet type ID field */
} __attribute__((packed));

struct ieee80211_hdr {
    __le16 frame_control;
    __le16 duration_id;
    u8 addr1[ETH_ALEN];
    u8 addr2[ETH_ALEN];
    u8 addr3[ETH_ALEN];
    __le16 seq_ctrl;
    u8 addr4[ETH_ALEN];
} __packed __aligned(2);

After some googling and digging into the source code. I found Linux kernel converts the 802.11 packet into a 802.3 packet by using ieee80211_data_to_8023. The reasons is explained in this article Why do i see Ethernet II protocol in wireshark in wireless connection?.

802.11 was designed to be "wireless Ethernet", and 802.11 interfaces have traditionally presented themselves to the OS as Ethernet interfaces so the OS only sees the packets after they've been translated back into familiar Ethernet II or 802.3 frames. This was necessary to make 802.11 work without requiring OSes to add a lot of code to understand all the new complexity that came with 802.11.