我正在尝试使用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数据包都来自以下几层:

  • L2-数据链接(例如Mac地址,ethertype,VLAN等)
  • L3-网络(例如IPv4 / IPv6 / ...)
  • L4-传输(例如UDP / TCP / ...)
  • L5-有效负载
    有些将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
    

    总结-需要:
  • 从L2开始,了解什么是醚类型,并基于它来解析L3
  • 在L3上,需要了解所有总len和L4协议类型(例如UDP或TCP)。
  • 在L4上,需要学习len(您也从L3知道它!!!)。
  • 解析有效载荷!

  • 如果没有VLAN或IPv4以外的任何其他以太类型,并且IHL 然后有效载荷从14 + 20 + 8开始

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

  • 祝好运!

    10-01 08:21
    查看更多