Beispiel #1
0
        internal void InitializeReceivedPacketBuffer(ReceivedPacketBuffer buffer)
        {
            buffer.SourceIPAddress      = 0;
            buffer.DestinationIPAddress = 0;
            buffer.Identification       = 0;

            if (buffer.Buffer == null)
            {
                buffer.Buffer = new byte[1500]; /* TODO: determine correct maximum size and make this a const */
            }
            if ((buffer.Holes == null) || (buffer.Holes.Length != DEFAULT_NUM_BUFFER_HOLES_ENTRIES_PER_BUFFER))
            {
                buffer.Holes = new ReceivedPacketBufferHoles[DEFAULT_NUM_BUFFER_HOLES_ENTRIES_PER_BUFFER];
            }
            buffer.Holes[0].FirstIndex = 0;
            buffer.Holes[0].LastIndex  = Int32.MaxValue;
            for (int i = 1; i < buffer.Holes.Length; i++)
            {
                buffer.Holes[i].FirstIndex = -1;
                buffer.Holes[i].LastIndex  = -1;
            }
            buffer.ActualBufferLength = 0;

            buffer.TimeoutInMachineTicks = Int64.MaxValue;
            buffer.IsEmpty = true;
            if (buffer.LockObject == null)
            {
                buffer.LockObject = new object();
            }
        }
Beispiel #2
0
        void AddReceivedPacketBufferHoleEntry(ReceivedPacketBuffer receivedPacketBuffer, Int32 firstIndex, Int32 lastIndex)
        {
            Int32 availableIndex = -1;

            for (Int32 i = 0; i < receivedPacketBuffer.Holes.Length; i++)
            {
                if (receivedPacketBuffer.Holes[i].FirstIndex == -1 && receivedPacketBuffer.Holes[i].LastIndex == -1)
                {
                    availableIndex = i;
                    break;
                }
            }

            // if we could not find an empty entry, enlarge the array.
            if (availableIndex == -1)
            {
                ReceivedPacketBufferHoles[] newHoles = new ReceivedPacketBufferHoles[receivedPacketBuffer.Holes.Length + 1];
                Array.Copy(receivedPacketBuffer.Holes, newHoles, receivedPacketBuffer.Holes.Length);
                receivedPacketBuffer.Holes = newHoles;
                availableIndex             = receivedPacketBuffer.Holes.Length - 1;
            }

            receivedPacketBuffer.Holes[availableIndex].FirstIndex = firstIndex;
            receivedPacketBuffer.Holes[availableIndex].LastIndex  = lastIndex;
        }
        internal void InitializeReceivedPacketBuffer(ReceivedPacketBuffer buffer)
        {
            if (buffer.Buffer == null)
            {
                buffer.Buffer = new byte[buffer.UDPPacketSize];
            }
            buffer.BytesReceived = 0;

            buffer.IsEmpty = true;
            if (buffer.LockObject == null)
            {
                buffer.LockObject = new object();
            }
        }
