c#


C# Newbie: How do I fix this code to do a DNS lookup?


This is my first time using C#, so I'm very much out of my element. But I have faith that the wonderful people here at Stack Overflow can help me out! I've come up with the following code (below) based on some other pieces of code I found floating around on the internet. What I am trying to do is to look up all the "text" DNS records (TXT) of a given domain. I've started out simple, with a Console Application in Visual C# 2008 Express looking up the records for google.com. I'll worry about customizing the domain based on command line parameters later; for now I'd just like to get this working. Any DNS lookup tools can tell you that google.com has this DNS text record in their DNS:
v=spf1 include:_netblocks.google.com ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all
But unfortunately that's not what I'm getting. Here's my code:
namespace DnsUtils
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
public class DnsTxt
{
[DllImport("dnsapi", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
private static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)]ref string pszName, QueryTypes wType, QueryOptions options, int aipServers, ref IntPtr ppQueryResults, int pReserved);
[DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)]
private static extern void DnsRecordListFree(IntPtr pRecordList, int FreeType);
public static string[] GetTXTRecords(string domain)
{
IntPtr ptr1 = IntPtr.Zero;
IntPtr ptr2 = IntPtr.Zero;
TXTRecord recTxt;
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
throw new NotSupportedException();
}
ArrayList list1 = new ArrayList();
UnicodeEncoding encoding = new UnicodeEncoding();
int num1 = DnsTxt.DnsQuery(ref domain, QueryTypes.DNS_TYPE_TEXT, QueryOptions.DNS_QUERY_BYPASS_CACHE, 0, ref ptr1, 0);
if (num1 != 0)
{
throw new Win32Exception(num1);
}
for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = recTxt.pNext)
{
recTxt = (TXTRecord)Marshal.PtrToStructure(ptr2, typeof(TXTRecord));
if (recTxt.wType == 16)
{
IntPtr pointerToAddressStringArray = Marshal.AllocHGlobal(IntPtr.Size);
IntPtr addressStringArray = Marshal.ReadIntPtr(pointerToAddressStringArray);
for (int i = 0; i < recTxt.dwStringCount; i++)
{
IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4);
int offset = 0;
ArrayList bytesList = new ArrayList();
byte newByte = Marshal.ReadByte(addressCharArray, offset++);
while (newByte != 0)
{
bytesList.Add(newByte);
newByte = Marshal.ReadByte(addressCharArray, offset++);
}
byte[] bytesArray = new byte[offset];
bytesList.CopyTo(bytesArray);
string textValue = encoding.GetString(bytesArray);
list1.Add(textValue);
}
Marshal.FreeHGlobal(pointerToAddressStringArray);
}
}
DnsTxt.DnsRecordListFree(ptr2, 0);
return (string[])list1.ToArray(typeof(string));
}
private enum QueryOptions
{
DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 1,
DNS_QUERY_BYPASS_CACHE = 8,
DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
DNS_QUERY_NO_HOSTS_FILE = 0x40,
DNS_QUERY_NO_LOCAL_NAME = 0x20,
DNS_QUERY_NO_NETBT = 0x80,
DNS_QUERY_NO_RECURSION = 4,
DNS_QUERY_NO_WIRE_QUERY = 0x10,
DNS_QUERY_RESERVED = -16777216,
DNS_QUERY_RETURN_MESSAGE = 0x200,
DNS_QUERY_STANDARD = 0,
DNS_QUERY_TREAT_AS_FQDN = 0x1000,
DNS_QUERY_USE_TCP_ONLY = 2,
DNS_QUERY_WIRE_ONLY = 0x100
}
private enum QueryTypes
{
DNS_TYPE_TEXT = 16
}
[StructLayout(LayoutKind.Sequential)]
private struct TXTRecord
{
public IntPtr pNext;
public string pName;
public short wType;
public short wDataLength;
public int flags;
public int dwTtl;
public int dwReserved;
public int dwStringCount;
public IntPtr pStringArray;
}
static void Main(string[] args)
{
try
{
string[] s = DnsUtils.DnsTxt.GetTXTRecords("google.com");
foreach (string st in s)
{
Console.WriteLine("Value: {0}", st);
}
}
catch (Win32Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
}
When I run this code, it prints Value: ?. Now I'm hoping that this means it actually did the DNS query and got the results as expected, but I just screwed something up in the part where it tries to convert an IntPtr to an array of strings (because I'm guessing it's harder to debug the former). Anyways, have any suggestions? Can anyone see where I went awry? Thanks in advance.
This line looks a bit off to me:
IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4);
It looks like you'd be reading the first 4 bytes of the first string entry of the TXT record as an IntPtr. I think something like:
string s = Marshal.PtrToStringAuto(recTxt.pStringArray);
would get you the first entry. After that, I think something like:
IntPtr p = new IntPtr(recTxt.pStringArray.ToInt32() + sizeof(uint) * i);
string s = Marshal.PtrToStringAuto(p);
would get the remainders.
As a simpler alternative you could avoid dealing with all the COM interop by creating a new nslookup process and parsing the StandardOuput to grab what you need.
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var startInfo = new ProcessStartInfo("nslookup");
startInfo.Arguments = "-type=TXT google.com";
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
using (var cmd = Process.Start(startInfo))
{
// This is where you grab the output from nslookup.
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
Console.Read();
}
}
}

