Inheritance: AProtocolHeader
Exemplo n.º 1
0
    /// <summary>
    /// This routine creates an instance of the Icmpv6EchoRequest 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="echoData">Byte array containing the binary ICMPv6 echo request header</param>
    /// <param name="bytesCopied">Number of bytes used in header</param>
    /// <returns>Returns the Icmpv6EchoRequest object created from the byte array</returns>
    public static Icmpv6EchoRequest Create(byte[] echoData, ref int bytesCopied)
    {
        Icmpv6EchoRequest icmpv6EchoRequestHeader = new Icmpv6EchoRequest();

        // Verify buffer is large enough
        if (echoData.Length < Icmpv6EchoRequest.Icmpv6EchoRequestLength)
            return null;

        // Properties are stored in network byte order so just grab the bytes
        //    from the buffer
        icmpv6EchoRequestHeader.echoId = BitConverter.ToUInt16(echoData, 0);
        icmpv6EchoRequestHeader.echoSequence = BitConverter.ToUInt16(echoData, 2);
        bytesCopied = Icmpv6EchoRequest.Icmpv6EchoRequestLength;
        return icmpv6EchoRequestHeader;
    }
Exemplo n.º 2
0
    /// <summary>
    /// This routine creates an instance of the Icmpv6EchoRequest 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="echoData">Byte array containing the binary ICMPv6 echo request header</param>
    /// <param name="bytesCopied">Number of bytes used in header</param>
    /// <returns>Returns the Icmpv6EchoRequest object created from the byte array</returns>
    static public Icmpv6EchoRequest Create(byte[] echoData, ref int bytesCopied)
    {
        Icmpv6EchoRequest icmpv6EchoRequestHeader = new Icmpv6EchoRequest();

        // Verify buffer is large enough
        if (echoData.Length < Icmpv6EchoRequest.Icmpv6EchoRequestLength)
        {
            return(null);
        }

        // Properties are stored in network byte order so just grab the bytes
        //    from the buffer
        icmpv6EchoRequestHeader.echoId       = BitConverter.ToUInt16(echoData, 0);
        icmpv6EchoRequestHeader.echoSequence = BitConverter.ToUInt16(echoData, 2);
        bytesCopied = Icmpv6EchoRequest.Icmpv6EchoRequestLength;
        return(icmpv6EchoRequestHeader);
    }
Exemplo n.º 3
0
        public ManualResetEvent pingDoneEvent;             // Event to indicate all outstanding receives are done
                                                           //    this ping class can be disposed

        /// <summary>
        /// Base constructor that initializes the member variables to default values. It also
        /// creates the events used and initializes the async callback function.
        /// </summary>
        public RawSocketPing()
        {
            pingSocket              = null;
            pingFamily              = AddressFamily.InterNetwork;
            pingTtl                 = 8;
            pingPayloadLength       = 8;
            pingSequence            = 0;
            pingReceiveTimeout      = 4000;
            pingOutstandingReceives = 0;
            destEndPoint            = new IPEndPoint(IPAddress.Loopback, 0);
            protocolHeaderList      = new ArrayList();
            pingReceiveEvent        = new ManualResetEvent(false);
            pingDoneEvent           = new ManualResetEvent(false);
            receiveCallback         = new AsyncCallback(PingReceiveCallback);
            icmpHeader              = null;
            icmpv6Header            = null;
            icmpv6EchoRequestHeader = null;
        }
