Ejemplo n.º 1
0
        public void Encapsulate(VpnChannel channel, VpnPacketBufferList packets, VpnPacketBufferList encapulatedPackets)
        {
            var vpnSendPacketBuffer = channel.GetVpnSendPacketBuffer();

            while (packets.Size > 0) //can't iterate over packets
            {
                var packet       = packets.RemoveAtEnd();
                var packetAppId  = packet.AppId;
                var packetBuffer = packet.Buffer;
                var fromBuffer   = DataReader.FromBuffer(packetBuffer);
                var fromBufferUnconsumedBufferLength = fromBuffer.UnconsumedBufferLength;
                var bytes = new byte[fromBufferUnconsumedBufferLength];
                fromBuffer.ReadBytes(bytes);

                var bytesRead  = 0;
                var ipv4Header = Ipv4Header.Create(bytes, ref bytesRead);

                var vpnPacketBufferStatus   = packet.Status;
                var packetTransportAffinity = packet.TransportAffinity;
                var packetTransportContext  = packet.TransportContext;

                encapulatedPackets.Append(packet);

                //parse ip datagram and inspect destination IP
                //if destIP isn't found in peer list, drop and send ICMP "no route to host"?
            }
        }
Ejemplo n.º 2
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);
            }
        }