# HG changeset patch # User Sebastien Bindel # Date 1478367507 -3600 # Parent e790e7c3331c32c901c14fda801cc99cfc993e43 internet: (fixes #2483) ARP Request reception add an ARP table entry - RFC 826 diff --git a/src/internet/model/arp-l3-protocol.cc b/src/internet/model/arp-l3-protocol.cc --- a/src/internet/model/arp-l3-protocol.cc +++ b/src/internet/model/arp-l3-protocol.cc @@ -175,7 +175,7 @@ // // If we're connected to a real world network, then some of the fields sizes // in an ARP packet can vary in ways not seen in simulations. We need to be - // able to detect ARP packets with headers we don't recongnize and not process + // able to detect ARP packets with headers we don't recognize and not process // them instead of crashing. The ArpHeader will return 0 if it can't deal // with the received header. // @@ -198,25 +198,49 @@ NS_LOG_LOGIC (cache->GetInterface ()->GetAddress (i).GetLocal () << ", "); } - /** - * \internal - * Note: we do not update the ARP cache when we receive an ARP request - * from an unknown node. See \bugid{107} - */ bool found = false; for (uint32_t i = 0; i < cache->GetInterface ()->GetNAddresses (); i++) { if (arp.IsRequest () && arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress (i).GetLocal ()) { + ArpCache::Entry *entry = cache->Lookup (arp.GetSourceIpv4Address ()); + if (entry!=0) + { + if (entry->IsWaitReply ()) + { + NS_LOG_LOGIC ("node=" << m_node->GetId () << ", got request from " << + arp.GetSourceIpv4Address () << + " for waiting entry -- flush and later send reply"); + entry->MarkAlive (arp.GetSourceHardwareAddress ()); + } + else + { + // Ignore-- already have an entry + NS_LOG_LOGIC("node=" << m_node->GetId () << ", got request from " << + arp.GetSourceIpv4Address () << " for non-waiting entry"); + entry->UpdateSeen (); + } + } + else + { + // No entry for this source, but add one now (RFC 826) + NS_LOG_LOGIC("node=" << m_node->GetId () << ", got request from " << + arp.GetSourceIpv4Address () << + " for non-existent entry -- adding "); + ArpCache::Entry *newEntry = cache->Add (arp.GetSourceIpv4Address ()); + newEntry->SetMacAddresss (arp.GetSourceHardwareAddress ()); + newEntry->UpdateSeen (); + } + found = true; - NS_LOG_LOGIC ("node="<GetId () <<", got request from " << + NS_LOG_LOGIC ("node="<GetId () <<", got request from " << arp.GetSourceIpv4Address () << " -- send reply"); SendArpReply (cache, arp.GetDestinationIpv4Address (), arp.GetSourceIpv4Address (), arp.GetSourceHardwareAddress ()); break; - } - else if (arp.IsReply () && + } + else if (arp.IsReply () && arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress (i).GetLocal ()) && arp.GetDestinationHardwareAddress () == device->GetAddress ()) { @@ -228,8 +252,8 @@ if (entry->IsWaitReply ()) { NS_LOG_LOGIC ("node="<< m_node->GetId () << - ", got reply from " << arp.GetSourceIpv4Address () - << " for waiting entry -- flush"); + ", got reply from " << arp.GetSourceIpv4Address () << + " for waiting entry -- flush"); Address from_mac = arp.GetSourceHardwareAddress (); entry->MarkAlive (from_mac); ArpCache::Ipv4PayloadHeaderPair pending = entry->DequeuePending (); @@ -243,8 +267,8 @@ else { // ignore this reply which might well be an attempt - // at poisening my arp cache. - NS_LOG_LOGIC ("node="<GetId ()<<", got reply from " << + // at poisoning my arp cache. + NS_LOG_LOGIC ("node=" << m_node->GetId () << ", got reply from " << arp.GetSourceIpv4Address () << " for non-waiting entry -- drop"); m_dropTrace (packet); @@ -252,7 +276,7 @@ } else { - NS_LOG_LOGIC ("node="<GetId ()<<", got reply for unknown entry -- drop"); + NS_LOG_LOGIC ("node=" << m_node->GetId () << ", got reply for unknown entry -- drop"); m_dropTrace (packet); } break; @@ -260,7 +284,7 @@ } if (found == false) { - NS_LOG_LOGIC ("node="<GetId ()<<", got request from " << + NS_LOG_LOGIC ("node=" << m_node->GetId () << ", got request from " << arp.GetSourceIpv4Address () << " for unknown address " << arp.GetDestinationIpv4Address () << " -- drop"); }