承接上一博文而来,继续解析网络数据包,对于承载在以太网上的三种协议进行了解析,主要是分为根据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