Howto: Add new RRtypes to NSD

September 20, 2012 by matthijs

People like to put stuff in the DNS. While we could put everything in a TXT record, in general it is better to define a new record type (RRtype). The latest addition is the TLSA record, to support the DANE protocol. The RRtype was added to NSD just one day after the RFC was published.

It must be said that NSD does not support all RRtypes. For example, the CDS RRtype, a record that allows a child zone to update its DS RRset at the parent, has been assigned a code point, but its specification has not been finished. Therefore, it hasn’t been implemented in NSD yet. Fortunately, NSD is written in such a way that it is very easy to add new RRtypes. Let us look at the changes we made to NSD in order to support the TLSA record.

First of all, the zone compiler needs to understand the new record. This requires editing the Yacc file zparser.y. We need to add a token for the TLSA record.

%token T_TLSA

The format of the TLSA record is defined to have four RDATA elements, three unsigned 8-bit integers and a hexadecimal and one raw data field that represents the certification association data element, presented as a hexadecimal string. The NSD zone compiler has functions defined that can convert these representation formats to their respective wire format. That makes the grammar rule fairly straightforward:

rdata_tlsa: STR sp STR sp STR sp str_sp_seq trail
    {
        zadd_rdata_wireformat(zparser_conv_byte(parser->region, $1.str));
        zadd_rdata_wireformat(zparser_conv_byte(parser->region, $3.str));
        zadd_rdata_wireformat(zparser_conv_byte(parser->region, $5.str));
        zadd_rdata_wireformat(zparser_conv_hex(parser->region, $7.str, $7.len));
    }
    ;

Now we need to add the TSLA grammar rule to the list of supported records. And for every RRtype, the zone compiler also needs to be able to parse the unkown record presentation format. This list is defined by the grammar rule type_and_rdata:

type_and_rdata:
    {
    ...
     |	T_TLSA sp rdata_tlsa
     |	T_TLSA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
    ...
    }
    ;

We also need to add the TLSA record to the DNS definitions. IANA has allocated the number 52 to represent the TLSA RRtype. This goes in dns.h:

#define TYPE_TLSA 52

In the file dns.c, an array of RRtype descriptors is declared. A descriptor consists of the RRtype code point (52, or TYPE_TLSA), the RRtype name (“TLSA”), the parser token (T_TLSA), the minimum and maximum number of RDATA elements (both 4) and the wire and representation format. The TLSA descriptor becomes:

    { TYPE_TLSA, "TLSA", T_TLSA, 4, 4,
      { RDATA_WF_BYTE, RDATA_WF_BYTE, RDATA_WF_BYTE, RDATA_WF_BINARY },
      { RDATA_ZF_BYTE, RDATA_ZF_BYTE, RDATA_ZF_BYTE, RDATA_ZF_HEX }
    },

Luckily, we don’t need to define new RDATA elements. The octet (RDATA_WF_BYTE) represented as an unsigned 8-bit integer (RDATA_ZF_BYTE) are well known formats and already exist a long time in NSD, as is the binary element (RDATA_WF_BINARY) represented as a hexadecimal string (RDATA_ZF_HEX). If you do need to introduce new RDATA elements, Yuri’s HOWTO-HACK-NEW-RRTYPE can be of great value in order to guide you through that effort.

So that’s it! This should provide you with enough information to hack your own RRtypes into NSD. You only have to edit three files in order to support a new RRtype (that does not require special processing). Nevertheless, it would be better to enable new RRtype support without having to touch the code. That’s why we hope in the future we can implement the DNS extension language into NSD.

3 Comments

  1. There is one thing that needs to be added: There is a #define RRTYPE_DESCRIPTORS_LENGTH (TYPE_SPF + 1). If you add a new RR type, you need to update this descriptors length, or you need to make an exception rule, like we did with DLV.

    Comment by matthijs — November 19, 2012 @ 10:03 am

  2. Yes, it’s simple but it depends on the specific requirments of the RR type. For instance, you need sometimes to parse rdata which is structured in a new way and this requires new parsing code in zparser.y and zonec.c (ILNP is a good example with its “half-AAAA” rdatas).

    Also, when you add TYPE_SOMETHING in dns.c, if the RR type number is at the end of the array and leave some holes before (again, the case of ILNP) do not forget to pad the array rrtype_descriptors.

    Comment by Stéphane Bortzmeyer — November 30, 2012 @ 9:28 am

  3. Thanks for this – turns out we didn’t document how to do the same for PowerDNS anywhere, your post inspired me to write it up here: http://bert-hubert.blogspot.nl/2012/11/adding-new-dns-record-types-to-powerdns.html

    Comment by bert hubert — November 30, 2012 @ 9:59 am

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Wed Sep 25 2013

© Stichting NLnet Labs

Science Park 400, 1098 XH Amsterdam, The Netherlands

labs@nlnetlabs.nl, subsidised by NLnet and SIDN.