From: Jelte Jansen Date: Thu, 16 Dec 2004 13:59:42 +0000 (+0000) Subject: wire2dname now allocates data itself X-Git-Tag: release-0.50~651 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8323261f6893887eff8a0edcc1fbb32657d2cf0b;p=thirdparty%2Fldns.git wire2dname now allocates data itself wire2dname now puts dname in ldns_rdf made start with status returns in wire2 functions moved wire2packet, wire2rr and wire2dname to wire2host.c added wire2host to makefile --- diff --git a/Makefile.in b/Makefile.in index b423a957..5126af0b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,12 +19,13 @@ LINTFLAGS = +quiet +posixlib -weak -warnposix -unrecog #INSTALL = $(srcdir)/install-sh -c #INSTALL_PROGRAM = $(INSTALL) -LIBDNS_SOURCES = rdata.c util.c rr.c packet.c +LIBDNS_SOURCES = rdata.c util.c rr.c packet.c wire2host.c LIBDNS_HEADERS = ldns/error.h \ ldns/packet.h \ ldns/prototype.h \ ldns/rdata.h \ ldns/rr.h \ + ldns/wire2host.h \ util.h \ buf.h LIBDNS_OBJECTS = $(LIBDNS_SOURCES:.c=.o) diff --git a/ldns/error.h b/ldns/error.h index aecc0b0c..2738c74a 100644 --- a/ldns/error.h +++ b/ldns/error.h @@ -11,16 +11,19 @@ */ #ifndef _ERROR_H -#define _ERORR_H +#define _ERROR_H /* we do negative error codes? */ #define __X -1 enum ldns_enum_status { - LDNS_E_OK = 0, - LDNS_E_EMPTY_LABEL = 1 * __X, - LDNS_E_DDD_OVERFLOW = 2 * __X + LDNS_STATUS_OK = 0, + LDNS_STATUS_EMPTY_LABEL = 1 * __X, + LDNS_STATUS_LABEL_OVERFLOW = 2 * __X, + LDNS_STATUS_DOMAINNAME_OVERFLOW = 3 * __X, + LDNS_STATUS_DDD_OVERFLOW = 4 * __X, + LDNS_PACKET_OVERFLOW = 5 * __X }; typedef enum ldns_enum_status ldns_status; diff --git a/ldns/ldns.h b/ldns/ldns.h index 7c92256d..78af9bc4 100644 --- a/ldns/ldns.h +++ b/ldns/ldns.h @@ -18,5 +18,6 @@ #include #include #include +#include #endif /* _LDNS_H */ diff --git a/ldns/packet.h b/ldns/packet.h index dede8389..03d1a1cb 100644 --- a/ldns/packet.h +++ b/ldns/packet.h @@ -13,6 +13,7 @@ #ifndef _LDNS_PACKET_H #define _LDNS_PACKET_H +#include #include #include @@ -119,14 +120,4 @@ ldns_pkt *ldns_pkt_new(); */ void ldns_pkt_free(ldns_pkt *packet); -/** - * Converts the data on the uint8_t bytearray (in wire format) to a DNS packet - * - * @param data pointer to the buffer with the data - * @param len the length of the data buffer (in bytes) - * @param packet pointer to the structure to hold the packet - * @return the number of bytes read from the wire - */ -size_t ldns_wire2pkt(ldns_pkt *packet, const uint8_t *data, size_t len); - #endif /* !_LDNS_PACKET_H */ diff --git a/ldns/rr.h b/ldns/rr.h index ba404f4d..91e6026b 100644 --- a/ldns/rr.h +++ b/ldns/rr.h @@ -17,6 +17,7 @@ #include #include #include +#include /** * The different RR classes. @@ -213,9 +214,4 @@ size_t ldns_rr_descriptor_minimum(ldns_rr_descriptor *descriptor); size_t ldns_rr_descriptor_maximum(ldns_rr_descriptor *descriptor); ldns_rdf_type ldns_rr_descriptor_field_type(ldns_rr_descriptor *descriptor, size_t index); -size_t ldns_wire2dname(uint8_t *dname, const uint8_t *wire, size_t max, - size_t *pos); -size_t ldns_wire2rr(ldns_rr *rr, const uint8_t *wire, size_t max, - size_t *pos, int section); - #endif /* _LDNS_RR_H */ diff --git a/packet.c b/packet.c index 7b671e76..c30cd6f0 100644 --- a/packet.c +++ b/packet.c @@ -13,122 +13,8 @@ #include #include - #include "util.h" -/* - * Set of macro's to deal with the dns message header as specified - * in RFC1035 in portable way. - * - */ - -/* - * - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ID | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | QDCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ANCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | NSCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * | ARCOUNT | - * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - * - */ - -/* The length of the header */ -#define QHEADERSZ 12 - -/* First octet of flags */ -#define RD_MASK 0x01U -#define RD_SHIFT 0 -#define RD(wirebuf) (*(wirebuf+2) & RD_MASK) -#define RD_SET(wirebuf) (*(wirebuf+2) |= RD_MASK) -#define RD_CLR(wirebuf) (*(wirebuf+2) &= ~RD_MASK) - -#define TC_MASK 0x02U -#define TC_SHIFT 1 -#define TC(wirebuf) (*(wirebuf+2) & TC_MASK) -#define TC_SET(wirebuf) (*(wirebuf+2) |= TC_MASK) -#define TC_CLR(wirebuf) (*(wirebuf+2) &= ~TC_MASK) - -#define AA_MASK 0x04U -#define AA_SHIFT 2 -#define AA(wirebuf) (*(wirebuf+2) & AA_MASK) -#define AA_SET(wirebuf) (*(wirebuf+2) |= AA_MASK) -#define AA_CLR(wirebuf) (*(wirebuf+2) &= ~AA_MASK) - -#define OPCODE_MASK 0x78U -#define OPCODE_SHIFT 3 -#define OPCODE(wirebuf) ((*(wirebuf+2) & OPCODE_MASK) >> OPCODE_SHIFT) -#define OPCODE_SET(wirebuf, opcode) \ - (*(wirebuf+2) = ((*(wirebuf+2)) & ~OPCODE_MASK) | ((opcode) << OPCODE_SHIFT)) - -#define QR_MASK 0x80U -#define QR_SHIFT 7 -#define QR(wirebuf) (*(wirebuf+2) & QR_MASK) -#define QR_SET(wirebuf) (*(wirebuf+2) |= QR_MASK) -#define QR_CLR(wirebuf) (*(wirebuf+2) &= ~QR_MASK) - -/* Second octet of flags */ -#define RCODE_MASK 0x0fU -#define RCODE_SHIFT 0 -#define RCODE(wirebuf) (*(wirebuf+3) & RCODE_MASK) -#define RCODE_SET(wirebuf, rcode) \ - (*(wirebuf+3) = ((*(wirebuf+3)) & ~RCODE_MASK) | (rcode)) - -#define CD_MASK 0x10U -#define CD_SHIFT 4 -#define CD(wirebuf) (*(wirebuf+3) & CD_MASK) -#define CD_SET(wirebuf) (*(wirebuf+3) |= CD_MASK) -#define CD_CLR(wirebuf) (*(wirebuf+3) &= ~CD_MASK) - -#define AD_MASK 0x20U -#define AD_SHIFT 5 -#define AD(wirebuf) (*(wirebuf+3) & AD_MASK) -#define AD_SET(wirebuf) (*(wirebuf+3) |= AD_MASK) -#define AD_CLR(wirebuf) (*(wirebuf+3) &= ~AD_MASK) - -#define Z_MASK 0x40U -#define Z_SHIFT 6 -#define Z(wirebuf) (*(wirebuf+3) & Z_MASK) -#define Z_SET(wirebuf) (*(wirebuf+3) |= Z_MASK) -#define Z_CLR(wirebuf) (*(wirebuf+3) &= ~Z_MASK) - -#define RA_MASK 0x80U -#define RA_SHIFT 7 -#define RA(wirebuf) (*(wirebuf+3) & RA_MASK) -#define RA_SET(wirebuf) (*(wirebuf+3) |= RA_MASK) -#define RA_CLR(wirebuf) (*(wirebuf+3) &= ~RA_MASK) - -/* Query ID */ -#define ID(wirebuf) (ntohs(*(uint16_t *)(wirebuf))) - -/* Counter of the question section */ -#define QDCOUNT_OFF 4 -/* -#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) -*/ -#define QDCOUNT(wirebuf) (read_uint16(wirebuf+QDCOUNT_OFF)) - -/* Counter of the answer section */ -#define ANCOUNT_OFF 6 -#define ANCOUNT(wirebuf) (read_uint16(wirebuf+ANCOUNT_OFF)) - -/* Counter of the authority section */ -#define NSCOUNT_OFF 8 -#define NSCOUNT(wirebuf) (read_uint16(wirebuf+NSCOUNT_OFF)) - -/* Counter of the additional section */ -#define ARCOUNT_OFF 10 -#define ARCOUNT(wirebuf) (read_uint16(wirebuf+ARCOUNT_OFF)) - /* Access functions * do this as functions to get type checking */ @@ -353,68 +239,3 @@ ldns_pkt_free(ldns_pkt *packet) FREE(packet); } -static size_t -ldns_wire2pkt_hdr(ldns_pkt *packet, - const uint8_t *wire, - size_t max, - size_t *pos) -{ - if (*pos + QHEADERSZ >= max) { - /* TODO: set t_status error. */ - return 0; - } else { - - pkt_set_id(packet, ID(wire)); - - pkt_set_qr(packet, QR(wire)); - pkt_set_opcode(packet, OPCODE(wire)); - pkt_set_aa(packet, AA(wire)); - pkt_set_tc(packet, TC(wire)); - pkt_set_rd(packet, RD(wire)); - pkt_set_ra(packet, RA(wire)); - pkt_set_ad(packet, AD(wire)); - pkt_set_cd(packet, CD(wire)); - pkt_set_rcode(packet, RCODE(wire)); - - pkt_set_qdcount(packet, QDCOUNT(wire)); - pkt_set_ancount(packet, ANCOUNT(wire)); - pkt_set_nscount(packet, NSCOUNT(wire)); - pkt_set_arcount(packet, ARCOUNT(wire)); - - *pos += QHEADERSZ; - /* TODO t_status succ. */ - return 0; - } -} - -/* TODO: error check, return status (of this and of wire2rrs) */ -size_t -ldns_wire2pkt(ldns_pkt *packet, const uint8_t *wire, size_t max) -{ - size_t pos = 0; - uint16_t i; - ldns_rr *rr; - size_t ret; - - pos += ldns_wire2pkt_hdr(packet, wire, max, &pos); - - /* TODO: section enum :) */ - for (i = 0; i < pkt_qdcount(packet); i++) { - rr = ldns_rr_new(); - ret = ldns_wire2rr(rr, wire, max, &pos, 0); - } - for (i = 0; i < pkt_ancount(packet); i++) { - rr = ldns_rr_new(); - ret = ldns_wire2rr(rr, wire, max, &pos, 1); - } - for (i = 0; i < pkt_nscount(packet); i++) { - rr = ldns_rr_new(); - ret = ldns_wire2rr(rr, wire, max, &pos, 2); - } - for (i = 0; i < pkt_arcount(packet); i++) { - rr = ldns_rr_new(); - ret = ldns_wire2rr(rr, wire, max, &pos, 3); - } - - return pos; -} diff --git a/rdata.c b/rdata.c index f93d73dc..831ade11 100644 --- a/rdata.c +++ b/rdata.c @@ -114,7 +114,7 @@ _ldns_octet(char *word, size_t *length) case '.': if (s[1] == '.') { fprintf(stderr,"Empty label"); - return LDNS_E_EMPTY_LABEL; + return LDNS_STATUS_EMPTY_LABEL; } *p = *s; *length++; @@ -134,7 +134,7 @@ _ldns_octet(char *word, size_t *length) *p = val; *length++; } else { - return LDNS_E_DDD_OVERFLOW; + return LDNS_STATUS_DDD_OVERFLOW; } } else { /* an espaced character, like \ ? @@ -153,7 +153,7 @@ _ldns_octet(char *word, size_t *length) if ( *s == '\0' ) { /* ok, it was the last one */ *p = '\0'; - return LDNS_E_OK; + return LDNS_STATUS_OK; } break; default: @@ -163,5 +163,5 @@ _ldns_octet(char *word, size_t *length) } } *p = '\0'; - return LDNS_E_OK; + return LDNS_STATUS_OK; } diff --git a/rr.c b/rr.c index d895803c..11a07bdc 100644 --- a/rr.c +++ b/rr.c @@ -355,145 +355,3 @@ ldns_rr_descriptor_field_type(ldns_rr_descriptor *descriptor, } } -/* TODO: general rdata2str or dname2str, with error - checks and return status etc */ -/* this is temp function for debugging wire2rr */ -/* do NOT pass compressed data here :p */ -void -ldns_dname2str(char *dest, uint8_t *dname) -{ - /* can we do with 1 pos var? or without at all? */ - uint8_t src_pos = 0; - uint8_t dest_pos = 0; - uint8_t len; - len = dname[src_pos]; - while (len > 0) { - src_pos++; - memcpy(&dest[dest_pos], &dname[src_pos], len); - dest_pos += len; - src_pos += len; - len = dname[src_pos]; - dest[dest_pos] = '.'; - dest_pos++; - } - dest_pos++; - dest[dest_pos] = '\0'; -} - -/* TODO: is there a better place for this function? - status_type return and remove printfs - #defines */ -size_t -ldns_wire2dname(uint8_t *dname, const uint8_t *wire, size_t max, size_t *pos) -{ - uint8_t label_size; - uint16_t pointer_target; - uint8_t *pointer_target_buf; - size_t dname_pos = 0; - size_t compression_pos = 0; - - if (*pos > max) { - /* TODO set error */ - return 0; - } - - label_size = wire[*pos]; - while (label_size > 0) { - /* compression */ - if (label_size >= 192) { - if (compression_pos == 0) { - compression_pos = *pos + 2; - } - - /* remove first two bits */ - /* TODO: can this be done in a better way? */ - pointer_target_buf = malloc(2); - pointer_target_buf[0] = wire[*pos] & 63; - pointer_target_buf[1] = wire[*pos+1]; - memcpy(&pointer_target, pointer_target_buf, 2); - pointer_target = ntohs(pointer_target); - - if (pointer_target == 0) { - fprintf(stderr, "POINTER TO 0\n"); - return 0; - } else if (pointer_target > max) { - fprintf(stderr, "POINTER TO OUTSIDE PACKET\n"); - return 0 ; - } - *pos = pointer_target; - label_size = wire[*pos]; - } - - if (label_size > MAXLABELLEN) { - /* TODO error: label size too large */ - fprintf(stderr, "LABEL SIZE ERROR: %d\n", - (int) label_size); - return 0; - } - if (*pos + label_size > max) { - /* TODO error: out of packet data */ - fprintf(stderr, "MAX PACKET ERROR: %d\n", - (int) (*pos + label_size)); - } - - dname[dname_pos] = label_size; - dname_pos++; - *pos = *pos + 1; - memcpy(&dname[dname_pos], &wire[*pos], label_size); - dname_pos += label_size; - *pos = *pos + label_size; - label_size = wire[*pos]; - } - - if (compression_pos > 0) { - *pos = compression_pos; - } else { - *pos = *pos + 1; - } - return *pos; -} - -/* TODO: ldns_status_type and error checking - defines for constants? - enum for sections? - remove owner print debug message - can *pos be incremented at READ_INT? or maybe use something like - RR_CLASS(wire)? -*/ -size_t -ldns_wire2rr(ldns_rr *rr, const uint8_t *wire, size_t max, - size_t *pos, int section) -{ - uint8_t *owner = malloc(MAXDOMAINLEN); - char *owner_str = malloc(MAXDOMAINLEN); - uint16_t rd_length; - - (void) ldns_wire2dname(owner, wire, max, pos); - - ldns_rr_set_owner(rr, owner); - - ldns_dname2str(owner_str, owner); - printf("owner: %s\n", owner_str); - FREE(owner_str); - - ldns_rr_set_class(rr, read_uint16(&wire[*pos])); - *pos = *pos + 2; - /* - ldns_rr_set_type(rr, read_uint16(&wire[*pos])); - */ - *pos = *pos + 2; - - if (section > 0) { - ldns_rr_set_ttl(rr, read_uint32(&wire[*pos])); - *pos = *pos + 4; - rd_length = read_uint16(&wire[*pos]); - *pos = *pos + 2; - /* TODO: wire2rdata */ - *pos = *pos + rd_length; - } - - return (size_t) 0; -} - - - diff --git a/run-test0.c b/run-test0.c index aab26265..e3fac25d 100644 --- a/run-test0.c +++ b/run-test0.c @@ -5,6 +5,7 @@ #include + #include #include "util.h" diff --git a/wire2host.c b/wire2host.c index c89a63f4..e57b6ff1 100644 --- a/wire2host.c +++ b/wire2host.c @@ -12,21 +12,142 @@ * * See the file LICENSE for the license */ +#include + +#include + +#include + +#include "util.h" + + +/* + * Set of macro's to deal with the dns message header as specified + * in RFC1035 in portable way. + * + */ + +/* + * + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ID | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | QDCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ANCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | NSCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ARCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + */ + +/* The length of the header */ +#define QHEADERSZ 12 + +/* First octet of flags */ +#define RD_MASK 0x01U +#define RD_SHIFT 0 +#define RD(wirebuf) (*(wirebuf+2) & RD_MASK) +#define RD_SET(wirebuf) (*(wirebuf+2) |= RD_MASK) +#define RD_CLR(wirebuf) (*(wirebuf+2) &= ~RD_MASK) + +#define TC_MASK 0x02U +#define TC_SHIFT 1 +#define TC(wirebuf) (*(wirebuf+2) & TC_MASK) +#define TC_SET(wirebuf) (*(wirebuf+2) |= TC_MASK) +#define TC_CLR(wirebuf) (*(wirebuf+2) &= ~TC_MASK) + +#define AA_MASK 0x04U +#define AA_SHIFT 2 +#define AA(wirebuf) (*(wirebuf+2) & AA_MASK) +#define AA_SET(wirebuf) (*(wirebuf+2) |= AA_MASK) +#define AA_CLR(wirebuf) (*(wirebuf+2) &= ~AA_MASK) + +#define OPCODE_MASK 0x78U +#define OPCODE_SHIFT 3 +#define OPCODE(wirebuf) ((*(wirebuf+2) & OPCODE_MASK) >> OPCODE_SHIFT) +#define OPCODE_SET(wirebuf, opcode) \ + (*(wirebuf+2) = ((*(wirebuf+2)) & ~OPCODE_MASK) | ((opcode) << OPCODE_SHIFT)) + +#define QR_MASK 0x80U +#define QR_SHIFT 7 +#define QR(wirebuf) (*(wirebuf+2) & QR_MASK) +#define QR_SET(wirebuf) (*(wirebuf+2) |= QR_MASK) +#define QR_CLR(wirebuf) (*(wirebuf+2) &= ~QR_MASK) + +/* Second octet of flags */ +#define RCODE_MASK 0x0fU +#define RCODE_SHIFT 0 +#define RCODE(wirebuf) (*(wirebuf+3) & RCODE_MASK) +#define RCODE_SET(wirebuf, rcode) \ + (*(wirebuf+3) = ((*(wirebuf+3)) & ~RCODE_MASK) | (rcode)) + +#define CD_MASK 0x10U +#define CD_SHIFT 4 +#define CD(wirebuf) (*(wirebuf+3) & CD_MASK) +#define CD_SET(wirebuf) (*(wirebuf+3) |= CD_MASK) +#define CD_CLR(wirebuf) (*(wirebuf+3) &= ~CD_MASK) + +#define AD_MASK 0x20U +#define AD_SHIFT 5 +#define AD(wirebuf) (*(wirebuf+3) & AD_MASK) +#define AD_SET(wirebuf) (*(wirebuf+3) |= AD_MASK) +#define AD_CLR(wirebuf) (*(wirebuf+3) &= ~AD_MASK) + +#define Z_MASK 0x40U +#define Z_SHIFT 6 +#define Z(wirebuf) (*(wirebuf+3) & Z_MASK) +#define Z_SET(wirebuf) (*(wirebuf+3) |= Z_MASK) +#define Z_CLR(wirebuf) (*(wirebuf+3) &= ~Z_MASK) + +#define RA_MASK 0x80U +#define RA_SHIFT 7 +#define RA(wirebuf) (*(wirebuf+3) & RA_MASK) +#define RA_SET(wirebuf) (*(wirebuf+3) |= RA_MASK) +#define RA_CLR(wirebuf) (*(wirebuf+3) &= ~RA_MASK) + +/* Query ID */ +#define ID(wirebuf) (ntohs(*(uint16_t *)(wirebuf))) + +/* Counter of the question section */ +#define QDCOUNT_OFF 4 +/* +#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) +*/ +#define QDCOUNT(wirebuf) (read_uint16(wirebuf+QDCOUNT_OFF)) + +/* Counter of the answer section */ +#define ANCOUNT_OFF 6 +#define ANCOUNT(wirebuf) (read_uint16(wirebuf+ANCOUNT_OFF)) + +/* Counter of the authority section */ +#define NSCOUNT_OFF 8 +#define NSCOUNT(wirebuf) (read_uint16(wirebuf+NSCOUNT_OFF)) + +/* Counter of the additional section */ +#define ARCOUNT_OFF 10 +#define ARCOUNT(wirebuf) (read_uint16(wirebuf+ARCOUNT_OFF)) + /** * transform a wireformatted rdata to our * internal representation. We need to the * length, and the type and put the data in */ +/* ssize_t -rdata_buf_to_rdf(ldns_rdf *rd, ldns_buf *buffer) +rdata_buf_to_rdf(ldns_rdf *rd, ldns_rdf *buffer) { - /* TODO TODO */ switch(RDATA_TYPESS) { case RDF_TYPE_NONE: break; case RDF_TYPE_DNAME: - /* can be compressed or not */ break; case RDF_TYPE_INT8: break; @@ -69,4 +190,234 @@ rdata_buf_to_rdf(ldns_rdf *rd, ldns_buf *buffer) } } +*/ + +/* TODO: general rdata2str or dname2str, with error + checks and return status etc */ +/* this is temp function for debugging wire2rr */ +/* do NOT pass compressed data here :p */ +void +ldns_dname2str(char *dest, ldns_rdf *dname) +{ + /* can we do with 1 pos var? or without at all? */ + uint8_t src_pos = 0; + uint8_t dest_pos = 0; + uint8_t len; + len = dname->_data[src_pos]; + while (len > 0) { + src_pos++; + memcpy(&dest[dest_pos], &(dname->_data[src_pos]), len); + dest_pos += len; + src_pos += len; + len = dname->_data[src_pos]; + dest[dest_pos] = '.'; + dest_pos++; + } + dest[dest_pos] = '\0'; +} + +/* TODO: is there a better place for this function? + status_type return and remove printfs + #defines */ +/* allocates memory to *dname! */ +ldns_status +ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos) +{ + uint8_t label_size; + uint16_t pointer_target; + uint8_t *pointer_target_buf; + size_t dname_pos = 0; + size_t uncompressed_length = 0; + size_t compression_pos = 0; + uint8_t *tmp_dname = XMALLOC(uint8_t, MAXDOMAINLEN); + + if (*pos > max) { + /* TODO set error */ + return 0; + } + + label_size = wire[*pos]; + while (label_size > 0) { + /* compression */ + if (label_size >= 192) { + if (compression_pos == 0) { + compression_pos = *pos + 2; + } + + /* remove first two bits */ + /* TODO: can this be done in a better way? */ + pointer_target_buf = malloc(2); + pointer_target_buf[0] = wire[*pos] & 63; + pointer_target_buf[1] = wire[*pos+1]; + memcpy(&pointer_target, pointer_target_buf, 2); + pointer_target = ntohs(pointer_target); + + if (pointer_target == 0) { + fprintf(stderr, "POINTER TO 0\n"); + return 0; + } else if (pointer_target > max) { + fprintf(stderr, "POINTER TO OUTSIDE PACKET\n"); + return 0 ; + } + *pos = pointer_target; + label_size = wire[*pos]; + } + + if (label_size > MAXLABELLEN) { + /* TODO error: label size too large */ + fprintf(stderr, "LABEL SIZE ERROR: %d\n", + (int) label_size); + return 0; + } + if (*pos + label_size > max) { + /* TODO error: out of packet data */ + fprintf(stderr, "MAX PACKET ERROR: %d\n", + (int) (*pos + label_size)); + } + + tmp_dname[dname_pos] = label_size; + dname_pos++; + *pos = *pos + 1; + memcpy(&tmp_dname[dname_pos], &wire[*pos], label_size); + uncompressed_length += label_size + 1; + dname_pos += label_size; + *pos = *pos + label_size; + label_size = wire[*pos]; + } + + if (compression_pos > 0) { + *pos = compression_pos; + } else { + *pos = *pos + 1; + } + + tmp_dname[dname_pos] = 0; + + *dname = MALLOC(ldns_rdf); + (*dname)->_type = LDNS_RDF_TYPE_DNAME; + (*dname)->_size = (uint16_t) dname_pos; + (*dname)->_data = XMALLOC(uint8_t, dname_pos); + memcpy((*dname)->_data, tmp_dname, dname_pos); + FREE(tmp_dname); + + return LDNS_STATUS_OK; +} + +/* maybe make this a goto error so data can be freed or something/ */ +#define STATUS_CHECK_RETURN(st) {if (st != LDNS_STATUS_OK) { return st; }} + +/* TODO: ldns_status_type and error checking + defines for constants? + enum for sections? + remove owner print debug message + can *pos be incremented at READ_INT? or maybe use something like + RR_CLASS(wire)? +*/ +ldns_status +ldns_wire2rr(ldns_rr *rr, const uint8_t *wire, size_t max, + size_t *pos, int section) +{ + ldns_rdf *owner; + char *owner_str = malloc(MAXDOMAINLEN); + uint16_t rd_length; + ldns_status status = LDNS_STATUS_OK; + + status = ldns_wire2dname(&owner, wire, max, pos); +/* + ldns_rr_set_owner(rr, owner); +*/ + ldns_dname2str(owner_str, owner); + printf("owner: %s\n", owner_str); + FREE(owner_str); + + ldns_rr_set_class(rr, read_uint16(&wire[*pos])); + *pos = *pos + 2; + /* + ldns_rr_set_type(rr, read_uint16(&wire[*pos])); + */ + *pos = *pos + 2; + + if (section > 0) { + ldns_rr_set_ttl(rr, read_uint32(&wire[*pos])); + *pos = *pos + 4; + rd_length = read_uint16(&wire[*pos]); + *pos = *pos + 2; + /* TODO: wire2rdata */ + *pos = *pos + rd_length; + } + + return (size_t) 0; +} + +static ldns_status +ldns_wire2pkt_hdr(ldns_pkt *packet, + const uint8_t *wire, + size_t max, + size_t *pos) +{ + if (*pos + QHEADERSZ >= max) { + /* TODO: set t_status error. */ + return LDNS_PACKET_OVERFLOW; + } else { + + pkt_set_id(packet, ID(wire)); + + pkt_set_qr(packet, QR(wire)); + pkt_set_opcode(packet, OPCODE(wire)); + pkt_set_aa(packet, AA(wire)); + pkt_set_tc(packet, TC(wire)); + pkt_set_rd(packet, RD(wire)); + pkt_set_ra(packet, RA(wire)); + pkt_set_ad(packet, AD(wire)); + pkt_set_cd(packet, CD(wire)); + pkt_set_rcode(packet, RCODE(wire)); + + pkt_set_qdcount(packet, QDCOUNT(wire)); + pkt_set_ancount(packet, ANCOUNT(wire)); + pkt_set_nscount(packet, NSCOUNT(wire)); + pkt_set_arcount(packet, ARCOUNT(wire)); + + *pos += QHEADERSZ; + /* TODO t_status succ. */ + return LDNS_STATUS_OK; + } +} + +/* TODO: error check, return status (of this and of wire2rrs) */ +ldns_status +ldns_wire2pkt(ldns_pkt *packet, const uint8_t *wire, size_t max) +{ + size_t pos = 0; + uint16_t i; + ldns_rr *rr; + ldns_status status = LDNS_STATUS_OK; + + status = ldns_wire2pkt_hdr(packet, wire, max, &pos); + STATUS_CHECK_RETURN(status); + + /* TODO: section enum :) */ + for (i = 0; i < pkt_qdcount(packet); i++) { + rr = ldns_rr_new(); + status = ldns_wire2rr(rr, wire, max, &pos, 0); + STATUS_CHECK_RETURN(status); + } + for (i = 0; i < pkt_ancount(packet); i++) { + rr = ldns_rr_new(); + status = ldns_wire2rr(rr, wire, max, &pos, 1); + + STATUS_CHECK_RETURN(status); + } + for (i = 0; i < pkt_nscount(packet); i++) { + rr = ldns_rr_new(); + status = ldns_wire2rr(rr, wire, max, &pos, 2); + STATUS_CHECK_RETURN(status); + } + for (i = 0; i < pkt_arcount(packet); i++) { + rr = ldns_rr_new(); + status = ldns_wire2rr(rr, wire, max, &pos, 3); + STATUS_CHECK_RETURN(status); + } + + return status; +}