Exemplo n.º 4
0
        /// <summary>
        /// This is the asynchronous callback that is fired when an async ReceiveFrom.
        /// An asynchronous ReceiveFrom is posted by calling BeginReceiveFrom. When this
        /// function is invoked, it calculates the elapsed time between when the ping
        /// packet was sent and when it was completed.
        /// </summary>
        /// <param name="ar">Asynchronous context for operation that completed</param>
        static void PingReceiveCallback(IAsyncResult ar)
        {
            RawSocketPing rawSock = (RawSocketPing)ar.AsyncState;
            TimeSpan      elapsedTime;
            int           bytesReceived = 0;
            ushort        receivedId    = 0;

            try
            {
                // Keep a count of how many async operations are outstanding -- one just completed
                //    so decrement the count.
                Interlocked.Decrement(ref rawSock.pingOutstandingReceives);

                // If we're done because ping is exiting and the socket has been closed,
                //    set the done event
                if (rawSock.pingSocket == null)
                {
                    if (rawSock.pingOutstandingReceives == 0)
                    {
                        rawSock.pingDoneEvent.Set();
                    }
                    return;
                }

                // Complete the receive op by calling EndReceiveFrom. This will return the number
                //    of bytes received as well as the source address of who sent this packet.
                bytesReceived = rawSock.pingSocket.EndReceiveFrom(ar, ref rawSock.castResponseEndPoint);

                // Calculate the elapsed time from when the ping request was sent and a response was
                //    received.
                elapsedTime = DateTime.Now - rawSock.pingSentTime;

                rawSock.responseEndPoint = (IPEndPoint)rawSock.castResponseEndPoint;

                // Here we unwrap the data received back into the respective protocol headers such
                //    that we can find the ICMP ID in the ICMP or ICMPv6 packet to verify that
                //    the echo response we received was really a response to our request.
                if (rawSock.pingSocket.AddressFamily == AddressFamily.InterNetwork)
                {
                    Ipv4Header v4Header;
                    IcmpHeader icmpv4Header;
                    byte[]     pktIcmp;
                    int        offset = 0;

                    // Remember, raw IPv4 sockets will return the IPv4 header along with all
                    //    subsequent protocol headers
                    v4Header = Ipv4Header.Create(rawSock.receiveBuffer, ref offset);
                    pktIcmp  = new byte[bytesReceived - offset];
                    Array.Copy(rawSock.receiveBuffer, offset, pktIcmp, 0, pktIcmp.Length);
                    icmpv4Header = IcmpHeader.Create(pktIcmp, ref offset);

                    /*Console.WriteLine("Icmp.Id = {0}; Icmp.Sequence = {1}",
                     *  icmpv4Header.Id,
                     *  icmpv4Header.Sequence
                     *  );*/

                    receivedId = icmpv4Header.Id;
                }
                else if (rawSock.pingSocket.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    Icmpv6Header      icmp6Header;
                    Icmpv6EchoRequest echoHeader;
                    byte[]            pktEchoRequest;
                    int offset = 0;

                    // For IPv6 raw sockets, the IPv6 header is never returned along with the
                    //    data received -- the received data always starts with the header
                    //    following the IPv6 header.
                    icmp6Header    = Icmpv6Header.Create(rawSock.receiveBuffer, ref offset);
                    pktEchoRequest = new byte[bytesReceived - offset];
                    Array.Copy(rawSock.receiveBuffer, offset, pktEchoRequest, 0, pktEchoRequest.Length);
                    echoHeader = Icmpv6EchoRequest.Create(pktEchoRequest, ref offset);

                    /*Console.WriteLine("Icmpv6.Id = {0}; Icmp.Sequence = {1}",
                     *  echoHeader.Id,
                     *  echoHeader.Sequence
                     *  );*/

                    receivedId = echoHeader.Id;
                }

                if (receivedId == rawSock.pingId)
                {
                    string elapsedString;

                    // Print out the usual statistics for ping
                    if (elapsedTime.Milliseconds < 1)
                    {
                        elapsedString = "<1";
                    }
                    else
                    {
                        elapsedString = "=" + elapsedTime.Milliseconds.ToString();
                    }

                    Console.WriteLine("Reply from {0}: byte={1} time{2}ms TTL={3} ",
                                      rawSock.responseEndPoint.Address.ToString(),
                                      bytesReceived,
                                      elapsedString,
                                      rawSock.pingTtl
                                      );
                }

                // Post another async receive if the count indicates for us to do so.
                if (rawSock.pingCount > 0)
                {
                    rawSock.pingSocket.BeginReceiveFrom(
                        rawSock.receiveBuffer,
                        0,
                        rawSock.receiveBuffer.Length,
                        SocketFlags.None,
                        ref rawSock.castResponseEndPoint,
                        rawSock.receiveCallback,
                        rawSock
                        );

                    // Keep track of outstanding async operations
                    Interlocked.Increment(ref rawSock.pingOutstandingReceives);
                }
                else
                {
                    // If we're done then set the done event
                    if (rawSock.pingOutstandingReceives == 0)
                    {
                        rawSock.pingDoneEvent.Set();
                    }
                }
                // If this is indeed the response to our echo request then signal the main thread
                //    that we received the response so it can send additional echo requests if
                //    necessary. This is done after another async ReceiveFrom is already posted.
                if (receivedId == rawSock.pingId)
                {
                    rawSock.pingReceiveEvent.Set();
                }
            }
            catch (SocketException err)
            {
                Console.WriteLine("Socket error occurred in async callback: {0}", err.Message);
            }
        }
Exemplo n.º 5
0
        /// <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);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Icmpv6EchoReply"/> class.
        /// Simple constructor for the ICMPv6 echo request header
        /// </summary>
        ///

        public Icmpv6EchoReply(Icmpv6EchoRequest icmpv6EchoRequest)
        {
            Id                = icmpv6EchoRequest.Id;
            Sequence          = icmpv6EchoRequest.Sequence;
            Icmpv6EchoPayload = icmpv6EchoRequest.Icmpv6EchoPayload;
        }