2020-02-21 04:21:16 +00:00
/*
Copyright ( c ) 2016 - 2020 Chung , Hyung - Hwan . All rights reserved .
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
2022-06-11 05:32:01 +00:00
IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
2020-02-21 04:21:16 +00:00
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-sck.h>
# include "hio-prv.h"
2020-02-21 04:21:16 +00:00
2022-06-22 06:44:28 +00:00
# include <sys/types.h>
2020-02-21 04:21:16 +00:00
# include <netinet/in.h>
2021-07-22 07:30:20 +00:00
struct hio_svc_dns_t
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_SVC_HEADER ;
/*HIO_DNS_SVC_HEADER;*/
2020-02-21 04:21:16 +00:00
} ;
2021-07-22 07:30:20 +00:00
struct hio_svc_dnc_t
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_SVC_HEADER ;
/*HIO_DNS_SVC_HEADER;*/
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * udp_sck ;
hio_dev_sck_t * tcp_sck ;
hio_skad_t serv_addr ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
hio_ntime_t send_tmout ;
hio_ntime_t reply_tmout ; /* default reply timeout */
2020-03-02 04:58:22 +00:00
/* For a question sent out, it may wait for a corresponding answer.
* if max_tries is greater than 0 , sending and waiting is limited
* to this value over udp and to 1 over tcp . if max_tries is 0 ,
* it sends out the question but never waits for a response .
* For a non - question message sent out , it never waits for a response
* regardless of max_tries . */
2021-07-22 07:30:20 +00:00
hio_oow_t max_tries ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
hio_dns_cookie_t cookie ;
2020-07-02 14:21:47 +00:00
2021-07-22 07:30:20 +00:00
hio_oow_t seq ;
hio_dns_msg_t * pending_req ;
2020-02-21 04:21:16 +00:00
} ;
struct dnc_sck_xtn_t
{
2021-07-22 07:30:20 +00:00
hio_svc_dnc_t * dnc ;
2020-02-29 16:56:36 +00:00
struct
{
2021-07-22 07:30:20 +00:00
hio_uint8_t * ptr ;
hio_oow_t len ;
hio_oow_t capa ;
2020-02-29 16:56:36 +00:00
} rbuf ; /* used by tcp socket */
2020-02-21 04:21:16 +00:00
} ;
typedef struct dnc_sck_xtn_t dnc_sck_xtn_t ;
/* ----------------------------------------------------------------------- */
struct dnc_dns_msg_xtn_t
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * dev ;
hio_tmridx_t rtmridx ;
hio_dns_msg_t * prev ;
hio_dns_msg_t * next ;
hio_skad_t servaddr ;
hio_svc_dnc_on_done_t on_done ;
hio_ntime_t wtmout ;
hio_ntime_t rtmout ;
2020-02-21 04:21:16 +00:00
int rmaxtries ; /* maximum number of tries to receive a reply */
int rtries ; /* number of tries made so far */
2020-03-01 17:43:42 +00:00
int pending ;
2020-02-21 04:21:16 +00:00
} ;
typedef struct dnc_dns_msg_xtn_t dnc_dns_msg_xtn_t ;
2021-07-22 07:30:20 +00:00
# if defined(HIO_HAVE_INLINE)
static HIO_INLINE dnc_dns_msg_xtn_t * dnc_dns_msg_getxtn ( hio_dns_msg_t * msg ) { return ( dnc_dns_msg_xtn_t * ) ( ( hio_uint8_t * ) hio_dns_msg_to_pkt ( msg ) + msg - > pktalilen ) ; }
2020-02-21 04:21:16 +00:00
# else
2021-07-22 07:30:20 +00:00
# define dnc_dns_msg_getxtn(msg) ((dnc_dns_msg_xtn_t*)((hio_uint8_t*)hio_dns_msg_to_pkt(msg) + msg->pktalilen))
2020-02-21 04:21:16 +00:00
# endif
2021-07-22 07:30:20 +00:00
static HIO_INLINE void chain_pending_dns_reqmsg ( hio_svc_dnc_t * dnc , hio_dns_msg_t * msg )
2020-02-21 04:21:16 +00:00
{
if ( dnc - > pending_req )
{
dnc_dns_msg_getxtn ( dnc - > pending_req ) - > prev = msg ;
dnc_dns_msg_getxtn ( msg ) - > next = dnc - > pending_req ;
}
dnc - > pending_req = msg ;
2020-03-01 17:43:42 +00:00
dnc_dns_msg_getxtn ( msg ) - > pending = 1 ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
static HIO_INLINE void unchain_pending_dns_reqmsg ( hio_svc_dnc_t * dnc , hio_dns_msg_t * msg )
2020-02-21 04:21:16 +00:00
{
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( msg ) ;
if ( msgxtn - > next ) dnc_dns_msg_getxtn ( msgxtn - > next ) - > prev = msgxtn - > prev ;
if ( msgxtn - > prev ) dnc_dns_msg_getxtn ( msgxtn - > prev ) - > next = msgxtn - > next ;
else dnc - > pending_req = msgxtn - > next ;
2020-03-01 17:43:42 +00:00
dnc_dns_msg_getxtn ( msg ) - > pending = 0 ;
}
2021-07-22 07:30:20 +00:00
static hio_dns_msg_t * make_dns_msg ( hio_svc_dnc_t * dnc , hio_dns_bhdr_t * bdns , 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_svc_dnc_on_done_t on_done , hio_oow_t xtnsize )
2020-03-01 17:43:42 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * msg ;
2020-03-01 17:43:42 +00:00
dnc_dns_msg_xtn_t * msgxtn ;
2021-07-22 07:30:20 +00:00
msg = hio_dns_make_msg ( dnc - > hio , bdns , qr , qr_count , rr , rr_count , edns , HIO_SIZEOF ( * msgxtn ) + xtnsize ) ;
if ( HIO_UNLIKELY ( ! msg ) ) return HIO_NULL ;
2020-03-01 17:43:42 +00:00
if ( bdns - > id < 0 )
{
2021-07-22 07:30:20 +00:00
hio_dns_pkt_t * pkt = hio_dns_msg_to_pkt ( msg ) ;
pkt - > id = hio_hton16 ( dnc - > seq ) ;
2020-03-01 17:43:42 +00:00
dnc - > seq + + ;
}
msgxtn = dnc_dns_msg_getxtn ( msg ) ;
msgxtn - > dev = dnc - > udp_sck ;
2021-07-22 07:30:20 +00:00
msgxtn - > rtmridx = HIO_TMRIDX_INVALID ;
2020-03-01 17:43:42 +00:00
msgxtn - > on_done = on_done ;
msgxtn - > wtmout = dnc - > send_tmout ;
msgxtn - > rtmout = dnc - > reply_tmout ;
2020-03-02 04:58:22 +00:00
msgxtn - > rmaxtries = dnc - > max_tries ;
2020-03-01 17:43:42 +00:00
msgxtn - > rtries = 0 ;
msgxtn - > servaddr = dnc - > serv_addr ;
return msg ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
static void release_dns_msg ( hio_svc_dnc_t * dnc , hio_dns_msg_t * msg )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dnc - > hio ;
2020-02-21 04:21:16 +00:00
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( msg ) ;
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - releasing dns message - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-02-21 04:21:16 +00:00
if ( msg = = dnc - > pending_req | | msgxtn - > next | | msgxtn - > prev )
{
/* it's chained in the pending request. unchain it */
unchain_pending_dns_reqmsg ( dnc , msg ) ;
}
2021-07-22 07:30:20 +00:00
if ( msgxtn - > rtmridx ! = HIO_TMRIDX_INVALID )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_deltmrjob ( hio , msgxtn - > rtmridx ) ;
HIO_ASSERT ( hio , msgxtn - > rtmridx = = HIO_TMRIDX_INVALID ) ;
2020-02-21 04:21:16 +00:00
}
2020-02-25 07:09:20 +00:00
/* TODO: add it to the free msg list instead of just freeing it. */
2021-07-22 07:30:20 +00:00
hio_dns_free_msg ( dnc - > hio , msg ) ;
2020-02-21 04:21:16 +00:00
}
2020-02-21 09:42:10 +00:00
/* ----------------------------------------------------------------------- */
2021-07-22 07:30:20 +00:00
static int handle_tcp_packet ( hio_dev_sck_t * dev , hio_dns_pkt_t * pkt , hio_uint16_t pktlen )
2020-02-29 16:56:36 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
dnc_sck_xtn_t * sckxtn = hio_dev_sck_getxtn ( dev ) ;
hio_svc_dnc_t * dnc = sckxtn - > dnc ;
hio_uint16_t id ;
hio_dns_msg_t * reqmsg ;
2020-02-29 16:56:36 +00:00
if ( ! pkt - > qr )
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG0 ( hio , " DNC - dropping dns request received over tcp ... \n " ) ; /* TODO: add source info */
2020-02-29 16:56:36 +00:00
return 0 ; /* drop request. nothing to do */
}
2021-07-22 07:30:20 +00:00
id = hio_ntoh16 ( pkt - > id ) ;
2020-02-29 16:56:36 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - got dns response over tcp - msgid:%d \n " , id ) ;
2020-02-29 16:56:36 +00:00
reqmsg = dnc - > pending_req ;
while ( reqmsg )
{
2021-07-22 07:30:20 +00:00
hio_dns_pkt_t * reqpkt = hio_dns_msg_to_pkt ( reqmsg ) ;
2020-02-29 16:56:36 +00:00
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
if ( dev = = ( hio_dev_sck_t * ) reqmsgxtn - > dev & & pkt - > id = = reqpkt - > id )
2020-02-29 16:56:36 +00:00
{
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , HIO_ENOERR , pkt , pktlen ) ;
2020-02-29 16:56:36 +00:00
release_dns_msg ( dnc , reqmsg ) ;
return 0 ;
}
reqmsg = reqmsgxtn - > next ;
}
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - unknown dns response over tcp... msgid:%d \n " , id ) ; /* TODO: add source info */
2020-02-29 16:56:36 +00:00
return 0 ;
}
2021-07-22 07:30:20 +00:00
static HIO_INLINE int copy_data_to_sck_rbuf ( hio_dev_sck_t * dev , const void * data , hio_uint16_t dlen )
2020-02-29 16:56:36 +00:00
{
2021-07-22 07:30:20 +00:00
dnc_sck_xtn_t * sckxtn = hio_dev_sck_getxtn ( dev ) ;
2020-02-29 16:56:36 +00:00
if ( sckxtn - > rbuf . capa - sckxtn - > rbuf . len < dlen )
{
2021-07-22 07:30:20 +00:00
hio_uint16_t newcapa ;
hio_uint8_t * tmp ;
2020-02-29 16:56:36 +00:00
newcapa = sckxtn - > rbuf . len + dlen ;
2021-07-22 07:30:20 +00:00
newcapa = HIO_ALIGN_POW2 ( newcapa , 512 ) ;
tmp = hio_reallocmem ( dev - > hio , sckxtn - > rbuf . ptr , newcapa ) ;
2020-02-29 16:56:36 +00:00
if ( ! tmp ) return - 1 ;
sckxtn - > rbuf . capa = newcapa ;
sckxtn - > rbuf . ptr = tmp ;
}
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( & sckxtn - > rbuf . ptr [ sckxtn - > rbuf . len ] , data , dlen ) ;
2020-02-29 16:56:36 +00:00
sckxtn - > rbuf . len + = dlen ;
return 0 ;
}
2020-02-21 09:42:10 +00:00
2021-07-22 07:30:20 +00:00
static int on_tcp_read ( hio_dev_sck_t * dev , const void * data , hio_iolen_t dlen , const hio_skad_t * srcaddr )
2020-02-21 09:42:10 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
dnc_sck_xtn_t * sckxtn = hio_dev_sck_getxtn ( dev ) ;
hio_uint16_t pktlen ;
hio_uint8_t * dptr ;
hio_iolen_t rem ;
2020-02-27 17:34:27 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( dlen < = - 1 ) )
2020-02-25 07:09:20 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - dns tcp read error ....%js \n " , hio_geterrmsg ( hio ) ) ; /* TODO: add source packet */
2020-02-28 07:41:25 +00:00
goto oops ;
2020-02-25 07:09:20 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( HIO_UNLIKELY ( dlen = = 0 ) )
2020-02-25 07:09:20 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG0 ( hio , " DNC - dns tcp read error ...premature tcp socket end \n " ) ; /* TODO: add source packet */
2020-02-28 07:41:25 +00:00
goto oops ;
2020-02-25 07:09:20 +00:00
}
2020-02-27 17:34:27 +00:00
2021-07-22 07:30:20 +00:00
dptr = ( hio_uint8_t * ) data ;
2020-02-28 08:10:29 +00:00
rem = dlen ;
do
{
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( sckxtn - > rbuf . len = = 1 ) )
2020-02-28 08:10:29 +00:00
{
2021-07-22 07:30:20 +00:00
pktlen = ( ( hio_uint16_t ) sckxtn - > rbuf . ptr [ 0 ] < < 8 ) | * ( hio_uint8_t * ) dptr ;
if ( HIO_UNLIKELY ( ( rem - 1 ) < pktlen ) ) goto incomplete_data ;
2020-02-29 16:56:36 +00:00
dptr + = 1 ; rem - = 1 ; sckxtn - > rbuf . len = 0 ;
2021-07-22 07:30:20 +00:00
handle_tcp_packet ( dev , ( hio_dns_pkt_t * ) dptr , pktlen ) ;
2020-02-29 16:56:36 +00:00
dptr + = pktlen ; rem - = pktlen ;
2020-02-28 08:10:29 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( HIO_UNLIKELY ( sckxtn - > rbuf . len > 1 ) )
2020-02-28 08:10:29 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint16_t cplen ;
2020-02-29 16:56:36 +00:00
2021-07-22 07:30:20 +00:00
pktlen = ( ( hio_uint16_t ) sckxtn - > rbuf . ptr [ 0 ] < < 8 ) | sckxtn - > rbuf . ptr [ 1 ] ;
if ( HIO_UNLIKELY ( sckxtn - > rbuf . len - 2 + rem < pktlen ) ) goto incomplete_data ;
2020-02-29 16:56:36 +00:00
cplen = pktlen - ( sckxtn - > rbuf . len - 2 ) ;
if ( copy_data_to_sck_rbuf ( dev , dptr , cplen ) < = - 1 ) goto oops ;
dptr + = cplen ; rem - = cplen ; sckxtn - > rbuf . len = 0 ;
2021-07-22 07:30:20 +00:00
handle_tcp_packet ( dev , ( hio_dns_pkt_t * ) & sckxtn - > rbuf . ptr [ 2 ] , pktlen ) ;
2020-02-28 08:10:29 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( rem > = 2 ) )
2020-02-28 08:10:29 +00:00
{
2021-07-22 07:30:20 +00:00
pktlen = ( ( hio_uint16_t ) * ( hio_uint8_t * ) dptr < < 8 ) | * ( ( hio_uint8_t * ) dptr + 1 ) ;
2020-02-29 16:56:36 +00:00
dptr + = 2 ; rem - = 2 ;
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( rem < pktlen ) ) goto incomplete_data ;
handle_tcp_packet ( dev , ( hio_dns_pkt_t * ) dptr , pktlen ) ;
2020-02-29 16:56:36 +00:00
dptr + = pktlen ; rem - = pktlen ;
2020-02-28 08:10:29 +00:00
}
else
{
incomplete_data :
2020-02-29 16:56:36 +00:00
if ( copy_data_to_sck_rbuf ( dev , dptr , rem ) < = - 1 ) goto oops ;
2020-02-28 08:10:29 +00:00
rem = 0 ;
}
}
}
while ( rem > 0 ) ;
2020-02-28 07:41:25 +00:00
2020-02-27 17:34:27 +00:00
return 0 ;
2020-02-28 07:41:25 +00:00
oops :
2021-07-22 07:30:20 +00:00
hio_dev_sck_halt ( dev ) ;
2020-02-21 09:42:10 +00:00
return 0 ;
}
2021-07-22 07:30:20 +00:00
static void on_tcp_reply_timeout ( hio_t * hio , const hio_ntime_t * now , hio_tmrjob_t * job )
2020-02-27 08:40:39 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * reqmsg = ( hio_dns_msg_t * ) job - > ctx ;
2020-02-28 07:41:25 +00:00
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * dev = reqmsgxtn - > dev ;
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
2020-02-27 08:40:39 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , reqmsgxtn - > rtmridx = = HIO_TMRIDX_INVALID ) ;
HIO_ASSERT ( hio , dev = = dnc - > tcp_sck ) ;
2020-02-27 08:40:39 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - unable to receive dns response in time over TCP - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( reqmsg ) - > id ) ) ;
2020-02-27 08:40:39 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , HIO_ETMOUT , HIO_NULL , 0 ) ;
2020-02-28 07:41:25 +00:00
release_dns_msg ( dnc , reqmsg ) ;
2020-02-27 08:40:39 +00:00
}
2021-07-22 07:30:20 +00:00
static int on_tcp_write ( hio_dev_sck_t * dev , hio_iolen_t wrlen , void * wrctx , const hio_skad_t * dstaddr )
2020-02-21 09:42:10 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dns_msg_t * msg = ( hio_dns_msg_t * ) wrctx ;
2020-02-27 08:40:39 +00:00
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( msg ) ;
2021-07-22 07:30:20 +00:00
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_errnum_t status ;
2020-02-27 08:40:39 +00:00
if ( wrlen < = - 1 )
{
2020-02-27 17:34:27 +00:00
/* send failure */
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
2020-02-27 17:34:27 +00:00
goto finalize ;
2020-02-27 08:40:39 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( hio_dns_msg_to_pkt ( msg ) - > qr = = 0 & & msgxtn - > rmaxtries > 0 )
2020-02-27 08:40:39 +00:00
{
/* question. schedule to wait for response */
2021-07-22 07:30:20 +00:00
hio_tmrjob_t tmrjob ;
2020-02-27 08:40:39 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - sent dns question over tcp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-05-15 06:18:49 +00:00
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & tmrjob , 0 , HIO_SIZEOF ( tmrjob ) ) ;
2020-02-27 08:40:39 +00:00
tmrjob . ctx = msg ;
2021-07-22 07:30:20 +00:00
hio_gettime ( hio , & tmrjob . when ) ;
HIO_ADD_NTIME ( & tmrjob . when , & tmrjob . when , & msgxtn - > rtmout ) ;
2020-02-27 08:40:39 +00:00
tmrjob . handler = on_tcp_reply_timeout ;
tmrjob . idxptr = & msgxtn - > rtmridx ;
2021-07-22 07:30:20 +00:00
msgxtn - > rtmridx = hio_instmrjob ( hio , & tmrjob ) ;
if ( msgxtn - > rtmridx = = HIO_TMRIDX_INVALID )
2020-02-27 08:40:39 +00:00
{
/* call the callback to indicate this operation failure in the middle of transaction */
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
HIO_DEBUG1 ( hio , " DNC - unable to schedule tcp timeout - msgid: %d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-02-27 17:34:27 +00:00
goto finalize ;
2020-02-27 08:40:39 +00:00
}
2020-03-01 17:43:42 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , msgxtn - > pending ! = 0 ) ;
2020-02-27 08:40:39 +00:00
}
else
{
2020-02-28 07:41:25 +00:00
/* no error. successfuly sent a message. no reply is expected */
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - sent dns message over tcp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
status = HIO_ENOERR ;
2020-02-27 17:34:27 +00:00
goto finalize ;
2020-02-27 08:40:39 +00:00
}
2020-02-25 07:09:20 +00:00
2020-02-21 09:42:10 +00:00
return 0 ;
2020-02-27 17:34:27 +00:00
finalize :
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( msgxtn - > on_done ) ) msgxtn - > on_done ( dnc , msg , status , HIO_NULL , 0 ) ;
2020-02-28 07:41:25 +00:00
release_dns_msg ( dnc , msg ) ;
2020-02-27 17:34:27 +00:00
return 0 ;
2020-02-21 09:42:10 +00:00
}
2021-07-22 07:30:20 +00:00
static int write_dns_msg_over_tcp ( hio_dev_sck_t * dev , hio_dns_msg_t * msg )
2020-02-21 09:42:10 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
2020-02-28 07:41:25 +00:00
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( msg ) ;
2021-07-22 07:30:20 +00:00
hio_uint16_t pktlen ;
hio_iovec_t iov [ 2 ] ;
2020-02-21 09:42:10 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - sending dns message over tcp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-05-15 06:18:49 +00:00
2021-07-22 07:30:20 +00:00
pktlen = hio_hton16 ( msg - > pktlen ) ;
2020-02-21 09:42:10 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , msgxtn - > rtries = = 0 ) ;
2020-03-01 17:43:42 +00:00
msgxtn - > rtries = 1 ;
2020-02-21 09:42:10 +00:00
2020-02-28 07:41:25 +00:00
/* TODO: Is it better to create 2 byte space when sending UDP and use it here instead of iov? */
2020-02-25 07:09:20 +00:00
iov [ 0 ] . iov_ptr = & pktlen ;
2021-07-22 07:30:20 +00:00
iov [ 0 ] . iov_len = HIO_SIZEOF ( pktlen ) ;
iov [ 1 ] . iov_ptr = hio_dns_msg_to_pkt ( msg ) ;
2020-02-28 07:41:25 +00:00
iov [ 1 ] . iov_len = msg - > pktlen ;
2021-07-22 07:30:20 +00:00
return hio_dev_sck_timedwritev ( dev , iov , HIO_COUNTOF ( iov ) , & msgxtn - > rtmout , msg , HIO_NULL ) ;
2020-02-28 07:41:25 +00:00
}
2021-07-22 07:30:20 +00:00
static void on_tcp_connect ( hio_dev_sck_t * dev )
2020-02-28 07:41:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_dns_msg_t * reqmsg ;
2020-02-28 07:41:25 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , dev = = dnc - > tcp_sck ) ;
2020-02-28 07:41:25 +00:00
reqmsg = dnc - > pending_req ;
while ( reqmsg )
{
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * nextreqmsg = reqmsgxtn - > next ;
2020-02-28 07:41:25 +00:00
2020-03-01 17:43:42 +00:00
if ( reqmsgxtn - > dev = = dev & & reqmsgxtn - > rtries = = 0 )
{
if ( write_dns_msg_over_tcp ( dev , reqmsg ) < = - 1 )
{
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , hio_geterrnum ( hio ) , HIO_NULL , 0 ) ;
2020-03-01 17:43:42 +00:00
release_dns_msg ( dnc , reqmsg ) ;
}
}
2020-02-28 07:41:25 +00:00
reqmsg = nextreqmsg ;
2020-02-21 09:42:10 +00:00
}
}
2021-07-22 07:30:20 +00:00
static void on_tcp_disconnect ( hio_dev_sck_t * dev )
2020-02-21 09:42:10 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_dns_msg_t * reqmsg ;
2020-02-21 09:42:10 +00:00
int status ;
/* UNABLE TO CONNECT or CONNECT TIMED OUT */
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
2020-02-27 08:40:39 +00:00
2021-07-22 07:30:20 +00:00
if ( status = = HIO_ENOERR )
2020-02-27 17:34:27 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG0 ( hio , " DNC - TCP DISCONNECTED \n " ) ;
2020-02-27 17:34:27 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG2 ( hio , " DNC - TCP UNABLE TO CONNECT %d -> %js \n " , status , hio_errnum_to_errstr ( status ) ) ;
2020-02-27 17:34:27 +00:00
}
2020-02-21 09:42:10 +00:00
2020-02-28 07:41:25 +00:00
reqmsg = dnc - > pending_req ;
while ( reqmsg )
{
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * nextreqmsg = reqmsgxtn - > next ;
2020-02-28 07:41:25 +00:00
if ( reqmsgxtn - > dev = = dev )
{
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , HIO_ENORSP , HIO_NULL , 0 ) ;
2020-02-28 07:41:25 +00:00
release_dns_msg ( dnc , reqmsg ) ;
}
reqmsg = nextreqmsg ;
}
2020-02-27 08:40:39 +00:00
/* let's forget about the tcp socket */
2021-07-22 07:30:20 +00:00
dnc - > tcp_sck = HIO_NULL ;
2020-02-21 09:42:10 +00:00
}
2021-07-22 07:30:20 +00:00
static int switch_reqmsg_transport_to_tcp ( hio_svc_dnc_t * dnc , hio_dns_msg_t * reqmsg )
2020-02-21 09:42:10 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dnc - > hio ;
2020-02-21 09:42:10 +00:00
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
dnc_sck_xtn_t * sckxtn ;
2021-07-22 07:30:20 +00:00
hio_dev_sck_make_t mkinfo ;
hio_dev_sck_connect_t cinfo ;
2020-02-21 09:42:10 +00:00
2020-02-28 08:10:29 +00:00
/* TODO: more reliable way to check if connection is ok.
* even if tcp_sck is not null , the connection could have been torn down . . . */
2020-02-21 09:42:10 +00:00
if ( ! dnc - > tcp_sck )
{
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & mkinfo , 0 , HIO_SIZEOF ( mkinfo ) ) ;
2021-08-17 07:00:22 +00:00
switch ( hio_skad_get_family ( & reqmsgxtn - > servaddr ) )
2020-02-21 09:42:10 +00:00
{
2021-07-22 07:30:20 +00:00
case HIO_AF_INET :
mkinfo . type = HIO_DEV_SCK_TCP4 ;
2020-02-21 09:42:10 +00:00
break ;
2021-07-22 07:30:20 +00:00
case HIO_AF_INET6 :
mkinfo . type = HIO_DEV_SCK_TCP6 ;
2020-02-21 09:42:10 +00:00
break ;
default :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINTERN ) ;
2020-02-21 09:42:10 +00:00
return - 1 ;
}
mkinfo . on_write = on_tcp_write ;
mkinfo . on_read = on_tcp_read ;
mkinfo . on_connect = on_tcp_connect ;
mkinfo . on_disconnect = on_tcp_disconnect ;
2021-07-22 07:30:20 +00:00
dnc - > tcp_sck = hio_dev_sck_make ( hio , HIO_SIZEOF ( * sckxtn ) , & mkinfo ) ;
2020-02-25 07:09:20 +00:00
if ( ! dnc - > tcp_sck ) return - 1 ;
2020-02-21 09:42:10 +00:00
2021-07-22 07:30:20 +00:00
sckxtn = ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dnc - > tcp_sck ) ;
2020-02-28 07:41:25 +00:00
sckxtn - > dnc = dnc ;
2020-02-21 09:42:10 +00:00
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & cinfo , 0 , HIO_SIZEOF ( cinfo ) ) ;
2020-02-28 07:41:25 +00:00
cinfo . remoteaddr = reqmsgxtn - > servaddr ;
cinfo . connect_tmout = reqmsgxtn - > rtmout ; /* TOOD: create a separate connect timeout or treate rtmout as a whole transaction time and calculate the remaining time from the transaction start, and use it */
2020-02-21 09:42:10 +00:00
2021-07-22 07:30:20 +00:00
if ( hio_dev_sck_connect ( dnc - > tcp_sck , & cinfo ) < = - 1 )
2020-02-28 07:41:25 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_kill ( dnc - > tcp_sck ) ;
dnc - > tcp_sck = HIO_NULL ;
2020-02-28 07:41:25 +00:00
return - 1 ; /* the connect request hasn't been honored. */
}
2020-02-27 17:34:27 +00:00
}
2020-02-28 07:41:25 +00:00
2020-02-25 07:09:20 +00:00
/* switch the belonging device to the tcp socket since the connect request has been acknowledged. */
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , reqmsgxtn - > rtmridx = = HIO_TMRIDX_INVALID ) ; /* ensure no timer job scheduled at this moment */
2020-02-28 07:41:25 +00:00
reqmsgxtn - > dev = dnc - > tcp_sck ;
reqmsgxtn - > rtries = 0 ;
2021-07-22 07:30:20 +00:00
if ( ! reqmsgxtn - > pending & & hio_dns_msg_to_pkt ( reqmsg ) - > qr = = 0 ) chain_pending_dns_reqmsg ( dnc , reqmsg ) ;
2020-02-25 07:09:20 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG6 ( hio , " DNC - switched transport to tcp - msgid:%d %p %p %p %p %p \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( reqmsg ) - > id ) , reqmsg , reqmsgxtn , reqmsgxtn - > dev , dnc - > udp_sck , dnc - > tcp_sck ) ;
2020-02-28 07:41:25 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_DEV_SCK_GET_PROGRESS ( dnc - > tcp_sck ) & HIO_DEV_SCK_CONNECTED )
2020-02-28 07:41:25 +00:00
{
2020-03-01 17:43:42 +00:00
if ( write_dns_msg_over_tcp ( reqmsgxtn - > dev , reqmsg ) < = - 1 )
{
/* the caller must not use reqmsg from now because it's freed here */
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , hio_geterrnum ( hio ) , HIO_NULL , 0 ) ;
2020-03-01 17:43:42 +00:00
release_dns_msg ( dnc , reqmsg ) ;
}
2020-02-28 07:41:25 +00:00
}
2020-02-25 07:09:20 +00:00
return 0 ;
2020-02-21 09:42:10 +00:00
}
/* ----------------------------------------------------------------------- */
2021-07-22 07:30:20 +00:00
static int on_udp_read ( hio_dev_sck_t * dev , const void * data , hio_iolen_t dlen , const hio_skad_t * srcaddr )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_dns_pkt_t * pkt ;
hio_dns_msg_t * reqmsg ;
hio_uint16_t id ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( dlen < = - 1 ) )
2020-02-27 17:34:27 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - dns read error ....%js \n " , hio_geterrmsg ( hio ) ) ; /* TODO: add source packet */
2020-02-27 17:34:27 +00:00
return 0 ;
}
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( dlen < HIO_SIZEOF ( * pkt ) ) )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG0 ( hio , " DNC - dns packet too small from .... \n " ) ; /* TODO: add source packet */
2020-02-21 04:21:16 +00:00
return 0 ; /* drop */
}
2021-07-22 07:30:20 +00:00
pkt = ( hio_dns_pkt_t * ) data ;
2020-02-21 04:21:16 +00:00
if ( ! pkt - > qr )
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG0 ( hio , " DNC - dropping dns request received ... \n " ) ; /* TODO: add source info */
2020-02-21 04:21:16 +00:00
return 0 ; /* drop request */
}
2021-07-22 07:30:20 +00:00
id = hio_ntoh16 ( pkt - > id ) ;
2020-02-21 04:21:16 +00:00
/* if id doesn't match one of the pending requests sent, drop it */
/* TODO: improve performance of dns response matching*/
reqmsg = dnc - > pending_req ;
while ( reqmsg )
{
2021-07-22 07:30:20 +00:00
hio_dns_pkt_t * reqpkt = hio_dns_msg_to_pkt ( reqmsg ) ;
2020-02-21 04:21:16 +00:00
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
if ( reqmsgxtn - > dev = = dev & & pkt - > id = = reqpkt - > id & & hio_equal_skads ( & reqmsgxtn - > servaddr , srcaddr , 0 ) )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
if ( reqmsgxtn - > rtmridx ! = HIO_TMRIDX_INVALID )
2020-02-27 08:40:39 +00:00
{
/* unschedule a timer job if any */
2021-07-22 07:30:20 +00:00
hio_deltmrjob ( hio , reqmsgxtn - > rtmridx ) ;
HIO_ASSERT ( hio , reqmsgxtn - > rtmridx = = HIO_TMRIDX_INVALID ) ;
2020-02-27 08:40:39 +00:00
}
2020-02-21 09:42:10 +00:00
////////////////////////
2020-03-02 04:58:22 +00:00
// for simple testing without actual truncated dns response
//pkt->tc = 1;
2020-02-21 09:42:10 +00:00
////////////////////////
2021-07-22 07:30:20 +00:00
if ( HIO_UNLIKELY ( pkt - > tc ) )
2020-02-21 04:21:16 +00:00
{
/* TODO: add an option for this behavior */
2020-02-28 07:41:25 +00:00
if ( switch_reqmsg_transport_to_tcp ( dnc , reqmsg ) > = 0 ) return 0 ;
2020-02-25 07:09:20 +00:00
/* TODO: add an option to call an error callback with TRUNCATION error code instead of fallback to received UDP truncated message */
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - received dns response over udp for msgid:%d \n " , id ) ;
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , HIO_ENOERR , data , dlen ) ;
2020-02-21 04:21:16 +00:00
release_dns_msg ( dnc , reqmsg ) ;
return 0 ;
}
2020-02-27 17:34:27 +00:00
2020-02-21 04:21:16 +00:00
reqmsg = reqmsgxtn - > next ;
}
/* the response id didn't match the ID of pending requests - need to wait longer? */
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - unknown dns response over udp... msgid:%d \n " , id ) ; /* TODO: add source info */
2020-02-21 04:21:16 +00:00
return 0 ;
}
2021-07-22 07:30:20 +00:00
static void on_udp_reply_timeout ( hio_t * hio , const hio_ntime_t * now , hio_tmrjob_t * job )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * reqmsg = ( hio_dns_msg_t * ) job - > ctx ;
2020-02-21 04:21:16 +00:00
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
hio_dev_sck_t * dev = msgxtn - > dev ;
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_errnum_t status = HIO_ETMOUT ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , msgxtn - > rtmridx = = HIO_TMRIDX_INVALID ) ;
HIO_ASSERT ( hio , dev = = dnc - > udp_sck ) ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - unable to receive dns response in time over udp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( reqmsg ) - > id ) ) ;
2020-02-21 04:21:16 +00:00
if ( msgxtn - > rtries < msgxtn - > rmaxtries )
{
2021-07-22 07:30:20 +00:00
hio_ntime_t * tmout ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
tmout = HIO_IS_POS_NTIME ( & msgxtn - > wtmout ) ? & msgxtn - > wtmout : HIO_NULL ;
HIO_DEBUG1 ( hio , " DNC - sending dns question again over udp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( reqmsg ) - > id ) ) ;
if ( hio_dev_sck_timedwrite ( dev , hio_dns_msg_to_pkt ( reqmsg ) , reqmsg - > pktlen , tmout , reqmsg , & msgxtn - > servaddr ) > = 0 ) return ; /* resent */
2020-02-21 04:21:16 +00:00
2020-02-27 17:34:27 +00:00
/* retry failed */
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
2020-02-21 04:21:16 +00:00
}
2020-02-27 17:34:27 +00:00
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( msgxtn - > on_done ) ) msgxtn - > on_done ( dnc , reqmsg , status , HIO_NULL , 0 ) ;
2020-02-27 17:34:27 +00:00
release_dns_msg ( dnc , reqmsg ) ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
static int on_udp_write ( hio_dev_sck_t * dev , hio_iolen_t wrlen , void * wrctx , const hio_skad_t * dstaddr )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dev - > hio ;
hio_dns_msg_t * msg = ( hio_dns_msg_t * ) wrctx ;
2020-02-21 04:21:16 +00:00
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( msg ) ;
2021-07-22 07:30:20 +00:00
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_errnum_t status ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , dev = = ( hio_dev_sck_t * ) msgxtn - > dev ) ;
2020-02-21 04:21:16 +00:00
if ( wrlen < = - 1 )
{
/* write has timed out or an error has occurred */
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
2020-02-27 17:34:27 +00:00
goto finalize ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
else if ( hio_dns_msg_to_pkt ( msg ) - > qr = = 0 & & msgxtn - > rmaxtries > 0 )
2020-02-21 04:21:16 +00:00
{
/* question. schedule to wait for response */
2021-07-22 07:30:20 +00:00
hio_tmrjob_t tmrjob ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - sent dns question over udp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
HIO_MEMSET ( & tmrjob , 0 , HIO_SIZEOF ( tmrjob ) ) ;
2020-02-21 04:21:16 +00:00
tmrjob . ctx = msg ;
2021-07-22 07:30:20 +00:00
hio_gettime ( hio , & tmrjob . when ) ;
HIO_ADD_NTIME ( & tmrjob . when , & tmrjob . when , & msgxtn - > rtmout ) ;
2020-02-21 04:21:16 +00:00
tmrjob . handler = on_udp_reply_timeout ;
tmrjob . idxptr = & msgxtn - > rtmridx ;
2021-07-22 07:30:20 +00:00
msgxtn - > rtmridx = hio_instmrjob ( hio , & tmrjob ) ;
if ( msgxtn - > rtmridx = = HIO_TMRIDX_INVALID )
2020-02-21 04:21:16 +00:00
{
/* call the callback to indicate this operation failure in the middle of transaction */
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
HIO_DEBUG1 ( hio , " DNC - unable to schedule udp timeout - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-02-27 17:34:27 +00:00
goto finalize ;
2020-02-21 04:21:16 +00:00
}
2020-05-15 06:18:49 +00:00
2020-02-27 17:34:27 +00:00
if ( msgxtn - > rtries = = 0 )
2020-02-21 04:21:16 +00:00
{
2020-02-27 17:34:27 +00:00
/* this is the first wait */
/* TODO: improve performance. hashing by id? */
/* chain it to the peing request list */
chain_pending_dns_reqmsg ( dnc , msg ) ;
2020-02-21 04:21:16 +00:00
}
2020-02-27 17:34:27 +00:00
msgxtn - > rtries + + ;
2020-02-21 04:21:16 +00:00
}
else
{
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - sent dns message over udp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-02-27 17:34:27 +00:00
/* sent an answer. however this may be a question if msgxtn->rmaxtries is 0. */
2021-07-22 07:30:20 +00:00
status = HIO_ENOERR ;
2020-02-27 17:34:27 +00:00
goto finalize ;
2020-02-21 04:21:16 +00:00
}
return 0 ;
2020-02-27 17:34:27 +00:00
finalize :
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( msgxtn - > on_done ) ) msgxtn - > on_done ( dnc , msg , status , HIO_NULL , 0 ) ;
2020-02-27 17:34:27 +00:00
release_dns_msg ( dnc , msg ) ;
return 0 ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
static void on_udp_connect ( hio_dev_sck_t * dev )
2020-02-21 04:21:16 +00:00
{
}
2021-07-22 07:30:20 +00:00
static void on_udp_disconnect ( hio_dev_sck_t * dev )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
/*hio_t* hio = dev->hio;*/
hio_svc_dnc_t * dnc = ( ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dev ) ) - > dnc ;
hio_dns_msg_t * reqmsg ;
2020-02-28 07:41:25 +00:00
reqmsg = dnc - > pending_req ;
while ( reqmsg )
{
dnc_dns_msg_xtn_t * reqmsgxtn = dnc_dns_msg_getxtn ( reqmsg ) ;
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * nextreqmsg = reqmsgxtn - > next ;
2020-02-28 07:41:25 +00:00
if ( reqmsgxtn - > dev = = dev )
{
2021-07-22 07:30:20 +00:00
if ( HIO_LIKELY ( reqmsgxtn - > on_done ) ) reqmsgxtn - > on_done ( dnc , reqmsg , HIO_ENORSP , HIO_NULL , 0 ) ;
2020-02-28 07:41:25 +00:00
release_dns_msg ( dnc , reqmsg ) ;
}
reqmsg = nextreqmsg ;
}
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
hio_svc_dnc_t * hio_svc_dnc_start ( hio_t * hio , const hio_skad_t * serv_addr , const hio_skad_t * bind_addr , const hio_ntime_t * send_tmout , const hio_ntime_t * reply_tmout , hio_oow_t max_tries )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_svc_dnc_t * dnc = HIO_NULL ;
hio_dev_sck_make_t mkinfo ;
2020-02-29 16:56:36 +00:00
dnc_sck_xtn_t * sckxtn ;
2021-07-22 07:30:20 +00:00
hio_ntime_t now ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
dnc = ( hio_svc_dnc_t * ) hio_callocmem ( hio , HIO_SIZEOF ( * dnc ) ) ;
if ( HIO_UNLIKELY ( ! dnc ) ) goto oops ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
dnc - > hio = hio ;
dnc - > svc_stop = hio_svc_dnc_stop ;
2020-02-21 04:21:16 +00:00
dnc - > serv_addr = * serv_addr ;
dnc - > send_tmout = * send_tmout ;
dnc - > reply_tmout = * reply_tmout ;
2020-03-02 04:58:22 +00:00
dnc - > max_tries = max_tries ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_MEMSET ( & mkinfo , 0 , HIO_SIZEOF ( mkinfo ) ) ;
2021-08-17 07:00:22 +00:00
switch ( hio_skad_get_family ( serv_addr ) )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
case HIO_AF_INET :
mkinfo . type = HIO_DEV_SCK_UDP4 ;
2020-02-21 04:21:16 +00:00
break ;
2021-07-22 07:30:20 +00:00
case HIO_AF_INET6 :
mkinfo . type = HIO_DEV_SCK_UDP6 ;
2020-02-21 04:21:16 +00:00
break ;
default :
2021-07-22 07:30:20 +00:00
hio_seterrnum ( hio , HIO_EINVAL ) ;
2020-02-21 04:21:16 +00:00
goto oops ;
}
mkinfo . on_write = on_udp_write ;
mkinfo . on_read = on_udp_read ;
mkinfo . on_connect = on_udp_connect ;
mkinfo . on_disconnect = on_udp_disconnect ;
2021-07-22 07:30:20 +00:00
dnc - > udp_sck = hio_dev_sck_make ( hio , HIO_SIZEOF ( * sckxtn ) , & mkinfo ) ;
2020-02-21 04:21:16 +00:00
if ( ! dnc - > udp_sck ) goto oops ;
2021-07-22 07:30:20 +00:00
sckxtn = ( dnc_sck_xtn_t * ) hio_dev_sck_getxtn ( dnc - > udp_sck ) ;
2020-02-29 16:56:36 +00:00
sckxtn - > dnc = dnc ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
if ( bind_addr ) /* TODO: get hio_dev_sck_bind_t? instead of bind_addr? */
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_dev_sck_bind_t bi ;
HIO_MEMSET ( & bi , 0 , HIO_SIZEOF ( bi ) ) ;
2020-02-21 04:21:16 +00:00
bi . localaddr = * bind_addr ;
2021-07-22 07:30:20 +00:00
if ( hio_dev_sck_bind ( dnc - > udp_sck , & bi ) < = - 1 ) goto oops ;
2020-02-21 04:21:16 +00:00
}
2020-07-03 15:56:33 +00:00
/* initialize the dns cookie key */
2021-07-22 07:30:20 +00:00
hio_gettime ( hio , & now ) ;
HIO_MEMCPY ( & dnc - > cookie . key [ 0 ] , & now . sec , ( HIO_SIZEOF ( now . sec ) < 8 ? HIO_SIZEOF ( now . sec ) : 8 ) ) ;
HIO_MEMCPY ( & dnc - > cookie . key [ 8 ] , & now . nsec , ( HIO_SIZEOF ( now . nsec ) < 8 ? HIO_SIZEOF ( now . nsec ) : 8 ) ) ;
2020-07-03 15:56:33 +00:00
2021-07-22 07:30:20 +00:00
HIO_SVCL_APPEND_SVC ( & hio - > actsvc , ( hio_svc_t * ) dnc ) ;
HIO_DEBUG1 ( hio , " DNC - STARTED SERVICE %p \n " , dnc ) ;
2020-02-21 04:21:16 +00:00
return dnc ;
oops :
if ( dnc )
{
2021-07-22 07:30:20 +00:00
if ( dnc - > udp_sck ) hio_dev_sck_kill ( dnc - > udp_sck ) ;
hio_freemem ( hio , dnc ) ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
return HIO_NULL ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
void hio_svc_dnc_stop ( hio_svc_dnc_t * dnc )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = dnc - > hio ;
2020-02-25 07:09:20 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( hio , " DNC - STOPPING SERVICE %p \n " , dnc ) ;
if ( dnc - > udp_sck ) hio_dev_sck_kill ( dnc - > udp_sck ) ;
if ( dnc - > tcp_sck ) hio_dev_sck_kill ( dnc - > tcp_sck ) ;
2020-02-21 04:21:16 +00:00
while ( dnc - > pending_req ) release_dns_msg ( dnc , dnc - > pending_req ) ;
2021-07-22 07:30:20 +00:00
HIO_SVCL_UNLINK_SVC ( dnc ) ;
hio_freemem ( hio , dnc ) ;
2020-02-21 04:21:16 +00:00
}
2020-03-01 17:43:42 +00:00
2021-07-22 07:30:20 +00:00
static HIO_INLINE int send_dns_msg ( hio_svc_dnc_t * dnc , hio_dns_msg_t * msg , int send_flags )
2020-02-21 04:21:16 +00:00
{
2020-03-01 17:43:42 +00:00
dnc_dns_msg_xtn_t * msgxtn = dnc_dns_msg_getxtn ( msg ) ;
2021-07-22 07:30:20 +00:00
hio_ntime_t * tmout ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
if ( ( send_flags & HIO_SVC_DNC_SEND_FLAG_PREFER_TCP ) & & switch_reqmsg_transport_to_tcp ( dnc , msg ) > = 0 ) return 0 ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_DEBUG1 ( dnc - > hio , " DNC - sending dns message over udp - msgid:%d \n " , ( int ) hio_ntoh16 ( hio_dns_msg_to_pkt ( msg ) - > id ) ) ;
2020-05-15 06:18:49 +00:00
2021-07-22 07:30:20 +00:00
tmout = HIO_IS_POS_NTIME ( & msgxtn - > wtmout ) ? & msgxtn - > wtmout : HIO_NULL ;
2020-03-01 17:43:42 +00:00
/* TODO: optionally, override dnc->serv_addr and use the target address passed as a parameter */
2021-07-22 07:30:20 +00:00
return hio_dev_sck_timedwrite ( dnc - > udp_sck , hio_dns_msg_to_pkt ( msg ) , msg - > pktlen , tmout , msg , & msgxtn - > servaddr ) ;
2020-03-01 17:43:42 +00:00
}
2020-02-25 07:09:20 +00:00
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * hio_svc_dnc_sendmsg ( hio_svc_dnc_t * dnc , hio_dns_bhdr_t * bdns , 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 , int send_flags , hio_svc_dnc_on_done_t on_done , hio_oow_t xtnsize )
2020-03-01 17:43:42 +00:00
{
/* send a request or a response */
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * msg ;
2020-02-21 04:21:16 +00:00
2020-03-01 17:43:42 +00:00
msg = make_dns_msg ( dnc , bdns , qr , qr_count , rr , rr_count , edns , on_done , xtnsize ) ;
2021-07-22 07:30:20 +00:00
if ( ! msg ) return HIO_NULL ;
2020-03-01 17:43:42 +00:00
2020-03-02 05:16:37 +00:00
if ( send_dns_msg ( dnc , msg , send_flags ) < = - 1 )
2020-02-21 04:21:16 +00:00
{
release_dns_msg ( dnc , msg ) ;
2021-07-22 07:30:20 +00:00
return HIO_NULL ;
2020-02-21 04:21:16 +00:00
}
2020-03-01 17:43:42 +00:00
2020-02-21 04:21:16 +00:00
return msg ;
}
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * hio_svc_dnc_sendreq ( hio_svc_dnc_t * dnc , hio_dns_bhdr_t * bdns , hio_dns_bqr_t * qr , hio_dns_bedns_t * edns , int send_flags , hio_svc_dnc_on_done_t on_done , hio_oow_t xtnsize )
2020-02-21 04:21:16 +00:00
{
/* send a request without resource records */
2021-07-22 07:30:20 +00:00
if ( bdns - > rcode ! = HIO_DNS_RCODE_NOERROR )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_seterrnum ( dnc - > hio , HIO_EINVAL ) ;
return HIO_NULL ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
return hio_svc_dnc_sendmsg ( dnc , bdns , qr , 1 , HIO_NULL , 0 , edns , send_flags , on_done , xtnsize ) ;
2020-02-21 04:21:16 +00:00
}
/* ----------------------------------------------------------------------- */
struct dnc_dns_msg_resolve_xtn_t
{
2021-07-22 07:30:20 +00:00
hio_dns_rrt_t qtype ;
2020-02-21 04:21:16 +00:00
int flags ;
2021-07-22 07:30:20 +00:00
hio_uint8_t client_cookie [ HIO_DNS_COOKIE_CLIENT_LEN ] ;
hio_svc_dnc_on_resolve_t on_resolve ;
2020-02-21 04:21:16 +00:00
} ;
typedef struct dnc_dns_msg_resolve_xtn_t dnc_dns_msg_resolve_xtn_t ;
2021-07-22 07:30:20 +00:00
# if defined(HIO_HAVE_INLINE)
static HIO_INLINE dnc_dns_msg_resolve_xtn_t * dnc_dns_msg_resolve_getxtn ( hio_dns_msg_t * msg ) { return ( ( dnc_dns_msg_resolve_xtn_t * ) ( ( hio_uint8_t * ) dnc_dns_msg_getxtn ( msg ) + HIO_SIZEOF ( dnc_dns_msg_xtn_t ) ) ) ; }
2020-02-21 04:21:16 +00:00
# else
2021-07-22 07:30:20 +00:00
# define dnc_dns_msg_resolve_getxtn(msg) ((dnc_dns_msg_resolve_xtn_t*)((hio_uint8_t*)dnc_dns_msg_getxtn(msg) + HIO_SIZEOF(dnc_dns_msg_xtn_t)))
2020-02-21 04:21:16 +00:00
# endif
2021-07-22 07:30:20 +00:00
static void on_dnc_resolve ( hio_svc_dnc_t * dnc , hio_dns_msg_t * reqmsg , hio_errnum_t status , const void * data , hio_oow_t dlen )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
hio_t * hio = hio_svc_dnc_gethio ( dnc ) ;
hio_dns_pkt_info_t * pi = HIO_NULL ;
2020-07-02 14:21:47 +00:00
dnc_dns_msg_resolve_xtn_t * resolxtn = dnc_dns_msg_resolve_getxtn ( reqmsg ) ;
2020-02-21 04:21:16 +00:00
if ( data )
{
2021-07-22 07:30:20 +00:00
hio_uint32_t i ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( hio , status = = HIO_ENOERR ) ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
pi = hio_dns_make_pkt_info ( hio , data , dlen ) ;
2020-02-21 04:21:16 +00:00
if ( ! pi )
{
2021-07-22 07:30:20 +00:00
status = hio_geterrnum ( hio ) ;
2020-02-27 17:34:27 +00:00
goto no_data ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
if ( resolxtn - > flags & HIO_SVC_DNC_RESOLVE_FLAG_COOKIE )
2020-07-02 14:21:47 +00:00
{
if ( pi - > edns . cookie . server_len > 0 )
{
2020-07-04 16:37:46 +00:00
/* remember the received server cookie to use it with other new requests */
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( dnc - > cookie . data . server , pi - > edns . cookie . data . server , pi - > edns . cookie . server_len ) ;
2020-07-02 14:21:47 +00:00
dnc - > cookie . server_len = pi - > edns . cookie . server_len ;
}
}
2021-07-22 07:30:20 +00:00
if ( ! ( resolxtn - > flags & HIO_SVC_DNC_RESOLVE_FLAG_BRIEF ) )
2020-07-02 14:21:47 +00:00
{
/* the full reply packet is requested. */
if ( resolxtn - > on_resolve ) resolxtn - > on_resolve ( dnc , reqmsg , status , pi , 0 ) ;
goto done ;
}
2020-07-01 09:40:34 +00:00
2021-07-22 07:30:20 +00:00
if ( pi - > hdr . rcode ! = HIO_DNS_RCODE_NOERROR )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
status = HIO_EINVAL ;
2020-02-27 17:34:27 +00:00
goto no_data ;
2020-02-21 04:21:16 +00:00
}
2020-02-27 17:34:27 +00:00
if ( pi - > ancount < 0 ) goto no_data ;
2020-02-21 04:21:16 +00:00
/* in the brief mode, we inspect the answer section only */
2021-07-22 07:30:20 +00:00
if ( resolxtn - > qtype = = HIO_DNS_RRT_Q_ANY )
2020-02-21 04:21:16 +00:00
{
/* return A or AAAA for ANY in the brief mode */
for ( i = 0 ; i < pi - > ancount ; i + + )
{
2021-07-22 07:30:20 +00:00
if ( pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_A | | pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_AAAA )
2020-02-21 04:21:16 +00:00
{
match_found :
2021-07-22 07:30:20 +00:00
if ( resolxtn - > on_resolve ) resolxtn - > on_resolve ( dnc , reqmsg , status , & pi - > rr . an [ i ] , HIO_SIZEOF ( pi - > rr . an [ i ] ) ) ;
2020-02-21 04:21:16 +00:00
goto done ;
}
}
}
for ( i = 0 ; i < pi - > ancount ; i + + )
{
/* it is a bit time taking to retreive the query type from the packet
* bundled in reqmsg as it requires parsing of the packet . let me use
* the query type i stored in the extension space . */
2020-07-02 14:21:47 +00:00
switch ( resolxtn - > qtype )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_Q_ANY :
case HIO_DNS_RRT_Q_AFXR : /* AFXR doesn't make sense in the brief mode. just treat it like ANY */
2020-02-21 04:21:16 +00:00
/* no A or AAAA found. so give the first entry in the answer */
goto match_found ;
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_Q_MAILA :
2020-02-21 04:21:16 +00:00
/* if you want to get the full RRs, don't use the brief mode. */
2021-07-22 07:30:20 +00:00
if ( pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_MD | | pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_MF ) goto match_found ;
2020-02-21 04:21:16 +00:00
break ;
2021-07-22 07:30:20 +00:00
case HIO_DNS_RRT_Q_MAILB :
2020-02-21 04:21:16 +00:00
/* if you want to get the full RRs, don't use the brief mode. */
2021-07-22 07:30:20 +00:00
if ( pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_MB | | pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_MG | |
pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_MR | | pi - > rr . an [ i ] . rrtype = = HIO_DNS_RRT_MINFO ) goto match_found ;
2020-02-21 04:21:16 +00:00
break ;
default :
2020-07-02 14:21:47 +00:00
if ( pi - > rr . an [ i ] . rrtype = = resolxtn - > qtype ) goto match_found ;
2020-02-21 04:21:16 +00:00
break ;
}
}
2020-02-27 17:34:27 +00:00
goto no_data ;
2020-02-21 04:21:16 +00:00
}
else
{
2020-02-27 17:34:27 +00:00
no_data :
2021-07-22 07:30:20 +00:00
if ( resolxtn - > on_resolve ) resolxtn - > on_resolve ( dnc , reqmsg , status , HIO_NULL , 0 ) ;
2020-02-21 04:21:16 +00:00
}
done :
2021-07-22 07:30:20 +00:00
if ( pi ) hio_dns_free_pkt_info ( hio_svc_dnc_gethio ( dnc ) , pi ) ;
2020-02-21 04:21:16 +00:00
}
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * hio_svc_dnc_resolve ( hio_svc_dnc_t * dnc , const hio_bch_t * qname , hio_dns_rrt_t qtype , int resolve_flags , hio_svc_dnc_on_resolve_t on_resolve , hio_oow_t xtnsize )
2020-02-21 04:21:16 +00:00
{
2021-07-22 07:30:20 +00:00
static hio_dns_bhdr_t qhdr =
2020-02-21 04:21:16 +00:00
{
- 1 , /* id */
0 , /* qr */
2021-07-22 07:30:20 +00:00
HIO_DNS_OPCODE_QUERY , /* opcode */
2020-02-21 04:21:16 +00:00
0 , /* aa */
0 , /* tc */
1 , /* rd */
0 , /* ra */
0 , /* ad */
0 , /* cd */
2021-07-22 07:30:20 +00:00
HIO_DNS_RCODE_NOERROR /* rcode */
2020-02-21 04:21:16 +00:00
} ;
2021-07-22 07:30:20 +00:00
hio_dns_bedns_t qedns =
2020-02-21 04:21:16 +00:00
{
4096 , /* uplen */
0 , /* edns version */
0 , /* dnssec ok */
0 , /* number of edns options */
2021-07-22 07:30:20 +00:00
HIO_NULL
2020-02-21 04:21:16 +00:00
} ;
2021-07-22 07:30:20 +00:00
hio_dns_beopt_t beopt_cookie ;
2020-07-01 15:54:23 +00:00
2021-07-22 07:30:20 +00:00
hio_dns_bqr_t qr ;
hio_dns_msg_t * reqmsg ;
2020-03-01 17:43:42 +00:00
dnc_dns_msg_resolve_xtn_t * resolxtn ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
qr . qname = ( hio_bch_t * ) qname ;
2020-02-21 04:21:16 +00:00
qr . qtype = qtype ;
2021-07-22 07:30:20 +00:00
qr . qclass = HIO_DNS_RRC_IN ;
2020-02-21 04:21:16 +00:00
2021-07-22 07:30:20 +00:00
if ( resolve_flags & HIO_SVC_DNC_RESOLVE_FLAG_COOKIE )
2020-07-01 15:54:23 +00:00
{
2021-07-22 07:30:20 +00:00
beopt_cookie . code = HIO_DNS_EOPT_COOKIE ;
2020-07-03 15:56:33 +00:00
beopt_cookie . dptr = & dnc - > cookie . data ;
2021-07-22 07:30:20 +00:00
beopt_cookie . dlen = HIO_DNS_COOKIE_CLIENT_LEN ;
2020-07-02 14:21:47 +00:00
if ( dnc - > cookie . server_len > 0 ) beopt_cookie . dlen + = dnc - > cookie . server_len ;
2020-07-03 15:56:33 +00:00
/* compute the client cookie */
2022-06-16 13:51:23 +00:00
HIO_STATIC_ASSERT_EXPR ( HIO_SIZEOF ( dnc - > cookie . data . client ) = = HIO_DNS_COOKIE_CLIENT_LEN ) ;
2021-07-22 07:30:20 +00:00
hio_sip_hash_24 ( dnc - > cookie . key , & dnc - > serv_addr , HIO_SIZEOF ( dnc - > serv_addr ) , dnc - > cookie . data . client ) ;
2020-07-01 15:54:23 +00:00
qedns . beonum = 1 ;
qedns . beoptr = & beopt_cookie ;
}
2021-07-22 07:30:20 +00:00
if ( resolve_flags & HIO_SVC_DNC_RESOLVE_FLAG_DNSSEC )
2020-07-04 16:37:46 +00:00
{
qedns . dnssecok = 1 ;
}
2021-07-22 07:30:20 +00:00
reqmsg = make_dns_msg ( dnc , & qhdr , & qr , 1 , HIO_NULL , 0 , & qedns , on_dnc_resolve , HIO_SIZEOF ( * resolxtn ) + xtnsize ) ;
2020-02-21 04:21:16 +00:00
if ( reqmsg )
{
2020-03-02 05:16:37 +00:00
int send_flags ;
2020-07-02 14:21:47 +00:00
#if 0
2021-07-22 07:30:20 +00:00
if ( ( resolve_flags & HIO_SVC_DNC_RESOLVE_FLAG_COOKIE ) & & dnc - > cookie . server_len = = 0 )
2020-07-01 15:54:23 +00:00
{
2020-07-02 14:21:47 +00:00
/* Exclude the server cookie from the packet when the server cookie is not available.
*
* ASSUMPTIONS :
2020-07-01 15:54:23 +00:00
* the eopt entries are at the back of the packet .
2021-07-22 07:30:20 +00:00
* only 1 eopt entry ( HIO_DNS_EOPT_COOKIE ) has been added .
2020-07-01 15:54:23 +00:00
*
* manipulate the data length of the EDNS0 RR and COOKIE option
* as if the server cookie data has not been added .
*/
2021-07-22 07:30:20 +00:00
hio_dns_rrtr_t * edns_rrtr ;
hio_dns_eopt_t * eopt ;
2020-07-01 15:54:23 +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 ) ;
reqmsg - > pktlen - = HIO_DNS_COOKIE_SERVER_MAX_LEN ;
2020-07-01 15:54:23 +00:00
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( dnc - > hio , edns_rrtr - > rrtype = = HIO_CONST_HTON16 ( HIO_DNS_RRT_OPT ) ) ;
HIO_ASSERT ( dnc - > hio , edns_rrtr - > dlen = = HIO_CONST_HTON16 ( HIO_SIZEOF ( hio_dns_eopt_t ) + HIO_DNS_COOKIE_MAX_LEN ) ) ;
edns_rrtr - > dlen = HIO_CONST_HTON16 ( HIO_SIZEOF ( hio_dns_eopt_t ) + HIO_DNS_COOKIE_CLIENT_LEN ) ;
2020-07-01 15:54:23 +00:00
2021-07-22 07:30:20 +00:00
eopt = ( hio_dns_eopt_t * ) ( edns_rrtr + 1 ) ;
HIO_ASSERT ( dnc - > hio , eopt - > dlen = = HIO_CONST_HTON16 ( HIO_DNS_COOKIE_MAX_LEN ) ) ;
eopt - > dlen = HIO_CONST_HTON16 ( HIO_DNS_COOKIE_CLIENT_LEN ) ;
2020-07-01 15:54:23 +00:00
}
2020-07-02 14:21:47 +00:00
# endif
2020-07-01 15:54:23 +00:00
2020-03-01 17:43:42 +00:00
resolxtn = dnc_dns_msg_resolve_getxtn ( reqmsg ) ;
resolxtn - > on_resolve = on_resolve ;
resolxtn - > qtype = qtype ;
2020-03-02 05:16:37 +00:00
resolxtn - > flags = resolve_flags ;
2020-07-02 14:21:47 +00:00
/* store in the extension area the client cookie set in the packet */
2021-07-22 07:30:20 +00:00
HIO_MEMCPY ( resolxtn - > client_cookie , dnc - > cookie . data . client , HIO_DNS_COOKIE_CLIENT_LEN ) ;
2020-03-01 17:43:42 +00:00
2021-07-22 07:30:20 +00:00
send_flags = ( resolve_flags & HIO_SVC_DNC_SEND_FLAG_ALL ) ;
if ( HIO_UNLIKELY ( qtype = = HIO_DNS_RRT_Q_AFXR ) ) send_flags | = HIO_SVC_DNC_SEND_FLAG_PREFER_TCP ;
2020-03-02 05:16:37 +00:00
if ( send_dns_msg ( dnc , reqmsg , send_flags ) < = - 1 )
2020-03-01 17:43:42 +00:00
{
release_dns_msg ( dnc , reqmsg ) ;
2021-07-22 07:30:20 +00:00
return HIO_NULL ;
2020-03-01 17:43:42 +00:00
}
2020-02-21 04:21:16 +00:00
}
return reqmsg ;
}
2020-03-03 08:49:24 +00:00
2021-07-22 07:30:20 +00:00
int hio_svc_dnc_checkclientcookie ( hio_svc_dnc_t * dnc , hio_dns_msg_t * reqmsg , hio_dns_pkt_info_t * respi )
2020-07-04 08:03:36 +00:00
{
2021-07-22 07:30:20 +00:00
hio_uint8_t xb [ HIO_DNS_COOKIE_CLIENT_LEN ] ;
hio_uint8_t * x ;
2020-07-04 08:03:36 +00:00
2021-07-22 07:30:20 +00:00
x = hio_dns_find_client_cookie_in_msg ( reqmsg , & xb ) ;
2020-07-04 08:03:36 +00:00
if ( x )
{
/* there is a client cookie in the request. */
if ( respi - > edns . cookie . client_len > 0 )
{
2021-07-22 07:30:20 +00:00
HIO_ASSERT ( dnc - > hio , respi - > edns . cookie . client_len = = HIO_DNS_COOKIE_CLIENT_LEN ) ;
return HIO_MEMCMP ( x , respi - > edns . cookie . data . client , HIO_DNS_COOKIE_CLIENT_LEN ) = = 0 ; /* 1 if ok, 0 if not */
2020-07-04 08:03:36 +00:00
}
else
{
/* no client cookie in the response - the server doesn't support cookie? */
return - 1 ;
}
}
return 2 ; /* ok because the request doesn't include the client cookie */
}
2020-03-03 08:49:24 +00:00
/* TODO: upon startup, read /etc/hosts. setup inotify or find a way to detect file changes..
* in resolve , add an option to use entries from / etc / hosts */
/* TODO: afxr client ... */
/* TODO: trace function to do its own recursive resolution?...
2021-07-22 07:30:20 +00:00
hio_dns_msg_t * hio_svc_dnc_trace ( hio_svc_dnc_t * dnc , const hio_bch_t * qname , hio_dns_rrt_t qtype , int resolve_flags , hio_svc_dnc_on_resolve_t on_resolve , hio_oow_t xtnsize )
2020-03-03 08:49:24 +00:00
{
}
*/