Getting DNS TXT records in C
Daniel Nashed – 10 May 2021 09:37:10
Getting the TXT records for a DNS entries is important today (checking SPF records, ACME challenges, DMARC records .. ).
But this isn't part of the standard resolver processes you would use for normal DNS queries.
I have been looking for TXT record resolution for a while and finally found it in one of my oldest IT books "DNS & Bind".
Even there wasn't a complete example and I needed to do a lot of research this morning.
The result doesn't look that complicated. But the devil is still in the detail.
This functionality has been always there and you would need it also to query MX records for example.
Windows implemented their own interface - DnsQuery(). The call also looks simple but I didn't find any example or full documentation for the call.
My new functionality in SpamGeek will be Linux only for now -- Because "libspf" is also only available for Linux ..
In case you need a routine to get the DNS TXT records, here is an example that uses the newer thread safe interface.
It needs to init a structure per thread. Or like in my example code per request.
The routine doesn't have all error logging and is more an example.
-- Daniel
#include
int GetTxtRecord (char *pszDomain)
{
unsigned char Buffer[8000] = {0};
unsigned char Result[2048] = {0};
const unsigned char *pResult = NULL;
struct __res_state ResState = {0};
ns_msg nsMsg = {0};
ns_rr rr;
int type = 0;
int ret = 0;
int size = 0;
int len = 0;
int count 0;
int i = 0;
int res_init = 0;
ret = res_ninit (&ResState);
if (ret)
{
printf ("error initializing resolver\n");
goto close;
}
res_init = 1;
memset(Buffer, 0, sizeof (Buffer));
size = res_nquery (&ResState, pszDomain, C_IN, T_TXT, Buffer, sizeof(Buffer)-1);
if (0 == size)
goto close;
ret = ns_initparse (Buffer, size, &nsMsg);
if (ret)
goto close;
count = ns_msg_count (nsMsg, ns_s_an);
for (i=0; i
{
ret = ns_parserr (&nsMsg, ns_s_an, i , &rr);
if (ret)
goto close;
type = ns_rr_type (rr);
if (ns_t_txt == type)
{
len = ns_rr_rdlen (rr);
pResult = ns_rr_rdata (rr);
if ( (len>1) && (len < sizeof(Result)) )
{
len--;
memcpy (Result, pResult+1, len);
Result[len] = '\0';
printf ("#%d [%s]\n", i, Result);
}
}
} /* for */
close:
if (res_init)
res_nclose (&ResState);
return ret;
}
- Comments [0]