Beispiel #4
0
        internal void InitializeReceivedPacketBuffer(ReceivedPacketBuffer buffer)
        {
            buffer.SourceIPAddress = 0;
            buffer.SourceIPPort    = 0;

            if (buffer.Buffer == null)
            {
                buffer.Buffer = new byte[1500]; /* TODO: determine correct maximum size and make this a const */
            }
            buffer.BufferBytesFilled = 0;

            buffer.IsEmpty = true;
            if (buffer.LockObject == null)
            {
                buffer.LockObject = new object();
            }
        }
        internal void InitializeReceivedPacketBuffer(ReceivedPacketBuffer buffer)
        {
            buffer.SourceIPAddress = 0;
            buffer.DestinationIPAddress = 0;
            buffer.Identification = 0;

            if (buffer.Buffer == null)
                buffer.Buffer = new byte[1500]; /* TODO: determine correct maximum size and make this a const */
            if ((buffer.Holes == null) || (buffer.Holes.Length != DEFAULT_NUM_BUFFER_HOLES_ENTRIES_PER_BUFFER))
                buffer.Holes = new ReceivedPacketBufferHoles[DEFAULT_NUM_BUFFER_HOLES_ENTRIES_PER_BUFFER];
            buffer.Holes[0].FirstIndex = 0;
            buffer.Holes[0].LastIndex = Int32.MaxValue;
            for (int i = 1; i < buffer.Holes.Length; i++)
            {
                buffer.Holes[i].FirstIndex = -1;
                buffer.Holes[i].LastIndex = -1;
            }
            buffer.ActualBufferLength = 0;

            buffer.TimeoutInMachineTicks = Int64.MaxValue;
            buffer.IsEmpty = true;
            if (buffer.LockObject == null)
                buffer.LockObject = new object();
        }
        void AddReceivedPacketBufferHoleEntry(ReceivedPacketBuffer receivedPacketBuffer, Int32 firstIndex, Int32 lastIndex)
        {
            Int32 availableIndex = -1;
            for (Int32 i = 0; i < receivedPacketBuffer.Holes.Length; i++)
            {
                if (receivedPacketBuffer.Holes[i].FirstIndex == -1 && receivedPacketBuffer.Holes[i].LastIndex == -1)
                {
                    availableIndex = i;
                    break;
                }
            }

            // if we could not find an empty entry, enlarge the array.
            if (availableIndex == -1)
            {
                ReceivedPacketBufferHoles[] newHoles = new ReceivedPacketBufferHoles[receivedPacketBuffer.Holes.Length + 1];
                Array.Copy(receivedPacketBuffer.Holes, newHoles, receivedPacketBuffer.Holes.Length);
                receivedPacketBuffer.Holes = newHoles;
                availableIndex = receivedPacketBuffer.Holes.Length - 1;
            }

            receivedPacketBuffer.Holes[availableIndex].FirstIndex = firstIndex;
            receivedPacketBuffer.Holes[availableIndex].LastIndex = lastIndex;
        }
        public IPv4Layer(EthernetInterface ethernetInterface)
        {
            // save a reference to our Ethernet; we'll use this to push IPv4 frames onto the Ethernet interface
            _ethernetInterface = ethernetInterface;

            // create and configure my ARP resolver; the ARP resolver will automatically wire itself up to receiving incoming ARP frames
            _arpResolver = new ArpResolver(ethernetInterface);

            // retrieve our IP address configuration from the config sector and configure ARP
            object networkInterface = Netduino.IP.Interop.NetworkInterface.GetNetworkInterface(0);
            bool dhcpIpConfigEnabled = (bool)networkInterface.GetType().GetMethod("get_IsDhcpEnabled").Invoke(networkInterface, new object[] { });
            /* NOTE: IsDynamicDnsEnabled is improperly implemented in NETMF; it should implement dynamic DNS--but instead it returns whether or not DNS addresses are assigned through DHCP */
            bool dhcpDnsConfigEnabled = (bool)networkInterface.GetType().GetMethod("get_IsDynamicDnsEnabled").Invoke(networkInterface, new object[] { });

            // randomize our ephemeral port assignment counter (so that we don't use the same port #s repeatedly after reboots)
            _nextEphemeralPort = (UInt16)(FIRST_EPHEMERAL_PORT + ((new Random()).NextDouble() * (UInt16.MaxValue - FIRST_EPHEMERAL_PORT - 1)));

            // configure our ARP resolver's default IP address settings
            if (dhcpIpConfigEnabled)
            {
                // in case of DHCP, temporarily set our IP address to IP_ADDRESS_ANY (0.0.0.0)
                _arpResolver.SetIpv4Address(0);
            }
            else
            {
                _ipv4configIPAddress = ConvertIPAddressStringToUInt32BE((string)networkInterface.GetType().GetMethod("get_IPAddress").Invoke(networkInterface, new object[] { }));
                _ipv4configSubnetMask = ConvertIPAddressStringToUInt32BE((string)networkInterface.GetType().GetMethod("get_SubnetMask").Invoke(networkInterface, new object[] { }));
                _ipv4configGatewayAddress = ConvertIPAddressStringToUInt32BE((string)networkInterface.GetType().GetMethod("get_GatewayAddress").Invoke(networkInterface, new object[] { }));
                _arpResolver.SetIpv4Address(_ipv4configIPAddress);
            }
            // retrieve our DnsServer IP address configuration
            if (!dhcpDnsConfigEnabled)
            {
                string[] dnsAddressesString = (string[])networkInterface.GetType().GetMethod("get_DnsAddresses").Invoke(networkInterface, new object[] { });
                _ipv4configDnsServerAddresses = new UInt32[dnsAddressesString.Length];
                for (int iDnsAddress = 0; iDnsAddress < _ipv4configDnsServerAddresses.Length; iDnsAddress++)
                {
                    _ipv4configDnsServerAddresses[iDnsAddress] = ConvertIPAddressStringToUInt32BE(dnsAddressesString[iDnsAddress]);
                }
            }

            // initialize our buffers
            for (int i = 0; i < _receivedPacketBuffers.Length; i++ )
            {
                _receivedPacketBuffers[i] = new ReceivedPacketBuffer();
                InitializeReceivedPacketBuffer(_receivedPacketBuffers[i]);
            }

            // wire up our IPv4PacketReceived handler
            _ethernetInterface.IPv4PacketReceived += _ethernetInterface_IPv4PacketReceived;
            // wire up our LinkStateChanged event handler
            _ethernetInterface.LinkStateChanged += _ethernetInterface_LinkStateChanged;

            // start our "loopback thread"
            _loopbackThread = new Thread(LoopbackInBackgroundThread);
            _loopbackThread.Start();

            // create our ICMPv4 handler instance
            _icmpv4Handler = new ICMPv4Handler(this);

            // create our DNS resolver instance
            _dnsResolver = new DnsResolver(this);

            // create our DHCP client instance
            _dhcpv4Client = new DHCPv4Client(this);
            _dhcpv4Client.IpConfigChanged += _dhcpv4Client_IpConfigChanged;
            _dhcpv4Client.DnsConfigChanged += _dhcpv4Client_DnsConfigChanged;

            // if we are configured to use DHCP, then create our DHCPv4Client instance now; its state machine will take care of ip configuration from there
            if (dhcpIpConfigEnabled || dhcpDnsConfigEnabled)
            {
                _dhcpv4Client.IsDhcpIpConfigEnabled = dhcpIpConfigEnabled;
                _dhcpv4Client.IsDhcpDnsConfigEnabled = dhcpDnsConfigEnabled;
            }

            // create our TCP handler instance
            _tcpHandler = new TcpHandler(this);

            // manually fire our LinkStateChanged event to set the initial state of our link.
            _ethernetInterface_LinkStateChanged(_ethernetInterface, _ethernetInterface.GetLinkState());
        }
