Reputation: 171
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
Reputation: 56
Each internet packet exists from the following Layers:
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:
If no VLANs, or any other ethertype other than IPv4, and IHL<=4
Then payload starts from 14 + 20 + 8
Good Luck!
Upvotes: 0