mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 18:19:42 +00:00
609 lines
21 KiB
HTML
609 lines
21 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||
<!--
|
||
- Copyright (C) 1999-2001, 2004, 2007, 2016 Internet Systems Consortium, Inc. ("ISC")
|
||
-
|
||
- 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/.
|
||
-->
|
||
|
||
<!-- $Id: rdata.html,v 1.15 2007/06/19 23:47:13 tbox Exp $ -->
|
||
|
||
<HTML>
|
||
<HEAD>
|
||
<TITLE>Adding new RDATA type</TITLE>
|
||
</HEAD>
|
||
<BODY>
|
||
<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>,
|
||
<CODE>dns_rdata_tostruct()</CODE> and <CODE>dns_rdata_compare()</CODE>)
|
||
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>
|
||
|
||
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.
|
||
|
||
<H2>Internal Format</H2>
|
||
The internal format chosen is DNS wire format without any compression being
|
||
applied to domain names in the rdata.
|
||
|
||
<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>
|
||
<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
|
||
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);</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>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>,
|
||
along with <CODE>downcase</CODE>, to enable a compressed domain name
|
||
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>
|
||
If the <CODE>active</CODE> buffer is not empty at completion and
|
||
<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>
|
||
<P>
|
||
<CODE>towire_<I>classname_typename</I>()</CODE> is required to set the
|
||
allowed name compression methods based on EDNS version if there is a
|
||
domain name in the rdata.
|
||
<PRE>
|
||
<CODE>if (dns_compress_getedns(cctx) >= #)
|
||
dns_compress_setmethods(cctx, DNS_COMPRESS_ALL);
|
||
else
|
||
dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);</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>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>
|
||
This is the rdata record to be converted from internal format to a structure.
|
||
<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;
|
||
|
||
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));
|
||
}
|
||
</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>
|
||
Write the 32 bit <CODE>value</CODE> in network order to <CODE>target</CODE>.
|
||
<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>
|
||
Returns <CODE>ISC_R_RANGE</CODE>, <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
||
<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>
|
||
Compares two regions returning -1, 0, 1 based on their DNSSEC ordering.
|
||
<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>
|
||
Convert the region referred to by <CODE>source</CODE> to base64 encoded text
|
||
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>
|
||
Returns <CODE>DNS_R_NOSPACE</CODE> and <CODE>DNS_R_SUCCESS</CODE>.
|
||
<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>
|
||
Returns <CODE>ISC_R_RANGE</CODE>, <CODE>DNS_R_SYNTAX</CODE>,
|
||
<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>
|