diff --git a/src/Makefile.in b/src/Makefile.in index 453d728e..4b78abf3 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -63,7 +63,7 @@ EXTENSION_LIBUV_LDFLAGS=@EXTENSION_LIBUV_LDFLAGS@ GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ getdns_error.lo list.lo request-internal.lo \ - rr-dict.lo stub.lo sync.lo util-internal.lo + rr-dict.lo rr-iter.lo stub.lo sync.lo util-internal.lo GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \ str2wire.lo @@ -241,16 +241,18 @@ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h $(sr request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ getdns/getdns.h $(srcdir)/getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \ - $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/gldns/rrdef.h + $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h getdns/getdns.h $(srcdir)/types-internal.h \ $(srcdir)/getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/context.h config.h \ $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h getdns/getdns.h $(srcdir)/gldns/pkthdr.h stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ - $(srcdir)/getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/context.h \ - $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/types-internal.h $(srcdir)/util-internal.h $(srcdir)/general.h + $(srcdir)/getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \ + $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/util-internal.h \ + $(srcdir)/general.h sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h $(srcdir)/getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \ config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/general.h \ @@ -258,7 +260,9 @@ sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h $( util-internal.lo util-internal.o: $(srcdir)/util-internal.c getdns/getdns.h $(srcdir)/dict.h $(srcdir)/util/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/getdns/getdns_extra.h getdns/getdns.h $(srcdir)/list.h \ $(srcdir)/util-internal.h $(srcdir)/context.h config.h $(srcdir)/extension/libmini_event.h config.h \ - $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-dict.h + $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \ diff --git a/src/rr-iter.c b/src/rr-iter.c new file mode 100644 index 00000000..773e450e --- /dev/null +++ b/src/rr-iter.c @@ -0,0 +1,127 @@ +/** + * + * /brief RR iterator over wireformat DNS packet + */ +/* + * Copyright (c) 2013, NLnet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. 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. + */ + +#include "rr-iter.h" +#include "config.h" +#include +#include + +static getdns_rr_iter * +find_rrtype(getdns_rr_iter *i) +{ + size_t dlen; + uint8_t *pos; + + /* Past the last RR in the pkt */ + if (GLDNS_QDCOUNT(i->pkt) + GLDNS_ANCOUNT(i->pkt) + + GLDNS_NSCOUNT(i->pkt) + GLDNS_ARCOUNT(i->pkt) <= i->n) { + + i->pos = NULL; + return NULL; + } + + /* This iterator was already done */ + if (!i->pos) + return NULL; + + pos = i->pos; + dlen = i->pkt_len - (pos - i->pkt); + + while (dlen >= 5) { /* At least space for type and class */ + + if (*pos == 0) { + i->rr_type = pos + 1; + return i; + } + if ((*pos & 0xC0) == 0xC0) { + i->rr_type = pos + 2; + return i; + } + if ((*pos & 0xC0) != 0) + break; /* Unknown label type */ + + if (*pos > dlen) + break; /* Label size overflows packet size! */ + + dlen -= *pos + 1; + pos += *pos + 1; + } + i->pos = NULL; + return NULL; +} + +getdns_rr_iter * +priv_getdns_rr_iter_init(getdns_rr_iter *i, uint8_t *pkt, size_t pkt_len) +{ + if (pkt_len < GLDNS_HEADER_SIZE + 5) + return NULL; + + i->pkt = pkt; + i->pkt_len = pkt_len; + i->n = 0; + i->pos = pkt + GLDNS_HEADER_SIZE; + + return find_rrtype(i); +} + + +getdns_rr_iter * +priv_getdns_rr_iter_next(getdns_rr_iter *i) +{ + size_t dlen; + + /* Already done */ + if (!i->pos) + return NULL; + + assert(i->rr_type); + + i->n += 1; + + if (i->n <= GLDNS_QDCOUNT(i->pkt)) { + i->pos = i->rr_type + 4; + return find_rrtype(i); + } + + dlen = i->pkt_len - (i->rr_type - i->pkt); + if (dlen < 10) + goto garbage; /* No space for type, class, ttl & rdlength */ + + if (gldns_read_uint16(i->rr_type + 8) > dlen - 10) + goto garbage; /* RData size overflos packet size */ + + i->pos = i->rr_type + 10 + gldns_read_uint16(i->rr_type + 8); + return find_rrtype(i); +garbage: + i->pos = NULL; + return NULL; +} + diff --git a/src/rr-iter.h b/src/rr-iter.h new file mode 100644 index 00000000..1179c027 --- /dev/null +++ b/src/rr-iter.h @@ -0,0 +1,52 @@ +/** + * + * /brief RR iterator over wireformat DNS packet + */ +/* + * Copyright (c) 2013, NLnet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. 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. + */ + +#ifndef RR_ITER_H_ +#define RR_ITER_H_ + +#include "getdns/getdns.h" + +typedef struct getdns_rr_iter { + uint8_t *pkt; + size_t pkt_len; + size_t n; /* Which RR are we currently at */ + uint8_t *pos; + uint8_t *rr_type; +} getdns_rr_iter; + +getdns_rr_iter *priv_getdns_rr_iter_init(getdns_rr_iter *i, + uint8_t *pkt, size_t pkt_len); + +getdns_rr_iter *priv_getdns_rr_iter_next(getdns_rr_iter *i); + +#endif + +/* rrs.h */ diff --git a/src/util-internal.c b/src/util-internal.c index 3c4e958e..afefa331 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -51,6 +51,7 @@ #include "gldns/str2wire.h" #include "gldns/gbuffer.h" #include "gldns/pkthdr.h" +#include "rr-iter.h" /** * this is a comprehensive list of extensions and their data types @@ -503,9 +504,9 @@ create_getdns_response(getdns_dns_req *completed_request) /* info (bools) about dns_req */ int dnssec_return_status; - -#if defined(WIRE_DEBUG) && WIRE_DEBUG char *str_pkt; + getdns_rr_iter rr_iter_storage, *rr_iter; + for ( netreq_p = completed_request->netreqs ; ! r && (netreq = *netreq_p) ; netreq_p++) { @@ -521,13 +522,27 @@ create_getdns_response(getdns_dns_req *completed_request) continue; } +#if defined(WIRE_DEBUG) && WIRE_DEBUG + for ( rr_iter = priv_getdns_rr_iter_init(&rr_iter_storage + , netreq->response + , netreq->response_len) + ; rr_iter + ; rr_iter = priv_getdns_rr_iter_next(rr_iter)) { + + fprintf( stderr, "n: %d, dname: %p, rr_type: %p " + "-> type: %d, class: %d\n" + , (int)rr_iter->n,rr_iter->pos,rr_iter->rr_type + , (int)gldns_read_uint16(rr_iter->rr_type) + , (int)gldns_read_uint16(rr_iter->rr_type + 2) + ); + } if ((str_pkt = gldns_wire2str_pkt( netreq->response, netreq->response_len))) { fprintf(stderr, "%s\n", str_pkt); free(str_pkt); } - } #endif + } dnssec_return_status = completed_request->dnssec_return_status || completed_request->dnssec_return_only_secure;