Related Links

How to build a dynamic ListBox within dynamic ListBox in Windows Phone App
RavenDB get total count for query not working
LINQ: Use .Except() on collections of different types by making them convertible/comparable?
Same Time Web Service Access Testing
Unable to access the value of QueryString outside the OnNavigatedTo method
Why is there need for an explicit Dispose() method in asp.net MVC Controllers? Can anyone explain its intricacies? (asp.net specific)
Dragabale text to a RadEditor
WPF 3D Dynamic Textures
SSL endpoint on a WCF service with only XML configuration file
WCF: The server has rejected the client credentials
Simulate click into a hidden window
string splitting. Finding the right way to do it
C# Find duplicate Values in Datagridview
.NET RSA Sign/Verify Data Licensing Keys
How to avoid an opened Comport if it is already opened
Eazfuscator.NET Embedding NLog

Categories

HOME
asterisk
spring-boot
ckan
kendo-ui-angular2
stata
ide
sip
salesforce
locale
snappy
android-ndk
azure-database-mysql
magento-1.9.2.1
spss
redhawksdr
sdk
kohana
collision-detection
jpql
fetch
ndepend
aspectj
mongodb-replica-set
comma
greensock
orange
react-jsx
android-wifi
webgl-earth
fibonacci
multipart
mattermost
ng-tags-input
screen-scraping
apdu
waterfall
android-xml
aws-certificate-manager
cloudformation
launchd
windows-10-mobile
multilanguage
ilog
javafxports
campaign-monitor
strategy-pattern
stochastic-process
libconfig
uitextview
php-mongodb
colorbox
apiman
smooth-streaming
android-doze-and-standby
wink
sharpssh
sp
cc
was
catalyst
huawei
computed-properties
mac-app-store
strtol
eclipse-mars
netlink
particle-system
recurring
queuing
diameter-protocol
webservices-client
web-standards
vspackage
fileinputstream
sicstus-prolog
connection-timeout
chunks
esri-arc-engine
shunting-yard
illegalargumentexception
mind-manager
powerpoint-2010
oxygenxml
satisfiability
jsmpp
git-subtree
pthreads-win32
nop
myrrix
nsnumber
nokogiri
source-depot
infinity.js
latex-suite
http-compression
vline
database-restore
orchestration
jqueryi-ui-buttonset
project-files
method-call
azure-appfabric
xcdatamodel
nstoolbar
oaw
database-agnostic
xslt-grouping
manuals
asp.net-1.1

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App