Beispiel #1
0
		/// <summary>
		/// Looks up the Layer-2 (MAC-48) physical address in the ARP cache for
		/// the specified IPv4 address.
		/// </summary>
		/// <param name="ifc">The interface to look an address up for.</param>
		/// <param name="ipAddress">The IPv4 address to look up the respective
		/// MAC-48 address for.</param>
		/// <returns>A MAC-48 address or null if the lookup could not be satisfied
		/// from the ARP cache.</returns>
		/// <exception cref="ArgumentNullException">Thrown if the ipAddress parameter
		/// is null.</exception>
		public MacAddress Lookup(Interface ifc, IpAddress ipAddress) {
			ipAddress.ThrowIfNull("ipAddress");
			if (!cache.ContainsKey(ifc.Name))
				cache.Add(ifc.Name, new ArpCache());
			ArpEntry entry = cache[ifc.Name][ipAddress];
			if (entry != null && entry.Expired == false)
				return entry.MacAddress;
			return null;
		}
Beispiel #2
0
        /// <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);
		}
Beispiel #3
0
        /// <summary>
        /// Initializes a new instance.
        /// </summary>
        /// <param name="destination">The IP address of the destination network. This,
        /// together with the netmask describes the destination network id.</param>
        /// <param name="netmask">The netmask that, together with the destination
        /// parameter describes the destination network id.</param>
        /// <param name="gateway">The gateway through which the destination network
        /// can be reached.</param>
        /// <param name="interface">The local interface through which the gateway
        /// can be reached.</param>
        /// <param name="metric">The metric of using the route.</param>
        void Init(IpAddress destination, IpAddress netmask, IpAddress gateway,
			Interface @interface, int metric) {
			destination.ThrowIfNull(nameof(destination));
			netmask.ThrowIfNull(nameof(netmask));
			@interface.ThrowIfNull(nameof(@interface));
			if (metric < 0)
				throw new ArgumentException("The metric value must be greater than " +
					"or equal to zero.", nameof(metric));
			Destination = destination;
			Netmask = netmask;
			Gateway = gateway;
			Interface = @interface;
			Metric = metric;
		}
Beispiel #4
0
        /// <summary>
        /// Initializes a new instance of the Route class.
        /// </summary>
        /// <param name="cidrNetworkId">The network id of the destination network in
        /// CIDR notation.</param>
        /// <param name="gateway">The gateway through which the destination network
        /// can be reached.</param>
        /// <param name="interface">The local interface through which the gateway
        /// can be reached.</param>
        /// <param name="metric">The metric of using the route.</param>
        public Route(string cidrNetworkId, string gateway,
			Interface @interface, int metric) {
				var tuple = IpAddress.ParseCIDRNotation(cidrNetworkId);
				Init(tuple.Item1, tuple.Item2, gateway != null ? new IpAddress(gateway)
					: null, @interface, metric);
		}
Beispiel #5
0
        /// <summary>
        /// Initializes a new instance of the Route class.
        /// </summary>
        /// <param name="destination">The IP address of the destination network. This,
        /// together with the netmask describes the destination network id.</param>
        /// <param name="netmask">The netmask that, together with the destination
        /// parameter describes the destination network id.</param>
        /// <param name="gateway">The gateway through which the destination network
        /// can be reached.</param>
        /// <param name="interface">The local interface through which the gateway
        /// can be reached.</param>
        /// <param name="metric">The metric of using the route.</param>
		public Route(IpAddress destination, IpAddress netmask,
			IpAddress gateway, Interface @interface, int metric) {
				Init(destination, netmask, gateway, @interface, metric);
		}
Beispiel #6
0
		/// <summary>
		/// Returns an enumerable collection of ARP entries for the specified
		/// interface.
		/// </summary>
		/// <param name="ifc">The interface whose ARP table to return.</param>
		/// <returns>An enumerable collection of ARP entries.</returns>
		/// <exception cref="ArgumentNullException">Thrown if the ifc parameter
		/// is null.</exception>
		public IEnumerable<ArpEntry> ArpTableOf(Interface ifc) {
			ifc.ThrowIfNull("ifc");
			if (!cache.ContainsKey(ifc.Name))
				cache.Add(ifc.Name, new ArpCache());
			return cache[ifc.Name].Values;
		}
Beispiel #7
0
		/// <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);
				}
			}
		}
Beispiel #8
0
	    /// <summary>
	    /// Registers a new network interface with the host.
	    /// </summary>
	    /// <param name="ifc"></param>
	    /// <exception cref="ArgumentNullException">Thrown if any of the
	    /// arguments is null.</exception>
	    public void RegisterInterface(Interface ifc) {
			ifc.ThrowIfNull("ifc");
			Interfaces.Add(ifc.Name, ifc);

			ifc.Hostname = Hostname;

			// Delegate the interface's events to the network stack.
			ifc.DataReceivedEvent += (sender, args) =>
				Network.OnInput(sender as Interface, args.Data, args.Type);
			ifc.SendFifoEmptyEvent += (sender, args) =>
				Network.OnAvailableToSent(sender as Interface);
		}
Beispiel #9
0
        /// <summary>
        /// Adds a route to the host's routing table.
        /// </summary>
        /// <param name="cidrNetworkId">The destination subnet specified in CIDR notation.</param>
        /// <param name="gateway">The gateway through which the destination network can be
        /// reached.</param>
        /// <param name="interface">The local interface through which the gateway can be
        /// reached.</param>
        /// <param name="metric">The added cost of using the route.</param>
        /// <param name="index">The index or row number at which to insert the route into
        /// the routing table.</param>
		public void AddRoute(string cidrNetworkId, string gateway,
			Interface @interface, int metric, int? index = null) {
				AddRoute(new Route(cidrNetworkId, gateway, @interface, metric));
		}