singrdk/base/Applications/Network/DNS/DNS.cs

351 lines
11 KiB
C#

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note: Simple Singularity test program.
//
using System;
using System.Diagnostics;
using System.Net.IP;
using Microsoft.SingSharp;
using Microsoft.Singularity;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using NetStack.Contracts;
using NetStack.Channels.Public;
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Configuration;
[assembly: Transform(typeof(ApplicationResourceTransform))]
namespace Microsoft.Singularity.Applications.Network
{
[ConsoleCategory(HelpMessage="Add network routing information", DefaultAction=true)]
internal class AddConfig
{
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DNSContract.Imp:Start> dnsRef;
[StringArrayParameter( "Servers", HelpMessage="Servers to add")]
internal string[] servers;
reflective internal AddConfig();
internal int AppMain()
{
DebugStub.Break();
DNS.Add(this);
return 0;
}
}
[ConsoleCategory(Action="show", HelpMessage="Show DNS information")]
internal class ShowConfig
{
[Endpoint]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[Endpoint]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DNSContract.Imp:Start> dnsRef;
reflective internal ShowConfig();
internal int AppMain()
{
return DNS.Show(this);
}
}
[ConsoleCategory(Action="delete", HelpMessage="Delete DNS information")]
internal class DeleteConfig
{
[Endpoint]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[Endpoint]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DNSContract.Imp:Start> dnsRef;
[StringArrayParameter( "Servers", Mandatory=true, Position=0, HelpMessage="Servers to delete")]
internal string[] servers;
reflective internal DeleteConfig();
internal int AppMain()
{
DNS.Delete(this);
return 0;
}
}
[ConsoleCategory(Action="rotate", HelpMessage="Rotate name servers")]
internal class RotateConfig
{
[Endpoint]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[Endpoint]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DNSContract.Imp:Start> dnsRef;
reflective internal RotateConfig();
internal int AppMain()
{
DNS.Rotate(this);
return 0;
}
}
[ConsoleCategory(Action="query", HelpMessage="Query DNS information")]
internal class QueryConfig
{
[Endpoint]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[Endpoint]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DNSContract.Imp:Start> dnsRef;
[Endpoint]
public readonly TRef<IPContract.Imp:Start> ipRef;
[StringParameter( "host", Mandatory=true, Position=0, HelpMessage="host to be queried")]
internal string name;
reflective internal QueryConfig();
internal int AppMain()
{
DNS.Query(this);
return 0;
}
}
public class DNS
{
internal static int Add(AddConfig! config)
{
DebugStub.Break();
if (config.servers == null) {
Console.WriteLine("no servers given");
return -1;
}
DNSContract.Imp dnsConn = ((!)config.dnsRef).Acquire();
if (dnsConn == null) {
Console.WriteLine("Could not initialize DNS endpoint.");
delete dnsConn;
return 1;
}
dnsConn.RecvReady();
for (int i = 0; i < config.servers.Length; i++) {
IPv4 resolver;
Console.WriteLine("Resolving {0}", config.servers[i]);
if (IPv4.Parse(config.servers[i], out resolver) == false) {
Console.WriteLine("Invalid IP address: {0}", config.servers[i]);
}
dnsConn.SendAddNameServer((uint)resolver);
dnsConn.RecvAck();
}
delete dnsConn;
return 0;
}
internal static int Delete(DeleteConfig! config)
{
if (config.servers == null) {
Console.WriteLine("no servers given");
return -1;
}
DNSContract.Imp dnsConn = ((!)config.dnsRef).Acquire();
if (dnsConn == null) {
Console.WriteLine("Could not initialize DNS endpoint.");
return 1;
}
dnsConn.RecvReady();
for (int i = 0; i < config.servers.Length; i++) {
IPv4 resolver;
if (IPv4.Parse(config.servers[i], out resolver) == false) {
Console.WriteLine("Invalid IP address: {0}", config.servers[i]);
}
dnsConn.SendRemoveNameServer((uint)resolver);
dnsConn.RecvAck();
}
delete dnsConn;
return 0;
}
private static bool QueryInternal(string! name)
{
// NOTE: use the System.NET APIs here, just to exercise our
// port of them. We could also accomplish this by using a
// DNS channel.
try {
System.Net.IPHostEntry hostInfo = System.Net.Dns.GetHostByName(name);
if (hostInfo == null) return false;
IPAddress[] addresses = hostInfo.AddressList;
if (addresses == null) return false;
String[] aliases = hostInfo.Aliases;
if (aliases == null) return false;
Console.Write("Host names: ");
int end = aliases.Length - 1;
for (int i = 0; i <= end; i++) {
Console.Write("{0}{1}", aliases[i], (i == end) ? "" : ", ");
}
Console.Write("\n");
end = addresses.Length - 1;
Console.Write("IP addresses: ");
for (int i = 0; i <= end; i++) {
Console.Write("{0}{1}", addresses[i], (i == end) ? "" : ", ");
}
Console.Write("\n");
return true;
}
catch (System.Net.Sockets.SocketException) {
return false;
}
}
internal static int Query(QueryConfig! config)
requires config.name != null;
{
bool isValid;
string name = config.name;
DNSContract.Imp dnsConn = ((!)config.dnsRef).Acquire();
if (dnsConn == null) {
Console.WriteLine("Could not initialize DNS endpoint.");
return 1;
}
dnsConn.RecvReady();
dnsConn.SendIsValidName(Bitter.FromString(name));
dnsConn.RecvIsValid(out isValid);
if (!isValid) {
Console.Write("Invalid name: {0}", name);
delete dnsConn;
return -1;
}
if (QueryInternal(name)) {
delete dnsConn;
return -1;
}
IPContract.Imp ipConn = ((!)config.ipRef).Acquire();
if (ipConn == null) {
Console.WriteLine("Could not initialize IP endpoint.");
delete dnsConn;
return -1;
}
try {
// Ad-hoc search list
char[]! in ExHeap repDomain;
ipConn.SendGetDomainName();
ipConn.RecvDomainName(out repDomain);
string domain = Bitter.ToString(repDomain);
delete repDomain;
if (domain == null) {
Console.WriteLine("Couldn't resolve \"" + name + "\"");
delete dnsConn;
delete ipConn;
return -1;
}
name = String.Concat(name, ".");
int index = 0;
do {
string guess = String.Concat(name, domain.Substring(index));
dnsConn.SendIsValidName(Bitter.FromString(guess));
dnsConn.RecvIsValid(out isValid);
if (isValid && QueryInternal(guess)) {
delete dnsConn;
delete ipConn;
return -1;
}
index = domain.IndexOf('.', index) + 1;
} while (index > 0 && index < domain.Length);
Console.WriteLine("No IP address found");
}
finally {
}
delete ipConn;
delete dnsConn;
return 0;
}
internal static int Rotate(RotateConfig! config)
{
DNSContract.Imp dnsConn = ((!)config.dnsRef).Acquire();
if (dnsConn == null) {
Console.WriteLine("Could not initialize DNS endpoint.");
return 1;
}
dnsConn.RecvReady();
dnsConn.SendRotateNameServers();
dnsConn.RecvAck();
delete dnsConn;
return 0;
}
internal static int Show(ShowConfig! config)
{
DNSContract.Imp dnsConn = ((!)config.dnsRef).Acquire();
if (dnsConn == null) {
Console.WriteLine("Could not initialize DNS endpoint.");
return 1;
}
dnsConn.RecvReady();
Utils.DNSShow(dnsConn);
delete dnsConn;
return 0;
}
} // end class DNS
}