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

c# Method not working as expected Address book project
Unity C# Instantiate prefab not working correctly
change C# object to type decided at run-time
Dynamic organizational chart in Windows Forms
Binding properties of nested entity
Connecting Python SocketServer with C# Client
In c# is it possible to pass or return operators like types [closed]
Updating the Identity AspNetUser does'nt work
Cast item to be type of received parametar
Is there a way to make this a selected item when defining the ListItem in C#?
How to work with sockets in UWP(Window 10)
ThreadPool or Task.Factory
Export data from Gridview to Excel in asp.net
How to run C# task method on separate thread without using Task.Run()
Adding App.Config to VS 2015 CodedUI Project breaks Test Execution on Test Agent 2013
Is it possible to specify the response content inside a IHttpActionResult response to be strongly typed? [duplicate]

Categories

HOME
qlikview
youtube-api
mobile
openacc
snappy
azure-eventhub
bigtable
salesforce-lightning
ms-access-2010
atlassian-fisheye
comments
procmon
gnuradio
virtualhost
pip
wavefront
doctrine2
angular-universal
solidity
console-application
box2d
loss
beacon
xforms
custom-component
ejb-3.1
fibonacci
connectiq
aws-iot
advertising
policy
aspxgridview
scrapy-spider
opencsv
gitosis
oracle-bpm-suite
mongoid5
mapquest
ngrok
collation
flume-ng
irr
datagridviewcombobox
azure-data-catalog
import.io
django-tables2
jscoverage
nservicebus6
dmalloc
try-catch-finally
dynatable
disassembly
stripes
virtualenvwrapper
nimbus
hotkeys
avi
mod
jcalendar
factorization
tooltwist
eggplant
httpmodule
jad
numerical-recipes
chunks
indices
frisby.js
sendy
pidgin
email-headers
fastcgi-mono-server
mixradio
grunt-wiredep
surfaceview
xcode5.1
sygic
static-class
listpicker
dynamic-expresso
kademlia
bho
ftpwebrequest
microsoft-speech-platform
blotter
cryptarithmetic-puzzle
derived-class
datasheet
stl-algorithm
symfony-1.2
sessiontracking
zipstream
designated-initializer
onresize
j++

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