/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // /////////////////////////////////////////////////////////////////////////////// /** * Microsoft Research, Cambridge * author: Yaron Weinsberg, Richard Black */ using NetStack.Common; using System; using System.Collections; using System.Net.IP; using Drivers.Net; using NetStack.NetDrivers; using NetStack.Protocols; #if !SINGULARITY using System.Reflection; using System.Net; #endif using Microsoft.Contracts; namespace NetStack.Runtime { // define the InterfaceList public class InterfaceList : ArrayList {} /** * The local host IP configuration */ public class HostConfiguration { private string hostname; private string domainname; private bool isRouter; private RoutingTable! routingTable; private IList! nameServers; private IPAdapterBindingTable! bindings; private ArrayList! dhcpClients; [NotDelayed] public HostConfiguration() { isRouter = false; RoutingTable rt = new RoutingTable(); routingTable = rt; bindings = new IPAdapterBindingTable(rt); nameServers = ArrayList.Synchronized(new ArrayList()); dhcpClients = new ArrayList(); base(); SetHostName("singularity"); SetDomainName("microsoft.com"); routingTable.AddRoute( new RouteEntry(IPv4Network.Loopback, IPv4.Loopback, IPv4.Loopback, RouteEntry.InterfaceMetric, RouteEntry.InterfaceRouteTag) ); } public string! GetHostName() { return hostname; } public bool SetHostName(string! name) { int dot = name.IndexOf('.'); if (dot >= 0) { string hostpart = name.Substring(0, dot); string domainpart = name.Substring(dot + 1); if ((ValidDnsName(hostpart, false) == false) || (ValidDnsName(domainpart, true) == false)) return false; hostname = hostpart; domainname = domainpart; return true; } if (ValidDnsName(name, false) == false) return false; hostname = name; return true; } public string! GetDomainName() { return domainname; } public bool SetDomainName(string! name) { if (ValidDnsName(name, true) == false) { return false; } domainname = name; return true; } private static bool ValidDnsName(string! name, bool dotsAllowed) { if (name.Length <= 2) return false; // Dashes are okay as long as not first or last character int last = name.Length - 1; if (name[0] == '-' || name[last] == '-') return false; for (int i = 0; i <= last; i++) { // Letters, digits, and dashes are okay if (Char.IsLetterOrDigit(name[i]) == true || name[i] == '-') continue; // Dots are okay in domain-names if (name[i] == '.' && dotsAllowed == true) continue; return false; } return true; } public bool IsRouter { get { return isRouter; } } public RoutingTable! RoutingTable { get { return routingTable; } } public IPAdapterBindingTable! Bindings { get { return bindings; } } public void AddNameServer(IPv4 address) { nameServers.Add(address); } public bool DeleteNameServer(IPv4 address) { lock (nameServers.SyncRoot) { int index = this.nameServers.IndexOf(address); if (index < 0) return false; nameServers.RemoveAt(index); return true; } } /// /// Get enumerable interface of IPv4 collection /// containing name servers. /// public IEnumerable! NameServers() { return nameServers; } /// /// Get the current name server. /// public IPv4 GetCurrentNameServer() { lock (nameServers.SyncRoot) { if (nameServers.Count > 0) { return (IPv4) (!) nameServers[0]; } return IPv4.Zero; } } /// /// Rotate name servers. /// public void RotateNameServers() { lock (nameServers.SyncRoot) { if (nameServers.Count < 2) return; IPv4 retiree = (IPv4) (!) nameServers[0]; nameServers.RemoveAt(0); nameServers.Add(retiree); } } public bool IsLocalAddress(IPv4 ipAddress) { return bindings.IsLocalAddress(ipAddress); } public bool StartDhcp(IAdapter adapter) { lock (dhcpClients) { foreach (DhcpClient! client in dhcpClients) { if (client.Adapter == adapter) return false; } DhcpClient dc = new DhcpClient(adapter); dc.Start(); dhcpClients.Add(dc); } return true; } public bool StopDhcp(IAdapter adapter) { lock (dhcpClients) { for (int i = 0; i < dhcpClients.Count; i++) { DhcpClient client = (DhcpClient!) dhcpClients[i]; if (client.Adapter == adapter) { client.Stop(); dhcpClients.RemoveAt(i); return true; } } } return false; } public bool IsRunningDhcp(IAdapter adapter) { lock (dhcpClients) { foreach (DhcpClient! client in dhcpClients) { if (client.Adapter == adapter) return true; } } return false; } } // an interface ip address public class InterfaceIPConfiguration { IPv4 address; IPv4 netmask; IPv4 gateway; int ttl; public InterfaceIPConfiguration(IPv4 address, IPv4 netmask, IPv4 gateway, int ttl) { this.address = address; this.netmask = netmask; this.gateway = gateway; this.ttl = ttl; } public InterfaceIPConfiguration(IPv4 address, IPv4 netmask, IPv4 gateway) : this(address, netmask, gateway, IPFormat.DefaultTTL) { } public IPv4 Address { get { return address; } } public IPv4 NetMask { get { return netmask; } } public IPv4 Gateway { get { return gateway; } } public int TTL { get { return ttl; } set { ttl = value; } } } // this is the local ip table entry // binds an IP to a specific adapter public class IPBinding { private IAdapter! adapter; private InterfaceIPConfiguration! ipConfig; public IPBinding(IAdapter! ad, InterfaceIPConfiguration! ipc) { adapter = ad; ipConfig = ipc; base(); } public IAdapter! Adapter { get { return adapter; } } public InterfaceIPConfiguration! IPConfiguration { get { return ipConfig; } } } public class IPAdapterBindingTable { Hashtable ipBindings; // RoutingTable routingTable; public IPAdapterBindingTable(RoutingTable routingTable) { this.ipBindings = new Hashtable(); this.routingTable = routingTable; } private void AddInterfaceRoutes(InterfaceIPConfiguration! ipConfig) { // // Add subnet route // IPv4Network subnet = new IPv4Network(ipConfig.Address, ipConfig.NetMask); routingTable.AddRoute( new RouteEntry(subnet, ipConfig.Address, ipConfig.Address, RouteEntry.DirectlyConnectedMetric, RouteEntry.InterfaceRouteTag) ); // // Add route to gateway // routingTable.AddRoute( new RouteEntry(ipConfig.Gateway, ipConfig.Address, ipConfig.Address, RouteEntry.DirectlyConnectedMetric, RouteEntry.InterfaceRouteTag) ); // // Add default route if none exists // if (routingTable.Lookup(IPv4Network.Default) == null) { routingTable.AddRoute( new RouteEntry(IPv4Network.Default, ipConfig.Gateway, ipConfig.Address, RouteEntry.DefaultRouteMetric, RouteEntry.InterfaceRouteTag) ); } } private void DeleteInterfaceRoutes(InterfaceIPConfiguration! ipConfig) { routingTable.DeleteInterfaceRoutes(ipConfig.Address); } public bool Add(IAdapter! adapter, InterfaceIPConfiguration! ipConfig) { if (ipBindings[ipConfig.Address] != null) { return false; } ipBindings[ipConfig.Address] = new IPBinding(adapter, ipConfig); AddInterfaceRoutes(ipConfig); return true; } /// /// Delete all IP address bindings associated with adapter. /// public void Flush(IAdapter adapter) { Stack flushItems = new Stack(); foreach (IPBinding! ipb in ipBindings.Values) { if (ipb.Adapter == adapter) { flushItems.Push(ipb.IPConfiguration); } } while (flushItems.Count != 0) { Flush((InterfaceIPConfiguration!) flushItems.Pop()); } } /// /// Delete specific IP address binding from adapter. /// internal void Flush(IAdapter adapter, IPv4 address) { IPBinding ipb = (IPBinding) ipBindings[address]; if (ipb != null && ipb.Adapter == adapter) { Flush(ipb.IPConfiguration); } } private void Flush(InterfaceIPConfiguration! ipConfig) { DeleteInterfaceRoutes(ipConfig); ipBindings.Remove(ipConfig.Address); } public IAdapter GetAdapter(IPv4 address) { IPBinding ipb = (IPBinding) ipBindings[address]; if (ipb == null) { return null; } return ipb.Adapter; } // is the given ip defined? public bool IsLocalAddress(IPv4 ipAddress) { return ipBindings[ipAddress] != null; } public ArrayList! GetAdapterIPConfigurations(IAdapter adapter) { ArrayList results = new ArrayList(); foreach (IPBinding! ipb in ipBindings.Values) { if (ipb.Adapter == adapter) results.Add(ipb.IPConfiguration); } return results; } } }