diff --git a/mio/bin/t01.c b/mio/bin/t01.c index 25cdc06..3a598d5 100644 --- a/mio/bin/t01.c +++ b/mio/bin/t01.c @@ -606,19 +606,37 @@ static int setup_ping4_tester (mio_t* mio) static void on_dnc_resolve(mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio_errnum_t status, const void* data, mio_oow_t dlen) { + mio_dns_pkt_info_t* pi = MIO_NULL; + if (status == MIO_ENOERR) { + mio_uint32_t i; + printf ("XXXXXXXXXXXXXXXXx RECEIVED XXXXXXXXXXXXXXXXXXXXXXXXX\n"); + pi = mio_dns_make_packet_info(mio_svc_dnc_getmio(dnc), data, dlen); + if (!pi) goto no_valid_reply; - //mio_dns_parse_packet (dnc, mio_dns_msg_to_pkt(reqmsg), - mio_dns_bdns_t bdns; - mio_dns_parse_packet (dnc, data, dlen, &bdns); + if (pi->hdr.rcode != MIO_DNS_RCODE_NOERROR) goto no_valid_reply; + if (pi->ancount < 0) goto no_valid_reply; + for (i = 0; i < pi->ancount; i++) + { + if (pi->rr.an[i].rrtype == MIO_DNS_RRT_A) + { + printf ("GOT THE RIGHT ANSSER .... \n"); + goto done; + } + } + goto no_valid_reply; } else { + no_valid_reply: printf ("XXXXXXXXXXXXXXXXx NO REPLY XXXXXXXXXXXXXXXXXXXXXXXXX\n"); } + +done: + if (pi) mio_dns_free_packet_info(mio_svc_dnc_getmio(dnc), pi); } /* ========================================================================= */ @@ -839,18 +857,18 @@ for (i = 0; i < 5; i++) { mio_dns_bqr_t qrs[] = { - { "code.miflux.com", MIO_DNS_QTYPE_A, MIO_DNS_QCLASS_IN }, - { "code.miflux.com", MIO_DNS_QTYPE_AAAA, MIO_DNS_QCLASS_IN }, - { "code.abiyo.net", MIO_DNS_QTYPE_A, MIO_DNS_QCLASS_IN }, - { "code6.abiyo.net", MIO_DNS_QTYPE_AAAA, MIO_DNS_QCLASS_IN }, - { "abiyo.net", MIO_DNS_QTYPE_MX, MIO_DNS_QCLASS_IN } + { "code.miflux.com", MIO_DNS_RRT_A, MIO_DNS_RRC_IN }, + { "code.miflux.com", MIO_DNS_RRT_AAAA, MIO_DNS_RRC_IN }, + { "code.abiyo.net", MIO_DNS_RRT_A, MIO_DNS_RRC_IN }, + { "code6.abiyo.net", MIO_DNS_RRT_AAAA, MIO_DNS_RRC_IN }, + { "abiyo.net", MIO_DNS_RRT_MX, MIO_DNS_RRC_IN } }; mio_dns_brr_t rrs[] = { - { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_QTYPE_A, MIO_DNS_QCLASS_IN, 86400, 0, MIO_NULL }, - { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_QTYPE_AAAA, MIO_DNS_QCLASS_IN, 86400, 0, MIO_NULL }, - { MIO_DNS_RR_PART_AUTHORITY, "dns.miflux.com", MIO_DNS_QTYPE_NS, MIO_DNS_QCLASS_IN, 86400, 0, MIO_NULL }//, - //{ MIO_DNS_RR_PART_ANSERT, "www.miflux.com", MIO_DNS_QTYPE_CNAME, MIO_DNS_QCLASS_IN, 60, 15, "code.miflux.com" } + { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_RRT_A, MIO_DNS_RRC_IN, 86400, 0, MIO_NULL }, + { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_RRT_AAAA, MIO_DNS_RRC_IN, 86400, 0, MIO_NULL }, + { MIO_DNS_RR_PART_AUTHORITY, "dns.miflux.com", MIO_DNS_RRT_NS, MIO_DNS_RRC_IN, 86400, 0, MIO_NULL }//, + //{ MIO_DNS_RR_PART_ANSERT, "www.miflux.com", MIO_DNS_RRT_CNAME, MIO_DNS_RRC_IN, 60, 15, "code.miflux.com" } }; mio_dns_beopt_t beopt[] = @@ -870,7 +888,7 @@ for (i = 0; i < 5; i++) beopt }; - mio_dns_bdns_t qhdr = + mio_dns_bhdr_t qhdr = { -1, /* id */ 0, /* qr */ @@ -884,7 +902,7 @@ for (i = 0; i < 5; i++) MIO_DNS_RCODE_NOERROR /* rcode */ }; - mio_dns_bdns_t rhdr = + mio_dns_bhdr_t rhdr = { 0x1234, /* id */ 1, /* qr */ @@ -903,7 +921,7 @@ for (i = 0; i < 5; i++) mio_svc_dnc_sendmsg (dnc, &rhdr, qrs, MIO_COUNTOF(qrs), rrs, MIO_COUNTOF(rrs), &qedns, MIO_NULL); } -if (mio_svc_dnc_resolve(dnc, "www.microsoft.com", MIO_DNS_QTYPE_A, on_dnc_resolve) <= -1) +if (mio_svc_dnc_resolve(dnc, "www.microsoft.com", MIO_DNS_RRT_A, on_dnc_resolve) <= -1) { printf ("resolve attempt failure ---> code.miflux.com\n"); } diff --git a/mio/lib/dns.c b/mio/lib/dns.c index 5782912..d61aa54 100644 --- a/mio/lib/dns.c +++ b/mio/lib/dns.c @@ -153,51 +153,51 @@ MIO_DEBUG1 (mio, "releasing dns msg %d\n", (int)mio_ntoh16(dns_msg_to_pkt(msg)-> static mio_oow_t encode_rdata_in_dns_msg (mio_svc_dnc_t* dnc, const mio_dns_brr_t* rr, mio_dns_rrtr_t* rrtr) { - switch (rr->qtype) + switch (rr->rrtype) { - case MIO_DNS_QTYPE_A: + case MIO_DNS_RRT_A: break; - case MIO_DNS_QTYPE_AAAA: + case MIO_DNS_RRT_AAAA: break; /* - case MIO_DNS_QTYPE_WKS: + case MIO_DNS_RRT_WKS: break; */ - case MIO_DNS_QTYPE_MX: + case MIO_DNS_RRT_MX: /* preference, exchange */ break; - case MIO_DNS_QTYPE_CNAME: - /*case MIO_DNS_QTYPE_MB: - case MIO_DNS_QTYPE_MD: - case MIO_DNS_QTYPE_MF: - case MIO_DNS_QTYPE_MG: - case MIO_DNS_QTYPE_MR:*/ - case MIO_DNS_QTYPE_NS: - case MIO_DNS_QTYPE_PTR: + case MIO_DNS_RRT_CNAME: + /*case MIO_DNS_RRT_MB: + case MIO_DNS_RRT_MD: + case MIO_DNS_RRT_MF: + case MIO_DNS_RRT_MG: + case MIO_DNS_RRT_MR:*/ + case MIO_DNS_RRT_NS: + case MIO_DNS_RRT_PTR: /* just a normal domain name */ break; #if 0 - case MIO_DNS_QTYPE_HINFO: + case MIO_DNS_RRT_HINFO: /* cpu, os */ break; #endif #if 0 - case MIO_DNS_QTYPE_MINFO: + case MIO_DNS_RRT_MINFO: /* rmailbx, emailbx */ #endif break; - case MIO_DNS_QTYPE_SOA: + case MIO_DNS_RRT_SOA: /* soa */ break; - case MIO_DNS_QTYPE_TXT: - case MIO_DNS_QTYPE_NULL: + case MIO_DNS_RRT_TXT: + case MIO_DNS_RRT_NULL: default: /* TODO: custom transformator? */ rrtr->dlen = mio_hton16(rr->dlen); @@ -207,7 +207,7 @@ static mio_oow_t encode_rdata_in_dns_msg (mio_svc_dnc_t* dnc, const mio_dns_brr_ return rr->dlen; } -static mio_dns_msg_t* build_dns_msg (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, void* ctx) +static mio_dns_msg_t* build_dns_msg (mio_svc_dnc_t* dnc, mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, void* ctx) { mio_t* mio = dnc->mio; mio_oow_t dnlen, msgbufsz, i; @@ -231,7 +231,7 @@ static mio_dns_msg_t* build_dns_msg (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, m for (i = 0; i < rr_count; i++) { - msgbufsz += mio_count_bcstr(rr[i].qname) + 2 + MIO_SIZEOF(*rrtr) + rr[i].dlen; + msgbufsz += mio_count_bcstr(rr[i].rrname) + 2 + MIO_SIZEOF(*rrtr) + rr[i].dlen; } edns_dlen = 0; @@ -305,17 +305,17 @@ static mio_dns_msg_t* build_dns_msg (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, m { mio_oow_t rdata_len; - dnlen = to_dn((mio_svc_dns_t*)dnc, rr[i].qname, dn, mio_count_bcstr(rr[i].qname) + 2); + dnlen = to_dn((mio_svc_dns_t*)dnc, rr[i].rrname, dn, mio_count_bcstr(rr[i].rrname) + 2); if (dnlen <= 0) { release_dns_msg (dnc, msg); - mio_seterrbfmt (mio, MIO_EINVAL, "invalid domain name - %hs", rr[i].qname); + mio_seterrbfmt (mio, MIO_EINVAL, "invalid domain name - %hs", rr[i].rrname); return MIO_NULL; } rrtr = (mio_dns_rrtr_t*)(dn + dnlen); - rrtr->qtype = mio_hton16(rr[i].qtype); - rrtr->qclass = mio_hton16(rr[i].qclass); + rrtr->rrtype = mio_hton16(rr[i].rrtype); + rrtr->rrclass = mio_hton16(rr[i].rrclass); rrtr->ttl = mio_hton32(rr[i].ttl); rdata_len = encode_rdata_in_dns_msg(dnc, &rr[i], rrtr); @@ -337,8 +337,8 @@ static mio_dns_msg_t* build_dns_msg (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, m /* add EDNS0 OPT RR */ *dn = 0; /* root domain. as if to_dn("") is called */ rrtr = (mio_dns_rrtr_t*)(dn + 1); - rrtr->qtype = MIO_CONST_HTON16(MIO_DNS_QTYPE_OPT); - rrtr->qclass = mio_hton16(edns->uplen); + rrtr->rrtype = MIO_CONST_HTON16(MIO_DNS_RRT_OPT); + rrtr->rrclass = mio_hton16(edns->uplen); rrtr->ttl = mio_hton32(MIO_DNS_EDNS_MAKE_TTL(bdns->rcode, edns->version, edns->dnssecok)); rrtr->dlen = mio_hton16((mio_uint16_t)edns_dlen); dn = (mio_uint8_t*)(rrtr + 1); @@ -482,6 +482,7 @@ MIO_DEBUG1 (mio, "sent dns message %d\n", (int)mio_ntoh16(dns_msg_to_pkt(msg)->i msg->rtmridx = mio_instmrjob(mio, &tmrjob); if (msg->rtmridx == MIO_TMRIDX_INVALID) { + /* call the callback to indicate this operation failure in the middle of transaction */ if (MIO_LIKELY(msg->ctx)) ((mio_svc_dnc_on_reply_t)msg->ctx) (dnc, msg, mio_geterrnum(mio), MIO_NULL, 0); release_dns_msg (dnc, msg); @@ -571,7 +572,7 @@ void mio_svc_dnc_stop (mio_svc_dnc_t* dnc) } -int mio_svc_dnc_sendmsg (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, mio_svc_dnc_on_reply_t on_reply) +int mio_svc_dnc_sendmsg (mio_svc_dnc_t* dnc, mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, mio_svc_dnc_on_reply_t on_reply) { /* send a request or a response */ mio_dns_msg_t* msg; @@ -589,10 +590,17 @@ int mio_svc_dnc_sendmsg (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, mio_dns_bqr_t return 0; } -int mio_svc_dnc_sendreq (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_bedns_t* edns, mio_svc_dnc_on_reply_t on_reply) +int mio_svc_dnc_sendreq (mio_svc_dnc_t* dnc, mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_bedns_t* edns, mio_svc_dnc_on_reply_t on_reply) { /* send requests without resource record */ mio_oow_t i; + + if (bdns->rcode != MIO_DNS_RCODE_NOERROR) + { + mio_seterrnum (dnc->mio, MIO_EINVAL); + return -1; + } + for (i = 0; i < qr_count; i++) { if (mio_svc_dnc_sendmsg(dnc, bdns, &qr[i], 1, MIO_NULL, 0, edns, on_reply) <= -1) return -1; @@ -600,9 +608,9 @@ int mio_svc_dnc_sendreq (mio_svc_dnc_t* dnc, mio_dns_bdns_t* bdns, mio_dns_bqr_t return 0; } -int mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname, mio_dns_qtype_t qtype, mio_svc_dnc_on_reply_t on_reply) +int mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname, mio_dns_rrt_t qtype, mio_svc_dnc_on_reply_t on_reply) { - static mio_dns_bdns_t qhdr = + static mio_dns_bhdr_t qhdr = { -1, /* id */ 0, /* qr */ @@ -631,7 +639,7 @@ int mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname, mio_dns_qty qr.qname = (mio_bch_t*)qname; qr.qtype = qtype; - qr.qclass = MIO_DNS_QCLASS_IN; + qr.qclass = MIO_DNS_RRC_IN; return mio_svc_dnc_sendreq(dnc, &qhdr, &qr, 1, &qedns, on_reply); } @@ -639,43 +647,56 @@ int mio_svc_dnc_resolve (mio_svc_dnc_t* dnc, const mio_bch_t* qname, mio_dns_qty /* ----------------------------------------------------------------------- */ -static mio_uint8_t* parse_domain_name (mio_t* mio, mio_uint8_t* ptr, mio_uint8_t* pktstart, mio_uint8_t* pktend) +static int parse_domain_name (mio_t* mio, mio_dns_pkt_info_t* pi) { - mio_oow_t totlen, seglen; + mio_oow_t seglen; mio_uint8_t* xptr; - if (ptr >= pktend) goto oops; - + if (MIO_UNLIKELY(pi->ptr >= pi->end)) goto oops; xptr = MIO_NULL; - totlen = 0; printf ("\t"); - while ((seglen = *ptr++) > 0) + if ((seglen = *pi->ptr++) == 0) + { +printf ("\n"); + if (pi->rrdptr) pi->rrdptr[0] = '\0'; + pi->rrdlen++; /* for a terminating null */ + return 0; + } + + do { if (MIO_LIKELY(seglen < 64)) { /* normal. 00XXXXXXXX */ normal: -printf ("[%.*s]", (int)seglen, ptr); - totlen += seglen; - ptr += seglen; - if (MIO_UNLIKELY(ptr >= pktend)) goto oops; +printf ("[%.*s]", (int)seglen, pi->ptr); + if (pi->rrdptr) + { + MIO_MEMCPY (pi->rrdptr, pi->ptr, seglen); + pi->rrdptr += seglen + 1; /* +1 for '.' */ + pi->rrdptr[-1] = '.'; + } + + pi->rrdlen += seglen + 1; /* +1 for '.' */ + pi->ptr += seglen; + if (MIO_UNLIKELY(pi->ptr >= pi->end)) goto oops; } else if (seglen >= 192) { /* compressed. 11XXXXXXXX XXXXXXXX */ mio_oow_t offset; - if (MIO_UNLIKELY(ptr >= pktend)) goto oops; /* check before ptr++ in the next line */ - offset = ((seglen & 0x3F) << 8) | *ptr++; + if (MIO_UNLIKELY(pi->ptr >= pi->end)) goto oops; + offset = ((seglen & 0x3F) << 8) | *pi->ptr++; - if (MIO_UNLIKELY(&pktstart[offset] >= pktend)) goto oops; - seglen = pktstart[offset]; + if (MIO_UNLIKELY(pi->ptr >= pi->end)) goto oops; + seglen = pi->start[offset]; if (seglen >= 64) goto oops; /* the pointed position must not contain another pointer */ - if (!xptr) xptr = ptr; /* some later parts can also be a poitner again. so xptr, once set, must not be set again */ - ptr = &pktstart[offset + 1]; - if (MIO_UNLIKELY(ptr >= pktend)) goto oops; + if (!xptr) xptr = pi->ptr; /* some later parts can also be a poitner again. so xptr, once set, must not be set again */ + pi->ptr = &pi->start[offset + 1]; + if (MIO_UNLIKELY(pi->ptr >= pi->end)) goto oops; goto normal; } @@ -690,69 +711,103 @@ printf ("[%.*s]", (int)seglen, ptr); goto oops; } } + while ((seglen = *pi->ptr++) > 0); printf ("\n"); - return xptr? xptr: ptr; + if (pi->rrdptr) pi->rrdptr[-1] = '\0'; + + if (xptr) pi->ptr = xptr; + return 0; oops: - mio_seterrbfmt (mio, MIO_EINVAL, "invalid packet"); - return MIO_NULL; + mio_seterrnum (mio, MIO_EINVAL); + return -1; } -static mio_uint8_t* parse_question (mio_t* mio, mio_uint8_t* ptr, mio_uint8_t* pktstart, mio_uint8_t* pktend) +static int parse_question (mio_t* mio, mio_oow_t pos, mio_dns_pkt_info_t* pi) { mio_dns_qrtr_t* qrtr; + mio_uint8_t* xrrdptr; - ptr = parse_domain_name(mio, ptr, pktstart, pktend); - if (!ptr) return MIO_NULL; + xrrdptr = pi->rrdptr; + if (parse_domain_name(mio, pi) <= -1) return -1; - qrtr = (mio_dns_qrtr_t*)ptr; - ptr += MIO_SIZEOF(*qrtr); - if (MIO_UNLIKELY(ptr >= pktend)) goto oops; + qrtr = (mio_dns_qrtr_t*)pi->ptr; + pi->ptr += MIO_SIZEOF(*qrtr); + pi->rrdlen += MIO_SIZEOF(*qrtr); + if (MIO_UNLIKELY(pi->ptr >= pi->end)) goto oops; - return ptr; + if (pi->rrdptr) + { + mio_dns_bqr_t* bqr; + bqr = pi->rr.qd; + bqr[pos].qname = (mio_bch_t*)xrrdptr; + bqr[pos].qtype = mio_ntoh16(qrtr->qtype); + bqr[pos].qclass = mio_ntoh16(qrtr->qclass); + } + + return 0; oops: - mio_seterrbfmt (mio, MIO_EINVAL, "invalid packet"); - return MIO_NULL; + mio_seterrnum (mio, MIO_EINVAL); + return -1; } -static mio_uint8_t* parse_answer (mio_t* mio, mio_uint8_t* ptr, mio_uint8_t* pktstart, mio_uint8_t* pktend) +static int parse_answer (mio_t* mio, mio_dns_rr_part_t rr_part, mio_oow_t pos, mio_dns_pkt_info_t* pi) { mio_dns_rrtr_t* rrtr; mio_uint16_t qtype, dlen; mio_oow_t remsize; + mio_uint8_t* xrrdptr; -//printf ("pktstart = %p pktend = %p, ptr = %p\n", pktstart, pktend, ptr); - ptr = parse_domain_name(mio, ptr, pktstart, pktend); - if (!ptr) return MIO_NULL; + xrrdptr = pi->rrdptr; + if (parse_domain_name(mio, pi) <= -1) return -1; - rrtr = (mio_dns_rrtr_t*)ptr; - if (MIO_UNLIKELY(pktend - ptr < MIO_SIZEOF(*rrtr))) goto oops; - ptr += MIO_SIZEOF(*rrtr); + rrtr = (mio_dns_rrtr_t*)pi->ptr; + if (MIO_UNLIKELY(pi->end - pi->ptr < MIO_SIZEOF(*rrtr))) goto oops; + pi->ptr += MIO_SIZEOF(*rrtr); dlen = mio_ntoh16(rrtr->dlen); - if (MIO_UNLIKELY(pktend - ptr < dlen)) goto oops; -//printf ("rrtr->dlen => %d\n", dlen); + if (MIO_UNLIKELY(pi->end - pi->ptr < dlen)) goto oops; - qtype = mio_ntoh16(rrtr->qtype); - remsize = pktend - ptr; + qtype = mio_ntoh16(rrtr->rrtype); + remsize = pi->end - pi->ptr; + + if (pi->rrdptr) + { + /* store information about the actual record */ + mio_dns_brr_t* brr; + + switch (rr_part) + { + case MIO_DNS_RR_PART_ANSWER: brr = pi->rr.an; break; + case MIO_DNS_RR_PART_AUTHORITY: brr = pi->rr.ns; break; + case MIO_DNS_RR_PART_ADDITIONAL: brr = pi->rr.ar; break; + } + + brr[pos].part = rr_part; + brr[pos].rrname = (mio_bch_t*)xrrdptr; + brr[pos].rrtype = mio_ntoh16(rrtr->rrtype); + brr[pos].rrclass = mio_ntoh16(rrtr->rrclass); + brr[pos].ttl = mio_ntoh32(rrtr->ttl); + brr[pos].dptr = pi->rrdptr; + brr[pos].dlen = dlen; + } switch (qtype) { - case MIO_DNS_QTYPE_OPT: + case MIO_DNS_RRT_OPT: { /* RFC 6891 The extended RCODE and flags, which OPT stores in the RR Time to Live (TTL) field, are structured as follows: - +0 (MSB) +1 (LSB) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 0: | EXTENDED-RCODE | VERSION | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2: | DO| Z | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * + 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 @@ -760,96 +815,146 @@ static mio_uint8_t* parse_answer (mio_t* mio, mio_uint8_t* ptr, mio_uint8_t* pkt 15). */ -printf ("OPT RR included....>>>>>>>>>>>>>>>>>>>>>>>>%d\n", (rrtr->ttl >> 24)); - /*rcode |= (rrtr->ttl >> 24);*/ - if (((rrtr->ttl >> 16) & 0xFF) != 0) goto oops; /* version not 0 */ - /* dnsok -> ((rrtr->ttl & 0x8000) >> 15) */ + /* TODO: do i need to check if rrname is ? */ + pi->edns.exist = 1; + pi->edns.uplen = mio_ntoh16(rrtr->rrclass); + pi->hdr.rcode |= (rrtr->ttl >> 24); + pi->edns.version = (rrtr->ttl >> 16) & 0xFF; + pi->edns.dnssecok = ((rrtr->ttl & 0x8000) >> 15); /*if ((rrtr->ttl & 0x7FFF) != 0) goto oops;*/ /* Z not 0 - ignore this for now */ break; } - case MIO_DNS_QTYPE_A: + case MIO_DNS_RRT_A: if (MIO_UNLIKELY(remsize < 4)) goto oops; break; - case MIO_DNS_QTYPE_AAAA: + case MIO_DNS_RRT_AAAA: if (MIO_UNLIKELY(remsize < 16)) goto oops; break; - - case MIO_DNS_QTYPE_CNAME: - { - mio_uint8_t* xptr; -printf ("\t"); - xptr = parse_domain_name(mio, ptr, pktstart, pktend); - if (!xptr) return MIO_NULL; - MIO_ASSERT (mio, xptr == ptr + dlen); + case MIO_DNS_RRT_CNAME: + { + #if !defined(MIO_BUILD_RELEASE) + mio_uint8_t* xptr = pi->ptr; + #endif +printf ("\t"); + if (parse_domain_name(mio, pi) <= -1) return -1; + MIO_ASSERT (mio, pi->ptr == xptr + dlen); + dlen = 0; /* to skip additional update on pi->ptr and data copy before return */ break; } } - ptr += dlen; - return ptr; - -oops: - mio_seterrbfmt (mio, MIO_EINVAL, "invalid packet"); - return MIO_NULL; -} - -int mio_dns_parse_packet (mio_svc_dnc_t* dnc, mio_dns_pkt_t* pkt, mio_oow_t len, mio_dns_bdns_t* bdns) -{ - mio_t* mio = dnc->mio; - mio_uint16_t i, rrc; - mio_uint8_t* ptr; - mio_uint8_t* pktend = (mio_uint8_t*)pkt + len; - - MIO_ASSERT (mio, len >= MIO_SIZEOF(*pkt)); - - bdns->id = mio_ntoh16(pkt->id); - - bdns->qr = pkt->qr & 0x01; - bdns->opcode = pkt->opcode & 0x0F; - bdns->aa = pkt->aa & 0x01; - bdns->tc = pkt->tc & 0x01; - bdns->rd = pkt->rd & 0x01; - bdns->ra = pkt->ra & 0x01; - bdns->ad = pkt->ad & 0x01; - bdns->cd = pkt->cd & 0x01; - bdns->rcode = pkt->rcode & 0x0F; - - ptr = (mio_uint8_t*)(pkt + 1); - - rrc = mio_ntoh16(pkt->qdcount); -printf ("question %d\n", rrc); - for (i = 0; i < rrc; i++) + if (dlen > 0) { - ptr = parse_question(mio, ptr, (mio_uint8_t*)pkt, pktend); - if (!ptr) return -1; - } - - rrc = mio_ntoh16(pkt->ancount); -printf ("answer %d\n", rrc); - for (i = 0; i < rrc; i++) - { - ptr = parse_answer(mio, ptr, (mio_uint8_t*)pkt, pktend); - if (!ptr) return -1; - } - - rrc = mio_ntoh16(pkt->nscount); -printf ("authority %d\n", rrc); - for (i = 0; i < rrc; i++) - { - ptr = parse_answer(mio, ptr, (mio_uint8_t*)pkt, pktend); - if (!ptr) return -1; - } - - rrc = mio_ntoh16(pkt->arcount); -printf ("additional %d\n", rrc); - for (i = 0; i < rrc; i++) - { - ptr = parse_answer(mio, ptr, (mio_uint8_t*)pkt, pktend); - if (!ptr) return -1; + pi->ptr += dlen; + pi->rrdlen += dlen; + if (pi->rrdptr) MIO_MEMCPY (pi->rrdptr, rrtr + 1, dlen); /* copy actual data */ } return 0; + +oops: + mio_seterrnum (mio, MIO_EINVAL); + 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_uint16_t i; + mio_dns_pkt_info_t pib, * pii; + + MIO_ASSERT (mio, len >= MIO_SIZEOF(*pkt)); + + MIO_MEMSET (&pib, 0, MIO_SIZEOF(pib)); + pii = &pib; + +redo: + pii->start = (mio_uint8_t*)pkt; + pii->end = (mio_uint8_t*)pkt + len; + pii->ptr = (mio_uint8_t*)(pkt + 1); + + pii->hdr.id = mio_ntoh16(pkt->id); + 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; + pii->qdcount = mio_ntoh16(pkt->qdcount); + pii->ancount = mio_ntoh16(pkt->ancount); + pii->nscount = mio_ntoh16(pkt->nscount); + pii->arcount = mio_ntoh16(pkt->arcount); + + for (i = 0; i < pii->qdcount; i++) + { + if (parse_question(mio, i, pii) <= -1) goto oops; + } + + for (i = 0; i < pii->ancount; i++) + { + if (parse_answer(mio, MIO_DNS_RR_PART_ANSWER, i, pii) <= -1) goto oops; + } + + for (i = 0; i < pii->nscount; i++) + { + if (parse_answer(mio, MIO_DNS_RR_PART_AUTHORITY, i, pii) <= -1) goto oops; + } + + for (i = 0; i < pii->arcount; i++) + { + if (parse_answer(mio, MIO_DNS_RR_PART_ADDITIONAL, i, pii) <= -1) goto oops; + } + + if (pii == &pib) + { + /* TODO: buffer management... */ + pii = (mio_dns_pkt_info_t*)mio_callocmem(mio, MIO_SIZEOF(*pii) + (MIO_SIZEOF(mio_dns_bqr_t) * pib.qdcount) + (MIO_SIZEOF(mio_dns_brr_t) * (pib.ancount + pib.nscount + pib.arcount)) + pib.rrdlen); + if (!pii) goto oops; + + pii->rr.qd = (mio_dns_bqr_t*)(&pii[1]); + pii->rr.an = (mio_dns_brr_t*)&pii->rr.qd[pib.qdcount]; + pii->rr.ns = (mio_dns_brr_t*)&pii->rr.an[pib.ancount]; + pii->rr.ar = (mio_dns_brr_t*)&pii->rr.ns[pib.nscount]; + pii->rrdptr = (mio_uint8_t*)&pii->rr.ar[pib.arcount]; + goto redo; + } + +printf (">>>>>>>> RRDLEN = %d\n", (int)pii->rrdlen); +printf (">>>>>>>> RCODE %d EDNS exist %d uplen %d version %d dnssecok %d\n", pii->hdr.rcode, pii->edns.exist, pii->edns.uplen, pii->edns.version, pii->edns.dnssecok); + for (i = 0; i < pii->qdcount; i++) + { + printf ("qd %d -> %s %d\n", i, pii->rr.qd[i].qname, pii->rr.qd[i].qtype); + } + + for (i = 0; i < pii->ancount; i++) + { + printf ("an %d -> %s %d\n", i, pii->rr.an[i].rrname, pii->rr.an[i].rrtype); + } + + for (i = 0; i < pii->nscount; i++) + { + printf ("ns %d -> %s %d\n", i, pii->rr.ns[i].rrname, pii->rr.ns[i].rrtype); + } + + for (i = 0; i < pii->arcount; i++) + { + printf ("ar %d -> %s %d\n", i, pii->rr.ar[i].rrname, pii->rr.ar[i].rrtype); + } + + return pii; + +oops: + if (pii && pii != &pib) mio_freemem (mio, pii); + return MIO_NULL; +} + +void mio_dns_free_packet_info (mio_t* mio, mio_dns_pkt_info_t* pi) +{ +/* TODO: better management */ + return mio_freemem (mio, pi); } diff --git a/mio/lib/mio-dns.h b/mio/lib/mio-dns.h index 7d3f03f..7809ae3 100644 --- a/mio/lib/mio-dns.h +++ b/mio/lib/mio-dns.h @@ -55,6 +55,10 @@ enum mio_dns_rcode_t MIO_DNS_RCODE_NXRRSET = 8, /* RR set exists when it should not */ MIO_DNS_RCODE_NOTAUTH = 9, /* not authorized or server not authoritative for zone*/ MIO_DNS_RCODE_NOTZONE = 10, /* name not contained in zone */ + + /* the standard rcode field is 4 bit long. so the max is 15. */ + /* items belows require EDNS0 */ + MIO_DNS_RCODE_BADVERS = 16, MIO_DNS_RCODE_BADSIG = 17, MIO_DNS_RCODE_BADTIME = 18, @@ -66,35 +70,64 @@ enum mio_dns_rcode_t }; typedef enum mio_dns_rcode_t mio_dns_rcode_t; -enum mio_dns_qtype_t -{ - MIO_DNS_QTYPE_A = 1, - MIO_DNS_QTYPE_NS = 2, - MIO_DNS_QTYPE_CNAME = 5, - MIO_DNS_QTYPE_SOA = 6, - MIO_DNS_QTYPE_NULL = 10, - MIO_DNS_QTYPE_PTR = 12, - MIO_DNS_QTYPE_MX = 15, - MIO_DNS_QTYPE_TXT = 16, - MIO_DNS_QTYPE_AAAA = 28, - MIO_DNS_QTYPE_EID = 31, - MIO_DNS_QTYPE_SRV = 33, - MIO_DNS_QTYPE_OPT = 41, - MIO_DNS_QTYPE_RRSIG = 46, - MIO_DNS_QTYPE_AFXR = 252, /* entire zone transfer */ - MIO_DNS_QTYPE_ANY = 255 -}; -typedef enum mio_dns_qtype_t mio_dns_qtype_t; -enum mio_dns_qclass_t +enum mio_dns_rrt_t { - MIO_DNS_QCLASS_IN = 1, /* internet */ - MIO_DNS_QCLASS_CH = 3, /* chaos */ - MIO_DNS_QCLASS_HS = 4, /* hesiod */ - MIO_DNS_QCLASS_NONE = 254, - MIO_DNS_QCLASS_ANY = 255 +/* + * [RFC1035] + * TYPE fields are used in resource records. Note that these types are a + * subset of QTYPEs. + */ + MIO_DNS_RRT_A = 1, + MIO_DNS_RRT_NS = 2, + MIO_DNS_RRT_CNAME = 5, + MIO_DNS_RRT_SOA = 6, + MIO_DNS_RRT_NULL = 10, + MIO_DNS_RRT_PTR = 12, + MIO_DNS_RRT_MX = 15, + MIO_DNS_RRT_TXT = 16, + MIO_DNS_RRT_AAAA = 28, + MIO_DNS_RRT_EID = 31, + MIO_DNS_RRT_SRV = 33, + MIO_DNS_RRT_OPT = 41, + MIO_DNS_RRT_RRSIG = 46, + +/* + * [RFC1035] + * QTYPE fields appear in the question part of a query. QTYPES are a + * superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the + * following QTYPEs are defined: + */ + MIO_DNS_RRT_Q_AFXR = 252, /* A request for a transfer of an entire zone */ + MIO_DNS_RRT_Q_MAILB = 253, /* A request for mailbox-related records (MB, MG or MR) */ + MIO_DNS_RRT_Q_MAILA = 254, /* A request for mail agent RRs (Obsolete - see MX) */ + MIO_DNS_RRT_Q_ANY = 255 /* A request for all records */ }; -typedef enum mio_dns_qclass_t mio_dns_qclass_t; +typedef enum mio_dns_rrt_t mio_dns_rrt_t; + +/* + * CLASS fields appear in resource records. The following CLASS mnemonics + * and values are defined: + */ +enum mio_dns_rrc_t +{ + MIO_DNS_RRC_IN = 1, /* internet */ + MIO_DNS_RRC_CH = 3, /* chaos */ + MIO_DNS_RRC_HS = 4, /* Hesiod [Dyer 87] */ + MIO_DNS_RRC_NONE = 254, + +/* + * + * QCLASS fields appear in the question section of a query. QCLASS values + * are a superset of CLASS values; every CLASS is a valid QCLASS. In + * addition to CLASS values, the following QCLASSes are defined: + */ + + MIO_DNS_RRC_Q_ANY = 255 +}; +typedef enum mio_dns_rrc_t mio_dns_rrc_t; + + enum mio_dns_eopt_code_t { @@ -188,8 +221,8 @@ typedef struct mio_dns_qrtr_t mio_dns_qrtr_t; struct mio_dns_rrtr_t { /* qname upto 64 bytes */ - mio_uint16_t qtype; - mio_uint16_t qclass; + mio_uint16_t rrtype; + mio_uint16_t rrclass; mio_uint32_t ttl; mio_uint16_t dlen; /* data length */ /* actual data if if dlen > 0 */ @@ -214,8 +247,8 @@ typedef struct mio_dns_eopt_t mio_dns_eopt_t; (((rd) & 0x01) << 8) | (((ra) & 0x01) << 7) | (((ad) & 0x01) << 5) | (((cd) & 0x01) << 4) | ((rcode) & 0x0F)) */ -/* breakdown of the dns message id and flags */ -struct mio_dns_bdns_t +/* breakdown of the dns message id and flags. it excludes rr count fields.*/ +struct mio_dns_bhdr_t { int id; /* auto-assign if negative. */ @@ -230,7 +263,7 @@ struct mio_dns_bdns_t mio_uint8_t cd; /* checking disabled - dnssec */ mio_uint8_t rcode; /* reply code - for reply only */ }; -typedef struct mio_dns_bdns_t mio_dns_bdns_t; +typedef struct mio_dns_bhdr_t mio_dns_bhdr_t; /* breakdown of question record */ struct mio_dns_bqr_t @@ -254,9 +287,9 @@ typedef enum mio_dns_rr_part_t mio_dns_rr_part_t; struct mio_dns_brr_t { mio_dns_rr_part_t part; - mio_bch_t* qname; - mio_uint16_t qtype; - mio_uint16_t qclass; + mio_bch_t* rrname; + mio_uint16_t rrtype; + mio_uint16_t rrclass; mio_uint32_t ttl; mio_uint16_t dlen; void* dptr; @@ -326,8 +359,9 @@ typedef struct mio_dns_bedns_t mio_dns_bedns_t; /* ---------------------------------------------------------------- */ -typedef struct mio_svc_dns_t mio_svc_dns_t; -typedef struct mio_svc_dnc_t mio_svc_dnc_t; +typedef struct mio_svc_dns_t mio_svc_dns_t; /* server service */ +typedef struct mio_svc_dnc_t mio_svc_dnc_t; /* client service */ +typedef struct mio_svc_dnr_t mio_svc_dnr_t; /* recursor service */ typedef void (*mio_svc_dnc_on_reply_t) ( mio_svc_dnc_t* dnc, @@ -337,6 +371,53 @@ typedef void (*mio_svc_dnc_on_reply_t) ( mio_oow_t len ); + +#define mio_svc_dns_getmio(svc) mio_svc_getmio(svc) +#define mio_svc_dnc_getmio(svc) mio_svc_getmio(svc) +#define mio_svc_dnr_getmio(svc) mio_svc_getmio(svc) + +/* ---------------------------------------------------------------- */ + + +struct mio_dns_pkt_info_t +{ + mio_uint8_t* start; + mio_uint8_t* end; + mio_uint8_t* ptr; + + mio_oow_t rrdlen; /* length needed to store RRs decoded */ + mio_uint8_t* rrdptr; + + + /* data information composed */ + mio_dns_bhdr_t hdr; + + struct + { + int exist; + mio_uint16_t uplen; /* udp payload len - will be placed in the qclass field of RR. */ + mio_uint8_t version; + mio_uint8_t dnssecok; + } edns; + + mio_uint16_t qdcount; /* number of questions */ + mio_uint16_t ancount; /* number of answers (answer part) */ + mio_uint16_t nscount; /* number of name servers (authority part. only NS types) */ + mio_uint16_t arcount; /* number of additional resource (additional part) */ + + struct + { + mio_dns_bqr_t* qd; + mio_dns_brr_t* an; + mio_dns_brr_t* ns; + mio_dns_brr_t* ar; + } rr; +}; +typedef struct mio_dns_pkt_info_t mio_dns_pkt_info_t; + + +/* ---------------------------------------------------------------- */ + #if defined(__cplusplus) extern "C" { #endif @@ -351,7 +432,7 @@ MIO_EXPORT void mio_svc_dnc_stop ( MIO_EXPORT int mio_svc_dnc_sendreq ( mio_svc_dnc_t* dnc, - mio_dns_bdns_t* bdns, + mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_bedns_t* edns, @@ -360,7 +441,7 @@ MIO_EXPORT int mio_svc_dnc_sendreq ( MIO_EXPORT int mio_svc_dnc_sendmsg ( mio_svc_dnc_t* dnc, - mio_dns_bdns_t* bdns, + mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, @@ -372,17 +453,25 @@ MIO_EXPORT int mio_svc_dnc_sendmsg ( MIO_EXPORT int mio_svc_dnc_resolve ( mio_svc_dnc_t* dnc, const mio_bch_t* qname, - mio_dns_qtype_t qtype, + mio_dns_rrt_t qtype, mio_svc_dnc_on_reply_t on_reply ); -MIO_EXPORT int mio_dns_parse_packet ( - mio_svc_dnc_t* dnc, - mio_dns_pkt_t* pkt, - mio_oow_t len, - mio_dns_bdns_t* bdns +/* ---------------------------------------------------------------- */ + +MIO_EXPORT mio_dns_pkt_info_t* mio_dns_make_packet_info ( + mio_t* mio, + const mio_dns_pkt_t* pkt, + mio_oow_t len ); + +MIO_EXPORT void mio_dns_free_packet_info ( + mio_t* mio, + mio_dns_pkt_info_t* pi +); + + #if defined(__cplusplus) } #endif diff --git a/mio/lib/mio.h b/mio/lib/mio.h index d358a5e..1772540 100644 --- a/mio/lib/mio.h +++ b/mio/lib/mio.h @@ -422,6 +422,7 @@ struct mio_svc_t else (mio)->actsvc.tail = (svc)->svc_prev; \ } while (0) +#define mio_svc_getmio(svc) (((mio_svc_t*)(svc))->mio) /* ========================================================================= * MIO LOGGING