以太网帧结构解析

由于需要做一个分析网卡接收的数据包的Project,需要了解以太网帧结构并解析,发现有很多内容从一般网络方面的知识是不够的,因此查阅了相关资料再此做一个记录以备忘。

以太网是目前最流行的有线的局域网技术,特别是上世纪九十年后发展的交换式局域网增加了有效数据速率,同时集线器和交换机等普通且便宜的硬件更助长了其普及程度。以太网的数据帧格式如下图所示:


数据字段:在交换式以太网中,一台主机向局域网中的另一台主机发送一个IP数据报,这个数据报封装在以太网帧结构中作为其有效载荷,以太网的最大传输单元(MTU)是1500字节,也就是限制了一个IP数据报最大为1500字节,如果超过1500字节,就要启用IP协议的分片策略进行传输。同时,数据字段最小长度为46字节,如果不够必须要填充到46字节。如IP数据报和填充部分会被网络层利用IP数据报首部的长度字段去除相关填充。

MAC地址字段:6个字节共128位的MAC物理地址,用于标识局域网中的每个主机,目的MAC可以是某个机器的物理地址,也可以是FF-FF-FF-FF-FF-FF广播MAC地址。

前同步码:前7字节都是10101010,最后一个字节是10101011。用于将发送方与接收方的时钟进行同步,主要是有不同的以太网类型,同时发送接收速率也不会完全精确的帧速率传输,因此需要在传输之前进行时钟同步。

CRC:循环冗余校验,用来让接收方的网卡适配器检查接收的到数据帧是否有错误,是否有比特翻转引入差错,如果引入了差错就会丢弃,这是网卡适配器直接从硬件响应的。此字段是发送方发送时由适配器从该帧中除了前同步码之外的其他比特进行映射计算获得。

类型字段:这是网络协议分层设计减小耦合度的精心设计,这允许以太网多路复用网络层协议,可以支持除了IP协议之外的其他不同网络层协议,或者是承载在以太网帧里的协议(如ARP协议)。接收方根据此字段进行多路分解,从而达到解析以太网帧的目的,将数据字段交给对应的上层网络层协议,这样就完成了以太网作为数据链路层协议的工作。

通过上述分析,可以看出,前同步码由网卡适配器接收帧时同步时钟使用,不会再接收方显示,CRC字段用来校验帧,如果校验不合格就丢弃了,只有合格的数据帧才会被网卡接收,故CRC字段也不用管理。因此解析以太网数据帧的关键就是获取类型字段,然后根据类型字段将数据字段的数据交给上层协议进行处理。同时保存下目的MAC地址和源MAC地址,以供后续其他使用。

根据 IEEE802.3,以太网类型字段(EtherType 字段)是两个八字节的字段。在量化评估中,字段中的第一个八位字节是最重要的。而当字段值大于等于十进制值 1536(即十六进制为 0600)时, EtherType 字段表示为 MAC 客户机协议(EtherType 解释)的种类。该类字段值取自 IEEE EtherType 字段寄存器。EtherType 字段是个极限空间,因此其分配是有限的。只有开发新的数据传输协议的人员需要使用 EtherType 字段,而不管他们实际上是否真正生产任何设备。IEEE RAC EtherType 字段批准权威机构负责检查和批准。具体详细定义如下:

以太类型值(16进制)对应协议 

0x0000 - 0x05DC   IEEE 802.3 长度  

0x0101 – 0x01FF实验  

0x0600 XEROX NS IDP  

0x0660   0x0661DLOG  

0x0800网际协议(IP)  

0x0801 X.75 Internet  

0x0802 NBS Internet  

0x0803 ECMA Internet  

0x0804  Chaosnet  

0x0805 X.25 Level 3  

0x0806地址解析协议(ARP : Address Resolution Protocol) 
0x0808 帧中继 ARP (Frame Relay ARP) [RFC1701] 
0x6559 原始帧中继(Raw Frame Relay) [RFC1701] 
0x8035动态 DARP (DRARP:Dynamic RARP)反向地址解析协议(RARP:Reverse Address Resolution Protocol) 
0x8037Novell Netware IPX  

0x809BEtherTalk  

0x80D5 IBM SNA Services over Ethernet  

0x80F3AppleTalk 地址解析协议(AARP:AppleTalk Address Resolution Protocol) 

0x8100 以太网自动保护开关(EAPS:Ethernet Automatic Protection Switching) 

0x8137 因特网包交换(IPX:Internet Packet Exchange) 

0x814C  简单网络管理协议(SNMP:Simple Network Management Protocol) 

