more dns cookie handling code
This commit is contained in:
		@ -56,6 +56,8 @@ struct mio_svc_dnc_t
 | 
			
		||||
	 * regardless of max_tries. */ 
 | 
			
		||||
	mio_oow_t max_tries; 
 | 
			
		||||
 | 
			
		||||
	mio_dns_cookie_t cookie;
 | 
			
		||||
 | 
			
		||||
	mio_oow_t seq;
 | 
			
		||||
	mio_dns_msg_t* pending_req;
 | 
			
		||||
};
 | 
			
		||||
@ -843,6 +845,7 @@ struct dnc_dns_msg_resolve_xtn_t
 | 
			
		||||
{
 | 
			
		||||
	mio_dns_rrt_t qtype;
 | 
			
		||||
	int flags;
 | 
			
		||||
	mio_uint8_t client_cookie[MIO_DNS_COOKIE_CLIENT_LEN];
 | 
			
		||||
	mio_svc_dnc_on_resolve_t on_resolve;
 | 
			
		||||
};
 | 
			
		||||
typedef struct dnc_dns_msg_resolve_xtn_t dnc_dns_msg_resolve_xtn_t;
 | 
			
		||||
@ -857,14 +860,7 @@ static void on_dnc_resolve (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnu
 | 
			
		||||
{
 | 
			
		||||
	mio_t* mio = mio_svc_dnc_getmio(dnc);
 | 
			
		||||
	mio_dns_pkt_info_t* pi = MIO_NULL;
 | 
			
		||||
	dnc_dns_msg_resolve_xtn_t* reqmsgxtn = dnc_dns_msg_resolve_getxtn(reqmsg);
 | 
			
		||||
 | 
			
		||||
	if (!(reqmsgxtn->flags & MIO_SVC_DNC_RESOLVE_FLAG_BRIEF))
 | 
			
		||||
	{
 | 
			
		||||
		/* the full reply packet is requested. no transformation is required */
 | 
			
		||||
		if (reqmsgxtn->on_resolve) reqmsgxtn->on_resolve (dnc, reqmsg, status, data, dlen);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	dnc_dns_msg_resolve_xtn_t* resolxtn = dnc_dns_msg_resolve_getxtn(reqmsg);
 | 
			
		||||
 | 
			
		||||
	if (data)
 | 
			
		||||
	{
 | 
			
		||||
@ -879,12 +875,46 @@ static void on_dnc_resolve (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnu
 | 
			
		||||
			goto no_data;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
if (pi->hdr.code == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
{
 | 
			
		||||
// retry with server cookie received....
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
		if (resolxtn->flags & MIO_SVC_DNC_RESOLVE_FLAG_COOKIE)
 | 
			
		||||
		{
 | 
			
		||||
			/* ------------------------------------------------- */
 | 
			
		||||
			if (pi->edns.cookie.client_len > 0)
 | 
			
		||||
			{
 | 
			
		||||
				if (MIO_MEMCMP(resolxtn->client_cookie, pi->edns.cookie.data.client, pi->edns.cookie.client_len) == 0)
 | 
			
		||||
				{
 | 
			
		||||
					pi->edns.cookie_verified = 1; /*  UGLY to set data in mio_dns_pkt_info_t */
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (pi->edns.cookie.server_len > 0)
 | 
			
		||||
			{
 | 
			
		||||
				MIO_MEMCPY (dnc->cookie.data.server, pi->edns.cookie.data.server, pi->edns.cookie.server_len);
 | 
			
		||||
				dnc->cookie.server_len = pi->edns.cookie.server_len;
 | 
			
		||||
			}
 | 
			
		||||
	
 | 
			
		||||
				
 | 
			
		||||
#if 0
 | 
			
		||||
			if (pi->hdr.rcode == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
			{
 | 
			
		||||
				/* TODO: retry it */
 | 
			
		||||
#if 0
 | 
			
		||||
				if (mio_svc_dnc_resolve(dnc, qname, resolxtn->qtype, resolxtn->flags, on_dnc_resolve, resolxtn->xtnsize) <= -1)
 | 
			
		||||
				{
 | 
			
		||||
				}
 | 
			
		||||
#endif
 | 
			
		||||
				/*how to retry?*/
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
			/* ------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!(resolxtn->flags & MIO_SVC_DNC_RESOLVE_FLAG_BRIEF))
 | 
			
		||||
		{
 | 
			
		||||
			/* the full reply packet is requested. */
 | 
			
		||||
			if (resolxtn->on_resolve) resolxtn->on_resolve (dnc, reqmsg, status, pi, 0);
 | 
			
		||||
			goto done;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (pi->hdr.rcode != MIO_DNS_RCODE_NOERROR) 
 | 
			
		||||
		{
 | 
			
		||||
@ -895,7 +925,7 @@ if (pi->hdr.code == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
		if (pi->ancount < 0) goto no_data;
 | 
			
		||||
 | 
			
		||||
		/* in the brief mode, we inspect the answer section only */
 | 
			
		||||
		if (reqmsgxtn->qtype == MIO_DNS_RRT_Q_ANY)
 | 
			
		||||
		if (resolxtn->qtype == MIO_DNS_RRT_Q_ANY)
 | 
			
		||||
		{
 | 
			
		||||
			/* return A or AAAA for ANY in the brief mode */
 | 
			
		||||
			for (i = 0; i < pi->ancount; i++)
 | 
			
		||||
@ -903,7 +933,7 @@ if (pi->hdr.code == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
				if (pi->rr.an[i].rrtype == MIO_DNS_RRT_A || pi->rr.an[i].rrtype == MIO_DNS_RRT_AAAA)
 | 
			
		||||
				{
 | 
			
		||||
				match_found:
 | 
			
		||||
					if (reqmsgxtn->on_resolve) reqmsgxtn->on_resolve (dnc, reqmsg, status, &pi->rr.an[i], MIO_SIZEOF(pi->rr.an[i]));
 | 
			
		||||
					if (resolxtn->on_resolve) resolxtn->on_resolve (dnc, reqmsg, status, &pi->rr.an[i], MIO_SIZEOF(pi->rr.an[i]));
 | 
			
		||||
					goto done;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@ -914,7 +944,7 @@ if (pi->hdr.code == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
			/* 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. */
 | 
			
		||||
			switch (reqmsgxtn->qtype)
 | 
			
		||||
			switch (resolxtn->qtype)
 | 
			
		||||
			{
 | 
			
		||||
				case MIO_DNS_RRT_Q_ANY: 
 | 
			
		||||
				case MIO_DNS_RRT_Q_AFXR: /* AFXR doesn't make sense in the brief mode. just treat it like ANY */
 | 
			
		||||
@ -933,7 +963,7 @@ if (pi->hdr.code == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				default:
 | 
			
		||||
					if (pi->rr.an[i].rrtype == reqmsgxtn->qtype) goto match_found;
 | 
			
		||||
					if (pi->rr.an[i].rrtype == resolxtn->qtype) goto match_found;
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@ -942,7 +972,7 @@ if (pi->hdr.code == MIO_DNS_RCODE_BADCOOKIE)
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	no_data:
 | 
			
		||||
		if (reqmsgxtn->on_resolve) reqmsgxtn->on_resolve (dnc, reqmsg, status, MIO_NULL, 0);
 | 
			
		||||
		if (resolxtn->on_resolve) resolxtn->on_resolve (dnc, reqmsg, status, MIO_NULL, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
@ -988,10 +1018,10 @@ mio_dns_msg_t* mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname,
 | 
			
		||||
 | 
			
		||||
	if (resolve_flags & MIO_SVC_DNC_RESOLVE_FLAG_COOKIE)
 | 
			
		||||
	{
 | 
			
		||||
		static mio_uint8_t dummy[48];
 | 
			
		||||
		beopt_cookie.code = MIO_DNS_EOPT_COOKIE;
 | 
			
		||||
		beopt_cookie.dlen = MIO_COUNTOF(dummy);
 | 
			
		||||
		beopt_cookie.dptr = dummy;
 | 
			
		||||
		beopt_cookie.dlen = MIO_DNS_COOKIE_CLIENT_LEN; 
 | 
			
		||||
		if (dnc->cookie.server_len > 0) beopt_cookie.dlen += dnc->cookie.server_len;
 | 
			
		||||
		beopt_cookie.dptr = &dnc->cookie.data;
 | 
			
		||||
 | 
			
		||||
		qedns.beonum = 1;
 | 
			
		||||
		qedns.beoptr = &beopt_cookie;
 | 
			
		||||
@ -1002,9 +1032,12 @@ mio_dns_msg_t* mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname,
 | 
			
		||||
	{
 | 
			
		||||
		int send_flags;
 | 
			
		||||
 | 
			
		||||
		if (resolve_flags & MIO_SVC_DNC_RESOLVE_FLAG_COOKIE)
 | 
			
		||||
#if 0
 | 
			
		||||
		if ((resolve_flags & MIO_SVC_DNC_RESOLVE_FLAG_COOKIE) && dnc->cookie.server_len == 0)
 | 
			
		||||
		{
 | 
			
		||||
			/* ASSUMPTIONS:
 | 
			
		||||
			/* Exclude the server cookie from the packet when the server cookie is not available.
 | 
			
		||||
			 *
 | 
			
		||||
			 * ASSUMPTIONS:
 | 
			
		||||
			 *  the eopt entries are at the back of the packet.
 | 
			
		||||
			 *  only 1 eopt entry(MIO_DNS_EOPT_COOKIE) has been added. 
 | 
			
		||||
			 * 
 | 
			
		||||
@ -1014,25 +1047,25 @@ mio_dns_msg_t* mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname,
 | 
			
		||||
			mio_dns_rrtr_t* edns_rrtr;
 | 
			
		||||
			mio_dns_eopt_t* eopt;
 | 
			
		||||
 | 
			
		||||
/* TODO: generate the client cookie and copy it */
 | 
			
		||||
/* if the server cookie is available, copy it to the packet. but the server cookike may still be shorter than 40. so some manipulation is still needed
 | 
			
		||||
 * if not, manipualte the length like below */
 | 
			
		||||
			edns_rrtr = (mio_dns_rrtr_t*)((mio_uint8_t*)mio_dns_msg_to_pkt(reqmsg) + reqmsg->ednsrrtroff);
 | 
			
		||||
			reqmsg->pktlen -= 40; /* maximum server cookie space */
 | 
			
		||||
			reqmsg->pktlen -= MIO_DNS_COOKIE_SERVER_MAX_LEN;
 | 
			
		||||
 | 
			
		||||
			MIO_ASSERT (dnc->mio, edns_rrtr->rrtype == MIO_CONST_HTON16(MIO_DNS_RRT_OPT));
 | 
			
		||||
			MIO_ASSERT (dnc->mio, edns_rrtr->dlen == MIO_CONST_HTON16(52));
 | 
			
		||||
			MIO_ASSERT (dnc->mio, edns_rrtr->dlen == MIO_CONST_HTON16(MIO_SIZEOF(mio_dns_eopt_t) + MIO_DNS_COOKIE_MAX_LEN));
 | 
			
		||||
			edns_rrtr->dlen = MIO_CONST_HTON16(MIO_SIZEOF(mio_dns_eopt_t) + MIO_DNS_COOKIE_CLIENT_LEN);
 | 
			
		||||
 | 
			
		||||
			edns_rrtr->dlen = MIO_CONST_HTON16(12);
 | 
			
		||||
			eopt = (mio_dns_eopt_t*)(edns_rrtr + 1);
 | 
			
		||||
			MIO_ASSERT (dnc->mio, eopt->dlen == MIO_CONST_HTON16(48));
 | 
			
		||||
			eopt->dlen = MIO_CONST_HTON16(8);
 | 
			
		||||
			MIO_ASSERT (dnc->mio, eopt->dlen == MIO_CONST_HTON16(MIO_DNS_COOKIE_MAX_LEN));
 | 
			
		||||
			eopt->dlen = MIO_CONST_HTON16(MIO_DNS_COOKIE_CLIENT_LEN);
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		resolxtn = dnc_dns_msg_resolve_getxtn(reqmsg);
 | 
			
		||||
		resolxtn->on_resolve = on_resolve;
 | 
			
		||||
		resolxtn->qtype = qtype;
 | 
			
		||||
		resolxtn->flags = resolve_flags;
 | 
			
		||||
		/* store in the extension area the client cookie set in the packet */
 | 
			
		||||
		MIO_MEMCPY (resolxtn->client_cookie, dnc->cookie.data.client, MIO_DNS_COOKIE_CLIENT_LEN);
 | 
			
		||||
 | 
			
		||||
		send_flags = (resolve_flags & MIO_SVC_DNC_SEND_FLAG_ALL);
 | 
			
		||||
		if (MIO_UNLIKELY(qtype == MIO_DNS_RRT_Q_AFXR)) send_flags |= MIO_SVC_DNC_SEND_FLAG_PREFER_TCP;
 | 
			
		||||
 | 
			
		||||
@ -277,7 +277,9 @@ static int parse_answer_rr (mio_t* mio, mio_dns_rr_part_t rr_part, mio_oow_t pos
 | 
			
		||||
			*/
 | 
			
		||||
 | 
			
		||||
			/* TODO: do i need to check if rrname is <ROOT>? */
 | 
			
		||||
			pi->edns.exist = 1;
 | 
			
		||||
			/* TODO: do i need to check if rr_part  is MIO_DNS_RR_PART_ADDITIONAL? the OPT pseudo-RR may exist in the ADDITIONAL section only */
 | 
			
		||||
			/* 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 */
 | 
			
		||||
			pi->edns.uplen = mio_ntoh16(rrtr->rrclass);
 | 
			
		||||
			pi->hdr.rcode |= (rrtr->ttl >> 24);
 | 
			
		||||
			pi->edns.version = (rrtr->ttl >> 16) & 0xFF;
 | 
			
		||||
@ -295,8 +297,26 @@ static int parse_answer_rr (mio_t* mio, mio_dns_rr_part_t rr_part, mio_oow_t pos
 | 
			
		||||
 | 
			
		||||
				if (eopt->code == MIO_CONST_HTON16(MIO_DNS_EOPT_COOKIE))
 | 
			
		||||
				{
 | 
			
		||||
					if (eopt_len < 8) goto oops; /* the client cookie must be 8 bytes */
 | 
			
		||||
					/* TODO: dns cookies */
 | 
			
		||||
					if (eopt_len == MIO_DNS_COOKIE_CLIENT_LEN)
 | 
			
		||||
					{
 | 
			
		||||
						/* client cookie only */
 | 
			
		||||
						MIO_MEMCPY (pi->edns.cookie.data.client, eopt + 1, eopt_len);
 | 
			
		||||
						pi->edns.cookie.client_len = eopt_len;
 | 
			
		||||
						pi->edns.cookie.server_len = 0;
 | 
			
		||||
					}
 | 
			
		||||
					else if (eopt_len >= (MIO_DNS_COOKIE_CLIENT_LEN + MIO_DNS_COOKIE_SERVER_MIN_LEN) &&
 | 
			
		||||
					         eopt_len <= (MIO_DNS_COOKIE_CLIENT_LEN + MIO_DNS_COOKIE_SERVER_MAX_LEN))
 | 
			
		||||
					{
 | 
			
		||||
						/* both client and server cookie */
 | 
			
		||||
						MIO_MEMCPY (&pi->edns.cookie.data, eopt + 1, eopt_len);
 | 
			
		||||
						pi->edns.cookie.client_len = MIO_DNS_COOKIE_CLIENT_LEN;
 | 
			
		||||
						pi->edns.cookie.server_len = eopt_len - MIO_DNS_COOKIE_CLIENT_LEN;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						/* wrong cookie length */
 | 
			
		||||
						goto oops;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				eopt_tot_len -= MIO_SIZEOF(mio_dns_eopt_t) + eopt_len;
 | 
			
		||||
 | 
			
		||||
@ -414,6 +414,29 @@ typedef enum mio_svc_dnc_resolve_flag_t  mio_svc_dnc_resolve_flag_t;
 | 
			
		||||
 | 
			
		||||
/* ---------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
#define MIO_DNS_COOKIE_CLIENT_LEN (8)
 | 
			
		||||
#define MIO_DNS_COOKIE_SERVER_MIN_LEN (16)
 | 
			
		||||
#define MIO_DNS_COOKIE_SERVER_MAX_LEN (40)
 | 
			
		||||
#define MIO_DNS_COOKIE_MAX_LEN (MIO_DNS_COOKIE_CLIENT_LEN + MIO_DNS_COOKIE_SERVER_MAX_LEN)
 | 
			
		||||
 | 
			
		||||
typedef struct mio_dns_cookie_data_t mio_dns_cookie_data_t;
 | 
			
		||||
#include <mio-pac1.h>
 | 
			
		||||
struct mio_dns_cookie_data_t
 | 
			
		||||
{
 | 
			
		||||
	mio_uint8_t client[MIO_DNS_COOKIE_CLIENT_LEN];
 | 
			
		||||
	mio_uint8_t server[MIO_DNS_COOKIE_SERVER_MAX_LEN];
 | 
			
		||||
};
 | 
			
		||||
#include <mio-upac.h>
 | 
			
		||||
 | 
			
		||||
typedef struct mio_dns_cookie_t mio_dns_cookie_t;
 | 
			
		||||
struct mio_dns_cookie_t
 | 
			
		||||
{
 | 
			
		||||
	mio_dns_cookie_data_t data;
 | 
			
		||||
	mio_uint8_t client_len;
 | 
			
		||||
	mio_uint8_t server_len;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ---------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
struct mio_dns_pkt_info_t
 | 
			
		||||
{
 | 
			
		||||
@ -433,6 +456,8 @@ struct mio_dns_pkt_info_t
 | 
			
		||||
		mio_uint16_t uplen; /* udp payload len - will be placed in the qclass field of RR. */
 | 
			
		||||
		mio_uint8_t  version; 
 | 
			
		||||
		mio_uint8_t  dnssecok;
 | 
			
		||||
		mio_dns_cookie_t cookie;
 | 
			
		||||
		int cookie_verified; /* UGLY: set via mio_svc_dnc_resolve() only. mio_dns_make_packet_info() doesn't set this */
 | 
			
		||||
	} edns;
 | 
			
		||||
 | 
			
		||||
	mio_uint16_t qdcount; /* number of questions */
 | 
			
		||||
@ -447,6 +472,7 @@ struct mio_dns_pkt_info_t
 | 
			
		||||
		mio_dns_brr_t* ns;
 | 
			
		||||
		mio_dns_brr_t* ar;
 | 
			
		||||
	} rr;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
typedef struct mio_dns_pkt_info_t mio_dns_pkt_info_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user