I'm building a program and want to store the latest version number in a TXT record on a domain I own. After obtaining the text record I intend to compare it to the current version number.
I can do the string comparison part, but I am completely lost as to how you're supposed to read DNS records.
How do I do this in C#?
This repo: MichaCo/DnsClient.NET has the capability of reading TXT records in a DNS endpoint.
You can use a helper class to retrieve them by making a dns lookup. I've written a lil script that can help you achieve this:
using Util;
using System;
namespace DnsClient
{
class Program
{
static void Main(string[] args)
{
var Domain = "www.contoso.com";
var RequiredRecord = "MS=ms47806392";
var RequiredValue = "ms47806392";
var RequiredKey = "MS";
// Check without trying to split the TXT Record
if (CheckDnsRecordExists(Domain, RequiredRecord))
Console.WriteLine($"Found TXT Record: {RequiredRecord}! :)");
else
Console.WriteLine("Not Found! :(");
// Check by trying to split the TXT Record and checking for it's value
if (CheckDnsRecordExists(Domain, RequiredKey, RequiredValue))
Console.WriteLine($"Found Version {RequiredValue} of RecordID: {RequiredValue}! :)");
else
Console.WriteLine("Not Found! :(");
Console.ReadKey();
}
private static bool CheckDnsRecordExists(string Domain, string RequiredRecord)
{
var Records = DnsInterop.GetTxtRecords(Domain);
foreach (var record in Records)
{
if (record == RequiredRecord)
{
return true;
}
}
return false;
}
private static bool CheckDnsRecordExists(string Domain, string RequiredKey, string RequiredValue, char Separator = '=')
{
var Records = DnsInterop.GetTxtRecords(Domain);
foreach (var record in Records)
{
var keyPair = record.Split(Separator);
if (keyPair[0] != null && keyPair[1] != null)
{
if (keyPair[0] == RequiredKey && keyPair[1] == RequiredValue)
{
return true;
}
}
}
return false;
}
}
}
This example class by @gordonmleigh, based on this answer https://stackoverflow.com/a/11884174 by Martin Liversage can help you retrieve TXT records given a specific domain.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
namespace Util
{
/// <summary>
/// Based on https://stackoverflow.com/a/11884174 (Martin Liversage)
/// </summary>
class DnsInterop
{
private const short DNS_TYPE_TEXT = 0x0010;
private const int DNS_QUERY_STANDARD = 0x00000000;
private const int DNS_ERROR_RCODE_NAME_ERROR = 9003;
private const int DNS_INFO_NO_RECORDS = 9501;
public static IEnumerable<string> GetTxtRecords(string domain)
{
var results = new List<string>();
var queryResultsSet = IntPtr.Zero;
DnsRecordTxt dnsRecord;
try
{
// get all text records
// pointer to results is returned in queryResultsSet
var dnsStatus = DnsQuery(
domain,
DNS_TYPE_TEXT,
DNS_QUERY_STANDARD,
IntPtr.Zero,
ref queryResultsSet,
IntPtr.Zero
);
// return null if no records or DNS lookup failed
if (dnsStatus == DNS_ERROR_RCODE_NAME_ERROR
|| dnsStatus == DNS_INFO_NO_RECORDS)
{
return null;
}
// throw an exception if other non success code
if (dnsStatus != 0)
throw new Win32Exception(dnsStatus);
// step through each result
for (
var pointer = queryResultsSet;
pointer != IntPtr.Zero;
pointer = dnsRecord.pNext)
{
dnsRecord = (DnsRecordTxt)
Marshal.PtrToStructure(pointer, typeof(DnsRecordTxt));
if (dnsRecord.wType == DNS_TYPE_TEXT)
{
var builder = new StringBuilder();
// pointer to array of pointers
// to each string that makes up the record
var stringArrayPointer = pointer + Marshal.OffsetOf(
typeof(DnsRecordTxt), "pStringArray").ToInt32();
// concatenate multiple strings in the case of long records
for (var i = 0; i < dnsRecord.dwStringCount; ++i)
{
var stringPointer = (IntPtr)Marshal.PtrToStructure(
stringArrayPointer, typeof(IntPtr));
builder.Append(Marshal.PtrToStringUni(stringPointer));
stringArrayPointer += IntPtr.Size;
}
results.Add(builder.ToString());
}
}
}
finally
{
if (queryResultsSet != IntPtr.Zero)
{
DnsRecordListFree(queryResultsSet,
(int)DNS_FREE_TYPE.DnsFreeRecordList);
}
}
return results;
}
[DllImport("Dnsapi.dll", EntryPoint = "DnsQuery_W",
ExactSpelling = true, CharSet = CharSet.Unicode,
SetLastError = true)]
static extern int DnsQuery(string lpstrName, short wType, int options,
IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved);
[DllImport("Dnsapi.dll")]
static extern void DnsRecordListFree(IntPtr pRecordList, int freeType);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct DnsRecordTxt
{
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 string pStringArray;
}
enum DNS_FREE_TYPE
{
DnsFreeFlat = 0,
DnsFreeRecordList = 1,
DnsFreeParsedMessageFields = 2
}
}
}
Hope it helps!
Based on DnsDig project I created a DLL which can be used on any .net (vb, c#, forms, web. etc..) project
https://devselz.com/software/devselz_dnsdig_dns-txt-etc-query-domain-register.zip
Download the DLL, unzip, and Add as reference to your project (if website place on root/bin folder):
(126KB in total)
Then use this example as for an ASP.Net website (vb.net code)
Imports DnsDig
Imports Heijden.DNS
Partial Class lib_u_l_Default
Inherits System.Web.UI.Page
Public Resolver As Resolver
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Resolver = New Resolver
Dim SW As New System.Diagnostics.Stopwatch
SW.Start()
Dim DNSResponse As Heijden.DNS.Response = Resolver.Query(Request.QueryString("d"), QType.TXT, QClass.ANY)
SW.Stop()
If DNSResponse.header.ANCOUNT > 0 Then
For Each answerRR As AnswerRR In DNSResponse.Answers
Response.Write("<br/>" & answerRR.ToString)
Next
End If
End Sub
End Class
RESULTS: https://yourwebsiteusingabovedlls.com/anyplacewhereabovecode/?d=goodyes.com
will write
goodyes.com. 3535 IN TXT "google-site-verification=IMw-tL0VWgMJbtcRgt_bu5UaVwpbNb94dvcOSObooa4" goodyes.com. 3535 IN TXT "v=spf1 include:_spf.buzondecorreo.com ~all"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.