diff --git a/mio/bin/t01.c b/mio/bin/t01.c index 058e5f9..c89db2c 100644 --- a/mio/bin/t01.c +++ b/mio/bin/t01.c @@ -705,16 +705,20 @@ static void on_dnc_resolve(mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnum printf (">>>>>>>> RRDLEN = %d\n", (int)pi->_rrdlen); - printf (">>>>>>>> RCODE %d EDNS exist %d uplen %d version %d dnssecok %d\n", pi->hdr.rcode, pi->edns.exist, pi->edns.uplen, pi->edns.version, pi->edns.dnssecok); + printf (">>>>>>>> RCODE %s(%d) EDNS exist %d uplen %d version %d dnssecok %d\n", mio_dns_rcode_to_bcstr(pi->hdr.rcode), pi->hdr.rcode, pi->edns.exist, pi->edns.uplen, pi->edns.version, pi->edns.dnssecok); if (pi->hdr.rcode == MIO_DNS_RCODE_BADCOOKIE) { - /* TODO: must retry */ + /* TODO: must retry?? there shoudl be no RRs in the payload */ } - if (pi->edns.cookie.client_len > 0 && !pi->edns.cookie_verified) /* TODO: do i need to check if cookie.server_len > 0? */ + if (mio_svc_dnc_checkclientcookie(dnc, reqmsg, pi) == 0) { /* client cookie is bad.. */ - printf ("CLIENT COOKIE IS BAD>>>>>>>>>>>>>>>>>>>\n"); + printf ("CLIENT COOKIE IS BAD>>>>>>>>>>>>>>>>>>>%d\n", mio_svc_dnc_checkclientcookie(dnc, reqmsg, pi)); + } + else + { + printf ("CLIENT COOKIE IS OK>>>>>>>>>>>>>>>>>>>%d\n", mio_svc_dnc_checkclientcookie(dnc, reqmsg, pi)); } //if (pi->hdr.rcode != MIO_DNS_RCODE_NOERROR) goto no_data; @@ -1003,6 +1007,11 @@ static void send_test_query (mio_t* mio, const mio_ntime_t* now, mio_tmrjob_t* j { printf ("resolve attempt failure ---> mailserver.manyhost.net\n"); } + + if (!mio_svc_dnc_resolve((mio_svc_dnc_t*)job->ctx, "ns2.switch.ch", MIO_DNS_RRT_A, MIO_SVC_DNC_RESOLVE_FLAG_COOKIE, on_dnc_resolve, 0)) + { + printf ("resolve attempt failure ---> ns2.switch.ch\n"); + } } int main (int argc, char* argv[]) @@ -1218,8 +1227,8 @@ for (i = 0; i < 5; i++) reply_tmout.nsec = 0; //mio_bcstrtoskad (mio, "8.8.8.8:53", &servaddr); - //mio_bcstrtoskad (mio, "130.59.31.29:53", &servaddr); // ns2.switch.ch - mio_bcstrtoskad (mio, "134.119.216.86:53", &servaddr); // ns.manyhost.net + mio_bcstrtoskad (mio, "130.59.31.29:53", &servaddr); // ns2.switch.ch + //mio_bcstrtoskad (mio, "134.119.216.86:53", &servaddr); // ns.manyhost.net //mio_bcstrtoskad (mio, "[fe80::c7e2:bd6e:1209:ac1b]:1153", &servaddr); //mio_bcstrtoskad (mio, "[fe80::c7e2:bd6e:1209:ac1b%eno1]:1153", &servaddr); @@ -1332,6 +1341,11 @@ for (i = 0; i < 5; i++) { printf ("resolve attempt failure ---> www.microsoft.com\n"); } + + if (!mio_svc_dnc_resolve(dnc, "ns2.switch.ch", MIO_DNS_RRT_CNAME, MIO_SVC_DNC_RESOLVE_FLAG_COOKIE, on_dnc_resolve, 0)) + { + printf ("resolve attempt failure ---> ns2.switch.ch\n"); + } //if (!mio_svc_dnc_resolve(dnc, "www.microsoft.com", MIO_DNS_RRT_A, MIO_SVC_DNC_RESOLVE_FLAG_BRIEF, on_dnc_resolve_brief, 0)) diff --git a/mio/lib/dns-cli.c b/mio/lib/dns-cli.c index 0acd612..c2f2db4 100644 --- a/mio/lib/dns-cli.c +++ b/mio/lib/dns-cli.c @@ -875,7 +875,7 @@ static void on_dnc_resolve (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnu MIO_ASSERT (mio, status == MIO_ENOERR); - pi = mio_dns_make_packet_info(mio, data, dlen); + pi = mio_dns_make_pkt_info(mio, data, dlen); if (!pi) { status = mio_geterrnum(mio); @@ -885,21 +885,13 @@ static void on_dnc_resolve (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnu 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) { + /* remember the server cookie received to use it with other new requests */ 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) { @@ -983,7 +975,7 @@ static void on_dnc_resolve (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnu } done: - if (pi) mio_dns_free_packet_info(mio_svc_dnc_getmio(dnc), pi); + if (pi) mio_dns_free_pkt_info(mio_svc_dnc_getmio(dnc), pi); } mio_dns_msg_t* mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname, mio_dns_rrt_t qtype, int resolve_flags, mio_svc_dnc_on_resolve_t on_resolve, mio_oow_t xtnsize) @@ -1091,6 +1083,29 @@ mio_dns_msg_t* mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname, return reqmsg; } +int mio_svc_dnc_checkclientcookie (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_dns_pkt_info_t* respi) +{ + mio_uint8_t xb[MIO_DNS_COOKIE_CLIENT_LEN]; + mio_uint8_t* x; + + x = mio_dns_find_client_cookie_in_msg(reqmsg, &xb); + if (x) + { + /* there is a client cookie in the request. */ + if (respi->edns.cookie.client_len > 0) + { + MIO_ASSERT (dnc->mio, respi->edns.cookie.client_len == MIO_DNS_COOKIE_CLIENT_LEN); + return MIO_MEMCMP(x, respi->edns.cookie.data.client, MIO_DNS_COOKIE_CLIENT_LEN) == 0; /* 1 if ok, 0 if not */ + } + 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 */ +} /* 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 */ diff --git a/mio/lib/dns.c b/mio/lib/dns.c index ead3132..ba51d58 100644 --- a/mio/lib/dns.c +++ b/mio/lib/dns.c @@ -463,7 +463,7 @@ oops: return -1; } -mio_dns_pkt_info_t* mio_dns_make_packet_info (mio_t* mio, const mio_dns_pkt_t* pkt, mio_oow_t len) +mio_dns_pkt_info_t* mio_dns_make_pkt_info (mio_t* mio, const mio_dns_pkt_t* pkt, mio_oow_t len) { mio_uint16_t i; mio_dns_pkt_info_t pib, * pii; @@ -544,7 +544,7 @@ oops: return MIO_NULL; } -void mio_dns_free_packet_info (mio_t* mio, mio_dns_pkt_info_t* pi) +void mio_dns_free_pkt_info (mio_t* mio, mio_dns_pkt_info_t* pi) { /* TODO: better management */ mio_freemem (mio, pi); @@ -874,3 +874,71 @@ void mio_dns_free_msg (mio_t* mio, mio_dns_msg_t* msg) /* TODO: better management */ mio_freemem (mio, msg); } + +mio_uint8_t* mio_dns_find_client_cookie_in_msg (mio_dns_msg_t* reqmsg, mio_uint8_t (*cookie)[MIO_DNS_COOKIE_CLIENT_LEN]) +{ + mio_dns_rrtr_t* edns_rrtr; + mio_dns_eopt_t* eopt; + mio_uint16_t rem, dlen; + + /* this function doesn't check malformed packet assuming + * reqmsg points to the packet message created with mio_dns_make_msg(). + * such a packet message must be well-formed */ + if (reqmsg->ednsrrtroff <= 0) return MIO_NULL; /* doesn't exist */ + + edns_rrtr = (mio_dns_rrtr_t*)((mio_uint8_t*)mio_dns_msg_to_pkt(reqmsg) + reqmsg->ednsrrtroff); + rem = mio_ntoh16(edns_rrtr->dlen); + + eopt = (mio_dns_eopt_t*)(edns_rrtr + 1); + while (rem >= MIO_SIZEOF(mio_dns_eopt_t)) + { + dlen = mio_ntoh16(eopt->dlen); + if (eopt->code == MIO_CONST_HTON16(MIO_DNS_EOPT_COOKIE)) + { + if (cookie) MIO_MEMCPY (cookie, eopt + 1, MIO_DNS_COOKIE_CLIENT_LEN); + return (mio_uint8_t*)(eopt + 1); + } + + rem -= dlen; + eopt = (mio_dns_eopt_t*)((mio_uint8_t*)(eopt + 1) + dlen); + } + + return MIO_NULL; +} + + +mio_bch_t* mio_dns_rcode_to_bcstr (mio_dns_rcode_t rcode) +{ + mio_bch_t* _errmsg[] = + { + "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" + }; + + return rcode < MIO_COUNTOF(_errmsg)? _errmsg[rcode]: "UNKNOWNERR"; +} diff --git a/mio/lib/mio-dns.h b/mio/lib/mio-dns.h index 9fd7757..786b0c8 100644 --- a/mio/lib/mio-dns.h +++ b/mio/lib/mio-dns.h @@ -458,7 +458,6 @@ struct mio_dns_pkt_info_t 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 */ @@ -540,15 +539,27 @@ MIO_EXPORT mio_dns_msg_t* mio_svc_dnc_resolve ( mio_oow_t xtnsize ); +/* + * -1: cookie in the request but no client cookie in the response. this may be ok or not ok depending on your policy + * 0: client cookie mismatch in the request in the response + * 1: client cookie match in the request in the response + * 2: no client cookie in the requset. so it deson't case about the response + */ +MIO_EXPORT int mio_svc_dnc_checkclientcookie ( + mio_svc_dnc_t* dnc, + mio_dns_msg_t* reqmsg, + mio_dns_pkt_info_t* respi +); + /* ---------------------------------------------------------------- */ -MIO_EXPORT mio_dns_pkt_info_t* mio_dns_make_packet_info ( +MIO_EXPORT mio_dns_pkt_info_t* mio_dns_make_pkt_info ( mio_t* mio, const mio_dns_pkt_t* pkt, mio_oow_t len ); -MIO_EXPORT void mio_dns_free_packet_info ( +MIO_EXPORT void mio_dns_free_pkt_info ( mio_t* mio, mio_dns_pkt_info_t* pi ); @@ -577,6 +588,18 @@ MIO_EXPORT void mio_dns_free_msg ( mio_dns_msg_t* msg ); +/* + * return the pointer to the client cookie data in the packet. + * if cookie is not MIO_NULL, it copies the client cookie there. + */ +MIO_EXPORT mio_uint8_t* mio_dns_find_client_cookie_in_msg ( + mio_dns_msg_t* reqmsg, + mio_uint8_t (*cookie)[MIO_DNS_COOKIE_CLIENT_LEN] +); + +MIO_EXPORT mio_bch_t* mio_dns_rcode_to_bcstr ( + mio_dns_rcode_t rcode +); #if defined(__cplusplus) }