Howto: Add new RRtypes to NSD

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.

Howto: Add new RRtypes to NSD

By Matthijs Mekking

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.