470 lines
13 KiB
C#
470 lines
13 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// 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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get enumerable interface of IPv4 collection
|
||
|
/// containing name servers.
|
||
|
/// </summary>
|
||
|
public IEnumerable! NameServers()
|
||
|
{
|
||
|
return nameServers;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the current name server.
|
||
|
/// </summary>
|
||
|
public IPv4 GetCurrentNameServer()
|
||
|
{
|
||
|
lock (nameServers.SyncRoot)
|
||
|
{
|
||
|
if (nameServers.Count > 0)
|
||
|
{
|
||
|
return (IPv4) (!) nameServers[0];
|
||
|
}
|
||
|
return IPv4.Zero;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Rotate name servers.
|
||
|
/// </summary>
|
||
|
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; // <IPv4,IPBinding>
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Delete all IP address bindings associated with adapter.
|
||
|
/// </summary>
|
||
|
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());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Delete specific IP address binding from adapter.
|
||
|
/// </summary>
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|