//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: DNS.cs // // 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 Stdin; [OutputEndpoint("data")] public readonly TRef Stdout; [Endpoint] public readonly TRef dnsRef; [StringArrayParameter( "Servers", HelpMessage="Servers to 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 Stdin; [Endpoint] public readonly TRef Stdout; [Endpoint] public readonly TRef 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 Stdin; [Endpoint] public readonly TRef Stdout; [Endpoint] public readonly TRef dnsRef; [StringArrayParameter( "Servers", Mandatory=true, Position=0, HelpMessage="Servers to to add")] 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 Stdin; [Endpoint] public readonly TRef Stdout; [Endpoint] public readonly TRef 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 Stdin; [Endpoint] public readonly TRef Stdout; [Endpoint] public readonly TRef dnsRef; [Endpoint] public readonly TRef 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) { 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 }