/// <summary> /// Resolves the specified IPv4 address to a Layer-2 (MAC-48) /// physical address. /// </summary> /// <param name="ifc">The interface to look an address up for.</param> /// <param name="ipAddress">The IPv4 address to resolve.</param> /// <exception cref="ArgumentNullException">Thrown if either of the /// arguments is null.</exception> /// <remarks>This API is exposed to the next higher-up layer. In other /// words, it is called by the Network layer to resolve an IPv4 address /// to the corresponding MAC-48 address.</remarks> public void Resolve(Interface ifc, IpAddress ipAddress) { ifc.ThrowIfNull("ifc"); ipAddress.ThrowIfNull("ipAddress"); // If there's already a pending ARP request for the IP, don't // issue another one. if (arpInProgress.Contains(ipAddress)) { return; } // Output an ARP request to physical broadcast address // FF:FF:FF:FF:FF:FF. arpInProgress.Add(ipAddress); ArpPacket packet = new ArpPacket(ifc.Nic.MacAddress, ifc.IpAddress, ipAddress); WriteLine(ifc.FullName + " is constructing an ARP request for " + ipAddress + "."); output(ifc, broadcastAddress, packet); }
/// <summary> /// Examines and processes the ARP message contained in the specified byte /// array. /// </summary> /// <param name="ifc">The interface through which the data was /// received.</param> /// <param name="data">A sequence of bytes containing an ARP packet.</param> /// <exception cref="ArgumentNullException">Thrown if either parameter /// is null.</exception> /// <exception cref="SerializationException">Thrown if the data array does /// not contain a valid ARP packet.</exception> public void OnInput(Interface ifc, byte[] data) { ifc.ThrowIfNull("ifc"); data.ThrowIfNull("data"); WriteLine(ifc.FullName + " has received an ARP message."); var packet = ArpPacket.Deserialize(data); // If it's our own packet, don't do anything with it. if (packet.MacAddressSender == ifc.Nic.MacAddress) { return; } // Update our ARP cache with the sender's information. if (!cache.ContainsKey(ifc.Name)) { cache.Add(ifc.Name, new ArpCache()); } cache[ifc.Name].Add(packet.IpAddressSender, new ArpEntry(packet.IpAddressSender, packet.MacAddressSender)); if (packet.IsResponse) { WriteLine(ifc.FullName + " is updating its ARP table with [" + packet.IpAddressSender + ", " + packet.MacAddressSender + "]"); } // Remove IP address from pending list, if present. arpInProgress.Remove(packet.IpAddressSender); if (packet.IsRequest) { // It's an ARP request and we are the recipient, so send an ARP reply // back to the sender. if (packet.IpAddressTarget == ifc.IpAddress) { var response = new ArpPacket(ifc.Nic.MacAddress, packet.IpAddressTarget, packet.MacAddressSender, packet.IpAddressSender); WriteLine(ifc.FullName + " is constructing an ARP response for " + packet.IpAddressSender + "."); output(ifc, packet.MacAddressSender, response); } } }
/// <summary> /// Resolves the specified IPv4 address to a Layer-2 (MAC-48) /// physical address. /// </summary> /// <param name="ifc">The interface to look an address up for.</param> /// <param name="ipAddress">The IPv4 address to resolve.</param> /// <exception cref="ArgumentNullException">Thrown if either of the /// arguments is null.</exception> /// <remarks>This API is exposed to the next higher-up layer. In other /// words, it is called by the Network layer to resolve an IPv4 address /// to the corresponding MAC-48 address.</remarks> public void Resolve(Interface ifc, IpAddress ipAddress) { ifc.ThrowIfNull("ifc"); ipAddress.ThrowIfNull("ipAddress"); // If there's already a pending ARP request for the IP, don't // issue another one. if (arpInProgress.Contains(ipAddress)) return; // Output an ARP request to physical broadcast address // FF:FF:FF:FF:FF:FF. arpInProgress.Add(ipAddress); ArpPacket packet = new ArpPacket(ifc.Nic.MacAddress, ifc.IpAddress, ipAddress); WriteLine(ifc.FullName + " is constructing an ARP request for " + ipAddress + "."); output(ifc, broadcastAddress, packet); }
/// <summary> /// Examines and processes the ARP message contained in the specified byte /// array. /// </summary> /// <param name="ifc">The interface through which the data was /// received.</param> /// <param name="data">A sequence of bytes containing an ARP packet.</param> /// <exception cref="ArgumentNullException">Thrown if either parameter /// is null.</exception> /// <exception cref="SerializationException">Thrown if the data array does /// not contain a valid ARP packet.</exception> public void OnInput(Interface ifc, byte[] data) { ifc.ThrowIfNull("ifc"); data.ThrowIfNull("data"); WriteLine(ifc.FullName + " has received an ARP message."); var packet = ArpPacket.Deserialize(data); // If it's our own packet, don't do anything with it. if (packet.MacAddressSender == ifc.Nic.MacAddress) return; // Update our ARP cache with the sender's information. if (!cache.ContainsKey(ifc.Name)) cache.Add(ifc.Name, new ArpCache()); cache[ifc.Name].Add(packet.IpAddressSender, new ArpEntry(packet.IpAddressSender, packet.MacAddressSender)); if(packet.IsResponse) WriteLine(ifc.FullName + " is updating its ARP table with [" + packet.IpAddressSender + ", " + packet.MacAddressSender + "]"); // Remove IP address from pending list, if present. arpInProgress.Remove(packet.IpAddressSender); if (packet.IsRequest) { // It's an ARP request and we are the recipient, so send an ARP reply // back to the sender. if (packet.IpAddressTarget == ifc.IpAddress) { var response = new ArpPacket(ifc.Nic.MacAddress, packet.IpAddressTarget, packet.MacAddressSender, packet.IpAddressSender); WriteLine(ifc.FullName + " is constructing an ARP response for " + packet.IpAddressSender + "."); output(ifc, packet.MacAddressSender, response); } } }