/// <summary>Parses Arp Packets and writes to the Ethernet the translation.</summary>
/// <remarks>IpopRouter makes nodes think they are in the same Layer 2 network
/// so that two nodes in the same network can communicate directly with each
/// other. IpopRouter masquerades for those that are not local.</remarks>
/// <param name="ep">The Ethernet packet to translate</param>
protected virtual void HandleArp(MemBlock packet)
{
// Can't do anything until we have network connectivity!
if (_dhcp_server == null)
{
return;
}
ArpPacket ap = new ArpPacket(packet);
// Not in our range!
if (!_dhcp_server.IPInRange((byte[])ap.TargetProtoAddress) &&
!_dhcp_server.IPInRange((byte[])ap.SenderProtoAddress))
{
ProtocolLog.WriteIf(IpopLog.Arp, String.Format("Bad Arp request from {0} for {1}",
Utils.MemBlockToString(ap.SenderProtoAddress, '.'),
Utils.MemBlockToString(ap.TargetProtoAddress, '.')));
return;
}
if (ap.Operation == ArpPacket.Operations.Reply)
{
// This would be a unsolicited Arp
if (ap.TargetProtoAddress.Equals(IPPacket.BroadcastAddress) &&
!ap.SenderHWAddress.Equals(EthernetPacket.BroadcastAddress))
{
HandleNewStaticIP(ap.SenderHWAddress, ap.SenderProtoAddress);
}
return;
}
// We only support request operation hereafter
if (ap.Operation != ArpPacket.Operations.Request)
{
return;
}
// Must return nothing if the node is checking availability of IPs
// Or he is looking himself up.
if (_ip_to_ether.ContainsKey(ap.TargetProtoAddress) ||
ap.SenderProtoAddress.Equals(IPPacket.BroadcastAddress) ||
ap.SenderProtoAddress.Equals(IPPacket.ZeroAddress))
{
return;
}
if (!ap.TargetProtoAddress.Equals(MemBlock.Reference(_dhcp_server.ServerIP)))
{
// Do not return messages if there is no connection to the remote address
Address baddr = null;
try {
baddr = _address_resolver.Resolve(ap.TargetProtoAddress);
} catch (AddressResolutionException ex) {
if (ex.Issue != AddressResolutionException.Issues.DoesNotExist)
{
throw;
}
// Otherwise nothing to do, mapping doesn't exist...
}
if (AppNode.Node.Address.Equals(baddr) || baddr == null)
{
ProtocolLog.WriteIf(IpopLog.Arp, String.Format("No mapping for: {0}",
Utils.MemBlockToString(ap.TargetProtoAddress, '.')));
return;
}
if (!_conn_handler.ContainsAddress(baddr))
{
ProtocolLog.WriteIf(IpopLog.Arp, String.Format(
"No connection to {0} for {1}", baddr,
Utils.MemBlockToString(ap.TargetProtoAddress, '.')));
_conn_handler.ConnectTo(baddr);
return;
}
}
ProtocolLog.WriteIf(IpopLog.Arp, String.Format("Sending Arp response for: {0}",
Utils.MemBlockToString(ap.TargetProtoAddress, '.')));
ArpPacket response = ap.Respond(EthernetPacket.UnicastAddress);
EthernetPacket res_ep = new EthernetPacket(ap.SenderHWAddress,
EthernetPacket.UnicastAddress, EthernetPacket.Types.Arp,
response.ICPacket);
Ethernet.Send(res_ep.ICPacket);
}