spf-discuss
[Top] [All Lists]

Re: Length of txt records

2004-06-22 05:54:21
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




<Prev in Thread] Current Thread [Next in Thread>