ashishmax31
ashishmax31

Reputation: 171

How to extract out the payload/data of an ethernet II frame?

I'm trying to implement the UDP protocol in userspace using golang. I've reached upto the point where I'm able to get raw ethernet II packets.

My code looks something like this:


type EthernetFrame struct {
    SrcAddress  []byte
    DestAddress []byte
    EtherType   []byte
    Payload     []byte
    CRC         []byte
}

func ReadEthernetPackets(ethernetSocket int) EthernetFrame {
    dataBytes := make([]byte, 1518)
    syscall.Read(ethernetSocket, dataBytes)
    return EthernetFrame {
        SrcAddress:  dataBytes[0:6],
        DestAddress: dataBytes[6:12],
        EtherType:   dataBytes[12:14],
        Payload:     dataBytes[14:1515],
        CRC:         dataBytes[1515:1518],
    }
}

I've seen here(https://commons.wikimedia.org/wiki/File:Ethernet_Type_II_Frame_format.svg) that an ethernet II frame can be anywhere between 64 to 1518 bytes long, but since there is no field in the header which says anything about the payload length, I've just assumed that all the frames would be of length 1518, in which case theoretically my code should work. But since the frames are mostly arriving with different lengths my assumption fails. How do I parse the bytes received and get only the payload? What should I keep the dataBytes length as?

Upvotes: 0

Views: 2198

Answers (1)

MK3
MK3

Reputation: 56

Each internet packet exists from the following Layers:

  1. L2 - Data Link (e.g. Mac addresses, ethertype, VLANs,...)
  2. L3 - Network (e.g IPv4 / IPv6 / ...)
  3. L4 - Transport (e.g. UDP / TCP / ...)
  4. L5 - Payload Some divide L5 to three different Layers (L5, L6 and L7 which is Session, Presentation and Application respectively). More details can be found in wiki OSI Moudel!

For L2, since you expect IPv4 (not IPv6, right?):

EthernetFrame {
  Dest Mac Addr,  # Len is 6 B
  Src Mac Addr,   # Len is 6 B
  EtherType,      # Len is 2 B - This value will be 0x0800
}

If this is IPv4, then EtherType==0x0800 If EtherType==0x8100, then this is VLAN, then after this expect to read another 2 B for VLAN data PCP / DEI / VID - more about VLAN! So your packet will look like:

EthernetFrame {
  Dest Mac Addr,  # Len is 6 B - Some Dest Mac
  Src Mac Addr,   # Len is 6 B - Some Src  Mac
  EtherType,      # Len is 2 B - 0x8100 - VLAN
  VlanData,       # Len is 2 B - VLAN Data - DEI / PCP / VID
  EtherType       # Len is 2 B - Again, need to parse...
}

Now if second EtherType==0x0800 then next Layer (L3 - Network) is IPv4. More about ethertype

L3 - Network Layer - from wiki https://en.wikipedia.org/wiki/IPv4? Since this IPv4, then L3 length is fxed to 5 B (40 bit), unless IHL > 5.

Version               - 4 b
IHL                   - 4 b
DSCP                  - 6 b
ECN                   - 2 b
Total Len             - 16 b - Include header + data
Identification        - 16 b
Flags                 - 3 b
Fragment offset       - 13 b
TTL (Time to Live)    - 8 b
Protocol              - 8 b (for next Layer parse, in your case will be UDP with 0x11)
Header Checksum       - 16 b
Src IP Addr           - 32 b
Dest IP Addr          - 32 b

Above packet describe IPv4 packet in case IHL<=4. Otherwise, add options tail to the packet in respect to IHL len.

At this stage you know the total len, and that Layer-4 is UDP. Check wiki https://en.wikipedia.org/wiki/User_Datagram_Protocol? L4 looks like - For UDP (TCP is different, other protocols are different..):

Source prot   - 2 B
Dest port     - 2 B
Length        - 2 B
Checksum      - 2 B

To summarize - need to:

  1. Start from L2, understand what is the ethertype, and based on it to parse L3
  2. On L3, need to learn all total len, and L4 protocol type (e.g. UDP or TCP).
  3. On L4, need to learn len (you also know it from L3 !!!).
  4. Parse the payload !!

If no VLANs, or any other ethertype other than IPv4, and IHL<=4 Then payload starts from 14 + 20 + 8

  • 14 B for L2
  • 20 B for L3
  • 8 B for L4

Good Luck!

Upvotes: 0

Related Questions