Beispiel #1
0
        // makes a room for a new entry, get rid of
        // the least recently used entry (LRU)
        public void PurgeLRUEntry()
        {
            if (arpEntries.Count == 0)
            {
                return;
            }

            // can use a LRU list to avoid O(n)
            // but this is a kind of a small table...
            IDictionaryEnumerator dicEnum = arpEntries.GetEnumerator();

            dicEnum.MoveNext();  // get the first entry

            ArpEntry lruElement = (ArpEntry)dicEnum.Value;

            while (dicEnum.MoveNext())
            {
                ArpEntry current = (ArpEntry)dicEnum.Value;
                if (current.EntryAge < lruElement.EntryAge)
                {
                    lruElement = current;
                }
            }
            RemoveEntry(lruElement);
        }
Beispiel #2
0
 // add a new entry
 // return false if there is no more room
 public bool AddEntry(ArpEntry e)
 {
     // if no more room, make one
     if (arpEntries.Count >= maxEntries)
     {
         PurgeLRUEntry();
     }
     e.EntryAge = this.defaultAge;
     arpEntries.Add(e.IPAddress, e);
     DebugPrint("Added entry {0}\n", e);
     return(true);
 }
Beispiel #3
0
        // an upper layer interface to get the mac
        // to a target IP. The upper protocol must
        // provide the Mux for the target IP.
        // if we have it then we return true + macAddress
        // and refresh the age to create a LRU list
        public bool Lookup(IPv4 targetIP, out EthernetAddress macAddress)
        {
            ArpEntry e = arpEntries[targetIP] as ArpEntry;

            if (e != null)
            {
                e.EntryAge = Age;
                macAddress = e.MacAddress;
                return(true);
            }
            macAddress = EthernetAddress.Zero;
            return(false);
        }
Beispiel #4
0
 private void RemoveEntry(ArpEntry e)
 {
     arpEntries.Remove(e.IPAddress);
     DebugPrint("Removed entry for {0}\n", e);
 }
Beispiel #5
0
        // Original note from Yaron:
        // ARP logic: see RFC 826 http://www.faqs.org/rfcs/rfc826.html
        //

        public void ProcessIncomingPacket(Bytes packet, IAdapter adapter)
        {
            //Get the ARP packet info located after the ethernet header
            ArpHeader arpHeader = new ArpHeader(packet, 14);

            DebugPrint("ARP: ProcessIncomingPacket\n");
            //do some checks to make sure the packet is copacetic
            if (arpHeader.htype != 0x1)
            {
                DebugPrint("ARP: ProcessIncomingPacket got wrong hardware type? 0x{0,8:x}\n",
                           arpHeader.htype);
                //delete packet;
                return;
            }

            if (arpHeader.ptype != 0x0800)
            {
                DebugPrint("ARP: ProcessIncomingPacket got wrong  protocol? 0x{0,8:x}\n",
                           arpHeader.ptype);
                //delete packet;
                return;
            }
            //ethernet address should be 6 bytes
            if (arpHeader.hlen != 6)
            {
                DebugPrint("ARP: ProcessIncomingPacket got wrong hw length? 0x{0,8:x}\n",
                           arpHeader.hlen);
                //delete packet;
                return;
            }

            if (arpHeader.plen != 4)
            {
                DebugPrint("ARP: ProcessIncomingPacket got wrong protocol address length? 0x{0,8:x}\n",
                           arpHeader.plen);
                //delete packet;
                return;
            }


            DebugPrint("Incoming packet\n");

            bool     merged  = false;
            bool     updated = false;
            ArpEntry target  = arpTable.Lookup(arpHeader.senderIPAddr);

            if (target != null && target.Dynamic == true)
            {
                DebugPrint("ARP UPDATE\n");
                // we have it already - just update the details...
                target.MacAddress = arpHeader.senderEthernetAddr;
                target.EntryAge   = arpTable.Age;
                merged            = true;
                updated           = true;
            }

            if (merged == false)
            {
                DebugPrint("ARP ADDITION\n");
                arpTable.AddEntry(new ArpEntry(arpHeader.senderIPAddr,
                                               arpHeader.senderEthernetAddr, true));
                merged = true;
                UpdatePendingRequests(arpHeader.senderIPAddr, arpHeader.senderEthernetAddr);
            }

            //Is this a local address
            bool forSelf = IP.IsLocalAddress(arpHeader.destIPAddr);

            if (forSelf == false)
            {
                //delete packet;
                return;
            }

            // now figure out the opcode
            if (arpHeader.op == ARP_REQUEST)
            {
                DebugPrint("Handling request ({0},{1}) ---> ({2},{3} \npkt dest {4} {5})\n",
                           arpHeader.senderIPAddr, arpHeader.senderEthernetAddr,
                           arpHeader.destIPAddr, adapter.HardwareAddress,
                           arpHeader.destIPAddr, arpHeader.destEthernetAddr
                           );

                int dataLength = EthernetHeader.Size + ArpHeader.Size;
                VTable.Assert(packet.Length >= dataLength);

                Bytes data = Bitter.SplitOff(ref packet, EthernetHeader.Size);

                EthernetHeader.Write(packet,
                                     adapter.HardwareAddress,
                                     arpHeader.senderEthernetAddr,
                                     EthernetHeader.PROTOCOL_ARP);

                //use arp header to format reply
                ArpHeader.Write(data, adapter.HardwareAddress,
                                arpHeader.destIPAddr, ArpHeader.ARP_REPLY,
                                arpHeader.senderEthernetAddr, arpHeader.senderIPAddr);
                adapter.PopulateTxRing(packet, data);
            }
            else
            {
                // otherwise we are done
                DebugPrint(
                    "Handling reply ({2},{3}) <--- ({0},{1})\n",
                    arpHeader.senderIPAddr, arpHeader.senderEthernetAddr,
                    arpHeader.destIPAddr, arpHeader.destEthernetAddr
                    );
                //delete packet;
            }

            if (merged && !updated)
            {
                DebugPrint(arpTable.ToString());
            }
        }