예제 #1
0
        /// <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);
        }