1999-02-12 03:13:27 +00:00
|
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
2000-06-21 23:50:43 +00:00
|
|
|
|
<!--
|
2016-06-27 14:56:38 +10:00
|
|
|
|
- Copyright (C) 1999-2001, 2004, 2007, 2016 Internet Systems Consortium, Inc. ("ISC")
|
2000-08-01 01:33:37 +00:00
|
|
|
|
-
|
2016-06-27 14:56:38 +10:00
|
|
|
|
- This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2000-06-21 23:50:43 +00:00
|
|
|
|
-->
|
|
|
|
|
|
2007-06-19 23:47:24 +00:00
|
|
|
|
<!-- $Id: rdata.html,v 1.15 2007/06/19 23:47:13 tbox Exp $ -->
|
2000-06-22 22:00:42 +00:00
|
|
|
|
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<HTML>
|
|
|
|
|
<HEAD>
|
|
|
|
|
<TITLE>Adding new RDATA type</TITLE>
|
|
|
|
|
</HEAD>
|
|
|
|
|
<BODY>
|
1999-02-16 02:56:03 +00:00
|
|
|
|
<H2>Overview</H2>
|
|
|
|
|
The dns rdata routines (<CODE>dns_rdata_fromtext()</CODE>,
|
|
|
|
|
<CODE>dns_rdata_totext()</CODE>, <CODE>dns_rdata_fromwire()</CODE>,
|
|
|
|
|
<CODE>dns_rdata_towire()</CODE> <CODE>dns_rdata_fromstruct()</CODE>,
|
2000-08-01 01:33:37 +00:00
|
|
|
|
<CODE>dns_rdata_tostruct()</CODE> and <CODE>dns_rdata_compare()</CODE>)
|
1999-02-16 02:56:03 +00:00
|
|
|
|
are designed to provide a single set of routines
|
|
|
|
|
for encoding, decoding and comparing dns data preventing the problems that
|
|
|
|
|
occurred in BIND 8.x and earlier where there were multiple places in the
|
|
|
|
|
code base that
|
|
|
|
|
decoded wire format to internal format or compared rdata sometimes with
|
|
|
|
|
subtly different behaviour (bugs) or didn't support a particular type leading
|
|
|
|
|
to internal inconsistancy.
|
|
|
|
|
<P>
|
|
|
|
|
Each of these generic routines calls type specific routines that provide
|
|
|
|
|
the type specific details.
|
|
|
|
|
<P>
|
|
|
|
|
From time to time new types are defined and it is necessary to add these types
|
|
|
|
|
into the existing structure.
|
|
|
|
|
This document is written to provide instruction on how to do this.
|
|
|
|
|
<H2>Adding new RDATA types</H2>
|
1999-02-12 03:13:27 +00:00
|
|
|
|
|
|
|
|
|
Adding a new rdata type requires determining if the new rdata type is class
|
|
|
|
|
specific or generic.
|
|
|
|
|
Writing code to perform the following set of operations
|
|
|
|
|
and then integrating it into the build by placing the code into the rdata
|
|
|
|
|
hierachy at the correct place.
|
|
|
|
|
Running <CODE>make clean</CODE> followed <CODE>make</CODE> in
|
|
|
|
|
<CODE>lib/dns</CODE> will cause the new rdata type to be picked up.
|
|
|
|
|
<P>
|
|
|
|
|
Each rdata module must perform the following operations:
|
|
|
|
|
<DL>
|
|
|
|
|
<DT>Convert from text format to internal format</DT>
|
|
|
|
|
<DT>Convert from internal format to text format</DT>
|
|
|
|
|
<DT>Convert from wire format to internal format</DT>
|
|
|
|
|
<DT>Convert from internal format to wire format</DT>
|
|
|
|
|
<DT>Convert from a structure to internal format</DT>
|
|
|
|
|
<DT>Convert from internal format to a structure</DT>
|
|
|
|
|
<DT>Compare two rdata in internal format<DT>
|
|
|
|
|
</DL>
|
|
|
|
|
<P>
|
|
|
|
|
There is an additional set of support <A HREF="#functions">functions</A> and
|
|
|
|
|
<A HREF="#macros">macros</A> only available to
|
|
|
|
|
to rdata code.
|
|
|
|
|
<H2>RDATA Hierarchy</H2>
|
|
|
|
|
The <CODE>rdata</CODE> hierarchy has the following format.
|
|
|
|
|
<PRE>
|
|
|
|
|
rdata/
|
|
|
|
|
generic/
|
|
|
|
|
<I>typename_typenumber</I>.h
|
|
|
|
|
<I>classname_classnumber</I>/
|
|
|
|
|
<I>typename_typenumber</I>.h
|
|
|
|
|
<PRE>
|
|
|
|
|
<P>
|
|
|
|
|
Initial rdata hierarchy:
|
|
|
|
|
<P>
|
|
|
|
|
<PRE>
|
|
|
|
|
rdata/
|
|
|
|
|
generic/
|
|
|
|
|
ns_2.h
|
|
|
|
|
md_3.h
|
|
|
|
|
mf_4.h
|
|
|
|
|
cname_5.h
|
|
|
|
|
soa_6.h
|
|
|
|
|
mb_7.h
|
|
|
|
|
mg_8.h
|
|
|
|
|
mr_9.h
|
|
|
|
|
null_10.h
|
|
|
|
|
ptr_12.h
|
|
|
|
|
hinfo_13.h
|
|
|
|
|
minfo_14.h
|
|
|
|
|
mx_15.h
|
|
|
|
|
txt_16.h
|
|
|
|
|
rp_17.h
|
|
|
|
|
afsdb_18.h
|
|
|
|
|
x25_19.h
|
|
|
|
|
isdn_20.h
|
|
|
|
|
rt_21.h
|
|
|
|
|
sig_24.h
|
|
|
|
|
key_25.h
|
|
|
|
|
gpos_27.h
|
|
|
|
|
loc_29.h
|
|
|
|
|
nxt_30.h
|
|
|
|
|
cert_37.h
|
|
|
|
|
dname_39.h
|
|
|
|
|
unspec_103.h
|
|
|
|
|
tkey_249.h
|
|
|
|
|
in_1/
|
|
|
|
|
a_1.h
|
|
|
|
|
wks_11.h
|
|
|
|
|
nsap_22.h
|
|
|
|
|
nsap-ptr_23.h
|
|
|
|
|
px_26.h
|
|
|
|
|
aaaa_28.h
|
|
|
|
|
srv_33.h
|
|
|
|
|
naptr_35.h
|
|
|
|
|
kx_36.h
|
|
|
|
|
a6_38.h
|
|
|
|
|
any_255/
|
|
|
|
|
tsig_250.h
|
|
|
|
|
</PRE>
|
|
|
|
|
|
|
|
|
|
<H2>CLASSNAME and TYPENAME</H2>
|
|
|
|
|
Class and type names must be from the following alphabet and less that 11
|
|
|
|
|
characters in length or otherwise they will be ignored.
|
|
|
|
|
Permissible alphabet: a to z, 0 to 9 and dash (-).
|
|
|
|
|
Dash is mapped to underscore (_) for the C function names below.
|
1999-02-16 02:56:03 +00:00
|
|
|
|
|
|
|
|
|
<H2>Internal Format</H2>
|
1999-04-22 12:27:55 +00:00
|
|
|
|
The internal format chosen is DNS wire format without any compression being
|
1999-02-16 02:56:03 +00:00
|
|
|
|
applied to domain names in the rdata.
|
|
|
|
|
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<H2>Convert from text format to internal format</H2>
|
|
|
|
|
The functions to convert from text format has the following call formats and
|
|
|
|
|
is declared as follows for class generic functions.
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
fromtext_<I>typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
|
|
|
|
|
isc_lex_t *lexer, dns_name_t *origin,
|
|
|
|
|
isc_boolean_t downcase, isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
Class specific functions contain the class name in addition to the
|
|
|
|
|
type name.
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
fromtext_<I>classname_typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
|
|
|
|
|
isc_lex_t *lexer, dns_name_t *origin,
|
|
|
|
|
isc_boolean_t downcase, isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
|
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>class</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This argument should be ignored when used with a class generic RR type
|
|
|
|
|
otherwise <CODE>REQUIRE(class == #)</CODE> should be present at the start
|
|
|
|
|
of the function.
|
|
|
|
|
<DT><CODE>type</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This should be tested with a <CODE>REQUIRE(type == #)</CODE> statement at
|
|
|
|
|
the begining of the function.
|
|
|
|
|
<DT><CODE>lexer</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is used to read the input text stream.
|
|
|
|
|
<DT><CODE>origin</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a absolute name used to qualify unqualified / partially qualified
|
|
|
|
|
domainnames in the text stream.
|
|
|
|
|
It is passed to the name parsing routines.
|
|
|
|
|
<DT><CODE>downcase</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is passed to the name parsing routines to determine whether to downcase
|
|
|
|
|
the names it generates or leave them in the case they are pesented in.
|
|
|
|
|
<DT><CODE>target</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a <CODE>BINARY</CODE> buffer used to write the internal format of the rdata record being read in to.
|
|
|
|
|
</DL>
|
|
|
|
|
|
|
|
|
|
<CODE>fromtext_<I>typename</I>()</CODE> reads tokens from <CODE>lexer</CODE>,
|
|
|
|
|
up to but not including the end of line (EOL) token or end of file (EOF) token.
|
|
|
|
|
If the EOL / EOF token is read it should be returned to the input stream.
|
|
|
|
|
<A HREF="#gettoken"><CODE>gettoken()</CODE></A>
|
|
|
|
|
should be used to read the next token from the input stream and
|
|
|
|
|
will return EOL / EOF tokens
|
|
|
|
|
automatically unless
|
|
|
|
|
they are specifcally requested.
|
|
|
|
|
<CODE>isc_lex_ungettoken()</CODE> should
|
|
|
|
|
be used to return EOL / EOF (or any other token) to the input stream if
|
|
|
|
|
the EOL / EOF token is read.
|
|
|
|
|
Unused tokens will cause <CODE>dns_rdata_fromtext()</CODE> to return
|
|
|
|
|
<CODE>DNS_R_EXTRATOKEN</CODE> if <CODE>fromtext_<I>typename</I>()</CODE> was successful.
|
|
|
|
|
<P>
|
|
|
|
|
<CODE>fromtext_<I>typename</I>()</CODE> reads external input and as such is a high security area and must be paranoid about its input.
|
|
|
|
|
<H2>Convert from internal format to text format</H2>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
totext_<I>typename</I>(dns_rdata_t *rdata, dns_name_t *origin,
|
|
|
|
|
isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
totext_<I>classname_typename</I>(dns_rdata_t *rdata, dns_name_t *origin,
|
|
|
|
|
isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>rdata</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is the rdata record to be converted from internal format to text.
|
|
|
|
|
<CODE>rdata->type</CODE> and <CODE>rdata->class</CODE> for class specific
|
|
|
|
|
RR types should be checked at the start of the function with
|
|
|
|
|
<CODE>REQUIRE(rdata->type ==<3D>#)</CODE> statements.
|
|
|
|
|
<DT><CODE>origin</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
If this in non <CODE>NULL</CODE> then any domainnames with this suffix
|
|
|
|
|
should be written out unqualified.
|
|
|
|
|
<A HREF="#name_prefix"><CODE>name_prefix()</CODE></A> can be used to
|
|
|
|
|
check if <CODE>origin</CODE> is <CODE>NULL</CODE> and provide the correct
|
|
|
|
|
arguments to the name conversion routines.
|
|
|
|
|
<DT><CODE>target</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a <CODE>TEXT</CODE> buffer used to hold the output.
|
|
|
|
|
</DL>
|
|
|
|
|
<H2>Convert from wire format to internal format</H2>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
fromwire_<I>typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
|
|
|
|
|
isc_buffer_t *source, dns_decompress_t *dctx,
|
|
|
|
|
isc_boolean_t downcase, isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
fromwire_<I>classname_typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
|
|
|
|
|
isc_buffer_t *source, dns_decompress_t *dctx,
|
|
|
|
|
isc_boolean_t downcase, isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
1999-02-24 06:31:35 +00:00
|
|
|
|
<P>
|
|
|
|
|
<CODE>fromwire_<I>classname_typename</I>()</CODE> is required to set the valid
|
|
|
|
|
decompression methods if there is a domain name in the rdata.
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>if (dns_decompress_edns(dctx) >= # || !dns_decompress_strict(dctx))
|
|
|
|
|
dns_decompress_setmethods(dctx, DNS_COMPRESS_ALL);
|
|
|
|
|
else
|
2000-03-23 05:18:46 +00:00
|
|
|
|
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);</CODE>
|
1999-02-24 06:31:35 +00:00
|
|
|
|
</PRE>
|
2000-08-01 01:33:37 +00:00
|
|
|
|
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>class</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This argument should be ignored when used with a class generic RR type
|
|
|
|
|
otherwise <CODE>REQUIRE(class == #)</CODE> should be present at the start
|
|
|
|
|
of the function.
|
|
|
|
|
<DT><CODE>type</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This should be tested with a <CODE>REQUIRE(type == #)</CODE> statement at
|
|
|
|
|
the begining of the function.
|
|
|
|
|
<DT><CODE>source</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a <CODE>BINARY</CODE> buffer with the <CODE>active</CODE> region
|
|
|
|
|
containing a RR record in wire format.
|
|
|
|
|
<DT><CODE>dctx</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is the decompression context and is passed to
|
|
|
|
|
<CODE>dns_name_fromwire()</CODE>,
|
2000-08-01 01:33:37 +00:00
|
|
|
|
along with <CODE>downcase</CODE>, to enable a compressed domain name
|
1999-02-12 03:13:27 +00:00
|
|
|
|
to be extracted from the source.
|
|
|
|
|
<DT><CODE>downcase</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is passed to <CODE>dns_name_fromwire()</CODE> to say whether the
|
|
|
|
|
extracted domainname should be downcased during the extraction.
|
|
|
|
|
<DT><CODE>target</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a <CODE>BINARY</CODE> buffer where the decompressed and checked
|
|
|
|
|
RR record is written.
|
|
|
|
|
</DL>
|
|
|
|
|
<CODE>fromwire_<I>typename</I>()</CODE> is a security sensitive routine
|
|
|
|
|
as it reads external data and should take extreme care to ensure that
|
|
|
|
|
the input data matches its description.
|
|
|
|
|
<P>
|
2000-08-01 01:33:37 +00:00
|
|
|
|
If the <CODE>active</CODE> buffer is not empty at completion and
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<CODE>fromwire_<I>typename</I>()</CODE> was otherwise successful
|
|
|
|
|
<CODE>dns_rdata_fromwire()</CODE> will return <CODE>DNS_R_EXTRADATA</CODE>.
|
|
|
|
|
<H2>Convert from internal format to wire format</H2>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
towire_<I>typename</I>(dns_rdata_t *rdata, dns_compress_t *cctx,
|
|
|
|
|
isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
towire_<I>classname_typename</I>(dns_rdata_t *rdata, dns_compress_t *cctx,
|
|
|
|
|
isc_buffer_t *target);<CODE>
|
|
|
|
|
</PRE>
|
1999-02-22 07:24:05 +00:00
|
|
|
|
<P>
|
|
|
|
|
<CODE>towire_<I>classname_typename</I>()</CODE> is required to set the
|
2000-08-01 01:33:37 +00:00
|
|
|
|
allowed name compression methods based on EDNS version if there is a
|
1999-02-22 07:24:05 +00:00
|
|
|
|
domain name in the rdata.
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>if (dns_compress_getedns(cctx) >= #)
|
|
|
|
|
dns_compress_setmethods(cctx, DNS_COMPRESS_ALL);
|
|
|
|
|
else
|
2000-03-23 05:18:46 +00:00
|
|
|
|
dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);</CODE>
|
1999-02-22 07:24:05 +00:00
|
|
|
|
</PRE>
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>rdata</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is the rdata record to be converted from internal format to text.
|
|
|
|
|
<CODE>rdata->type</CODE> and <CODE>rdata->class</CODE> for class specific
|
|
|
|
|
RR types should be checked at the start of the function with
|
|
|
|
|
<CODE>REQUIRE(rdata->type ==<3D>#)</CODE> statements.
|
|
|
|
|
<DT><CODE>cctx</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is the compression context, it should be passed to <CODE>dns_name_towire()</CODE> when putting domainnames on the wire.
|
|
|
|
|
<DT><CODE>target</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a <CODE>BINARY</CODE> buffer used to write the rdata to.
|
|
|
|
|
</DL>
|
|
|
|
|
Simple RR types without domainnames can use the following code to
|
|
|
|
|
transfer the contents of the <CODE>rdata</CODE> to the target buffer.
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>return (<A HREF="#mem_tobuffer">mem_tobuffer</A>(target, rdata->data, rdata->length));</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<H2>Convert from a structure to internal format</H2>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
fromstruct_<I>typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
|
|
|
|
|
void *source, isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
fromstruct_<I>classname_typename</I>(dns_rdataclass_t class, dns_rdatatype_t type,
|
|
|
|
|
void *source, isc_buffer_t *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>class</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This argument should be ignored when used with a class generic RR type
|
|
|
|
|
otherwise <CODE>REQUIRE(class == #)</CODE> should be present at the start
|
|
|
|
|
of the function.
|
|
|
|
|
<DT><CODE>type</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This should be tested with a <CODE>REQUIRE(type == #)</CODE> statement at
|
|
|
|
|
the beginning of the function.
|
|
|
|
|
<DT><CODE>source</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This points to a type specific structure.
|
|
|
|
|
<DT><CODE>target</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
This is a <CODE>BINARY</CODE> buffer used to write the internal format of the rdata record being read in to.
|
|
|
|
|
</DL>
|
|
|
|
|
<H2>Convert from internal format to a structure</H2>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
tostruct_<I>typename</I>(dns_rdata_t *rdata, void *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static dns_result_t
|
|
|
|
|
tostruct_<I>classname_typename</I>(dns_rdata_t *rdata, void *target);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>rdata</CODE></DT>
|
|
|
|
|
<DD>
|
1999-04-22 12:27:55 +00:00
|
|
|
|
This is the rdata record to be converted from internal format to a structure.
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<CODE>rdata->type</CODE> and <CODE>rdata->class</CODE> for class specific
|
|
|
|
|
RR types should be checked at the start of the function with
|
|
|
|
|
<CODE>REQUIRE(rdata->type ==<3D>#)</CODE> statements.
|
|
|
|
|
<DT><CODE>target</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
Pointer to a type specific structure.
|
|
|
|
|
</DL>
|
|
|
|
|
<H2>Compare two rdata in internal format</H2>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static int
|
|
|
|
|
compare_<I>typename</I>(dns_rdata_t *rdata1, dns_rdata_t *rdata2);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
<PRE>
|
|
|
|
|
<CODE>static int
|
|
|
|
|
compare_<I>classname_typename</I>(dns_rdata_t *rdata1, dns_rdata_t *rdata2);</CODE>
|
|
|
|
|
</PRE>
|
|
|
|
|
Compares <CODE>rdata1</CODE> and <CODE>rdata2<CODE> as required for DNSSEC
|
|
|
|
|
ordering. The routine should
|
|
|
|
|
ensure that the <CODE>type</CODE> and <CODE>class</CODE> of the two rdata
|
|
|
|
|
match with <CODE>REQUIRE(rdata1->type == rdata2->type);</CODE> and
|
|
|
|
|
<CODE>REQUIRE(rdata1->class == rdata2->class);</CODE> statements. The
|
|
|
|
|
<CODE>rdata->type</CODE> should also be verified and if the RR type is
|
|
|
|
|
class specific the <CODE>rdata->class</CLASS>.
|
|
|
|
|
<P>
|
|
|
|
|
<CODE>compare_<I>classname_typename</I>()</CODE> returns -1, 0, 1.
|
|
|
|
|
<H2><A NAME="functions">Support Functions</A></H2>
|
|
|
|
|
The following static support functions are available to use.
|
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>static unsigned int<BR>
|
|
|
|
|
name_length(dns_name_t *name);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Returns the length of <CODE>name</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
txt_totext(isc_region_t *source, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Extracts the octet length tagged text string at the start of
|
|
|
|
|
<CODE>source</CODE> and writes it as a quoted string to <CODE>target</CODE>.
|
|
|
|
|
<CODE>source</CODE> is adjusted so that it points to first octet after the
|
|
|
|
|
text string.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE> or <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Take the text region <CODE>source</CODE> and convert it to a length tagged
|
|
|
|
|
text string writing it to <CODE>target</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE>, <CODE>DNS_R_TEXTTOLONG</CODE>
|
|
|
|
|
or <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Read a octet length tagged text string from <CODE>source</CODE> and
|
|
|
|
|
write it to <CODE>target</CODE>.
|
|
|
|
|
Ensures that octet length tagged text string was wholly within the active
|
|
|
|
|
area of <CODE>source</CODE>.
|
|
|
|
|
Adjusts the active area of <CODE>source</CODE> so that it refers to the first
|
|
|
|
|
octet after the octet length tagged text string.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_UNEXPECTEDEND</CODE>, <CODE>DNS_R_NOSPACE</CODE> or
|
|
|
|
|
<CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><A NAME="name_prefix"><CODE>static isc_boolean_t<BR>
|
|
|
|
|
name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);</CODE>
|
|
|
|
|
</A></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
If <CODE>origin</CODE> is NULL or the root label set <CODE>target<CODE> to
|
|
|
|
|
refer to <CODE>name</CODE> and return <CODE>ISC_FALSE</CODE>.
|
|
|
|
|
Otherwise see if <CODE>name</CODE> is a sub domain of <CODE>origin</CODE>
|
|
|
|
|
and are not equal.
|
|
|
|
|
If so make <CODE>target</CODE> refer to the prefix of <CODE>name</CODE> and
|
|
|
|
|
return <CODE>ISC_TRUE</CODE>.
|
|
|
|
|
Otherwise make <CODE>target</CODE> refer to <CODE>name</CODE> and return
|
|
|
|
|
<CODE>ISC_FALSE</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
Typical use:
|
|
|
|
|
<PRE><CODE>
|
|
|
|
|
static dns_result_t
|
|
|
|
|
totext_<I>typename</I>(dns_rdata_t *rdata, dns_name_t *origin,
|
|
|
|
|
isc_buffer_t * target)
|
|
|
|
|
{
|
|
|
|
|
isc_region_t region;
|
|
|
|
|
dns_name_t name, prefix;
|
|
|
|
|
isc_boolean_t sub;
|
|
|
|
|
|
1999-04-22 12:27:55 +00:00
|
|
|
|
dns_name_init(&name, NULL);
|
|
|
|
|
dns_name_init(&prefix, NULL);
|
|
|
|
|
dns_rdata_toregion(rdata, &region);
|
|
|
|
|
dns_name_fromregion(&name, &region);
|
|
|
|
|
sub = <B>name_prefix</B>(&name, origin, &prefix);
|
|
|
|
|
return (dns_name_totext(&prefix, sub, target));
|
1999-02-12 03:13:27 +00:00
|
|
|
|
}
|
|
|
|
|
</CODE></PRE>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
str_totext(char *source, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
This adds the <CODE>NULL</CODE> terminated string <CODE>source</CODE>
|
|
|
|
|
up to but not including <CODE>NULL</CODE> to <CODE>target</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static isc_boolean_t<BR>
|
|
|
|
|
buffer_empty(isc_buffer_t *source);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>ISC_TRUE</CODE> if the active region of <CODE>source</CODE> is
|
|
|
|
|
empty otherwise <CODE>ISC_FALSE</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static void<BR>
|
|
|
|
|
buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region,
|
|
|
|
|
unsigned int type);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Make <CODE>buffer</CODE> refer to the memory in <CODE>region</CODE> and
|
|
|
|
|
make it active.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
1999-04-22 12:27:55 +00:00
|
|
|
|
Write the 32 bit <CODE>value</CODE> in network order to <CODE>target</CODE>.
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Write them 16 bit <CODE>value</CODE> in network order to <CODE>target</CODE>.
|
|
|
|
|
<P>
|
2000-05-15 21:14:38 +00:00
|
|
|
|
Returns <CODE>ISC_R_RANGE</CODE>, <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static isc_uint32_t<BR>
|
|
|
|
|
uint32_fromregion(isc_region_t *region);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Returns the 32 bit at the start of <CODE>region</CODE> in host order.
|
|
|
|
|
<P>
|
|
|
|
|
Requires <CODE>(region->length >= 4)</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static isc_uint16_t<BR>
|
|
|
|
|
uint16_fromregion(isc_region_t *region);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Returns the 16 bit at the start of <CODE>region</CODE> in host order.
|
|
|
|
|
<P>
|
|
|
|
|
Requires <CODE>(region->length >= 2)</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
<A NAME="gettoken">gettoken</A>(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect, isc_boolean_t eol);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Gets the next token from the input stream <CODE>lexer</CODE>. Ensure that the
|
|
|
|
|
returned token matches <CODE>expect</CODE> (isc_tokentype_qstring can also
|
|
|
|
|
return isc_tokentype_string), or isc_tokentype_eol and isc_tokentype_eof if
|
|
|
|
|
<CODE>eol</CODE> is <CODE>ISC_TRUE</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_UNEXPECTED</CODE>, <CODE>DNS_R_UNEXPECTEDEND</CODE>,
|
|
|
|
|
<CODE>DNS_R_UNEXPECTEDTOKEN</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
</DT>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
<A NAME="mem_tobuffer">mem_tobuffer</A>(isc_buffer_t *target, void *base, unsigned int length);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Add the memory referred to by <CODE>base</CODE> to <CODE>target</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static int<BR>
|
|
|
|
|
compare_region(isc_region_t *r1, isc_region_t *r2)</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
1999-04-22 12:27:55 +00:00
|
|
|
|
Compares two regions returning -1, 0, 1 based on their DNSSEC ordering.
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static int<BR>
|
|
|
|
|
hexvalue(char value);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Returns the hexadecimal value of <CODE>value</CODE> or -1 if not
|
|
|
|
|
a hexadecimal character.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static int<BR>
|
|
|
|
|
decvalue(char value);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Returns the decimal value of <CODE>value</CODE> or -1 if not
|
|
|
|
|
a decimal character.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
base64_totext(isc_region_t *source, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
1999-04-22 12:27:55 +00:00
|
|
|
|
Convert the region referred to by <CODE>source</CODE> to base64 encoded text
|
1999-02-12 03:13:27 +00:00
|
|
|
|
and put it into <CODE>target</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE> or <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target,
|
|
|
|
|
int length);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Read a series of tokens from <CODE>lexer</CODE> that containing base64 data
|
|
|
|
|
until one of end of line, <CODE>length</CODE> (<CODE>length</CODE> >= 0)
|
|
|
|
|
bytes have been read or base64 pad characters are seen.
|
|
|
|
|
If <CODE>length</CODE> < 0 it is ignored otherwise it is an error if there
|
|
|
|
|
are not <CODE>length</CODE> octets of data or when processing a token
|
|
|
|
|
<CODE>length</CODE> octets would have been exceeded.
|
|
|
|
|
<P>
|
|
|
|
|
Returns <CODE>DNS_R_BADBASE64</CODE>, <CODE>DNS_R_UNEXPECTED</CODE>,
|
|
|
|
|
<CODE>DNS_R_UNEXPECTEDEND</CODE>, <CODE>DNS_R_UNEXPECTEDTOKEN</CODE>
|
|
|
|
|
and <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
<P>
|
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
time_totext(unsigned long value, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Convert the date represented by <CODE>value</CODE> into YYYYMMDDHHMMSS format
|
|
|
|
|
taking into account the active epochs. This code is Y2K and Y2038 compliant.
|
|
|
|
|
<P>
|
1999-04-22 12:27:55 +00:00
|
|
|
|
Returns <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<DT><CODE>static dns_result_t<BR>
|
|
|
|
|
time_tobuffer(char *source, isc_buffer_t *target);</CODE></DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Take the date in <CODE>source</CODE> and convert it seconds since January 1,
|
|
|
|
|
1970 (ignoring leap seconds) and place the least significant 32 bits into
|
|
|
|
|
<CODE>target</CODE>.
|
|
|
|
|
<P>
|
2000-05-15 21:14:38 +00:00
|
|
|
|
Returns <CODE>ISC_R_RANGE</CODE>, <CODE>DNS_R_SYNTAX</CODE>,
|
1999-02-12 03:13:27 +00:00
|
|
|
|
<CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
</DL>
|
|
|
|
|
<H2><A NAME="macros">Support Macros<A></H2>
|
|
|
|
|
The following macro is available:
|
|
|
|
|
<DL>
|
|
|
|
|
<DT><CODE>RETERR(x)</CODE><DT>
|
|
|
|
|
<DD>
|
|
|
|
|
<P>
|
|
|
|
|
Evaluate <CODE>x</CODE> and call <CODE>return (<I><value of x></I>);</CODE> if the result is not <CODE>DNS_R_SUCCESS</CODE>.
|
|
|
|
|
</DL>
|
|
|
|
|
</BODY>
|
|
|
|
|
</HTML>
|