Beispiel #8
0
        void _ethernetInterface_IPv4PacketReceived(object sender, byte[] buffer, int index, int count)
        {
            // if IPv4 header is less than 20 bytes then drop packet
            if (count < 20)
            {
                return;
            }

            // if version field is not 4 (IPv4) then drop packet
            if ((buffer[index] >> 4) != 4)
            {
                return;
            }

            // get header and datagram lengths
            byte   headerLength = (byte)((buffer[index] & 0x0F) * 4);
            UInt16 totalLength  = (UInt16)((buffer[index + 2] << 8) + buffer[index + 3]);
            // check header checksum; calculating checksum over the entire header--including the checksum value--should result in 0x000.
            UInt16 checksum = Utility.CalculateInternetChecksum(buffer, index, headerLength);

            // if checksum does not match then drop packet
            if (checksum != 0x0000)
            {
                return;
            }

            /* NOTE: while we support reassmbly of fragmented frames, we will not process frames larger than 1536 bytes total. */
            /* NOTE: we have to cache partial frames in this class until all fragments are received (or timeout occurs) since we may not receive the fragment which indicates which socketHandle is the target until the 2nd or later fragment */

            /* TODO: add timer-based function which cleans up timed-out ReceivedPacketBuffers, in case we did not receive all fragments of a frame. */

            /* NOTE: we will enable a 30 second timeout PER INCOMING DATAGRAM; if all fragments have not been received before the timeout then we will discard the datagram from our buffers and send an ICMPv4 Time Exceeded (code 1) message;
             *       we do not restart the timeout after every fragment...it is a maximum timeout for the entire datagram.  also note that we can only send the ICMP timeout if we have received frame 0 (with the source port information) */
            UInt16 identification = (UInt16)((buffer[index + 4] << 8) + buffer[index + 5]);
            byte   flags          = (byte)(buffer[index + 6] >> 5);
            bool   moreFragments  = ((flags & 0x1) == 0x1);

            UInt16 fragmentOffset = (UInt16)((((((UInt16)buffer[index + 6]) & 0x1F) << 8) + buffer[index + 7]) << 3);

            ProtocolType protocol = (ProtocolType)buffer[index + 9];

            // get our source and destination IP addresses
            UInt32 sourceIPAddress      = (UInt32)((buffer[index + 12] << 24) + (buffer[index + 13] << 16) + (buffer[index + 14] << 8) + buffer[index + 15]);
            UInt32 destinationIPAddress = (UInt32)((buffer[index + 16] << 24) + (buffer[index + 17] << 16) + (buffer[index + 18] << 8) + buffer[index + 19]);

            /* save this datagram in an incoming frame buffer; discard it if we do not have enough incoming frame buffers */
            ReceivedPacketBuffer receivedPacketBuffer = GetReceivedPacketBuffer(sourceIPAddress, destinationIPAddress, identification);

            if (receivedPacketBuffer == null) /* if we cannot retrieve or allocate a buffer, drop the packet */
            {
                return;
            }
            bool  fragmentsMissing     = false;
            Int32 actualFragmentLength = System.Math.Max(System.Math.Min(totalLength, count) - headerLength, 0);

            lock (receivedPacketBuffer.LockObject)
            {
                // copy the fragment into our packet buffer
                Array.Copy(buffer, index + headerLength, receivedPacketBuffer.Buffer, fragmentOffset, actualFragmentLength);
                // now recalculate the "holes" in our fragment
                for (int i = 0; i < receivedPacketBuffer.Holes.Length; i++)
                {
                    // if this fragment does not fill this hole, proceed to the next hole
                    if (fragmentOffset > receivedPacketBuffer.Holes[i].LastIndex)
                    {
                        continue;
                    }
                    if (fragmentOffset < receivedPacketBuffer.Holes[i].FirstIndex)
                    {
                        continue;
                    }

                    // this fragment fills part/all of the hole at the current index; clear the current index so we can populate new hole entr(ies)
                    Int32 holeFirstIndex = receivedPacketBuffer.Holes[i].FirstIndex;
                    Int32 holeLastIndex  = receivedPacketBuffer.Holes[i].LastIndex;
                    receivedPacketBuffer.Holes[i].FirstIndex = -1;
                    receivedPacketBuffer.Holes[i].LastIndex  = -1;

                    if (fragmentOffset > holeFirstIndex)
                    {
                        // our fragment does not fill the entire hole; create a hole entry to indicate that the first part of the hole is still not filled.
                        AddReceivedPacketBufferHoleEntry(receivedPacketBuffer, holeFirstIndex, fragmentOffset - 1);
                    }

                    if (fragmentOffset + actualFragmentLength - 1 < holeLastIndex)
                    {
                        // our fragment does not fill the entire hole; create a hole entry to indicate that the last part of the hole is still not filled.
                        AddReceivedPacketBufferHoleEntry(receivedPacketBuffer, fragmentOffset + actualFragmentLength, holeLastIndex);
                    }
                }
                // now determine if there are any missing fragments
                for (int i = 0; i < receivedPacketBuffer.Holes.Length; i++)
                {
                    // if this fragment is the final fragment (which lets us know the total size of our buffer), eliminate the "infinite-reaching" hole
                    if (moreFragments == false)
                    {
                        receivedPacketBuffer.ActualBufferLength = fragmentOffset + actualFragmentLength;
                        if (receivedPacketBuffer.Holes[i].LastIndex == Int32.MaxValue)
                        {
                            if (receivedPacketBuffer.Holes[i].FirstIndex == fragmentOffset + actualFragmentLength)
                            {
                                // this is now just dummy area beyond the datagram; remove it.
                                receivedPacketBuffer.Holes[i].FirstIndex = -1;
                                receivedPacketBuffer.Holes[i].LastIndex  = -1;
                            }
                            else
                            {
                                // modify this hole to end at the proper LastIndex (since we now know the length of our reassembled datagram
                                receivedPacketBuffer.Holes[i].LastIndex = fragmentOffset + actualFragmentLength - 1;
                            }
                        }
                    }

                    if (receivedPacketBuffer.Holes[i].FirstIndex != -1 || receivedPacketBuffer.Holes[i].LastIndex != -1)
                    {
                        fragmentsMissing = true;
                    }
                }
            }

            if (!fragmentsMissing)
            {
                CallSocketPacketReceivedHandler(sourceIPAddress, destinationIPAddress, protocol, receivedPacketBuffer.Buffer, 0, receivedPacketBuffer.ActualBufferLength);
                // since we are caching the buffer locally in the socket class, free the packet buffer.
                InitializeReceivedPacketBuffer(receivedPacketBuffer);
            }
        }
