454 lines
13 KiB
C#
454 lines
13 KiB
C#
// ----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
///
|
|
// Microsoft Research, Cambridge
|
|
//
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Net.IP;
|
|
|
|
using Microsoft.Contracts;
|
|
using Microsoft.Singularity;
|
|
|
|
using NetStack.Common;
|
|
using NetStack.Protocols;
|
|
using NetStack.NetDrivers;
|
|
|
|
#if !SINGULARITY
|
|
using System.Reflection;
|
|
using System.Net;
|
|
#endif
|
|
|
|
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()
|
|
{
|
|
RoutingTable! routingTableOnStack = new RoutingTable();
|
|
|
|
isRouter = false;
|
|
routingTable = routingTableOnStack;
|
|
nameServers = ArrayList.Synchronized(new ArrayList());
|
|
bindings = new IPAdapterBindingTable(routingTableOnStack);
|
|
dhcpClients = new ArrayList();
|
|
|
|
base();
|
|
|
|
SetHostName("singularity");
|
|
SetDomainName("microsoft.com");
|
|
#if false
|
|
IAdapter loopbackAdapter = new LoopbackAdapter();
|
|
|
|
Core.Instance().RegisterAdapter(loopbackAdapter, "loopback", LoopbackAdapter.RingSize);
|
|
|
|
this.bindings.Add(loopbackAdapter,
|
|
new InterfaceIPConfiguration(
|
|
IPv4.Loopback,
|
|
new IPv4(0xff000000),
|
|
IPv4.Loopback,
|
|
1));
|
|
#endif
|
|
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;
|
|
}
|
|
}
|
|
}
|