/// <summary> /// This routine builds the ICMPv6 packet and payload into a byte array. /// It also computes the IPv6 pseudo header checksum that appears in the /// ICMPv6 packet. /// </summary> /// <param name="payLoad">A byte array representing the ICMPv6 payload</param> /// <returns>A byte array of the ICMPv6 packet and payload</returns> public override byte[] GetProtocolPacketBytes(byte[] payLoad) { byte[] icmpv6Packet, pseudoHeader, byteValue; int offset = 0, payLoadLength; // Build the ICMPv6 packet first since its required in the pseudo header calculation icmpv6Packet = new byte[Icmpv6HeaderLength + payLoad.Length]; offset = 0; icmpv6Packet[offset++] = icmpType; icmpv6Packet[offset++] = icmpCode; icmpv6Packet[offset++] = 0; icmpv6Packet[offset++] = 0; // Copy the payload into the build ICMPv6 packet Array.Copy(payLoad, 0, icmpv6Packet, offset, payLoad.Length); // Now build the pseudo header pseudoHeader = new byte[40 + icmpv6Packet.Length]; offset = 0; byteValue = ipv6Header.SourceAddress.GetBytes(); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; byteValue = ipv6Header.DestinationAddress.GetBytes(); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // Packet total length payLoadLength = NetworkingHelpers.HostToNetworkOrder(Icmpv6HeaderLength + payLoad.Length); byteValue = BitConverter.GetBytes(payLoadLength); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // 3 bytes of zero padding pseudoHeader[offset++] = (byte)0; pseudoHeader[offset++] = (byte)0; pseudoHeader[offset++] = (byte)0; pseudoHeader[offset++] = (byte)ipv6Header.NextHeader; // Next is the icmpv6 header and its payload Array.Copy(icmpv6Packet, 0, pseudoHeader, offset, icmpv6Packet.Length); offset += icmpv6Packet.Length; // Compute checksum on pseudo header Checksum = ComputeChecksum(pseudoHeader); // Go back and put the checksum value into the marshalled byte array byteValue = BitConverter.GetBytes(icmpChecksum); Array.Copy(byteValue, 0, icmpv6Packet, 2, byteValue.Length); return(icmpv6Packet); }
/// <summary> /// This method builds the byte array representation of the UDP header as it would appear /// on the wire. To do this it must build the IPv4 or IPv6 pseudo header in order to /// calculate the checksum on the packet. This requires knowledge of the IPv4 or IPv6 header /// so one of these must be set before a UDP packet can be set. /// /// The IPv4 pseudo header consists of: /// 4-byte source IP address /// 4-byte destination address /// 1-byte zero field /// 1-byte protocol field /// 2-byte UDP length /// 2-byte source port /// 2-byte destination port /// 2-byte UDP packet length /// 2-byte UDP checksum (zero) /// UDP payload (padded to the next 16-bit boundary) /// The IPv6 pseudo header consists of: /// 16-byte source address /// 16-byte destination address /// 4-byte payload length /// 3-byte zero pad /// 1-byte protocol value /// 2-byte source port /// 2-byte destination port /// 2-byte UDP length /// 2-byte UDP checksum (zero) /// UDP payload (padded to the next 16-bit boundary) /// </summary> /// <param name="payLoad">Payload that follows the UDP header</param> /// <returns></returns> public override byte[] GetProtocolPacketBytes(byte[] payLoad) { byte[] udpPacket = new byte[UdpHeaderLength + payLoad.Length], pseudoHeader = null, byteValue = null; int offset = 0; // Build the UDP packet first byteValue = BitConverter.GetBytes(srcPort); Array.Copy(byteValue, 0, udpPacket, offset, byteValue.Length); offset += byteValue.Length; byteValue = BitConverter.GetBytes(destPort); Array.Copy(byteValue, 0, udpPacket, offset, byteValue.Length); offset += byteValue.Length; byteValue = BitConverter.GetBytes(udpLength); Array.Copy(byteValue, 0, udpPacket, offset, byteValue.Length); offset += byteValue.Length; udpPacket[offset++] = 0; // Checksum is initially zero udpPacket[offset++] = 0; // Copy payload to end of packet Array.Copy(payLoad, 0, udpPacket, offset, payLoad.Length); if (ipv4PacketHeader != null) { pseudoHeader = new byte[UdpHeaderLength + 12 + payLoad.Length]; // Build the IPv4 pseudo header offset = 0; // Source address byteValue = ipv4PacketHeader.SourceAddress.GetBytes(); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // Destination address byteValue = ipv4PacketHeader.DestinationAddress.GetBytes(); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // 1 byte zero pad plus next header protocol value pseudoHeader[offset++] = 0; pseudoHeader[offset++] = ipv4PacketHeader.Protocol; // Packet length byteValue = BitConverter.GetBytes(udpLength); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // Copy the UDP packet to the end of this Array.Copy(udpPacket, 0, pseudoHeader, offset, udpPacket.Length); } else if (ipv6PacketHeader != null) { uint ipv6PayloadLength; pseudoHeader = new byte[UdpHeaderLength + 40 + payLoad.Length]; // Build the IPv6 pseudo header offset = 0; // Source address byteValue = ipv6PacketHeader.SourceAddress.GetBytes(); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // Destination address byteValue = ipv6PacketHeader.DestinationAddress.GetBytes(); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; ipv6PayloadLength = (uint)NetworkingHelpers.HostToNetworkOrder((int)(payLoad.Length + UdpHeaderLength)); // Packet payload: ICMPv6 headers plus payload byteValue = BitConverter.GetBytes(ipv6PayloadLength); Array.Copy(byteValue, 0, pseudoHeader, offset, byteValue.Length); offset += byteValue.Length; // 3 bytes zero pad plus next header protocol value pseudoHeader[offset++] = 0; pseudoHeader[offset++] = 0; pseudoHeader[offset++] = 0; pseudoHeader[offset++] = ipv6PacketHeader.NextHeader; // Copy the UDP packet to the end of this Array.Copy(udpPacket, 0, pseudoHeader, offset, udpPacket.Length); } if (pseudoHeader != null) { Checksum = ComputeChecksum(pseudoHeader); } // Put checksum back into packet byteValue = BitConverter.GetBytes(udpChecksum); Array.Copy(byteValue, 0, udpPacket, 6, byteValue.Length); return(udpPacket); }