0x86DD网际协议v6(IPv6,Internet Protocol version 6) 

0x8809 OAM 
几个重要字段的含义如下: 
 Dest addr:以太网OAM报文的目的MAC地址,为组播MAC地址0180c2000002。  Source addr:以太网OAM报文的源MAC地址,为发送端的桥MAC地址,该地址是一个单播MAC地址。 
 Type:以太网OAM报文的协议类型,为0x8809。 
 Subtype:以太网OAM报文的协议子类型,为0x03。 
Flags:Flags域,包含了以太网OAM实体的状态信息。 
 Code:本字段指明了OAMPDU的报文类型。0x00表示Information OAMPDU、0x01表示Event Notification OAMPDU、0x04表示Loopback Control OAMPDU。 以下是几种常用的OAMPDU报文的作用:  Information OAMPDU 
Information OAMPDU报文用于将以太网OAM实体的状态信息(包括本地信息、远端信息和自定义信息)发给远端的以太网OAM实体,保持以太网OAM连接。  Event Notification OAMPDU Event Notification OAMPDU(事件通知OAMPDU)报文一般用于链路监控,是用于对连接本端和远端以太网OAM实体的链路发生的故障进行告警。  Loopback Control OAMPDU 
Loopback Control OAMPDU(环路控制OAMPDU)报文主要用于远端环回控制,环回控制OAMPDU报文用来控制远端设备的OAM环回状态,该报文中带有使能或去使能环回功能的信息,根据该信息开启或关闭远端环回功能。 

0x880B点对点协议(PPP:Point-to-Point Protocol) 

0x880C 通用交换管理协议(GSMP:General Switch Management Protocol) 

0x8847 多协议标签交换(单播) MPLS:Multi-Protocol Label Switching <unicast>) 

0x8848 多协议标签交换(组播)(MPLS, Multi-Protocol Label Switching <multicast>) 

0x8863 以太网上的 PPP(发现阶段)(PPPoE:PPP Over Ethernet <Discovery Stage>) 

0x8864 以太网上的 PPP(PPP 会话阶段) (PPPoE,PPP Over Ethernet<PPP Session Stage>) 

0x88BB 轻量级访问点协议(LWAPP:Light Weight Access Point Protocol)  0x88CC  链接层发现协议(LLDP:Link Layer Discovery Protocol) 

0x8E88 局域网上的 EAP(EAPOL:EAP over LAN) 

0x9000 配置测试协议(Loopback) 

0x9100 VLAN 标签协议标识符(VLAN Tag Protocol Identifier) 

0x9200 VLAN 标签协议标识符(VLAN Tag Protocol Identifier)  

0xFFFF 保留

对于常用的以太网承载的协议和功能被标注出来了,只需要通过判断这个类型字段就可以解析以太网数据帧并交由上层协议进一步处理了。

下面是在抓取到网卡适配器的数据帧后进行解析的代码,按照上述规范比较简单。

/// <summary>
    /// Define the Ethernet packet to parse the caught packet
    /// </summary>
    public class EthernetParket
    {
        public string DstMAC = "";
        public string SrcMAC = "";

        public string Type = "";

        public byte[] Data;

        public EthernetParket(byte[] rawFrame)
        {
            if (rawFrame.Length < 46 || rawFrame.Length > 1500)
            {
                throw new Exception("Frame too short!");
            }
            
            //Set the Destination MAC and Source MAC
            DstMAC = Util.JoinByteArr(Util.SubByteArr(rawFrame, 0, 6), "-");
            SrcMAC = Util.JoinByteArr(Util.SubByteArr(rawFrame, 6, 6), "-");

            //Set the upper layer protocal type
            Type = rawFrame[12].ToString("X2") + rawFrame[13].ToString("X2");

            //Set the upper layer data
            Data = Util.SubByteArr(rawFrame, 14);
        }
    }
    
    /// <summary>
    /// The most common used function to parse raw byte data
    /// Defined as static class and method for the performance
    /// </summary>
    public static class Util
    {
        public static byte[] SubByteArr(byte[] arr, int start, uint count = 0)
        {
            int s = start;
            uint e = 0;
            int len = arr.Length;
            if (start < 0)
            {
                s = len + start;
            }
            count = 0 == count ? (uint)(len - s) : count;
            e = (uint)s + count;

            byte[] a = new byte[count];
            for (int i = s, j = 0; i < e; i++, j++)
            {
                a[j] = arr[i];
            }
            return a;
        }

    }


发布了158 篇原创文章 · 获赞 41 · 访问量 33万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览