2019-02-14 10:09:11 +00:00
/*
2020-02-20 15:35:16 +00:00
Copyright ( c ) 2016 - 2020 Chung , Hyung - Hwan . All rights reserved .
2019-02-14 10:09:11 +00:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE AUTHOR " AS IS " AND ANY EXPRESS OR
IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WAfRRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2021-07-22 07:30:20 +00:00
# include <hio-dns.h>
# include "hio-prv.h"
2019-02-14 10:09:11 +00:00
/* ----------------------------------------------------------------------- */
# define DN_AT_END(ptr) (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0'))
2021-07-22 07:30:20 +00:00
static hio_oow_t to_dn ( const hio_bch_t * str , hio_uint8_t * buf )
2019-02-14 10:09:11 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint8_t * bp = buf ;
/*HIO_ASSERT (HIO_SIZEOF(hio_uint8_t) == HIO_SIZEOF(hio_bch_t));*/
2019-02-14 10:09:11 +00:00
2019-02-16 18:22:32 +00:00
if ( str & & ! DN_AT_END ( str ) )
2019-02-14 10:09:11 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint8_t * lp ;
hio_oow_t len ;
const hio_bch_t * seg ;
const hio_bch_t * cur = str - 1 ;
2019-02-14 10:09:11 +00:00
do
{
2020-02-24 16:39:29 +00:00
lp = bp + + ;
2019-02-14 10:09:11 +00:00
seg = + + cur ;
while ( * cur ! = ' \0 ' & & * cur ! = ' . ' )
{
2020-02-24 16:39:29 +00:00
* bp + + = * cur ;
2019-02-14 10:09:11 +00:00
cur + + ;
}
len = cur - seg ;
if ( len < = 0 | | len > 63 ) return 0 ;
2021-07-22 07:30:20 +00:00
* lp = ( hio_uint8_t ) len ;
2019-02-14 10:09:11 +00:00
}
while ( ! DN_AT_END ( cur ) ) ;
}
2020-02-24 16:39:29 +00:00
* bp + + = 0 ;
2019-02-14 10:09:11 +00:00
/* the length includes the terminating zero. */
return bp - buf ;
}
2021-07-22 07:30:20 +00:00
static hio_oow_t to_dn_capa ( const hio_bch_t * str )
2020-02-24 16:39:29 +00:00
{
2021-07-22 07:30:20 +00:00
hio_oow_t capa = 0 ;
2020-02-24 16:39:29 +00:00
2021-07-22 07:30:20 +00:00
/*HIO_ASSERT (HIO_SIZEOF(hio_uint8_t) == HIO_SIZEOF(hio_bch_t));*/
2020-02-24 16:39:29 +00:00
if ( str & & ! DN_AT_END ( str ) )
{
2021-07-22 07:30:20 +00:00
hio_oow_t len ;
const hio_bch_t * seg ;
const hio_bch_t * cur = str - 1 ;
2020-02-24 16:39:29 +00:00
do
{
capa + + ;
seg = + + cur ;
while ( * cur ! = ' \0 ' & & * cur ! = ' . ' )
{
capa + + ;
cur + + ;
}
len = cur - seg ;
if ( len < = 0 | | len > 63 ) return 0 ;
}
while ( ! DN_AT_END ( cur ) ) ;
}
capa + + ;
/* the length includes the terminating zero. */
return capa ;
}
2021-07-22 07:30:20 +00:00
static hio_oow_t dn_length ( hio_uint8_t * ptr , hio_oow_t len )
2019-02-14 10:09:11 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint8_t * curptr ;
hio_oow_t curlen , seglen ;
2019-02-14 10:09:11 +00:00
curptr = ptr ;
curlen = len ;
do
{
if ( curlen < = 0 ) return 0 ;
seglen = * curptr + + ;
curlen = curlen - 1 ;
if ( seglen = = 0 ) break ;
else if ( seglen > curlen | | seglen > 63 ) return 0 ;
curptr + = seglen ;
curlen - = seglen ;
}
while ( 1 ) ;
return curptr - ptr ;
}
2020-02-11 15:51:41 +00:00
/* ----------------------------------------------------------------------- */
2021-07-22 07:30:20 +00:00
static int parse_domain_name ( hio_t * hio , hio_dns_pkt_info_t * pi )
2020-02-11 15:51:41 +00:00
{
2021-07-22 07:30:20 +00:00
hio_oow_t seglen ;
hio_uint8_t * xptr ;
2020-02-11 15:51:41 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( pi - > _ptr > = pi - > _end ) ) goto oops ;
xptr = HIO_NULL ;
2020-02-12 10:06:05 +00:00
2020-02-13 16:27:29 +00:00
if ( ( seglen = * pi - > _ptr + + ) = = 0 )
2020-02-13 09:31:02 +00:00
{
2020-02-13 16:27:29 +00:00
if ( pi - > _rrdptr ) pi - > _rrdptr [ 0 ] = ' \0 ' ;
pi - > _rrdlen + + ; /* for a terminating null */
2020-02-13 09:31:02 +00:00
return 0 ;
}
do
2020-02-11 15:51:41 +00:00
{
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( seglen < 64 ) )
2020-02-11 15:51:41 +00:00
{
2020-02-12 10:06:05 +00:00
/* normal. 00XXXXXXXX */
normal :
2020-02-13 16:27:29 +00:00
if ( pi - > _rrdptr )
2020-02-13 09:31:02 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( pi - > _rrdptr , pi - > _ptr , seglen ) ;
2020-02-13 16:27:29 +00:00
pi - > _rrdptr + = seglen + 1 ; /* +1 for '.' */
pi - > _rrdptr [ - 1 ] = ' . ' ;
2020-02-13 09:31:02 +00:00
}
2020-02-13 16:27:29 +00:00
pi - > _rrdlen + = seglen + 1 ; /* +1 for '.' */
pi - > _ptr + = seglen ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( pi - > _ptr > = pi - > _end ) ) goto oops ;
2020-02-11 15:51:41 +00:00
}
2020-02-12 10:06:05 +00:00
else if ( seglen > = 192 )
{
/* compressed. 11XXXXXXXX XXXXXXXX */
2021-07-22 07:30:20 +00:00
hio_oow_t offset ;
2020-02-11 15:51:41 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( pi - > _ptr > = pi - > _end ) ) goto oops ;
2020-02-13 16:27:29 +00:00
offset = ( ( seglen & 0x3F ) < < 8 ) | * pi - > _ptr + + ;
2020-02-12 10:06:05 +00:00
2021-07-22 07:30:20 +00:00
/*if (HIO_UNLIKELY(pi->_ptr >= pi->_end)) goto oops; <- this condition can be true if the function is called for the domain name at the back of the last RR */
2020-04-28 11:27:24 +00:00
2020-02-13 16:27:29 +00:00
seglen = pi - > _start [ offset ] ;
2020-02-12 10:06:05 +00:00
if ( seglen > = 64 ) goto oops ; /* the pointed position must not contain another pointer */
2020-04-28 11:27:24 +00:00
if ( ! xptr ) xptr = pi - > _ptr ; /* some later parts can also be a pointer again. so xptr, once set, must not be set again */
2020-02-13 16:27:29 +00:00
pi - > _ptr = & pi - > _start [ offset + 1 ] ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( pi - > _ptr > = pi - > _end ) ) goto oops ;
2020-02-12 10:06:05 +00:00
goto normal ;
}
else if ( seglen > = 128 )
{
/* 128 to 191. 10XXXXXXXX */
goto oops ;
}
else
{
/* 64 to 127. 01XXXXXXXX */
goto oops ;
}
2020-02-11 15:51:41 +00:00
}
2020-02-13 16:27:29 +00:00
while ( ( seglen = * pi - > _ptr + + ) > 0 ) ;
2020-02-11 15:51:41 +00:00
2020-02-13 16:27:29 +00:00
if ( pi - > _rrdptr ) pi - > _rrdptr [ - 1 ] = ' \0 ' ;
2020-02-13 09:31:02 +00:00
2020-02-13 16:27:29 +00:00
if ( xptr ) pi - > _ptr = xptr ;
2020-02-13 09:31:02 +00:00
return 0 ;
2020-02-11 15:51:41 +00:00
2020-02-12 10:06:05 +00:00
oops :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
2020-02-13 09:31:02 +00:00
return - 1 ;
2020-02-11 15:51:41 +00:00
}
2021-07-22 07:30:20 +00:00
static int parse_question_rr ( hio_t * hio , hio_oow_t pos , hio_dns_pkt_info_t * pi )
2020-02-12 10:06:05 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_qrtr_t * qrtr ;
hio_uint8_t * xrrdptr ;
2020-02-12 10:06:05 +00:00
2020-02-13 16:27:29 +00:00
xrrdptr = pi - > _rrdptr ;
2021-07-22 07:30:20 +00:00
if ( parse_domain_name ( hio , pi ) < = - 1 ) return - 1 ;
2020-02-12 10:06:05 +00:00
2021-07-22 07:30:20 +00:00
qrtr = ( hio_dns_qrtr_t * ) pi - > _ptr ;
if ( HIO_UNLIKELY ( pi - > _ptr > pi - > _end | | pi - > _end - pi - > _ptr < HIO_SIZEOF ( * qrtr ) ) ) goto oops ;
2020-06-25 03:08:22 +00:00
2021-07-22 07:30:20 +00:00
pi - > _ptr + = HIO_SIZEOF ( * qrtr ) ;
/*pi->_rrdlen += HIO_SIZEOF(*qrtr);*/
2020-02-12 10:06:05 +00:00
2020-02-13 16:27:29 +00:00
if ( pi - > _rrdptr )
2020-02-13 09:31:02 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_bqr_t * bqr ;
2020-02-13 09:31:02 +00:00
bqr = pi - > rr . qd ;
2021-07-22 07:30:20 +00:00
bqr [ pos ] . qname = ( hio_bch_t * ) xrrdptr ;
bqr [ pos ] . qtype = hio_ntoh16 ( qrtr - > qtype ) ;
bqr [ pos ] . qclass = hio_ntoh16 ( qrtr - > qclass ) ;
2020-02-13 09:31:02 +00:00
}
return 0 ;
2020-02-12 10:06:05 +00:00
oops :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
2020-02-13 09:31:02 +00:00
return - 1 ;
2020-02-12 10:06:05 +00:00
}
2021-07-22 07:30:20 +00:00
static int parse_answer_rr ( hio_t * hio , hio_dns_rr_part_t rr_part , hio_oow_t pos , hio_dns_pkt_info_t * pi )
2020-02-11 15:51:41 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_rrtr_t * rrtr ;
hio_uint16_t qtype , dlen ;
hio_uint8_t * xrrdptr , * xrrdptr2 ;
2020-02-11 15:51:41 +00:00
2020-02-13 16:27:29 +00:00
xrrdptr = pi - > _rrdptr ;
2021-07-22 07:30:20 +00:00
if ( parse_domain_name ( hio , pi ) < = - 1 ) return - 1 ;
2020-02-11 15:51:41 +00:00
2021-07-22 07:30:20 +00:00
rrtr = ( hio_dns_rrtr_t * ) pi - > _ptr ;
if ( HIO_UNLIKELY ( pi - > _ptr > pi - > _end | | pi - > _end - pi - > _ptr < HIO_SIZEOF ( * rrtr ) ) ) goto oops ;
2020-06-25 03:08:22 +00:00
2021-07-22 07:30:20 +00:00
pi - > _ptr + = HIO_SIZEOF ( * rrtr ) ;
dlen = hio_ntoh16 ( rrtr - > dlen ) ;
if ( HIO_UNLIKELY ( pi - > _ptr > pi - > _end | | pi - > _end - pi - > _ptr < dlen ) ) goto oops ;
2020-02-12 15:23:36 +00:00
2021-07-22 07:30:20 +00:00
qtype = hio_ntoh16 ( rrtr - > rrtype ) ;
2020-02-13 09:31:02 +00:00
2020-02-17 14:54:21 +00:00
xrrdptr2 = pi - > _rrdptr ;
2020-02-12 15:23:36 +00:00
switch ( qtype )
{
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_OPT :
2020-02-12 15:23:36 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint16_t eopt_tot_len , eopt_len ;
hio_dns_eopt_t * eopt ;
2020-06-30 16:11:39 +00:00
2020-02-12 15:23:36 +00:00
/* RFC 6891
The extended RCODE and flags , which OPT stores in the RR Time to Live
( TTL ) field , are structured as follows :
+ - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - +
0 : | EXTENDED - RCODE | VERSION |
+ - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - +
2 : | DO | Z |
+ - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - +
2020-02-13 09:31:02 +00:00
2020-02-12 15:23:36 +00:00
EXTENDED - RCODE
Forms the upper 8 bits of extended 12 - bit RCODE ( together with the
4 bits defined in [ RFC1035 ] . Note that EXTENDED - RCODE value 0
indicates that an unextended RCODE is in use ( values 0 through
15 ) .
*/
2020-02-13 09:31:02 +00:00
/* TODO: do i need to check if rrname is <ROOT>? */
2021-07-22 07:30:20 +00:00
/* TODO: do i need to check if rr_part is HIO_DNS_RR_PART_ADDITIONAL? the OPT pseudo-RR may exist in the ADDITIONAL section only */
2020-07-02 14:21:47 +00:00
/* TODO: do i need to check if there is more than 1 OPT RRs */
pi - > edns . exist + + ; /* you may treat this as the number of OPT RRs */
2021-07-22 07:30:20 +00:00
pi - > edns . uplen = hio_ntoh16 ( rrtr - > rrclass ) ;
2020-02-13 09:31:02 +00:00
pi - > hdr . rcode | = ( rrtr - > ttl > > 24 ) ;
pi - > edns . version = ( rrtr - > ttl > > 16 ) & 0xFF ;
pi - > edns . dnssecok = ( ( rrtr - > ttl & 0x8000 ) > > 15 ) ;
2020-02-12 15:23:36 +00:00
/*if ((rrtr->ttl & 0x7FFF) != 0) goto oops;*/ /* Z not 0 - ignore this for now */
2020-06-30 16:11:39 +00:00
2021-07-22 07:30:20 +00:00
eopt = ( hio_dns_eopt_t * ) ( rrtr + 1 ) ;
2020-06-30 16:11:39 +00:00
eopt_tot_len = dlen ;
while ( eopt_tot_len > 0 )
{
2021-07-22 07:30:20 +00:00
if ( eopt_tot_len < HIO_SIZEOF ( hio_dns_eopt_t ) ) goto oops ;
2020-06-30 16:11:39 +00:00
2021-07-22 07:30:20 +00:00
eopt_len = hio_ntoh16 ( eopt - > dlen ) ;
if ( eopt_tot_len - HIO_SIZEOF ( hio_dns_eopt_t ) < eopt_len ) goto oops ; /* wrong eopt length */
2020-06-30 16:11:39 +00:00
2021-07-22 07:30:20 +00:00
if ( eopt - > code = = HIO_CONST_HTON16 ( HIO_DNS_EOPT_COOKIE ) )
2020-06-30 16:11:39 +00:00
{
2021-07-22 07:30:20 +00:00
if ( eopt_len = = HIO_DNS_COOKIE_CLIENT_LEN )
2020-07-02 14:21:47 +00:00
{
/* client cookie only */
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( pi - > edns . cookie . data . client , eopt + 1 , eopt_len ) ;
2020-07-02 14:21:47 +00:00
pi - > edns . cookie . client_len = eopt_len ;
pi - > edns . cookie . server_len = 0 ;
}
2021-07-22 07:30:20 +00:00
else if ( eopt_len > = ( HIO_DNS_COOKIE_CLIENT_LEN + HIO_DNS_COOKIE_SERVER_MIN_LEN ) & &
eopt_len < = ( HIO_DNS_COOKIE_CLIENT_LEN + HIO_DNS_COOKIE_SERVER_MAX_LEN ) )
2020-07-02 14:21:47 +00:00
{
/* both client and server cookie */
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( & pi - > edns . cookie . data , eopt + 1 , eopt_len ) ;
pi - > edns . cookie . client_len = HIO_DNS_COOKIE_CLIENT_LEN ;
pi - > edns . cookie . server_len = eopt_len - HIO_DNS_COOKIE_CLIENT_LEN ;
2020-07-02 14:21:47 +00:00
}
else
{
/* wrong cookie length */
goto oops ;
}
2020-06-30 16:11:39 +00:00
}
2021-07-22 07:30:20 +00:00
eopt_tot_len - = HIO_SIZEOF ( hio_dns_eopt_t ) + eopt_len ;
eopt = ( hio_dns_eopt_t * ) ( ( hio_uint8_t * ) eopt + HIO_SIZEOF ( hio_dns_eopt_t ) + eopt_len ) ;
2020-06-30 16:11:39 +00:00
}
goto verbatim ; /* keep the entire option data including cookies */
2020-02-12 15:23:36 +00:00
}
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_A :
if ( HIO_UNLIKELY ( dlen ! = HIO_SIZEOF ( hio_ip4ad_t ) ) ) goto oops ;
2020-02-17 14:54:21 +00:00
goto verbatim ;
2020-02-12 15:23:36 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_AAAA :
if ( HIO_UNLIKELY ( dlen ! = HIO_SIZEOF ( hio_ip6ad_t ) ) ) goto oops ;
2020-02-17 14:54:21 +00:00
goto verbatim ;
2020-02-13 09:31:02 +00:00
2021-07-22 07:30:20 +00:00
/*case HIO_DNS_RRT_MB:
case HIO_DNS_RRT_MD :
case HIO_DNS_RRT_MF :
case HIO_DNS_RRT_MG :
case HIO_DNS_RRT_MR : */
case HIO_DNS_RRT_CNAME :
case HIO_DNS_RRT_NS :
case HIO_DNS_RRT_PTR :
2020-02-12 15:23:36 +00:00
{
2021-07-22 07:30:20 +00:00
# if !defined(HIO_BUILD_RELEASE)
hio_uint8_t * xptr = pi - > _ptr ;
2020-02-13 09:31:02 +00:00
# endif
2021-07-22 07:30:20 +00:00
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
HIO_ASSERT ( hio , pi - > _ptr = = xptr + dlen ) ;
2020-02-12 15:23:36 +00:00
break ;
}
2020-02-17 14:54:21 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_MX :
2020-04-28 11:27:24 +00:00
{
2021-07-22 07:30:20 +00:00
# if !defined(HIO_BUILD_RELEASE)
hio_uint8_t * xptr = pi - > _ptr ;
2020-04-28 11:27:24 +00:00
# endif
2021-07-22 07:30:20 +00:00
hio_dns_brrd_mx_t * mx ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
pi - > _rrdlen + = HIO_SIZEOF ( * mx ) ;
if ( HIO_UNLIKELY ( pi - > _end - pi - > _ptr < 2 ) ) goto oops ;
2020-04-28 11:27:24 +00:00
if ( pi - > _rrdptr )
{
2021-07-22 07:30:20 +00:00
mx = ( hio_dns_brrd_mx_t * ) pi - > _rrdptr ;
pi - > _rrdptr + = HIO_SIZEOF ( * mx ) ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( & mx - > preference , pi - > _ptr , 2 ) ; pi - > _ptr + = 2 ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
mx - > preference = hio_ntoh16 ( mx - > preference ) ;
mx - > exchange = ( hio_bch_t * ) pi - > _rrdptr ;
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
2020-04-28 11:27:24 +00:00
}
else
{
pi - > _ptr + = 2 ;
2021-07-22 07:30:20 +00:00
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
2020-04-28 11:27:24 +00:00
}
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , pi - > _ptr = = xptr + dlen ) ;
2020-04-28 11:27:24 +00:00
break ;
}
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_SOA :
2020-02-17 14:54:21 +00:00
{
2021-07-22 07:30:20 +00:00
# if !defined(HIO_BUILD_RELEASE)
hio_uint8_t * xptr = pi - > _ptr ;
2020-02-17 14:54:21 +00:00
# endif
2021-07-22 07:30:20 +00:00
hio_dns_brrd_soa_t * soa ;
2020-02-17 14:54:21 +00:00
2021-07-22 07:30:20 +00:00
pi - > _rrdlen + = HIO_SIZEOF ( * soa ) ;
2020-02-17 14:54:21 +00:00
if ( pi - > _rrdptr )
{
2021-07-22 07:30:20 +00:00
soa = ( hio_dns_brrd_soa_t * ) pi - > _rrdptr ;
pi - > _rrdptr + = HIO_SIZEOF ( * soa ) ;
soa - > mname = ( hio_bch_t * ) pi - > _rrdptr ;
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
soa - > rname = ( hio_bch_t * ) pi - > _rrdptr ;
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
if ( HIO_UNLIKELY ( pi - > _end - pi - > _ptr < 20 ) ) goto oops ;
HIO_MEMCPY ( & soa - > serial , pi - > _ptr , 20 ) ;
soa - > serial = hio_ntoh32 ( soa - > serial ) ;
soa - > refresh = hio_ntoh32 ( soa - > refresh ) ;
soa - > retry = hio_ntoh32 ( soa - > retry ) ;
soa - > expire = hio_ntoh32 ( soa - > expire ) ;
soa - > minimum = hio_ntoh32 ( soa - > minimum ) ;
2020-02-17 14:54:21 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
if ( parse_domain_name ( hio , pi ) < = - 1 ) goto oops ;
if ( HIO_UNLIKELY ( pi - > _end - pi - > _ptr < 20 ) ) goto oops ;
2020-02-17 14:54:21 +00:00
}
2020-02-19 15:42:29 +00:00
pi - > _ptr + = 20 ;
2020-02-17 14:54:21 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , pi - > _ptr = = xptr + dlen ) ;
2020-02-17 14:54:21 +00:00
break ;
}
default :
verbatim :
pi - > _ptr + = dlen ;
pi - > _rrdlen + = dlen ;
if ( pi - > _rrdptr )
{
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( pi - > _rrdptr , rrtr + 1 , dlen ) ; /* copy actual data */
2020-02-17 14:54:21 +00:00
pi - > _rrdptr + = dlen ;
}
2020-02-12 15:23:36 +00:00
}
2020-02-11 15:51:41 +00:00
2020-02-17 14:54:21 +00:00
if ( pi - > _rrdptr )
2020-02-13 09:31:02 +00:00
{
2020-02-17 14:54:21 +00:00
/* store information about the actual record */
2021-07-22 07:30:20 +00:00
hio_dns_brr_t * brr ;
2020-02-17 14:54:21 +00:00
switch ( rr_part )
2020-02-14 10:06:29 +00:00
{
2021-07-22 07:30:20 +00:00
case HIO_DNS_RR_PART_ANSWER : brr = pi - > rr . an ; break ;
case HIO_DNS_RR_PART_AUTHORITY : brr = pi - > rr . ns ; break ;
case HIO_DNS_RR_PART_ADDITIONAL : brr = pi - > rr . ar ; break ;
2020-04-28 11:27:24 +00:00
default : goto oops ;
2020-02-14 10:06:29 +00:00
}
2020-02-17 14:54:21 +00:00
brr [ pos ] . part = rr_part ;
2021-07-22 07:30:20 +00:00
brr [ pos ] . rrname = ( hio_bch_t * ) xrrdptr ;
brr [ pos ] . rrtype = hio_ntoh16 ( rrtr - > rrtype ) ;
brr [ pos ] . rrclass = hio_ntoh16 ( rrtr - > rrclass ) ;
brr [ pos ] . ttl = hio_ntoh32 ( rrtr - > ttl ) ;
2020-02-17 14:54:21 +00:00
brr [ pos ] . dptr = xrrdptr2 ;
/* this length may be different from the length in the header as transformation is performed on some RR data.
* for a domain name , it ' s inclusive of the termining null . */
brr [ pos ] . dlen = pi - > _rrdptr - xrrdptr2 ;
2020-02-13 09:31:02 +00:00
}
return 0 ;
2020-02-11 15:51:41 +00:00
2020-02-12 10:06:05 +00:00
oops :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
2020-02-13 09:31:02 +00:00
return - 1 ;
2020-02-11 15:51:41 +00:00
}
2021-07-22 07:30:20 +00:00
hio_dns_pkt_info_t * hio_dns_make_pkt_info ( hio_t * hio , const hio_dns_pkt_t * pkt , hio_oow_t len )
2020-02-11 15:51:41 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint16_t i ;
hio_dns_pkt_info_t pib , * pii ;
2020-02-11 15:51:41 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , len > = HIO_SIZEOF ( * pkt ) ) ;
2020-02-11 15:51:41 +00:00
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & pib , 0 , HIO_SIZEOF ( pib ) ) ;
2020-06-25 03:08:22 +00:00
2021-08-08 04:10:29 +00:00
/* pib is used as the initial workspace and also indicates that it's the first run.
* at the second run , pii is set to a dynamically allocated memory block large enough
2020-06-25 03:08:22 +00:00
* to hold actual data . */
pii = & pib ;
2020-02-13 09:31:02 +00:00
redo :
2021-07-22 07:30:20 +00:00
pii - > _start = ( hio_uint8_t * ) pkt ;
pii - > _end = ( hio_uint8_t * ) pkt + len ;
pii - > _ptr = ( hio_uint8_t * ) ( pkt + 1 ) ;
2020-02-13 09:31:02 +00:00
2021-07-22 07:30:20 +00:00
pii - > hdr . id = hio_ntoh16 ( pkt - > id ) ;
2020-02-13 09:31:02 +00:00
pii - > hdr . qr = pkt - > qr & 0x01 ;
pii - > hdr . opcode = pkt - > opcode & 0x0F ;
pii - > hdr . aa = pkt - > aa & 0x01 ;
pii - > hdr . tc = pkt - > tc & 0x01 ;
pii - > hdr . rd = pkt - > rd & 0x01 ;
pii - > hdr . ra = pkt - > ra & 0x01 ;
pii - > hdr . ad = pkt - > ad & 0x01 ;
pii - > hdr . cd = pkt - > cd & 0x01 ;
pii - > hdr . rcode = pkt - > rcode & 0x0F ;
2021-07-22 07:30:20 +00:00
pii - > qdcount = hio_ntoh16 ( pkt - > qdcount ) ;
pii - > ancount = hio_ntoh16 ( pkt - > ancount ) ;
pii - > nscount = hio_ntoh16 ( pkt - > nscount ) ;
pii - > arcount = hio_ntoh16 ( pkt - > arcount ) ;
2020-02-13 09:31:02 +00:00
for ( i = 0 ; i < pii - > qdcount ; i + + )
{
2021-07-22 07:30:20 +00:00
if ( parse_question_rr ( hio , i , pii ) < = - 1 ) goto oops ;
2020-02-13 09:31:02 +00:00
}
for ( i = 0 ; i < pii - > ancount ; i + + )
{
2021-07-22 07:30:20 +00:00
if ( parse_answer_rr ( hio , HIO_DNS_RR_PART_ANSWER , i , pii ) < = - 1 ) goto oops ;
2020-02-13 09:31:02 +00:00
}
for ( i = 0 ; i < pii - > nscount ; i + + )
{
2021-07-22 07:30:20 +00:00
if ( parse_answer_rr ( hio , HIO_DNS_RR_PART_AUTHORITY , i , pii ) < = - 1 ) goto oops ;
2020-02-13 09:31:02 +00:00
}
2020-02-11 15:51:41 +00:00
2020-02-13 09:31:02 +00:00
for ( i = 0 ; i < pii - > arcount ; i + + )
{
2021-07-22 07:30:20 +00:00
if ( parse_answer_rr ( hio , HIO_DNS_RR_PART_ADDITIONAL , i , pii ) < = - 1 ) goto oops ;
2020-02-13 09:31:02 +00:00
}
2020-02-11 15:51:41 +00:00
2020-02-13 09:31:02 +00:00
if ( pii = = & pib )
{
2020-06-25 03:08:22 +00:00
/* TODO: better buffer management... */
2021-07-22 07:30:20 +00:00
pii = ( hio_dns_pkt_info_t * ) hio_callocmem ( hio , HIO_SIZEOF ( * pii ) + ( HIO_SIZEOF ( hio_dns_bqr_t ) * pib . qdcount ) + ( HIO_SIZEOF ( hio_dns_brr_t ) * ( pib . ancount + pib . nscount + pib . arcount ) ) + pib . _rrdlen ) ;
2020-02-13 09:31:02 +00:00
if ( ! pii ) goto oops ;
2021-07-22 07:30:20 +00:00
pii - > rr . qd = ( hio_dns_bqr_t * ) ( & pii [ 1 ] ) ;
pii - > rr . an = ( hio_dns_brr_t * ) & pii - > rr . qd [ pib . qdcount ] ;
pii - > rr . ns = ( hio_dns_brr_t * ) & pii - > rr . an [ pib . ancount ] ;
pii - > rr . ar = ( hio_dns_brr_t * ) & pii - > rr . ns [ pib . nscount ] ;
pii - > _rrdptr = ( hio_uint8_t * ) & pii - > rr . ar [ pib . arcount ] ;
2020-06-25 03:08:22 +00:00
/* _rrdptr points to the beginning of memory where additional data will
* be held for some RRs . _rrdlen is the length of total additional data .
* the additional data refers to the data that is pointed to by the
2021-07-22 07:30:20 +00:00
* breakdown RRs ( hio_dns_bqr_t / hio_dns_brr_t ) but is not stored in them . */
2020-06-25 03:08:22 +00:00
2020-02-13 09:31:02 +00:00
goto redo ;
}
2020-02-11 15:51:41 +00:00
2020-02-13 09:31:02 +00:00
return pii ;
oops :
2021-07-22 07:30:20 +00:00
if ( pii & & pii ! = & pib ) hio_freemem ( hio , pii ) ;
return HIO_NULL ;
2020-02-13 09:31:02 +00:00
}
2021-07-22 07:30:20 +00:00
void hio_dns_free_pkt_info ( hio_t * hio , hio_dns_pkt_info_t * pi )
2020-02-13 09:31:02 +00:00
{
/* TODO: better management */
2021-07-22 07:30:20 +00:00
hio_freemem ( hio , pi ) ;
2020-02-16 11:03:25 +00:00
}
/* ----------------------------------------------------------------------- */
2021-07-22 07:30:20 +00:00
static int encode_rrdata_in_dns_msg ( hio_t * hio , const hio_dns_brr_t * rr , hio_uint16_t * dxlen , void * dptr )
2020-02-16 11:03:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_oow_t xlen ; /* actual data length after encoding */
2020-02-24 16:39:29 +00:00
2020-02-16 11:03:25 +00:00
switch ( rr - > rrtype )
{
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_A :
if ( HIO_UNLIKELY ( rr - > dlen ! = HIO_SIZEOF ( hio_ip4ad_t ) ) ) goto inval ;
2020-02-25 07:09:20 +00:00
goto verbatim ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_AAAA :
if ( HIO_UNLIKELY ( rr - > dlen ! = HIO_SIZEOF ( hio_ip6ad_t ) ) ) goto inval ;
2020-02-25 07:09:20 +00:00
goto verbatim ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
/*case HIO_DNS_RRT_MB:
case HIO_DNS_RRT_MD :
case HIO_DNS_RRT_MF :
case HIO_DNS_RRT_MG :
case HIO_DNS_RRT_MR : */
case HIO_DNS_RRT_CNAME :
case HIO_DNS_RRT_NS :
case HIO_DNS_RRT_PTR :
2020-02-16 11:03:25 +00:00
/* just a normal domain name */
2020-02-24 16:39:29 +00:00
if ( dptr )
xlen = to_dn ( rr - > dptr , dptr ) ;
else
xlen = to_dn_capa ( rr - > dptr ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( xlen < = 0 ) ) goto inval ;
2020-02-16 11:03:25 +00:00
break ;
#if 0
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_HINFO :
2020-02-16 11:03:25 +00:00
/* cpu, os */
break ;
# endif
#if 0
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_MINFO :
2020-02-16 11:03:25 +00:00
/* rmailbx, emailbx */
# endif
2020-02-24 16:39:29 +00:00
xlen = rr - > dlen ;
2020-02-16 11:03:25 +00:00
break ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_MX :
2020-04-28 11:27:24 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_brrd_mx_t * mx ;
hio_oow_t tmp ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( rr - > dlen ! = HIO_SIZEOF ( hio_dns_brrd_mx_t ) ) ) goto inval ;
mx = ( hio_dns_brrd_mx_t * ) rr - > dptr ;
2020-04-28 11:27:24 +00:00
xlen = 0 ;
if ( dptr )
{
2021-07-22 07:30:20 +00:00
hio_uint16_t ti ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
ti = hio_hton16 ( mx - > preference ) ;
HIO_MEMCPY ( ( hio_uint8_t * ) dptr + xlen , & ti , HIO_SIZEOF ( ti ) ) ; xlen + = HIO_SIZEOF ( ti ) ;
2020-04-28 11:27:24 +00:00
2021-07-22 07:30:20 +00:00
tmp = to_dn ( mx - > exchange , ( hio_uint8_t * ) dptr + xlen ) ;
if ( HIO_UNLIKELY ( tmp < = 0 ) ) goto inval ;
2020-04-28 11:27:24 +00:00
xlen + = tmp ;
}
else
{
xlen + = 2 ;
tmp = to_dn_capa ( mx - > exchange ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( tmp < = 0 ) ) goto inval ;
2020-04-28 11:27:24 +00:00
xlen + = tmp ;
}
break ;
}
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_SOA :
2020-03-02 04:58:22 +00:00
{
2020-02-16 11:03:25 +00:00
/* soa */
2021-07-22 07:30:20 +00:00
hio_dns_brrd_soa_t * soa ;
hio_oow_t tmp ;
2020-03-02 04:58:22 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( rr - > dlen ! = HIO_SIZEOF ( hio_dns_brrd_soa_t ) ) ) goto inval ;
2020-03-02 04:58:22 +00:00
2021-07-22 07:30:20 +00:00
soa = ( hio_dns_brrd_soa_t * ) rr - > dptr ;
2020-03-02 04:58:22 +00:00
xlen = 0 ;
if ( dptr )
{
2021-07-22 07:30:20 +00:00
hio_uint32_t ti ;
2020-03-02 04:58:22 +00:00
2021-07-22 07:30:20 +00:00
tmp = to_dn ( soa - > mname , ( hio_uint8_t * ) dptr + xlen ) ;
if ( HIO_UNLIKELY ( tmp < = 0 ) ) goto inval ;
2020-03-02 04:58:22 +00:00
xlen + = tmp ;
2021-07-22 07:30:20 +00:00
tmp = to_dn ( soa - > rname , ( hio_uint8_t * ) dptr + xlen ) ;
if ( HIO_UNLIKELY ( tmp < = 0 ) ) goto inval ;
2020-03-02 04:58:22 +00:00
xlen + = tmp ;
2021-07-22 07:30:20 +00:00
ti = hio_hton32 ( soa - > serial ) ;
HIO_MEMCPY ( ( hio_uint8_t * ) dptr + xlen , & ti , HIO_SIZEOF ( ti ) ) ; xlen + = HIO_SIZEOF ( ti ) ;
ti = hio_hton32 ( soa - > refresh ) ;
HIO_MEMCPY ( ( hio_uint8_t * ) dptr + xlen , & ti , HIO_SIZEOF ( ti ) ) ; xlen + = HIO_SIZEOF ( ti ) ;
ti = hio_hton32 ( soa - > retry ) ;
HIO_MEMCPY ( ( hio_uint8_t * ) dptr + xlen , & ti , HIO_SIZEOF ( ti ) ) ; xlen + = HIO_SIZEOF ( ti ) ;
ti = hio_hton32 ( soa - > expire ) ;
HIO_MEMCPY ( ( hio_uint8_t * ) dptr + xlen , & ti , HIO_SIZEOF ( ti ) ) ; xlen + = HIO_SIZEOF ( ti ) ;
ti = hio_hton32 ( soa - > minimum ) ;
HIO_MEMCPY ( ( hio_uint8_t * ) dptr + xlen , & ti , HIO_SIZEOF ( ti ) ) ; xlen + = HIO_SIZEOF ( ti ) ;
2020-03-02 04:58:22 +00:00
}
else
{
tmp = to_dn_capa ( soa - > mname ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( tmp < = 0 ) ) goto inval ;
2020-03-02 04:58:22 +00:00
xlen + = tmp ;
tmp = to_dn_capa ( soa - > rname ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( tmp < = 0 ) ) goto inval ;
2020-03-02 04:58:22 +00:00
xlen + = tmp ;
xlen + = 20 ;
}
2020-02-16 11:03:25 +00:00
break ;
2020-03-02 04:58:22 +00:00
}
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_TXT :
case HIO_DNS_RRT_NULL :
2020-02-16 11:03:25 +00:00
default :
2020-02-25 07:09:20 +00:00
verbatim :
2020-02-16 11:03:25 +00:00
/* TODO: custom transformator? */
2021-07-22 07:30:20 +00:00
if ( dptr ) HIO_MEMCPY ( dptr , rr - > dptr , rr - > dlen ) ;
2020-02-24 16:39:29 +00:00
xlen = rr - > dlen ;
break ;
2020-02-16 11:03:25 +00:00
}
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( xlen > HIO_TYPE_MAX ( hio_uint16_t ) ) ) goto inval ;
* dxlen = ( hio_uint16_t ) xlen ;
2020-02-25 07:09:20 +00:00
return 0 ;
inval :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
2020-02-25 07:09:20 +00:00
return - 1 ;
2020-02-16 11:03:25 +00:00
}
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * hio_dns_make_msg ( hio_t * hio , hio_dns_bhdr_t * bhdr , hio_dns_bqr_t * qr , hio_oow_t qr_count , hio_dns_brr_t * rr , hio_oow_t rr_count , hio_dns_bedns_t * edns , hio_oow_t xtnsize )
2020-02-16 11:03:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_oow_t dnlen , msgbufsz , pktlen , i ;
hio_dns_msg_t * msg ;
hio_dns_pkt_t * pkt ;
hio_uint8_t * dn ;
hio_dns_qrtr_t * qrtr ;
hio_dns_rrtr_t * rrtr ;
2020-02-16 11:03:25 +00:00
int rr_sect ;
2021-07-22 07:30:20 +00:00
hio_uint32_t edns_dlen ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
pktlen = HIO_SIZEOF ( * pkt ) ;
2020-02-16 11:03:25 +00:00
for ( i = 0 ; i < qr_count ; i + + )
{
2020-02-25 07:09:20 +00:00
dnlen = to_dn_capa ( qr [ i ] . qname ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( dnlen < = 0 ) )
2020-02-25 07:09:20 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
return HIO_NULL ;
2020-02-25 07:09:20 +00:00
}
2021-07-22 07:30:20 +00:00
pktlen + = dnlen + HIO_SIZEOF ( * qrtr ) ;
2020-02-16 11:03:25 +00:00
}
for ( i = 0 ; i < rr_count ; i + + )
{
2021-07-22 07:30:20 +00:00
hio_uint16_t rrdata_len ;
2020-02-25 07:09:20 +00:00
dnlen = to_dn_capa ( rr [ i ] . rrname ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( dnlen < = 0 ) )
2020-02-24 16:39:29 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
return HIO_NULL ;
2020-02-24 16:39:29 +00:00
}
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( encode_rrdata_in_dns_msg ( hio , & rr [ i ] , & rrdata_len , HIO_NULL ) < = - 1 ) ) return HIO_NULL ;
pktlen + = dnlen + HIO_SIZEOF ( * rrtr ) + rrdata_len ;
2020-02-16 11:03:25 +00:00
}
edns_dlen = 0 ;
if ( edns )
{
2021-07-22 07:30:20 +00:00
hio_dns_beopt_t * beopt ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
pktlen + = 1 + HIO_SIZEOF ( * rrtr ) ; /* edns0 OPT RR - 1 for the root name */
2020-02-16 11:03:25 +00:00
beopt = edns - > beoptr ;
for ( i = 0 ; i < edns - > beonum ; i + + )
{
2021-07-22 07:30:20 +00:00
edns_dlen + = HIO_SIZEOF ( hio_dns_eopt_t ) + beopt - > dlen ;
if ( HIO_UNLIKELY ( edns_dlen > HIO_TYPE_MAX ( hio_uint16_t ) ) )
2020-02-16 11:03:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EINVAL , " edns options too large " ) ;
return HIO_NULL ;
2020-02-16 11:03:25 +00:00
}
beopt + + ;
}
pktlen + = edns_dlen ;
}
else
{
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( bhdr - > rcode > 0x0F ) )
2020-02-16 11:03:25 +00:00
{
/* rcode is larger than 4 bits. but edns info is not provided */
2021-07-22 07:30:20 +00:00
hio_seterrbfmt ( hio , HIO_EINVAL , " rcode too large without edns - %d " , bhdr - > rcode ) ;
return HIO_NULL ;
2020-02-16 11:03:25 +00:00
}
}
2021-07-22 07:30:20 +00:00
msgbufsz = HIO_SIZEOF ( * msg ) + HIO_ALIGN_POW2 ( pktlen , HIO_SIZEOF_VOID_P ) + xtnsize ;
2020-02-16 11:03:25 +00:00
/* TODO: msg buffer reuse */
2021-08-04 16:50:40 +00:00
msg = ( hio_dns_msg_t * ) hio_callocmem ( hio , msgbufsz ) ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( ! msg ) ) return HIO_NULL ;
2020-02-16 11:03:25 +00:00
msg - > msglen = msgbufsz ; /* record the instance size */
2021-07-22 07:30:20 +00:00
msg - > pktalilen = HIO_ALIGN_POW2 ( pktlen , HIO_SIZEOF_VOID_P ) ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
pkt = hio_dns_msg_to_pkt ( msg ) ; /* actual packet data begins after the message structure */
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
dn = ( hio_uint8_t * ) ( pkt + 1 ) ; /* skip the dns packet header */
2020-02-16 11:03:25 +00:00
for ( i = 0 ; i < qr_count ; i + + )
{
/* dnlen includes the ending <zero> */
2020-02-24 16:39:29 +00:00
dnlen = to_dn ( qr [ i ] . qname , dn ) ;
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , dnlen > 0 ) ;
2020-02-25 07:09:20 +00:00
2021-07-22 07:30:20 +00:00
qrtr = ( hio_dns_qrtr_t * ) ( dn + dnlen ) ;
qrtr - > qtype = hio_hton16 ( qr [ i ] . qtype ) ;
qrtr - > qclass = hio_hton16 ( qr [ i ] . qclass ) ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
dn = ( hio_uint8_t * ) ( qrtr + 1 ) ;
2020-02-16 11:03:25 +00:00
}
2021-07-22 07:30:20 +00:00
for ( rr_sect = HIO_DNS_RR_PART_ANSWER ; rr_sect < = HIO_DNS_RR_PART_ADDITIONAL ; )
2020-02-16 11:03:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_oow_t match_count = 0 ;
2020-02-16 11:03:25 +00:00
for ( i = 0 ; i < rr_count ; i + + )
{
if ( rr [ i ] . part = = rr_sect )
{
2021-07-22 07:30:20 +00:00
hio_uint16_t rrdata_len ;
2020-02-16 11:03:25 +00:00
2020-02-24 16:39:29 +00:00
dnlen = to_dn ( rr [ i ] . rrname , dn ) ;
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , dnlen > 0 ) ;
2020-02-25 07:09:20 +00:00
2021-07-22 07:30:20 +00:00
rrtr = ( hio_dns_rrtr_t * ) ( dn + dnlen ) ;
rrtr - > rrtype = hio_hton16 ( rr [ i ] . rrtype ) ;
rrtr - > rrclass = hio_hton16 ( rr [ i ] . rrclass ) ;
rrtr - > ttl = hio_hton32 ( rr [ i ] . ttl ) ;
2020-02-16 11:03:25 +00:00
2021-07-22 07:30:20 +00:00
encode_rrdata_in_dns_msg ( hio , & rr [ i ] , & rrdata_len , rrtr + 1 ) ; /* this must succeed */
rrtr - > dlen = hio_hton16 ( rrdata_len ) ;
dn = ( hio_uint8_t * ) ( rrtr + 1 ) + rrdata_len ;
2020-02-16 11:03:25 +00:00
match_count + + ;
}
}
rr_sect = rr_sect + 1 ;
2021-07-22 07:30:20 +00:00
( ( hio_dns_pkt_alt_t * ) pkt ) - > rrcount [ rr_sect ] = hio_hton16 ( match_count ) ;
2020-02-16 11:03:25 +00:00
}
if ( edns )
{
2021-07-22 07:30:20 +00:00
hio_dns_eopt_t * eopt ;
hio_dns_beopt_t * beopt ;
2020-02-16 11:03:25 +00:00
/* add EDNS0 OPT RR */
* dn = 0 ; /* root domain. as if to_dn("") is called */
2021-07-22 07:30:20 +00:00
rrtr = ( hio_dns_rrtr_t * ) ( dn + 1 ) ;
rrtr - > rrtype = HIO_CONST_HTON16 ( HIO_DNS_RRT_OPT ) ;
rrtr - > rrclass = hio_hton16 ( edns - > uplen ) ;
rrtr - > ttl = hio_hton32 ( HIO_DNS_EDNS_MAKE_TTL ( bhdr - > rcode , edns - > version , edns - > dnssecok ) ) ;
rrtr - > dlen = hio_hton16 ( ( hio_uint16_t ) edns_dlen ) ;
dn = ( hio_uint8_t * ) ( rrtr + 1 ) ;
2020-02-16 11:03:25 +00:00
beopt = edns - > beoptr ;
2021-07-22 07:30:20 +00:00
eopt = ( hio_dns_eopt_t * ) dn ;
msg - > ednsrrtroff = ( hio_uint8_t * ) rrtr - ( hio_uint8_t * ) pkt ;
2020-02-16 11:03:25 +00:00
for ( i = 0 ; i < edns - > beonum ; i + + )
{
2021-07-22 07:30:20 +00:00
eopt - > code = hio_hton16 ( beopt - > code ) ;
eopt - > dlen = hio_hton16 ( beopt - > dlen ) ;
HIO_MEMCPY ( + + eopt , beopt - > dptr , beopt - > dlen ) ;
eopt = ( hio_dns_eopt_t * ) ( ( hio_uint8_t * ) eopt + beopt - > dlen ) ;
2020-02-16 11:03:25 +00:00
beopt + + ;
}
2021-07-22 07:30:20 +00:00
pkt - > arcount = hio_hton16 ( ( hio_ntoh16 ( pkt - > arcount ) + 1 ) ) ;
2020-02-16 11:03:25 +00:00
dn + = edns_dlen ;
}
2021-07-22 07:30:20 +00:00
pkt - > qdcount = hio_hton16 ( qr_count ) ;
pkt - > id = hio_hton16 ( ( hio_uint16_t ) bhdr - > id ) ;
2020-02-16 11:03:25 +00:00
/*pkt->qr = (rr_count > 0);
2021-07-22 07:30:20 +00:00
pkt - > opcode = HIO_DNS_OPCODE_QUERY ; */
2020-02-16 11:03:25 +00:00
pkt - > qr = bhdr - > qr & 0x01 ;
pkt - > opcode = bhdr - > opcode & 0x0F ;
pkt - > aa = bhdr - > aa & 0x01 ;
pkt - > tc = bhdr - > tc & 0x01 ;
pkt - > rd = bhdr - > rd & 0x01 ;
pkt - > ra = bhdr - > ra & 0x01 ;
pkt - > ad = bhdr - > ad & 0x01 ;
pkt - > cd = bhdr - > cd & 0x01 ;
pkt - > rcode = bhdr - > rcode & 0x0F ;
2021-07-22 07:30:20 +00:00
msg - > pktlen = dn - ( hio_uint8_t * ) pkt ;
HIO_ASSERT ( hio , msg - > pktlen = = pktlen ) ;
HIO_ASSERT ( hio , msg - > pktalilen = = HIO_ALIGN_POW2 ( pktlen , HIO_SIZEOF_VOID_P ) ) ;
2020-02-16 11:03:25 +00:00
return msg ;
}
2021-07-22 07:30:20 +00:00
void hio_dns_free_msg ( hio_t * hio , hio_dns_msg_t * msg )
2020-02-16 11:03:25 +00:00
{
/* TODO: better management */
2021-07-22 07:30:20 +00:00
hio_freemem ( hio , msg ) ;
2020-02-11 15:51:41 +00:00
}
2020-07-04 08:03:36 +00:00
2021-07-22 07:30:20 +00:00
hio_uint8_t * hio_dns_find_client_cookie_in_msg ( hio_dns_msg_t * reqmsg , hio_uint8_t ( * cookie ) [ HIO_DNS_COOKIE_CLIENT_LEN ] )
2020-07-04 08:03:36 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_rrtr_t * edns_rrtr ;
hio_dns_eopt_t * eopt ;
hio_uint16_t rem , dlen ;
2020-07-04 08:03:36 +00:00
/* this function doesn't check malformed packet assuming
2021-07-22 07:30:20 +00:00
* reqmsg points to the packet message created with hio_dns_make_msg ( ) .
2020-07-04 08:03:36 +00:00
* such a packet message must be well - formed */
2021-07-22 07:30:20 +00:00
if ( reqmsg - > ednsrrtroff < = 0 ) return HIO_NULL ; /* doesn't exist */
2020-07-04 08:03:36 +00:00
2021-07-22 07:30:20 +00:00
edns_rrtr = ( hio_dns_rrtr_t * ) ( ( hio_uint8_t * ) hio_dns_msg_to_pkt ( reqmsg ) + reqmsg - > ednsrrtroff ) ;
rem = hio_ntoh16 ( edns_rrtr - > dlen ) ;
2020-07-04 08:03:36 +00:00
2021-07-22 07:30:20 +00:00
eopt = ( hio_dns_eopt_t * ) ( edns_rrtr + 1 ) ;
while ( rem > = HIO_SIZEOF ( hio_dns_eopt_t ) )
2020-07-04 08:03:36 +00:00
{
2021-07-22 07:30:20 +00:00
dlen = hio_ntoh16 ( eopt - > dlen ) ;
if ( eopt - > code = = HIO_CONST_HTON16 ( HIO_DNS_EOPT_COOKIE ) )
2020-07-04 08:03:36 +00:00
{
2021-07-22 07:30:20 +00:00
if ( cookie ) HIO_MEMCPY ( cookie , eopt + 1 , HIO_DNS_COOKIE_CLIENT_LEN ) ;
return ( hio_uint8_t * ) ( eopt + 1 ) ;
2020-07-04 08:03:36 +00:00
}
rem - = dlen ;
2021-07-22 07:30:20 +00:00
eopt = ( hio_dns_eopt_t * ) ( ( hio_uint8_t * ) ( eopt + 1 ) + dlen ) ;
2020-07-04 08:03:36 +00:00
}
2021-07-22 07:30:20 +00:00
return HIO_NULL ;
2020-07-04 08:03:36 +00:00
}
2021-07-22 07:30:20 +00:00
hio_bch_t * hio_dns_rcode_to_bcstr ( hio_dns_rcode_t rcode )
2020-07-04 08:03:36 +00:00
{
2021-07-22 07:30:20 +00:00
hio_bch_t * _errmsg [ ] =
2020-07-04 08:03:36 +00:00
{
" NOERR " ,
" FORMERR " ,
" SERVFAIL " ,
" NXDOMAIN " ,
" NOTIMPL " ,
" REFUSED " ,
" YXDOMAIN " ,
" YXRRSET " ,
" NXRRSET " ,
" NOAUTH " ,
" NOTZONE " , /* 10 */
" UNKNOWNERR " ,
" UNKNOWNERR " ,
" UNKNOWNERR " ,
" UNKNOWNERR " ,
" UNKNOWNERR " ,
" UNKNOWNERR " ,
" BADVERS " , /* 16 */
" BADSIG " ,
" BADTIME " ,
" BADMODE " ,
" BADNAME " ,
" BADALG " ,
" BADTRUNC " ,
" BADCOOKIE "
} ;
2021-07-22 07:30:20 +00:00
return rcode < HIO_COUNTOF ( _errmsg ) ? _errmsg [ rcode ] : " UNKNOWNERR " ;
2020-07-04 08:03:36 +00:00
}