I don't remember the details but when writing/updating our DNS client to
support SPF TXT lookups, I found that TXT record are "delimited" every 255
bytes.
Byte = length of next block of characters (max 255)
255 characters
Byte = length of next block of characters (max 255)
....
etc.
This is the part of the logic I used to correctly get the large TXT records:
position ... current position in the response packet/buffer (RRBuffer)
rec.szTXT is the text record I am returning (pre-allocated)
int j = 0;
for (int i = 0; i < RR.RDlength; i++) {
int ch = RRBuffer[position+i];
if ((ch > 127) || (ch < 32)) {
continue;
}
// 255 mod check
if ((i == 0) || ((i % 255) != 0)) {
rec.szTXT[j] = ch;
j++;
}
}
I should note that this was tested across many systems with large TXT
records and it works for both UDP and TCP response packets.
I should also not the original designer of the DNS Client (which no need to
consider TXT) did have a function that used what seems to be some byte
oriented masking concept. I never quite figured it out but it wasn't
working for the TXT records and was returned junk. Maybe you can figure it
out:
struct tBitMask {
unsigned misc : 6;
unsigned p1 : 1;
unsigned p2 : 1;
};
struct tmask {
union {
tBitMask mask;
unsigned char value;
};
};
BOOL GetString(char *buf, const int bufsize, char *Name, int &cpos, BOOL
StreamSock=FALSE)
{
assert(Name != NULL);
assert(buf != NULL);
assert(bufsize != 0);
assert(cpos >= 0);
assert(cpos < bufsize);
int Current = cpos;
BYTE Level = 0;
ZeroMemory((void *) Name, DGRAM_SIZE);
while (TRUE) {
WORD location;
tmask mask;
char label[DGRAM_BUFFER_SIZE];
ZeroMemory(&label, DGRAM_BUFFER_SIZE);
if (Current + 1 > bufsize || Current + 1 < 0) {
return FALSE;
}
CopyMemory((void *) &mask, (void *) &buf[Current], 1);
if (mask.value > 63) {
mask.mask.p1 = 0;
mask.mask.p2 = 0;
if (Current + 1 >= bufsize || Current + 1 < 0) {
return FALSE;
}
char value[2];
CopyMemory((void *) &value[0], (void *) &mask, 1);
CopyMemory((void *) &value[1], (void *) &buf[Current+1], 1);
CopyMemory((void *) &location, (void *) &value, 2);
if (Level == 0) {
cpos = Current + 2;
Level++;
}
Current = ntohs(location);
if (StreamSock) Current+=2;
} else {
if (buf[Current] == 0) {
Name[strlen(Name)-1] = 0;
Current++;
if (Level == 0)
cpos = Current;
break;
}
if (Current + 1 > bufsize ||
Current + buf[Current] + 1 > bufsize ||
Current < 0 ||
buf[Current] > 63) {
return FALSE;
}
strncpy((char *) &label, &buf[Current+1], buf[Current]);
Current += buf[Current]+1;
strcat(Name, (char *) &label);
Name[strlen(Name)] = '.';
}
}
return TRUE;
}
This GetString() function works for getting all the "text" for all other
records, except TXT (or not all TXT records). But I never saw any reference
in the DNS RFC specs to such parsing using the BitMask, and Byte unions.
Makes any sense? Is this is a standard TXT parser?
Anyway, the loop I provided above works for TXT records for both UDP/TCP
response packets. I use the loop for the TXT record and GetString for the
rest of the RR types where a string needs to be obtained.
--
Hector Santos, Santronics Software, Inc.
http://www.santronics.com
----- Original Message -----
From: "Tim Meadowcroft" <meercat(_at_)gmail(_dot_)com>
To: <spf-discuss(_at_)v2(_dot_)listbox(_dot_)com>
Sent: Monday, June 21, 2004 1:54 PM
Subject: Re: [spf-discuss] Length of txt records
On Mon, 21 Jun 2004 12:39:42 -0400, Erik Aronesty
<info(_at_)zoneedit(_dot_)com>
wrote:
Some companies have lots of remote offices which users can send mail
from.
We have plenty of domains that have more IP's than can fit in a 255-char
TXT
record.
I believe a DNS TXT record can be up to 65535 (0xFFFF) bytes long as
it's length is defined by 16 bit unsigned number
(http://rfc.net/rfc1035.html#s3.2.1. - RDLENGTH field).
I understand some DNS servers may enforce lower limits, but a TXT
record can be over 255 (of course, keeping the packet under the usual
UDP single packet size of about 1500 bytes is a good idea).
--
Tim
-------
Sender Policy Framework: http://spf.pobox.com/
Archives at http://archives.listbox.com/spf-discuss/current/
Send us money! http://spf.pobox.com/donations.html
To unsubscribe, change your address, or temporarily deactivate your
subscription,
please go to
http://v2.listbox.com/member/?listname=spf-discuss(_at_)v2(_dot_)listbox(_dot_)com