/// <summary> /// Constructor for the ICMPv6 header which also takes a reference to the /// encompassing IPv6 header. This is necessary since the IPv6 protocol /// defines a pseudo header checksum which requires the checksum to be /// calculated over fields in the ICMPv6 header and payload as well as /// fields from the IPv6 packet. /// </summary> /// <param name="packetHeader">Reference to the Ipv6Header object encompassing the ICMPv6 packet</param> public Icmpv6Header(Ipv6Header packetHeader) : base() { icmpType = 0; icmpCode = 0; icmpChecksum = 0; ipv6Header = packetHeader; }
/// <summary> /// Simple constructor for the UDP header. /// </summary> public UdpHeader() : base() { srcPort = 0; destPort = 0; udpLength = 0; udpChecksum = 0; ipv6PacketHeader = null; ipv4PacketHeader = null; }
/// <summary> /// This routine creates an instance of the Ipv6Header class from a byte /// array that is a received IGMP packet. This is useful when a packet /// is received from the network and the header object needs to be /// constructed from those values. /// </summary> /// <param name="ipv6Packet">Byte array containing the binary IPv6 header</param> /// <param name="bytesCopied">Number of bytes used in header</param> /// <returns>Returns the Ipv6Header object created from the byte array</returns> public static Ipv6Header Create(byte[] ipv6Packet, ref int bytesCopied) { Ipv6Header ipv6Header = new Ipv6Header(); byte[] addressBytes = new byte[16]; uint tempVal = 0, tempVal2 = 0; // Ensure byte array is large enough to contain an IPv6 header if (ipv6Packet.Length < Ipv6Header.Ipv6HeaderLength) return null; tempVal = ipv6Packet[0]; tempVal = (tempVal >> 4) & 0xF; ipv6Header.ipVersion = (byte)tempVal; tempVal = ipv6Packet[0]; tempVal = (tempVal & 0xF) >> 4; ipv6Header.ipTrafficClass = (byte)(tempVal | (uint)((ipv6Packet[1] >> 4) & 0xF)); tempVal2 = ipv6Packet[1]; tempVal2 = (tempVal2 & 0xF) << 16; tempVal = ipv6Packet[2]; tempVal = tempVal << 8; ipv6Header.ipFlow = tempVal2 | tempVal | ipv6Packet[3]; ipv6Header.ipNextHeader = ipv6Packet[4]; ipv6Header.ipHopLimit = ipv6Packet[5]; Array.Copy(ipv6Packet, 6, addressBytes, 0, 16); ipv6Header.SourceAddress = new IPv6Address(addressBytes); Array.Copy(ipv6Packet, 24, addressBytes, 0, 16); ipv6Header.DestinationAddress = new IPv6Address(addressBytes); bytesCopied = Ipv6Header.Ipv6HeaderLength; return ipv6Header; }
/// <summary> /// This routine builds the appropriate ICMP echo packet depending on the /// protocol family requested. /// </summary> public void BuildPingPacket() { // Initialize the socket if it hasn't already been done Console.WriteLine("Building the ping packet..."); Console.WriteLine("Initializing the socket if not done yet..."); if (pingSocket == null) { InitializeSocket(); } // Clear any existing headers in the list Console.WriteLine("Clearing any existing headers in the list using Clear()..."); protocolHeaderList.Clear(); if (destEndPoint.AddressFamily == AddressFamily.InterNetwork) { // Create the ICMP header and initialize the members Console.WriteLine("Creating the ICMP header and initialize the members..."); icmpHeader = new IcmpHeader(); icmpHeader.Id = pingId; icmpHeader.Sequence = pingSequence; icmpHeader.Type = IcmpHeader.EchoRequestType; icmpHeader.Code = IcmpHeader.EchoRequestCode; // Build the data payload of the ICMP echo request Console.WriteLine("Building the data payload of the ICMP echo request..."); pingPayload = new byte[pingPayloadLength]; for (int i = 0; i < pingPayload.Length; i++) { pingPayload[i] = (byte)'e'; } // Add ICMP header to the list of headers Console.WriteLine("Adding ICMP header to the list of headers using Add()..."); protocolHeaderList.Add(icmpHeader); } else if (destEndPoint.AddressFamily == AddressFamily.InterNetworkV6) { Ipv6Header ipv6Header; // Required for pseudo header checksum IPEndPoint localInterface; byte[] localAddressBytes = new byte[28]; Console.WriteLine("This part is for IPv6..."); // An IPv6 header is required since the IPv6 protocol specifies that the // pseudo header checksum needs to be calculated on ICMPv6 packets which // requires the source and destination address that will appear in the // IPv6 packet. ipv6Header = new Ipv6Header(); // We definitely know the destination IPv6 address but the stack will // choose the "appropriate" local v6 interface depending on the // routing table which may be different than the address we bound // the socket to. Because of this we will call the Winsock ioctl // SIO_ROUTING_INTERFACE_QUERY which will return the local interface // for a given destination address by querying the routing table. Console.WriteLine("Implementing the IOControl()..."); pingSocket.IOControl( WinsockIoctl.SIO_ROUTING_INTERFACE_QUERY, SockaddrConvert.GetSockaddrBytes(destEndPoint), localAddressBytes ); localInterface = SockaddrConvert.GetEndPoint(localAddressBytes); // Fill out the fields of the IPv6 header used in the pseudo-header checksum calculation Console.WriteLine("Filling out the IPv6 header fields..."); ipv6Header.SourceAddress = localInterface.Address; ipv6Header.DestinationAddress = destEndPoint.Address; ipv6Header.NextHeader = 58; // IPPROTO_ICMP6 // Initialize the ICMPv6 header Console.WriteLine("Initializing the ICMPv6 header..."); icmpv6Header = new Icmpv6Header(ipv6Header); icmpv6Header.Type = Icmpv6Header.Icmpv6EchoRequestType; icmpv6Header.Code = Icmpv6Header.Icmpv6EchoRequestCode; // Initialize the payload Console.WriteLine("Initializing the payload..."); pingPayload = new byte[pingPayloadLength]; for (int i = 0; i < pingPayload.Length; i++) { pingPayload[i] = (byte)'e'; } // Create the ICMPv6 echo request header Console.WriteLine("Creating the ICMPv6 echo request header..."); icmpv6EchoRequestHeader = new Icmpv6EchoRequest(); icmpv6EchoRequestHeader.Id = pingId; // Add the headers to the protocol header list Console.WriteLine("Adding the headers to the protocol header list..."); protocolHeaderList.Add(icmpv6Header); protocolHeaderList.Add(icmpv6EchoRequestHeader); } }