承载于以太网帧之上的数据包的解析——ARP、IPv4、IPv6

承接上一博文而来,继续解析网络数据包,对于承载在以太网上的三种协议进行了解析,主要是分为根据RFC定义的标准先解析头部数据,然后得到有效载荷,即为协议包含的实体数据,更上层进行进一步处理。

一、ARP协议

该协议作为局域网IP地址和MAC地址映射的重要协议,与DNS将域名与IP地址进行映射有异曲同工之妙。当以太网的类型字段为 0x0806时即为ARP协议数据包。定义如下图:

硬件类型即为以太网的代码。ARP支持的协议类型为IP(0x0800),硬件地址长度即MAC地址长度为6,协议地址长度为IP地址长度为4,OP字段为当前数据报的类型,0x0001表示请求包,0x0002表示应答包。这些就构成了ARP数据报头,一共8个Byte。

随后的20个Byte分别如上图所示,用来进行MAC地址和IP地址映射。

解析如下:

    /// <summary>
    /// Define the ARP packet header by RFC826
    /// </summary>
    public class ARPPacketHeader : INetworkLayerHeader
    {
        public ushort HardwareType = 0;         //2 Bytes 硬件类型
        public ushort ProtocalType = 0;         //2 Bytes 协议类型
        public byte HardwareAddressLength = 6;  //1 Byte  硬件地址长度(即MAC地址长度为6)
        public byte ProtocolAddressLength = 4;  //1 Byte  协议地址长度(即IP地址长度为4)
        public ushort OP = 0;                   //2 Byte  ARP包类型(0x0001:请求包  0x0002:应答包)
    }
/// <summary>
    /// Parse the ARP packet
    /// </summary>
    public class ARPPacket : INetworkLayerPacket
    {
        private byte[] RawPacket;

        public ARPPacketHeader Header;
        public string SenderMAC;
        public string SenderIP;
        public string ReceiverMAC;
        public string ReceiverIP;

        public ARPPacket(byte[] rawArpPacket)
        {
            SenderMAC = Util.JoinByteArr(Util.SubByteArr(rawArpPacket, 8, 6), "-");
            SenderIP = Util.JoinByteArr(Util.SubByteArr(rawArpPacket, 14, 4), ".", "d");
            ReceiverMAC = Util.JoinByteArr(Util.SubByteArr(rawArpPacket, 18, 6), "-");
            ReceiverIP = Util.JoinByteArr(Util.SubByteArr(rawArpPacket, 24, 4), ".", "d");

            RawPacket = rawArpPacket;
        }

        public INetworkLayerHeader getHeader()
        {
            Header = new ARPPacketHeader();
            Header.HardwareType = (ushort)((ushort)(RawPacket[0] << 8) + (ushort)RawPacket[1]);
            Header.ProtocalType = (ushort)((ushort)(RawPacket[2] << 8) + (ushort)RawPacket[3]);
            Header.HardwareAddressLength = (byte)RawPacket[4];
            Header.ProtocolAddressLength = (byte)RawPacket[5];
            Header.OP = (ushort)((ushort)(RawPacket[6] << 8) + (ushort)RawPacket[7]);
            return Header;
        }

        public byte[] getBody()
        {
            return Util.SubByteArr(RawPacket, 8);
        }
    }

二、IPv4协议

解析过程与上述类似,可以进行类比。作为最广泛的网络层协议,详细结构就不赘述。直接看结构图:

解析过程如下:

    /// <summary>
    /// Define the IPv4 packet header by RFC791
    /// </summary>
    public class IPv4PacketHeader : INetworkLayerHeader
    {
        public byte Version = 4;            //3 bits  版本号
        public byte Length = 0;             //5 bits  头部长度
        public byte Tos = 0;                //1 Byte  服务类型
        public ushort DatagramLength = 0;   //2 Bytes 数据包长度

        public ushort Identification = 0;   //2 Bytes 标识
        public byte Mark = 0;               //3 bits  标志
        public ushort Offset = 0;           //13 bits 片偏移

        public byte TTL = 0;                //1 Byte  数据包寿命
        public byte UpperProtocal = 0;      //1 Byte  上层协议
        public ushort HeaderChecksum = 0;   //2 Byte  头部检查和

        public string SrcIP = "";              //4 Bytes  源IP地址

        public string DstIP = "";              //4 Bytes  目的IP地址
    }
    /// <summary>
    /// Parse the IPv4 packet
    /// </summary>
    public class IPv4Packet : INetworkLayerPacket
    {
        private byte[] RawPacket;

        public IPv4PacketHeader Header;
        public byte[] Body;

        public IPv4Packet(byte[] rawPacket)
        {
            RawPacket = rawPacket;
        }

        public INetworkLayerHeader getHeader()
        {
            Header = new IPv4PacketHeader();
            Header.Length = (byte)(RawPacket[0] & 0x1f);
            Header.Tos = RawPacket[1];
            Header.DatagramLength = (ushort)((ushort)(RawPacket[2] << 8) + (ushort)RawPacket[3]);
            Header.Identification = (ushort)((ushort)(RawPacket[4] << 8) + (ushort)RawPacket[5]);
            Header.Mark = (byte)(RawPacket[6] >> 5);
            Header.Offset = (ushort)((ushort)((RawPacket[6] & 0x1f) << 8) + (ushort)RawPacket[7]);
            Header.TTL = RawPacket[8];
            Header.UpperProtocal = RawPacket[9];
            Header.HeaderChecksum = (ushort)((ushort)(RawPacket[10] << 8) + (ushort)RawPacket[11]);

            Header.SrcIP = Util.JoinByteArr(Util.SubByteArr(RawPacket, 12, 4), ".", "d");
            Header.DstIP = Util.JoinByteArr(Util.SubByteArr(RawPacket, 16, 4), ".", "d");
            return Header;
        }

        public byte[] getBody()
        {
            Body = Util.SubByteArr(RawPacket, 20);
            return Body;
        }
    }

三、IPv6协议

IPv6是用来替代IPv4以解决地址空间不足的问题而发展起来的,同时改协议在IPv4的基础上也做了很大其他方面的改动,如不允许在中间路由器上进行分片操作等。目前应用范围虽然难以达到取代IPv4的程度,但是提供了较大优势。下图为其数据报结构:

解析过程如下:

    /// <summary>
    /// Define the IPv6 packet header by RFC 2460
    /// </summary>
    public class IPv6PacketHeader : INetworkLayerHeader
    {
        public byte Version = 6;            //3 bits   版本号
        public byte Tos = 0;                //1 Byte   流量(服务)类型
        public uint FlowTag = 0;            //21 bits  流标签

        public ushort AvaiLoad = 0;         //2 Bytes  有效载荷长度
        public byte NextHeader = 0;         //1 Byte   下个首部(与IPv4中的协议字段值相同)
        public byte HopLimit = 0;           //1 Byte   跳数限制

        public string SrcIP = "";           //16 Bytes 源IPv6地址

        public string DstIP = "";           //16 Bytes 目的IPv6地址
    }
    /// <summary>
    /// Parse the IPv6 packet
    /// </summary>
    public class IPv6Packet : INetworkLayerPacket
    {
        private byte[] RawPacket;

        public IPv6PacketHeader Header;
        public byte[] Body;

        public IPv6Packet(byte[] rawPacket)
        {
            RawPacket = rawPacket;
        }

        public INetworkLayerHeader getHeader()
        {
            Header = new IPv6PacketHeader();
            Header.Tos = (byte)((RawPacket[0] & 0x1fu) << 3 + RawPacket[1] >> 5);
            Header.FlowTag = (uint)((RawPacket[1] & 0x1fu) << 16 + RawPacket[2] << 8 + RawPacket[3]);
            Header.AvaiLoad = (ushort)((ushort)(RawPacket[4] << 8) + (ushort)RawPacket[5]);
            Header.NextHeader = RawPacket[6];
            Header.HopLimit = RawPacket[7];

            Header.SrcIP = Util.JoinByteArr(Util.SubByteArr(RawPacket, 8, 16), ":", "X2", 2);
            Header.DstIP = Util.JoinByteArr(Util.SubByteArr(RawPacket, 24, 16), ":", "X2", 2);
            return Header;
        }

        public Byte[] getBody()
        {
            Body = Util.SubByteArr(RawPacket, 40);
            return Body;
        }
    }

通过对这些协议的亲自剖析,可以更加对网络传输有了更深的理解,同时对应用层的应用开发也有很好的指导作用。

时间: 2024-10-25 00:44:06

承载于以太网帧之上的数据包的解析——ARP、IPv4、IPv6的相关文章

010 使用netmap函数接管网卡,接收数据包,回应ARP请求

一.本文目的: 上一节中,我们已经在CentOS 6.7 上安装好了netmap,也能接收和发送包了,这节我们来调用netmap中的API,接管网卡,对网卡上收到的数据包做分析,并回应ARP请求. 二.netmap API简要介绍: 1.netmap API 主要包含在两个头文件中:netmap.h和netmap_user.h.在netmap/sys/net/目录下,其中netmap_user.h调用netmap.h. 2.netmap API一共七八个函数调用:nm_open()生成文件描述符

