/// <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); }