Beispiel #9
0
        public IPv4Layer(EthernetInterface ethernetInterface)
        {
            // save a reference to our Ethernet; we'll use this to push IPv4 frames onto the Ethernet interface
            _ethernetInterface = ethernetInterface;

            // create and configure my ARP resolver; the ARP resolver will automatically wire itself up to receiving incoming ARP frames
            _arpResolver = new ArpResolver(ethernetInterface);

            // retrieve our IP address configuration from the config sector and configure ARP
            object networkInterface    = Netduino.IP.Interop.NetworkInterface.GetNetworkInterface(0);
            bool   dhcpIpConfigEnabled = (bool)networkInterface.GetType().GetMethod("get_IsDhcpEnabled").Invoke(networkInterface, new object[] { });
            /* NOTE: IsDynamicDnsEnabled is improperly implemented in NETMF; it should implement dynamic DNS--but instead it returns whether or not DNS addresses are assigned through DHCP */
            bool dhcpDnsConfigEnabled = (bool)networkInterface.GetType().GetMethod("get_IsDynamicDnsEnabled").Invoke(networkInterface, new object[] { });

            // randomize our ephemeral port assignment counter (so that we don't use the same port #s repeatedly after reboots)
            _nextEphemeralPort = (UInt16)(FIRST_EPHEMERAL_PORT + ((new Random()).NextDouble() * (UInt16.MaxValue - FIRST_EPHEMERAL_PORT - 1)));

            // configure our ARP resolver's default IP address settings
            if (dhcpIpConfigEnabled)
            {
                // in case of DHCP, temporarily set our IP address to IP_ADDRESS_ANY (0.0.0.0)
                _arpResolver.SetIpv4Address(0);
            }
            else
            {
                _ipv4configIPAddress      = ConvertIPAddressStringToUInt32BE((string)networkInterface.GetType().GetMethod("get_IPAddress").Invoke(networkInterface, new object[] { }));
                _ipv4configSubnetMask     = ConvertIPAddressStringToUInt32BE((string)networkInterface.GetType().GetMethod("get_SubnetMask").Invoke(networkInterface, new object[] { }));
                _ipv4configGatewayAddress = ConvertIPAddressStringToUInt32BE((string)networkInterface.GetType().GetMethod("get_GatewayAddress").Invoke(networkInterface, new object[] { }));
                _arpResolver.SetIpv4Address(_ipv4configIPAddress);
            }
            // retrieve our DnsServer IP address configuration
            if (!dhcpDnsConfigEnabled)
            {
                string[] dnsAddressesString = (string[])networkInterface.GetType().GetMethod("get_DnsAddresses").Invoke(networkInterface, new object[] { });
                _ipv4configDnsServerAddresses = new UInt32[dnsAddressesString.Length];
                for (int iDnsAddress = 0; iDnsAddress < _ipv4configDnsServerAddresses.Length; iDnsAddress++)
                {
                    _ipv4configDnsServerAddresses[iDnsAddress] = ConvertIPAddressStringToUInt32BE(dnsAddressesString[iDnsAddress]);
                }
            }

            // initialize our buffers
            for (int i = 0; i < _receivedPacketBuffers.Length; i++)
            {
                _receivedPacketBuffers[i] = new ReceivedPacketBuffer();
                InitializeReceivedPacketBuffer(_receivedPacketBuffers[i]);
            }

            // wire up our IPv4PacketReceived handler
            _ethernetInterface.IPv4PacketReceived += _ethernetInterface_IPv4PacketReceived;
            // wire up our LinkStateChanged event handler
            _ethernetInterface.LinkStateChanged += _ethernetInterface_LinkStateChanged;

            // start our "loopback thread"
            _loopbackThread = new Thread(LoopbackInBackgroundThread);
            _loopbackThread.Start();

            // create our ICMPv4 handler instance
            _icmpv4Handler = new ICMPv4Handler(this);

            // create our DNS resolver instance
            _dnsResolver = new DnsResolver(this);

            // create our DHCP client instance
            _dhcpv4Client = new DHCPv4Client(this);
            _dhcpv4Client.IpConfigChanged  += _dhcpv4Client_IpConfigChanged;
            _dhcpv4Client.DnsConfigChanged += _dhcpv4Client_DnsConfigChanged;

            // if we are configured to use DHCP, then create our DHCPv4Client instance now; its state machine will take care of ip configuration from there
            if (dhcpIpConfigEnabled || dhcpDnsConfigEnabled)
            {
                _dhcpv4Client.IsDhcpIpConfigEnabled  = dhcpIpConfigEnabled;
                _dhcpv4Client.IsDhcpDnsConfigEnabled = dhcpDnsConfigEnabled;
            }

            // create our TCP handler instance
            _tcpHandler = new TcpHandler(this);

            // manually fire our LinkStateChanged event to set the initial state of our link.
            _ethernetInterface_LinkStateChanged(_ethernetInterface, _ethernetInterface.GetLinkState());
        }
        internal void InitializeReceivedPacketBuffer(ReceivedPacketBuffer buffer)
        {
            buffer.SourceIPAddress = 0;
            buffer.SourceIPPort = 0;

            if (buffer.Buffer == null)
                buffer.Buffer = new byte[1500]; /* TODO: determine correct maximum size and make this a const */
            buffer.BufferBytesFilled = 0;

            buffer.IsEmpty = true;
            if (buffer.LockObject == null)
                buffer.LockObject = new object();
        }