利用Wireshark截取数据包,并对数据包进行解析

利用Wireshark截取ICMP数据包,并对数据包进行解析 wireshark安装文件下载地址:http://yunpan.cn/QiHGK5sPtWRyN (提取码:0bbc) 安装步骤: 解压文件之后,在\wireshark-win32-1.4.9中文版\文件夹中找到安装文件,双击即可安装. 安装完成之后,双击wireshark图标即可启动,界面如下: 抓包步骤: 1.点击开始按钮列出可以抓包的接口: 2.点击选项可以配置抓包参数: 3.配置完成点击开始,即可开始抓包: 4.点击停止完成抓

【转载】串口中怎样接收一个完整数据包的解析

这里以串口作为传输媒介,介绍下怎样来发送接收一个完整的数据包.过程涉及到封包与解包.设计一个良好的包传输机制很有利于数据传输的稳定性以及正确性.串口只是一种传输媒介,这种包机制同时也可以用于SPI,I2C的总线下的数据传输.在单片机通信系统(多机通信以及PC与单片机通信)中,是很常见的问题. 一.根据帧头帧尾或者帧长检测一个数据帧 1.帧头+数据+校验+帧尾 这是一个典型的方案,但是对帧头与帧尾在设计的时候都要注意,也就是说帧头.帧尾不能在所传输的数据域中出现,一旦出现可能就被误判.如果用中断来

Wireshark数据包分析之ARP协议包解读

*此篇博客仅作为个人笔记和学习参考 ARP请求报文格式 ARP回应报文格式 ARP数据包 ARP请求包 ARP回应包 原文地址:http://blog.51cto.com/13444271/2125341

以太网,IP,TCP,UDP数据包分析

http://www.cnblogs.com/feitian629/archive/2012/11/16/2774065.html 1.ISO开放系统有以下几层: 7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层 2.TCP/IP 网络协议栈分为应用层(Application).传输层(Transport).网络层(Network)和链路层(Link)四层. 通信过程中,每层协议都要加上一个数据首部(header),称为封装(Encapsulation),如

报文段、数据报、数据包和帧

帧与数据包 数据包,就是从最上层,一层一层封装,直到网络层的,最后借由数据链路层发送出去的数据单元. 帧,是数据链路层的传输单元. 这么一看,数据包和帧好像没什么不一样,好像数据传递的都是一样的.可是为什么会把它们区分开呢?学习 TCP/IP 协议的同学应该都知道,数据链路层中有 MTU 这样一个东西,它是帧最大传输单元. 数据包是一个完整的数据单元,但是如果数据包的大小超过了 MTU 呢?所以,可能许多帧组合在一起,才能形成一个完整的数据包,这就是帧和数据包的关系. 数据包与数据报 说完了数据

以太网帧结构解析

由于需要做一个分析网卡接收的数据包的Project,需要了解以太网帧结构并解析,发现有很多内容从一般网络方面的知识是不够的,因此查阅了相关资料再此做一个记录以备忘. 以太网是目前最流行的有线的局域网技术,特别是上世纪九十年后发展的交换式局域网增加了有效数据速率,同时集线器和交换机等普通且便宜的硬件更助长了其普及程度.以太网的数据帧格式如下图所示: 数据字段:在交换式以太网中,一台主机向局域网中的另一台主机发送一个IP数据报,这个数据报封装在以太网帧结构中作为其有效载荷,以太网的最大传输单元(MT

NS3网络仿真(9): 构建以太网帧

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 在NS3使用了一个叫Packet的类来表示一个数据帧,本节尝试用它构造一个以太网帧. 以下是一个典型的ARP请求帧: 我们就用Packet来创建一个同样的帧. 首先创建一个空的数据包: Ptr<Packet>pkt = Create<Packet>(); 接下来加上ARP头: //加入arp头 ArpHeader ah; ah.SetRequest(Mac48Address(&qu

基于Jpcap的TCP/IP数据包分析(一)

基于Jpcap的TCP/IP数据包分析原作:赵新辉目 录第一章 以太网的结构和TCP/IP1.1 以太网的结构1.1.1 基于网络架构的以太网1.1.2 以太网的数据交换1.1.3 以太网帧的结构1.2 IP数据报的构成 1.2.1 IP地址1.2.2 路由1.2.3 IP数据报的构成1.2.4 其他报文结构1.3 TCP/UDP1.3.1 TCP/UDP的作用1.3.2 TCP和UDP报文的结构第二章 Jpcap类库2.1 Jpcap的使用2.1.1 Jpcap的运行环境的安装2.1.2 Jp