diff options
Diffstat (limited to 'src/libknot/packet/packet.c')
-rw-r--r-- | src/libknot/packet/packet.c | 316 |
1 files changed, 179 insertions, 137 deletions
diff --git a/src/libknot/packet/packet.c b/src/libknot/packet/packet.c index 2e6e922..52ed72b 100644 --- a/src/libknot/packet/packet.c +++ b/src/libknot/packet/packet.c @@ -14,12 +14,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <config.h> #include <assert.h> +#include <stdlib.h> #include "packet/packet.h" #include "util/debug.h" #include "common.h" -#include "util/descriptor.h" +#include "common/descriptor.h" #include "util/wire.h" #include "tsig.h" @@ -35,13 +37,6 @@ ? DEFAULT_##type##_QUERY \ : DEFAULT_##type) - - -typedef enum { - KNOT_PACKET_DUPL_IGNORE, - KNOT_PACKET_DUPL_SKIP, - KNOT_PACKET_DUPL_MERGE -} knot_packet_duplicate_handling_t; /*----------------------------------------------------------------------------*/ /* Non-API functions */ /*----------------------------------------------------------------------------*/ @@ -52,7 +47,7 @@ typedef enum { static void knot_packet_init_pointers_response(knot_packet_t *pkt) { dbg_packet_detail("Packet pointer: %p\n", pkt); - + char *pos = (char *)pkt + PREALLOC_PACKET; // put QNAME directly after the structure @@ -66,10 +61,6 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt) pkt->question.qname->labels = (uint8_t *)pos; pos += PREALLOC_QNAME_LABELS; - pkt->owner_tmp = (uint8_t *)pos; - dbg_packet_detail("Tmp owner: %p\n", pkt->owner_tmp); - pos += PREALLOC_RR_OWNER; - // then answer, authority and additional sections if (DEFAULT_ANCOUNT == 0) { pkt->answer = NULL; @@ -77,14 +68,14 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt) pkt->answer = (const knot_rrset_t **)pos; pos += DEFAULT_ANCOUNT * sizeof(const knot_rrset_t *); } - + if (DEFAULT_NSCOUNT == 0) { pkt->authority = NULL; } else { pkt->authority = (const knot_rrset_t **)pos; pos += DEFAULT_NSCOUNT * sizeof(const knot_rrset_t *); } - + if (DEFAULT_ARCOUNT == 0) { pkt->additional = NULL; } else { @@ -100,21 +91,6 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt) pkt->max_ns_rrsets = DEFAULT_NSCOUNT; pkt->max_ar_rrsets = DEFAULT_ARCOUNT; - // then domain names for compression and offsets - pkt->compression.dnames = (const knot_dname_t **)pos; - pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(const knot_dname_t *); - pkt->compression.offsets = (size_t *)pos; - pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(size_t); - pkt->compression.to_free = (int *)pos; - pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(int); - - dbg_packet_detail("Compression dnames: %p\n", pkt->compression.dnames); - dbg_packet_detail("Compression offsets: %p\n", pkt->compression.offsets); - dbg_packet_detail("Compression to_free: %p\n", pkt->compression.to_free); - - pkt->compression.max = DEFAULT_DOMAINS_IN_RESPONSE; - pkt->compression.default_count = DEFAULT_DOMAINS_IN_RESPONSE; - // wildcard nodes and SNAMEs associated with them pkt->wildcard_nodes.nodes = (const knot_node_t **)pos; pos += DEFAULT_WILDCARD_NODES * sizeof(const knot_node_t *); @@ -145,7 +121,7 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt) static void knot_packet_init_pointers_query(knot_packet_t *pkt) { dbg_packet_detail("Packet pointer: %p\n", pkt); - + char *pos = (char *)pkt + PREALLOC_PACKET; // put QNAME directly after the structure @@ -169,14 +145,14 @@ static void knot_packet_init_pointers_query(knot_packet_t *pkt) pkt->answer = (const knot_rrset_t **)pos; pos += DEFAULT_ANCOUNT_QUERY * sizeof(const knot_rrset_t *); } - + if (DEFAULT_NSCOUNT_QUERY == 0) { pkt->authority = NULL; } else { pkt->authority = (const knot_rrset_t **)pos; pos += DEFAULT_NSCOUNT_QUERY * sizeof(const knot_rrset_t *); } - + if (DEFAULT_ARCOUNT_QUERY == 0) { pkt->additional = NULL; } else { @@ -232,10 +208,8 @@ static int knot_packet_parse_header(const uint8_t *wire, size_t *pos, } header->id = knot_wire_get_id(wire); - // copy some of the flags: OPCODE and RD - // do this by copying flags1 and setting QR to 1, AA to 0 and TC to 0 header->flags1 = knot_wire_get_flags1(wire); - // do not copy flags2 (all set by server) + header->flags2 = knot_wire_get_flags2(wire); header->qdcount = knot_wire_get_qdcount(wire); header->ancount = knot_wire_get_ancount(wire); @@ -298,6 +272,7 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos, if (question->qname == NULL) { return KNOT_ENOMEM; } + knot_dname_to_lower(question->qname); } else { assert(question->qname != NULL); /* When alloc=0, must be set. */ void *parsed = knot_dname_parse_from_wire(wire, pos, @@ -306,6 +281,7 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos, if (!parsed) { return KNOT_EMALF; } + knot_dname_to_lower(question->qname); } question->qtype = knot_wire_read_u16(wire + i + 1); question->qclass = knot_wire_read_u16(wire + i + 3); @@ -356,26 +332,74 @@ static int knot_packet_realloc_rrsets(const knot_rrset_t ***rrsets, /*----------------------------------------------------------------------------*/ -static knot_rdata_t *knot_packet_parse_rdata(const uint8_t *wire, - size_t *pos, size_t total_size, size_t rdlength, - const knot_rrtype_descriptor_t *desc) +static int knot_packet_parse_rdata(knot_rrset_t *rr, const uint8_t *wire, + size_t *pos, size_t total_size, + size_t rdlength) { - knot_rdata_t *rdata = knot_rdata_new(); - if (rdata == NULL) { - return NULL; + if (!rr || !wire || !pos || rdlength == 0) { + return KNOT_EINVAL; } - int rc = knot_rdata_from_wire(rdata, wire, pos, total_size, rdlength, - desc); - if (rc != KNOT_EOK) { - dbg_packet("rdata_from_wire() returned: %s\n", - knot_strerror(rc)); - knot_rdata_free(&rdata); - return NULL; - } - return rdata; + /*! \todo As I'm revising it, seems highly inefficient to me. + * We just need to skim through the packet, + * check if it is in valid format and store pointers to various + * parts in rdata instead of copying memory blocks and + * parsing domain names (with additional allocation) and then + * use use the wireformat for lookup again. Compression could + * be handled in-situ without additional memory allocs... + */ + + int ret = knot_rrset_rdata_from_wire_one(rr, wire, pos, total_size, + rdlength); + if (ret != KNOT_EOK) { + dbg_packet("packet: parse_rdata: Failed to parse RDATA (%s).\n", + knot_strerror(ret)); + return ret; + } + +// uint8_t* rd = knot_rrset_create_rdata(rr, rdlength); +// if (!rd) { +// return KNOT_ERROR; +// } +// uint8_t* np = rd + rdlength; + +// const rdata_descriptor_t *desc = get_rdata_descriptor(knot_rrset_type(rr)); +// if (!desc) { +// /*! \todo Free rdata mem ? Not essential, but nice. */ +// return KNOT_EINVAL; +// } + +// for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) { +// const int id = desc->block_types[i]; +// if (descriptor_item_is_dname(id)) { +// knot_dname_t *dn = NULL; +// dn = knot_dname_parse_from_wire(wire, pos, total_size, NULL, NULL); +// if (dn == NULL) { +// return KNOT_EMALF; +// } +// /* Store ptr in rdata. */ +// *((knot_dname_t**)rd) = dn; +// rd += sizeof(knot_dname_t*); +// } else if (descriptor_item_is_fixed(id)) { +// memcpy(rd, wire + *pos, id); +// rd += id; /* Item represents fixed len here */ +// *pos += id; +// } else if (descriptor_item_is_remainder(id)) { +// size_t rchunk = np - rd; +// memcpy(rd, wire + *pos, rchunk); +// rd += rchunk; +// *pos += rchunk; +// } else { +// //NAPTR +// assert(knot_rrset_type(rr) == KNOT_RRTYPE_NAPTR); +// assert(0); +// } + +// } + + return KNOT_EOK; } /*----------------------------------------------------------------------------*/ @@ -393,6 +417,7 @@ static knot_rrset_t *knot_packet_parse_rr(const uint8_t *wire, size_t *pos, if (owner == NULL) { return NULL; } + knot_dname_to_lower(owner); dbg_packet_exec_verb( char *name = knot_dname_to_str(owner); @@ -435,7 +460,7 @@ dbg_packet_exec_verb( if (size - *pos < rdlength) { dbg_packet("Malformed RR: Not enough data to parse RR" " RDATA (size: %zu, position: %zu).\n", size, *pos); - knot_rrset_deep_free(&rrset, 1, 1, 0); + knot_rrset_deep_free(&rrset, 1, 1); return NULL; } @@ -445,20 +470,14 @@ dbg_packet_exec_verb( return rrset; } + // parse RDATA - knot_rdata_t *rdata = knot_packet_parse_rdata(wire, pos, size, - rdlength, - knot_rrtype_descriptor_by_type(rrset->type)); - if (rdata == NULL) { + /*! \todo Merge with add_rdata_to_rr in zcompile, should be a rrset func + * probably. */ + int ret = knot_packet_parse_rdata(rrset, wire, pos, size, rdlength); + if (ret != KNOT_EOK) { dbg_packet("Malformed RR: Could not parse RDATA.\n"); - knot_rrset_deep_free(&rrset, 1, 1, 0); - return NULL; - } - - if (knot_rrset_add_rdata(rrset, rdata) != KNOT_EOK) { - dbg_packet("Malformed RR: Could not add RDATA to RRSet.\n"); - knot_rdata_free(&rdata); - knot_rrset_deep_free(&rrset, 1, 1, 0); + knot_rrset_deep_free(&rrset, 1, 1); return NULL; } @@ -473,7 +492,7 @@ static int knot_packet_add_rrset(knot_rrset_t *rrset, short *max_rrsets, short default_rrsets, const knot_packet_t *packet, - knot_packet_duplicate_handling_t dupl) + knot_packet_flag_t flags) { assert(rrset != NULL); assert(rrsets != NULL); @@ -482,8 +501,8 @@ static int knot_packet_add_rrset(knot_rrset_t *rrset, dbg_packet_exec_verb( char *name = knot_dname_to_str(rrset->owner); - dbg_packet_verb("packet_add_rrset(), owner: %s, type: %s\n", - name, knot_rrtype_to_string(rrset->type)); + dbg_packet_verb("packet_add_rrset(), owner: %s, type: %u\n", + name, rrset->type); free(name); ); @@ -493,33 +512,30 @@ dbg_packet_exec_verb( return KNOT_ENOMEM; } - if (dupl == KNOT_PACKET_DUPL_SKIP && + if ((flags & KNOT_PACKET_DUPL_SKIP) && knot_packet_contains(packet, rrset, KNOT_RRSET_COMPARE_PTR)) { - /*! \todo This should also return > 0, as it means that the - RRSet was not used actually. */ - return KNOT_EOK; + return 2; } - if (dupl == KNOT_PACKET_DUPL_MERGE) { + // Try to merge rdata to rrset if flag NO_MERGE isn't set. + if ((flags & KNOT_PACKET_DUPL_NO_MERGE) == 0) { // try to find the RRSet in this array of RRSets for (int i = 0; i < *rrset_count; ++i) { - dbg_packet_exec_detail( char *name = knot_dname_to_str((*rrsets)[i]->owner); dbg_packet_detail("Comparing to RRSet: owner: %s, " - "type: %s\n", name, - knot_rrtype_to_string( - (*rrsets)[i]->type)); + "type: %u\n", name, + (*rrsets)[i]->type); free(name); ); - if (knot_rrset_match((*rrsets)[i], rrset, + if (knot_rrset_equal((*rrsets)[i], rrset, KNOT_RRSET_COMPARE_HEADER)) { /*! \todo Test this!!! */ // no duplicate checking here, the packet should // look exactly as it came from wire int rc = knot_rrset_merge( - (void **)((*rrsets) + i), (void **)&rrset); + ((knot_rrset_t *)(*rrsets)[i]), rrset); if (rc != KNOT_EOK) { return rc; } @@ -542,7 +558,8 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos, const knot_rrset_t ***rrsets, short *rrset_count, short *max_rrsets, short default_rrsets, - knot_packet_t *packet) + knot_packet_t *packet, + knot_packet_flag_t flags) { assert(pos != NULL); assert(wire != NULL); @@ -573,13 +590,15 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos, ++(*parsed_rrs); err = knot_packet_add_rrset(rrset, rrsets, rrset_count, - max_rrsets, default_rrsets, packet, - KNOT_PACKET_DUPL_MERGE); + max_rrsets, default_rrsets, packet, flags); if (err < 0) { break; - } else if (err > 0) { // merged + } else if (err == 1) { // merged, shallow data copy dbg_packet_detail("RRSet merged, freeing.\n"); - knot_rrset_deep_free(&rrset, 1, 0, 0); // TODO: ok?? + knot_rrset_deep_free(&rrset, 1, 0); + continue; + } else if (err == 2) { // skipped + knot_rrset_deep_free(&rrset, 1, 1); continue; } @@ -588,7 +607,7 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos, // remove the last RRSet from the list of RRSets // - just decrement the count --(*rrset_count); - knot_rrset_deep_free(&rrset, 1, 1, 1); + knot_rrset_deep_free(&rrset, 1, 1); break; } @@ -638,12 +657,6 @@ static void knot_packet_free_allocated_space(knot_packet_t *pkt) free(pkt->additional); } - if (pkt->compression.max > pkt->compression.default_count) { - free(pkt->compression.dnames); - free(pkt->compression.offsets); - free(pkt->compression.to_free); - } - if (pkt->wildcard_nodes.max > pkt->wildcard_nodes.default_count) { free(pkt->wildcard_nodes.nodes); free(pkt->wildcard_nodes.snames); @@ -656,8 +669,8 @@ static void knot_packet_free_allocated_space(knot_packet_t *pkt) /*----------------------------------------------------------------------------*/ -static int knot_packet_parse_rr_sections(knot_packet_t *packet, - size_t *pos) +static int knot_packet_parse_rr_sections(knot_packet_t *packet, size_t *pos, + knot_packet_flag_t flags) { assert(packet != NULL); assert(packet->wireformat != NULL); @@ -673,7 +686,7 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, if ((err = knot_packet_parse_rrs(packet->wireformat, pos, packet->size, packet->header.ancount, &packet->parsed_an, &packet->answer, &packet->an_rrsets, &packet->max_an_rrsets, - DEFAULT_RRSET_COUNT(ANCOUNT, packet), packet)) != KNOT_EOK) { + DEFAULT_RRSET_COUNT(ANCOUNT, packet), packet, flags)) != KNOT_EOK) { return err; } @@ -686,7 +699,7 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, if ((err = knot_packet_parse_rrs(packet->wireformat, pos, packet->size, packet->header.nscount, &packet->parsed_ns, &packet->authority, &packet->ns_rrsets, &packet->max_ns_rrsets, - DEFAULT_RRSET_COUNT(NSCOUNT, packet), packet)) != KNOT_EOK) { + DEFAULT_RRSET_COUNT(NSCOUNT, packet), packet, flags)) != KNOT_EOK) { return err; } @@ -699,7 +712,7 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, if ((err = knot_packet_parse_rrs(packet->wireformat, pos, packet->size, packet->header.arcount, &packet->parsed_ar, &packet->additional, &packet->ar_rrsets, &packet->max_ar_rrsets, - DEFAULT_RRSET_COUNT(ARCOUNT, packet), packet)) != KNOT_EOK) { + DEFAULT_RRSET_COUNT(ARCOUNT, packet), packet, flags)) != KNOT_EOK) { return err; } @@ -744,7 +757,14 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc) { - knot_packet_t *pkt; + mm_ctx_t mm; + mm_ctx_init(&mm); + return knot_packet_new_mm(prealloc, &mm); +} + +knot_packet_t *knot_packet_new_mm(knot_packet_prealloc_type_t prealloc, mm_ctx_t *mm) +{ + knot_packet_t *pkt = NULL; void (*init_pointers)(knot_packet_t *pkt) = NULL; size_t size = 0; @@ -762,9 +782,10 @@ knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc) break; } - pkt = (knot_packet_t *)malloc(size); + pkt = (knot_packet_t *)mm->alloc(mm->ctx, size); CHECK_ALLOC_LOG(pkt, NULL); memset(pkt, 0, size); + memcpy(&pkt->mm, mm, sizeof(mm_ctx_t)); if (init_pointers != NULL) { init_pointers(pkt); } @@ -781,7 +802,7 @@ knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc) int knot_packet_parse_from_wire(knot_packet_t *packet, const uint8_t *wireformat, size_t size, - int question_only) + int question_only, knot_packet_flag_t flags) { if (packet == NULL || wireformat == NULL) { return KNOT_EINVAL; @@ -821,7 +842,7 @@ int knot_packet_parse_from_wire(knot_packet_t *packet, if (packet->header.qdcount == 1) { if ((err = knot_packet_parse_question(wireformat, &pos, size, - &packet->question, packet->prealloc_type + &packet->question, packet->prealloc_type == KNOT_PACKET_PREALLOC_NONE) ) != KNOT_EOK) { return err; @@ -838,7 +859,7 @@ dbg_packet_exec_detail( } /*! \todo Replace by call to parse_rest()? */ - err = knot_packet_parse_rest(packet); + err = knot_packet_parse_rest(packet, flags); dbg_packet_exec_detail( knot_packet_dump(packet); @@ -849,7 +870,7 @@ dbg_packet_exec_detail( /*----------------------------------------------------------------------------*/ -int knot_packet_parse_rest(knot_packet_t *packet) +int knot_packet_parse_rest(knot_packet_t *packet, knot_packet_flag_t flags) { if (packet == NULL) { return KNOT_EINVAL; @@ -864,13 +885,13 @@ int knot_packet_parse_rest(knot_packet_t *packet) // If there is less data then required, the next function will find out. // If there is more data than required, it also returns EMALF. - + size_t pos = packet->parsed; /*! \todo If we already parsed some part of the packet, it is not ok * to begin parsing from the Answer section. */ - return knot_packet_parse_rr_sections(packet, &pos); + return knot_packet_parse_rr_sections(packet, &pos, flags); } /*----------------------------------------------------------------------------*/ @@ -898,7 +919,7 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet, if (packet->parsed_an == packet->header.ancount) { assert(packet->parsed < packet->size); //dbg_packet("Trailing garbage, ignoring...\n"); - // there may be other data in the packet + // there may be other data in the packet // (authority or additional). return KNOT_EOK; } @@ -911,7 +932,7 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet, dbg_packet_verb("Failed to parse RR!\n"); return KNOT_EMALF; } - + dbg_packet_detail("Parsed. Pos: %zu.\n", pos); packet->parsed = pos; @@ -960,7 +981,7 @@ int knot_packet_parse_next_rr_additional(knot_packet_t *packet, dbg_packet_verb("Failed to parse RR!\n"); return KNOT_EMALF; } - + dbg_packet_detail("Parsed. Pos: %zu.\n", pos); packet->parsed = pos; @@ -981,6 +1002,13 @@ size_t knot_packet_size(const knot_packet_t *packet) /*----------------------------------------------------------------------------*/ +size_t knot_packet_max_size(const knot_packet_t *packet) +{ + return packet->max_size; +} + +/*----------------------------------------------------------------------------*/ + size_t knot_packet_question_size(const knot_packet_t *packet) { return (KNOT_WIRE_HEADER_SIZE + 4 @@ -1005,7 +1033,7 @@ int knot_packet_set_max_size(knot_packet_t *packet, int max_size) if (packet->max_size < max_size) { // reallocate space for the wire format (and copy anything // that might have been there before - uint8_t *wire_new = (uint8_t *)malloc(max_size); + uint8_t *wire_new = packet->mm.alloc(packet->mm.ctx, max_size); if (wire_new == NULL) { return KNOT_ENOMEM; } @@ -1016,7 +1044,8 @@ int knot_packet_set_max_size(knot_packet_t *packet, int max_size) packet->wireformat = wire_new; if (packet->max_size > 0 && packet->free_wireformat) { - free(wire_old); + if (packet->mm.free) + packet->mm.free(wire_old); } packet->free_wireformat = 1; @@ -1068,6 +1097,14 @@ uint8_t knot_packet_opcode(const knot_packet_t *packet) /*----------------------------------------------------------------------------*/ +knot_question_t *knot_packet_question(knot_packet_t *packet) +{ + if (packet == NULL) return NULL; + return &packet->question; +} + +/*----------------------------------------------------------------------------*/ + const knot_dname_t *knot_packet_qname(const knot_packet_t *packet) { if (packet == NULL) { @@ -1087,7 +1124,7 @@ uint16_t knot_packet_qtype(const knot_packet_t *packet) /*----------------------------------------------------------------------------*/ -void knot_packet_set_qtype(knot_packet_t *packet, knot_rr_type_t qtype) +void knot_packet_set_qtype(knot_packet_t *packet, uint16_t qtype) { assert(packet != NULL); packet->question.qtype = qtype; @@ -1130,7 +1167,7 @@ int knot_packet_rcode(const knot_packet_t *packet) if (packet == NULL) { return KNOT_EINVAL; } - + return knot_wire_flags_get_rcode(packet->header.flags2); } @@ -1141,7 +1178,7 @@ int knot_packet_tc(const knot_packet_t *packet) if (packet == NULL) { return KNOT_EINVAL; } - + return knot_wire_flags_get_tc(packet->header.flags1); } @@ -1290,19 +1327,19 @@ int knot_packet_contains(const knot_packet_t *packet, } for (int i = 0; i < packet->an_rrsets; ++i) { - if (knot_rrset_match(packet->answer[i], rrset, cmp)) { + if (knot_rrset_equal(packet->answer[i], rrset, cmp)) { return 1; } } for (int i = 0; i < packet->ns_rrsets; ++i) { - if (knot_rrset_match(packet->authority[i], rrset, cmp)) { + if (knot_rrset_equal(packet->authority[i], rrset, cmp)) { return 1; } } for (int i = 0; i < packet->ar_rrsets; ++i) { - if (knot_rrset_match(packet->additional[i], rrset, cmp)) { + if (knot_rrset_equal(packet->additional[i], rrset, cmp)) { return 1; } } @@ -1351,18 +1388,18 @@ dbg_packet_exec( char *name = knot_dname_to_str( (((knot_rrset_t **)(pkt->tmp_rrsets))[i])->owner); dbg_packet_verb("Freeing tmp RRSet on ptr: %p (ptr to ptr:" - " %p, type: %s, owner: %s)\n", + " %p, type: %u, owner: %s)\n", (((knot_rrset_t **)(pkt->tmp_rrsets))[i]), &(((knot_rrset_t **)(pkt->tmp_rrsets))[i]), - knot_rrtype_to_string( - (((knot_rrset_t **)(pkt->tmp_rrsets))[i])->type), + (((knot_rrset_t **)(pkt->tmp_rrsets))[i])->type, name); free(name); ); // TODO: this is quite ugly, but better than copying whole // function (for reallocating rrset array) + // TODO sort out freeing, this WILL leak. knot_rrset_deep_free( - &(((knot_rrset_t **)(pkt->tmp_rrsets))[i]), 1, 1, 1); + &(((knot_rrset_t **)(pkt->tmp_rrsets))[i]), 1, 1); } } @@ -1490,32 +1527,22 @@ void knot_packet_free(knot_packet_t **packet) dbg_packet("Freeing tmp RRSets...\n"); knot_packet_free_tmp_rrsets(*packet); - dbg_packet("Freeing copied dnames for compression...\n"); - for (int i = 0; i < (*packet)->compression.count; ++i) { - if ((*packet)->compression.to_free[i]) { - knot_dname_release( - (knot_dname_t *)(*packet)->compression.dnames[i]); - } - } - - /*! \note The above code will free the domain names pointed to by - * the list of wildcard nodes. It should not matter, however. - */ - // check if some additional space was allocated for the packet dbg_packet("Freeing additional allocated space...\n"); knot_packet_free_allocated_space(*packet); // free the space for wireformat if ((*packet)->wireformat != NULL && (*packet)->free_wireformat) { - free((*packet)->wireformat); + if ((*packet)->mm.free) + (*packet)->mm.free((*packet)->wireformat); } // free EDNS options knot_edns_free_options(&(*packet)->opt_rr); dbg_packet("Freeing packet structure\n"); - free(*packet); + if ((*packet)->mm.free) + (*packet)->mm.free(*packet); *packet = NULL; } @@ -1527,7 +1554,7 @@ static void knot_packet_dump_rrsets(const knot_rrset_t **rrsets, assert((rrsets != NULL && *rrsets != NULL) || count < 1); for (int i = 0; i < count; ++i) { - knot_rrset_dump(rrsets[i], 0); + knot_rrset_dump(rrsets[i]); } } #endif @@ -1566,10 +1593,10 @@ void knot_packet_dump(const knot_packet_t *packet) char *qname = knot_dname_to_str(packet->question.qname); dbg_packet(" QNAME: %s\n", qname); free(qname); - dbg_packet(" QTYPE: %u (%s)\n", packet->question.qtype, - knot_rrtype_to_string(packet->question.qtype)); - dbg_packet(" QCLASS: %u (%s)\n", packet->question.qclass, - knot_rrclass_to_string(packet->question.qclass)); + dbg_packet(" QTYPE: %u (%u)\n", packet->question.qtype, + packet->question.qtype); + dbg_packet(" QCLASS: %u (%u)\n", packet->question.qclass, + packet->question.qclass); } dbg_packet("\nAnswer RRSets:\n"); @@ -1592,3 +1619,18 @@ void knot_packet_dump(const knot_packet_t *packet) #endif } +static int knot_packet_free_section(const knot_rrset_t **s, short count) { + /*! \todo The API is really incompatible here. */ + for (short i = 0; i < count; ++i) + knot_rrset_deep_free((knot_rrset_t **)s + i, 1, 1); + return count; +} + +int knot_packet_free_rrsets(knot_packet_t *packet) +{ + int ret = 0; + ret += knot_packet_free_section(packet->answer, packet->an_rrsets); + ret += knot_packet_free_section(packet->authority, packet->ns_rrsets); + ret += knot_packet_free_section(packet->additional, packet->ar_rrsets); + return ret; +} |