Encapsulates an Arp Packet and provides the mechanisms to generate new Arp Packets. This is immutable.
The Header is of the format: Field Position Hardware Type2 Bytes Protocol Type2 Bytes Hardware Length1 Byte Protocol Length1 Byte Operation2 Bytes Sender HW AddressHW Length Sender Proto AddressProto Length Target HW AddressHW Length Target Proto AddressProto Length
Inheritance: NetworkPacket
Ejemplo n.º 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);
    }