我正在尝试使用golang在用户空间中实现UDP协议。我已经达到可以获取原始以太网II数据包的地步。
我的代码如下所示:
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],
}
}
我在这里(https://commons.wikimedia.org/wiki/File:Ethernet_Type_II_Frame_format.svg)看到,以太网II帧的长度可以在64到1518字节之间,但是由于标头中没有任何字段说明有效负载长度,因此我只是假设所有帧都可以长度为1518,理论上我的代码应该可以正常工作。但是由于帧大多以不同的长度到达,所以我的假设失败了。
如何解析收到的字节并仅获取有效载荷?我应该将
dataBytes
的长度保持为什么? 最佳答案
每个Internet数据包都来自以下几层:
有些将L5分为三个不同的层(L5,L6和L7,分别是 session ,表示和应用程序)。
可以在Wiki OSI Moudel中找到更多详细信息!
对于L2,由于您期望使用IPv4(不是IPv6,对吗?):
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
}
如果这是IPv4,则为
EtherType==0x0800
如果是EtherType==0x8100
,那么这是VLAN,在此之后,期望再读取2 B来获取VLAN数据PCP / DEI / VID-more about VLAN!因此,您的数据包将如下所示:
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...
}
现在,如果第二个
EtherType==0x0800
,则下一层(L3-网络)为IPv4。More about ethertype
L3-网络层-来自Wiki https://en.wikipedia.org/wiki/IPv4?
从此IPv4开始,除非IHL> 5,否则L3的长度固定为5 B(40位)。
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
上面的数据包描述了
IHL<=4
情况下的IPv4数据包。否则,请向数据包添加有关IHL len的选项tail。在此阶段,您知道了总长度,并且第4层是UDP。
检查Wiki https://en.wikipedia.org/wiki/User_Datagram_Protocol吗?
L4看起来像-对于UDP(TCP不同,其他协议也不同..):
Source prot - 2 B
Dest port - 2 B
Length - 2 B
Checksum - 2 B
总结-需要:
如果没有VLAN或IPv4以外的任何其他以太类型,并且IHL 然后有效载荷从
14 + 20 + 8
开始L2的
祝好运!