diff --git a/src/common/mempattern.h b/src/common/mempattern.h index 7bef8513616633dfcbcff69a692b9d9b64d7223a..c7062cafadaaa7c2439fe586702ad1a6f071596b 100644 --- a/src/common/mempattern.h +++ b/src/common/mempattern.h @@ -34,6 +34,9 @@ typedef void* (*mm_alloc_t)(void* ctx, size_t len); typedef void (*mm_free_t)(void *p); typedef void (*mm_flush_t)(void *p); +/* Reusable functions. */ +static inline void mm_nofree(void *p) {} + /* Memory allocation context. */ typedef struct mm_ctx { void *ctx; /* \note Must be first */ diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y index 663adad2e59c87515b8c9c566ad999ce8968cee2..9aab081e6355acdcb482cc62402086ce5a993ec6 100644 --- a/src/knot/conf/cf-parse.y +++ b/src/knot/conf/cf-parse.y @@ -263,7 +263,7 @@ static void conf_acl_item(void *scanner, char *item) static int conf_key_exists(void *scanner, char *item) { /* Find existing node in keys. */ - knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item), 0); + knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item)); conf_key_t* r = 0; WALK_LIST (r, new_config->keys) { if (knot_dname_compare(r->k.name, sample) == 0) { @@ -283,7 +283,7 @@ static int conf_key_add(void *scanner, knot_tsig_key_t **key, char *item) *key = 0; /* Find in keys */ - knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item), 0); + knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item)); conf_key_t* r = 0; WALK_LIST (r, new_config->keys) { @@ -338,7 +338,7 @@ static void conf_zone_start(void *scanner, char *name) { /* Check domain name. */ knot_dname_t *dn = NULL; if (this_zone->name != NULL) { - dn = knot_dname_new_from_str(this_zone->name, nlen, 0); + dn = knot_dname_new_from_str(this_zone->name, nlen); } if (dn == NULL) { free(this_zone->name); @@ -608,7 +608,7 @@ keys: } if (fqdn != NULL && !conf_key_exists(scanner, fqdn)) { - knot_dname_t *dname = knot_dname_new_from_str(fqdn, fqdnl, 0); + knot_dname_t *dname = knot_dname_new_from_str(fqdn, fqdnl); if (!dname) { cf_error(scanner, "key name '%s' not in valid domain name format", fqdn); diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c index 35af4368883746ad800868cdde82f71ebc2065e0..12bee2600076471da6e7eae4e28ab48747526a79 100644 --- a/src/knot/ctl/knotc_main.c +++ b/src/knot/ctl/knotc_main.c @@ -145,7 +145,7 @@ static int cmd_remote_print_reply(const knot_rrset_t *rr) static int cmd_remote_reply(int c) { uint8_t *rwire = malloc(SOCKET_MTU_SZ); - knot_packet_t *reply = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE); + knot_packet_t *reply = knot_packet_new(); if (!rwire || !reply) { free(rwire); knot_packet_free(&reply); diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c index 685a48b6235ae2b8c8907f7dc6c9904670393c60..9ccfa3faba20bd9d231eaa5de9523db0548e4f84 100644 --- a/src/knot/ctl/remote.c +++ b/src/knot/ctl/remote.c @@ -454,7 +454,7 @@ static int remote_send_chunk(int c, knot_packet_t *pkt, const char* d, uint16_t dlen, uint8_t* rwire, size_t rlen) { int ret = KNOT_ERROR; - knot_packet_t *resp = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE); + knot_packet_t *resp = knot_packet_new_mm(&pkt->mm); if (!resp) { return ret; } @@ -465,7 +465,7 @@ static int remote_send_chunk(int c, knot_packet_t *pkt, const char* d, knot_packet_free(&resp); return ret; } - ret = knot_response_init_from_query(resp, pkt, 1); + ret = knot_response_init_from_query(resp, pkt); if (ret != KNOT_EOK) { knot_packet_free(&resp); return ret; @@ -525,7 +525,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_ } knot_dname_t *realm = knot_dname_new_from_str(KNOT_CTL_REALM, - KNOT_CTL_REALM_LEN, NULL); + KNOT_CTL_REALM_LEN); if (!knot_dname_is_subdomain(qname, realm) != 0) { dbg_server("remote: qname != *%s\n", KNOT_CTL_REALM_EXT); knot_dname_free(&realm); @@ -536,7 +536,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_ /* Command: * QNAME: leftmost label of QNAME */ - size_t cmd_len = knot_dname_label_size(qname, 0); + size_t cmd_len = *knot_dname_name(qname); char *cmd = strndup((char*)qname->name + 1, cmd_len); /* Data: @@ -588,7 +588,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_ int remote_process(server_t *s, conf_iface_t *ctl_if, int r, uint8_t* buf, size_t buflen) { - knot_packet_t *pkt = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + knot_packet_t *pkt = knot_packet_new(); if (!pkt) { dbg_server("remote: not enough space to allocate query\n"); return KNOT_ENOMEM; @@ -674,7 +674,7 @@ knot_packet_t* remote_query(const char *query, const knot_tsig_key_t *key) return NULL; } - knot_packet_t *qr = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + knot_packet_t *qr = knot_packet_new(); if (!qr) { return NULL; } @@ -689,25 +689,23 @@ knot_packet_t* remote_query(const char *query, const knot_tsig_key_t *key) } /* Question section. */ - knot_question_t q; char *qname = strcdup(query, KNOT_CTL_REALM_EXT); - q.qname = knot_dname_new_from_str(qname, strlen(qname), 0); - if (!q.qname) { + knot_dname_t *dname = knot_dname_new_from_str(qname, strlen(qname)); + if (!dname) { knot_packet_free(&qr); free(qname); return NULL; } - q.qtype = KNOT_RRTYPE_ANY; - q.qclass = KNOT_CLASS_CH; /* Cannot return != KNOT_EOK, but still. */ - if (knot_query_set_question(qr, &q) != KNOT_EOK) { + if (knot_query_set_question(qr, dname, KNOT_CLASS_CH, KNOT_RRTYPE_ANY) != KNOT_EOK) { knot_packet_free(&qr); + knot_dname_free(&dname); free(qname); return NULL; } - knot_dname_release(q.qname); + knot_dname_free(&dname); free(qname); return qr; @@ -724,7 +722,7 @@ int remote_query_append(knot_packet_t *qry, knot_rrset_t *data) size_t bsize = 0; int ret = knot_rrset_to_wire(data, sp, &bsize, qry->max_size, &rrs, 0); if (ret == KNOT_EOK) { - qry->header.nscount += rrs; + knot_wire_add_nscount(qry->wireformat, rrs); } /* Finalize packet size. */ @@ -760,7 +758,7 @@ knot_rrset_t* remote_build_rr(const char *k, uint16_t t) } /* Assert K is FQDN. */ - knot_dname_t *key = knot_dname_new_from_nonfqdn_str(k, strlen(k), 0); + knot_dname_t *key = knot_dname_new_from_str(k, strlen(k)); if (!key) { return NULL; } @@ -808,7 +806,7 @@ int remote_create_ns(knot_rrset_t *rr, const char *d) } /* Create dname. */ - knot_dname_t *dn = knot_dname_new_from_nonfqdn_str(d, strlen(d), NULL); + knot_dname_t *dn = knot_dname_new_from_str(d, strlen(d)); if (!dn) { return KNOT_ERROR; } diff --git a/src/knot/server/notify.c b/src/knot/server/notify.c index e6c95649fd10542228d40c23a514339bcff53d6c..244aa6b91c103149984144ca882a674094c74c43 100644 --- a/src/knot/server/notify.c +++ b/src/knot/server/notify.c @@ -47,7 +47,7 @@ static int notify_request(const knot_rrset_t *rrset, uint8_t *buffer, size_t *size) { - knot_packet_t *pkt = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + knot_packet_t *pkt = knot_packet_new(); CHECK_ALLOC_LOG(pkt, KNOT_ENOMEM); /*! \todo Get rid of the numeric constant. */ @@ -63,14 +63,7 @@ static int notify_request(const knot_rrset_t *rrset, return KNOT_ERROR; } - knot_question_t question; - - // this is ugly!! - question.qname = rrset->owner; - question.qtype = rrset->type; - question.qclass = rrset->rclass; - - rc = knot_query_set_question(pkt, &question); + rc = knot_query_set_question(pkt, rrset->owner, rrset->rclass, rrset->type); if (rc != KNOT_EOK) { knot_packet_free(&pkt); return KNOT_ERROR; @@ -78,7 +71,6 @@ static int notify_request(const knot_rrset_t *rrset, /* Set random query ID. */ knot_packet_set_random_id(pkt); - knot_wire_set_id(pkt->wireformat, pkt->header.id); /*! \todo add the SOA RR to the Answer section as a hint */ /*! \todo this should not use response API!! */ @@ -123,14 +115,13 @@ static int notify_request(const knot_rrset_t *rrset, int notify_create_response(knot_packet_t *request, uint8_t *buffer, size_t *size) { - knot_packet_t *response = - knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + knot_packet_t *response = knot_packet_new_mm(&request->mm); CHECK_ALLOC_LOG(response, KNOT_ENOMEM); /* Set maximum packet size. */ int rc = knot_packet_set_max_size(response, *size); if (rc == KNOT_EOK) { - rc = knot_response_init_from_query(response, request, 1); + rc = knot_response_init_from_query(response, request); } /* Aggregated result check. */ diff --git a/src/knot/server/rrl.c b/src/knot/server/rrl.c index f064d8fd87738c3b312905c877e9fab2940663d7..2bacd06e171ac098f685e3fd54e79075f09d82c3 100644 --- a/src/knot/server/rrl.c +++ b/src/knot/server/rrl.c @@ -99,8 +99,8 @@ static uint8_t rrl_clsid(rrl_req_t *p) } /* Check query type for spec. classes. */ - if (p->qst) { - switch(p->qst->qtype) { + if (p->query) { + switch(knot_packet_qtype(p->query)) { case KNOT_RRTYPE_ANY: /* ANY spec. class */ return CLS_ANY; break; @@ -143,7 +143,7 @@ static int rrl_clsname(char *dst, size_t maxlen, uint8_t cls, dbg_rrl_verb("%s: using zone/fallback name\n", __func__); break; default: - if (p->qst) dn = p->qst->qname; + if (p->query) dn = knot_packet_qname(p->query); break; } diff --git a/src/knot/server/rrl.h b/src/knot/server/rrl.h index 59ac9a6bfd622246763916f107a118e92750f24f..549a7b6bd392c37e8ad45aabfb6f3ed43cd7a3a9 100644 --- a/src/knot/server/rrl.h +++ b/src/knot/server/rrl.h @@ -78,7 +78,7 @@ typedef struct rrl_req { const uint8_t *w; uint16_t len; unsigned flags; - const knot_question_t *qst; + knot_packet_t *query; } rrl_req_t; /*! diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c index f8fe90bb4caa14c36d5f641e376b287aa8677465..bb76713c919b59437f94406f1caa0366e7676507 100644 --- a/src/knot/server/tcp-handler.c +++ b/src/knot/server/tcp-handler.c @@ -166,7 +166,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen /* Parse query. */ size_t resp_len = qbuf_maxlen; // 64K knot_packet_type_t qtype = KNOT_QUERY_NORMAL; - knot_packet_t *packet = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + knot_packet_t *packet = knot_packet_new(); if (packet == NULL) { int ret = knot_ns_error_response_from_query_wire(ns, qbuf, n, KNOT_RCODE_SERVFAIL, @@ -268,8 +268,6 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen break; } - knot_packet_free(&packet); - /* Send answer. */ if (res == KNOT_EOK) { tcp_reply(fd, qbuf, resp_len); @@ -278,6 +276,8 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen qtype, fd, knot_strerror(res));; } + knot_packet_free(&packet); + return res; } diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c index 259ac5aa1169028d8727505b4e3f12b7e647994f..de4a354f4dbf88043ddcc606b82080bdc0e6ecbb 100644 --- a/src/knot/server/udp-handler.c +++ b/src/knot/server/udp-handler.c @@ -152,7 +152,7 @@ int udp_handle(struct answer_ctx *ans, int fd, return KNOT_EOK; #endif - knot_packet_t *packet = knot_packet_new_mm(KNOT_PACKET_PREALLOC_QUERY, ans->mm); + knot_packet_t *packet = knot_packet_new_mm(ans->mm); if (packet == NULL) { dbg_net("udp: failed to create packet\n"); int ret = knot_ns_error_response_from_query_wire(ns, qbuf, qbuflen, @@ -220,7 +220,7 @@ int udp_handle(struct answer_ctx *ans, int fd, rrl_req_t rrl_rq; memset(&rrl_rq, 0, sizeof(rrl_req_t)); rrl_rq.w = qbuf; /* Wire */ - rrl_rq.qst = &packet->question; + rrl_rq.query = packet; rcu_read_lock(); rrl_rq.flags = packet->flags; @@ -535,7 +535,7 @@ int udp_reader(iohandler_t *h, dthread_t *thread) mm_ctx_t mm; mm.ctx = pool; mm.alloc = (mm_alloc_t)mp_alloc; - mm.free = NULL; + mm.free = mm_nofree; /* Create UDP answering context. */ struct answer_ctx ans_ctx; diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c index c7c1abfcca05e5157395c61474f7eadc31177fde..0d032e48f49d21b777b0e0b5d3035e74d526c364 100644 --- a/src/knot/server/xfr-handler.c +++ b/src/knot/server/xfr-handler.c @@ -563,7 +563,7 @@ static int xfr_task_finalize(xfrworker_t *w, knot_ns_xfr_t *rq) static int xfr_task_resp(xfrworker_t *w, knot_ns_xfr_t *rq) { knot_nameserver_t *ns = w->master->ns; - knot_packet_t *re = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE); + knot_packet_t *re = knot_packet_new(); if (re == NULL) { return KNOT_ENOMEM; } diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index d1a3bf694e4d07f9339d37e0636a52836f1e67cb..c69b0d13bcc7f0e64600f5ecd82daa55578ecc98 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -581,7 +581,7 @@ static int zones_load_zone(knot_zone_t **dst, const char *zone_name, /* Check if loaded origin matches. */ const knot_dname_t *dname = knot_zone_name(*dst); knot_dname_t *dname_req = NULL; - dname_req = knot_dname_new_from_str(zone_name, strlen(zone_name), 0); + dname_req = knot_dname_new_from_str(zone_name, strlen(zone_name)); if (knot_dname_compare(dname, dname_req) != 0) { log_server_error("Origin of the zone db file is " "different than '%s'\n", @@ -1035,8 +1035,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst, /* Convert the zone name into a domain name. */ /* Local allocation, will be discarded. */ - knot_dname_t *dname = knot_dname_new_from_str(z->name, strlen(z->name), - NULL); + knot_dname_t *dname = knot_dname_new_from_str(z->name, strlen(z->name)); if (dname == NULL) { log_server_error("Error creating domain name from zone" " name\n"); @@ -1521,7 +1520,7 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype, rq->packet_nr = (int)knot_packet_id(query); /* Duplicate query to keep it in memory during forwarding. */ - rq->query = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + rq->query = knot_packet_new(); if (!rq->query) { xfr_task_free(rq); rcu_read_unlock(); @@ -1535,7 +1534,7 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype, rcu_read_unlock(); return KNOT_ENOMEM; } - rq->query->free_wireformat = 1; + rq->query->flags |= KNOT_PF_FREE_WIRE; memcpy(rq->query->wireformat, query->wireformat, knot_packet_size(query)); /* Retain pointer to zone and issue. */ @@ -2050,7 +2049,6 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver, int ret = knot_ns_prep_normal_response(nameserver, query, &resp, &zone, (transport == NS_TRANSPORT_TCP) ? *rsize : 0); - query->zone = zone; switch (ret) { case KNOT_EOK: @@ -2641,8 +2639,7 @@ int zones_save_zone(const knot_ns_xfr_t *xfr) /* Check if the new zone apex dname matches zone name. */ knot_dname_t *cur_name = knot_dname_new_from_str(zd->conf->name, - strlen(zd->conf->name), - NULL); + strlen(zd->conf->name)); const knot_dname_t *new_name = NULL; new_name = knot_node_owner(knot_zone_contents_apex(new_zone)); int r = knot_dname_compare(cur_name, new_name); diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index 1d3c5c4e0bebe0551600b051bd8249c98018a493..5bd0b7596d3d78c07496cca963513e0b370c8a2f 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -308,7 +308,7 @@ static int check_rrsig_rdata(err_handler_t *handler, /* label number at the 2nd index should be same as owner's */ uint8_t labels_rdata = knot_rrset_rdata_rrsig_labels(rrsig, rr_pos); - int tmp = knot_dname_label_count(knot_rrset_owner(rrset)) - + int tmp = knot_dname_wire_labels(knot_rrset_owner(rrset)->name, NULL) - labels_rdata; if (tmp != 0) { @@ -685,7 +685,7 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, /* Local allocation, will be discarded. */ knot_dname_t *next_dname = knot_dname_new_from_str((char *)next_dname_decoded, - real_size, NULL); + real_size); if (next_dname == NULL) { free(next_dname_decoded); log_zone_warning("Could not create new dname!\n"); @@ -893,13 +893,15 @@ static int sem_check_node_optional(knot_zone_contents_t *zone, if (glue_node == NULL) { /* Try wildcard. */ knot_dname_t *wildcard = - knot_dname_new_from_str("*", 1, NULL); + knot_dname_new_from_str("*", 1); if (wildcard == NULL) { knot_dname_free(&ns_dname); return KNOT_ENOMEM; } - knot_dname_left_chop_no_copy(ns_dname); + knot_dname_t *old_ns_dname = ns_dname; + ns_dname = knot_dname_left_chop(ns_dname); + knot_dname_free(&old_ns_dname); if (knot_dname_cat(wildcard, ns_dname) == NULL) { @@ -1244,7 +1246,7 @@ void log_cyclic_errors_in_zone(err_handler_t *handler, /* Local allocation, will be discarded. */ knot_dname_t *next_dname = knot_dname_new_from_str((char *)next_dname_decoded, - real_size, NULL); + real_size); if (next_dname == NULL) { dbg_semcheck("Could not allocate dname!\n"); free(next_dname_decoded); diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c index ac414f1b991ce258cd83812c86bb46d1ef75d66b..c6cb2aff3c26366247cec5366e51d070c149402e 100644 --- a/src/knot/zone/zone-load.c +++ b/src/knot/zone/zone-load.c @@ -257,8 +257,7 @@ static int add_rdata_to_rr(knot_rrset_t *rrset, const scanner_t *scanner) knot_dname_t *dname = knot_dname_new_from_wire(scanner->r_data + scanner->r_data_blocks[i], - scanner->r_data_blocks[i + 1] - scanner->r_data_blocks[i], - NULL); + scanner->r_data_blocks[i + 1] - scanner->r_data_blocks[i]); if (dname == NULL) { return KNOT_ERROR; } @@ -319,8 +318,7 @@ static void process_rr(const scanner_t *scanner) } else { current_owner = knot_dname_new_from_wire(scanner->r_owner, - scanner->r_owner_length, - NULL); + scanner->r_owner_length); if (current_owner == NULL) { parser->ret = KNOT_ERROR; return; @@ -603,7 +601,7 @@ int knot_zload_open(zloader_t **dst, const char *source, const char *origin, } context->origin_from_config = - knot_dname_new_from_str(origin, strlen(origin), NULL); + knot_dname_new_from_str(origin, strlen(origin)); assert(context->origin_from_config); knot_dname_to_lower(context->origin_from_config); /* Add first DNAME to lookup tree. */ diff --git a/src/libknot/dname.c b/src/libknot/dname.c index 754efe485ecef85665a53883c19b804f324ef6ba..ff037c949266c18a7a210fddd8f229ba183106f4 100644 --- a/src/libknot/dname.c +++ b/src/libknot/dname.c @@ -31,96 +31,20 @@ #include "util/utils.h" #include "util/wire.h" -/*! \todo dnames allocated from TLS cache will be discarded after thread - * termination. This shouldn't happpen. - */ -#if 0 -/* - * Memory cache. - */ -#include "common/slab/slab.h" -#include <stdio.h> -#include <pthread.h> - -/*! \brief TLS unique key for each thread cache. */ -static pthread_key_t dname_ckey; -static pthread_once_t dname_once = PTHREAD_ONCE_INIT; - -/*! \brief Destroy thread dname cache (automatically called). */ -static void knot_dname_cache_free(void *ptr) -{ - slab_cache_t* cache = (slab_cache_t*)ptr; - if (cache) { - slab_cache_destroy(cache); - free(cache); - } -} - -/*! \brief Cleanup for main() TLS. */ -static void knot_dname_cache_main_free() -{ - knot_dname_cache_free(pthread_getspecific(dname_ckey)); -} - -static void knot_dname_cache_init() -{ - (void) pthread_key_create(&dname_ckey, knot_dname_cache_free); - atexit(knot_dname_cache_main_free); // Main thread cleanup -} -#endif - -/*! - * \brief Allocate item from thread cache. - * \retval Allocated dname instance on success. - * \retval NULL on error. - */ -static knot_dname_t* knot_dname_alloc() -{ - return malloc(sizeof(knot_dname_t)); - - /*! \todo dnames allocated from TLS cache will be discarded after thread - * termination. This shouldn't happpen. - */ -#if 0 - /* Initialize dname cache TLS key. */ - (void)pthread_once(&dname_once, knot_dname_cache_init); - - /* Create cache if not exists. */ - slab_cache_t* cache = pthread_getspecific(dname_ckey); - if (knot_unlikely(!cache)) { - cache = malloc(sizeof(slab_cache_t)); - if (!cache) { - return 0; - } - - /* Initialize cache. */ - slab_cache_init(cache, sizeof(knot_dname_t)); - (void)pthread_setspecific(dname_ckey, cache); - } - - return slab_cache_alloc(cache); -#endif -} /*----------------------------------------------------------------------------*/ /* Non-API functions */ /*----------------------------------------------------------------------------*/ -static int knot_dname_set(knot_dname_t *dname, uint8_t *wire, - short wire_size, const uint8_t *labels, - short label_count) +static knot_dname_t *knot_dname_new() { - dname->name = wire; - dname->size = wire_size; - dname->label_count = label_count; + knot_dname_t *dname = malloc(sizeof(knot_dname_t)); - assert(label_count >= 0); - - dname->labels = (uint8_t *)malloc(dname->label_count * sizeof(uint8_t)); - CHECK_ALLOC_LOG(dname->labels, -1); - memcpy(dname->labels, labels, dname->label_count); + dname->name = NULL; + dname->count = 1; + dname->size = 0; - return 0; + return dname; } /*! @@ -141,258 +65,72 @@ static int knot_dname_set(knot_dname_t *dname, uint8_t *wire, static int knot_dname_str_to_wire(const char *name, uint size, knot_dname_t *dname) { - if (size > KNOT_MAX_DNAME_LENGTH) { - return -1; - } - - uint wire_size; - int root = (*name == '.' && size == 1); - // root => different size - if (root) { - wire_size = 1; - } else { - wire_size = size + 1; + if (size == 0 || size > KNOT_MAX_DNAME_LENGTH) { + return KNOT_EINVAL; } - uint8_t *wire; - uint8_t labels[KNOT_MAX_DNAME_LABELS]; - short label_count = 0; - - // signed / unsigned issues?? - wire = (uint8_t *)malloc(wire_size * sizeof(uint8_t)); - if (wire == NULL) { - return -1; + unsigned wire_size = size + 1; + if (name[0] == '.' && size == 1) { + wire_size = 1; /* Root label. */ + size = 0; /* Do not parse input. */ + } else if (name[size - 1] != '.') { + ++wire_size; /* No FQDN, reserve last root label. */ } - dbg_dname_verb("Allocated space for wire format of dname: %p\n", wire); - - if (root) { - *wire = '\0'; - label_count = 0; - return knot_dname_set(dname, wire, wire_size, labels, - label_count); - } + /* Create wire. */ + uint8_t *wire = malloc(wire_size * sizeof(uint8_t)); + if (wire == NULL) + return KNOT_ENOMEM; + *wire = '\0'; const uint8_t *ch = (const uint8_t *)name; - uint8_t *label_start = wire; - uint8_t *w = wire + 1; - uint8_t label_length = 0; - - while (ch - (const uint8_t *)name < size) { - assert(w - wire - 1 == ch - (const uint8_t *)name); - + const uint8_t *np = ch + size; + uint8_t *label = wire; + uint8_t *w = wire + 1; /* Reserve 1 for label len */ + while (ch != np) { if (*ch == '.') { /* Zero-length label inside a dname - invalid. */ - if (label_length == 0) { + if (*label == 0) { free(wire); - return -1; + return KNOT_EMALF; } - dbg_dname_detail("Position %zd (%p): " - "label length: %u\n", - label_start - wire, - label_start, label_length); - *label_start = label_length; - labels[label_count++] = label_start - wire; - label_start = w; - label_length = 0; + label = w; + *label = '\0'; } else { - assert(w - wire < wire_size); - dbg_dname_detail("Position %zd (%p): character: %c\n", - w - wire, w, *ch); *w = *ch; - ++label_length; + *label += 1; } - ++w; ++ch; - assert(ch >= (const uint8_t *)name); } - --ch; - if (*ch == '.') { // put 0 for root label if the name ended with . - --w; - dbg_dname_detail("Position %zd (%p): character: (null)\n", - w - wire, w); - *w = 0; - } else { // otherwise we did not save the last label length - dbg_dname_detail("Position %zd (%p): label length: %u\n", - label_start - wire, - label_start, label_length); - *label_start = label_length; - labels[label_count++] = label_start - wire; + /* Check for non-FQDN name. */ + if (*label > 0) { + *w = '\0'; } - return knot_dname_set(dname, wire, wire_size, labels, label_count); -} - -/*----------------------------------------------------------------------------*/ - -static inline int knot_dname_tolower(uint8_t c, int cs) -{ - return (cs) ? c : knot_tolower(c); -} - -/*----------------------------------------------------------------------------*/ - -static int knot_dname_compare_labels(const uint8_t *label1, - const uint8_t *label2, int cs) -{ - const uint8_t *pos1 = label1; - const uint8_t *pos2 = label2; - - int label_length = (*pos1 < *pos2) ? *pos1 : *pos2; - int i = 0; - - while (i < label_length - && knot_dname_tolower(*(++pos1), cs) - == knot_dname_tolower(*(++pos2), cs)) { - ++i; - } - - if (i < label_length) { // difference in some octet - return (knot_dname_tolower(*pos1, cs) - - knot_dname_tolower(*pos2, cs)); - } - - return (label1[0] - label2[0]); -} - -/*----------------------------------------------------------------------------*/ - -static int knot_dname_find_labels(knot_dname_t *dname, int alloc) -{ - const uint8_t *name = dname->name; - const uint8_t *pos = name; - const uint size = dname->size; - - uint8_t labels[KNOT_MAX_DNAME_LABELS]; - short label_count = 0; - - while (pos - name < size && *pos != '\0' && label_count < KNOT_MAX_DNAME_LABELS ) { - if (*pos > 63) { /* Check label lengths. */ - dbg_dname("Wrong wire format of domain name!\n"); - dbg_dname("Label %d exceeds 63 bytes.\n", label_count); - return -1; - } - labels[label_count++] = pos - name; - pos += *pos + 1; - } - - // TODO: how to check if the domain name has right format? - if (label_count == KNOT_MAX_DNAME_LABELS) { - dbg_dname("Wrong wire format of domain name!\n"); - dbg_dname("Too many labels: %s\n", name); - return -1; - } - - if (pos - name > size || *pos != '\0' ) { - dbg_dname("Wrong wire format of domain name!\n"); - dbg_dname("Position: %"PRIuPTR", character: %d, expected size: %d\n", - pos - name, *pos, size); - return -1; - } - - if (alloc) { - dname->labels - = (uint8_t *)malloc(label_count * sizeof(uint8_t)); - CHECK_ALLOC_LOG(dname->labels, KNOT_ENOMEM); - } - - memcpy(dname->labels, labels, label_count); - dname->label_count = label_count; - - return 0; + dname->name = wire; + dname->size = wire_size; + return KNOT_EOK; } /*----------------------------------------------------------------------------*/ -static int knot_dname_cmp(const knot_dname_t *d1, const knot_dname_t *d2, - int cs) +static int knot_label_is_equal(const uint8_t *lb1, const uint8_t *lb2) { -dbg_dname_exec_verb( - char *name1 = knot_dname_to_str(d1); - char *name2 = knot_dname_to_str(d2); - - dbg_dname_verb("Comparing dnames %s and %s\n", name1, name2); - - for (int i = 0; i < strlen(name1); ++i) { - name1[i] = knot_tolower(name1[i]); - } - for (int i = 0; i < strlen(name2); ++i) { - name2[i] = knot_tolower(name2[i]); - } - - dbg_dname_detail("After to lower: %s and %s\n", name1, name2); - - free(name1); - free(name2); -); - - if (!cs && d1 == d2) { - return 0; - } - - int l1 = d1->label_count; - int l2 = d2->label_count; - dbg_dname_detail("Label counts: %d and %d\n", l1, l2); - assert(l1 >= 0); - assert(l2 >= 0); - - // compare labels from last to first - while (l1 > 0 && l2 > 0) { - dbg_dname_detail("Comparing labels %d and %d\n", - l1 - 1, l2 - 1); - dbg_dname_detail(" at offsets: %d and %d\n", - d1->labels[l1 - 1], d2->labels[l2 - 1]); - int res = knot_dname_compare_labels( - &d1->name[d1->labels[--l1]], - &d2->name[d2->labels[--l2]], - cs); - if (res != 0) { - return res; - } // otherwise the labels are identical, continue with previous - } - - // if all labels matched, the shorter name is first - if (l1 == 0 && l2 > 0) { - return -1; - } - - if (l1 > 0 && l2 == 0) { - return 1; - } - - return 0; + return (*lb1 == *lb2) && memcmp(lb1 + 1, lb2 + 1, *lb1) == 0; } /*----------------------------------------------------------------------------*/ /* API functions */ /*----------------------------------------------------------------------------*/ -knot_dname_t *knot_dname_new() -{ - knot_dname_t *dname = knot_dname_alloc(); - - dname->name = NULL; - dname->labels = NULL; - dname->node = NULL; - dname->count = 1; - dname->size = 0; - dname->label_count = 0; - - return dname; -} - -/*----------------------------------------------------------------------------*/ - -knot_dname_t *knot_dname_new_from_str(const char *name, uint size, - struct knot_node *node) +knot_dname_t *knot_dname_new_from_str(const char *name, uint size) { if (name == NULL || size == 0) { return NULL; } -// knot_dname_t *dname = knot_dname_alloc(); knot_dname_t *dname = knot_dname_new(); if (dname == NULL) { @@ -408,47 +146,18 @@ knot_dname_t *knot_dname_new_from_str(const char *name, uint size, return NULL; } -dbg_dname_exec_verb( - dbg_dname_verb("Created dname with size: %d\n", dname->size); - dbg_dname_verb("Label offsets: "); - for (int i = 0; i < dname->label_count; ++i) { - dbg_dname_verb("%d, ", dname->labels[i]); - } - dbg_dname_verb("\n"); -); - if (dname->size <= 0) { dbg_dname("Could not parse domain name " "from string: '%.*s'\n", size, name); } assert(dname->name != NULL); - dname->node = node; return dname; } /*----------------------------------------------------------------------------*/ -knot_dname_t *knot_dname_new_from_nonfqdn_str(const char *name, uint size, - struct knot_node *node) -{ - knot_dname_t *dname = NULL; - - if (name[size - 1] != '.') { - char *fqdn = strcdup(name, "."); - dname = knot_dname_new_from_str(fqdn, size + 1, node); - free(fqdn); - } else { - dname = knot_dname_new_from_str(name, size, node); - } - - return dname; -} - -/*----------------------------------------------------------------------------*/ - -knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, uint size, - struct knot_node *node) +knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, uint size) { if (name == NULL) { /* && size != 0) { !OS: Nerozumjaju */ dbg_dname("No name given!\n"); @@ -469,116 +178,26 @@ knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, uint size, return NULL; } + /*! \todo this won't work for non-linear names */ memcpy(dname->name, name, size); dname->size = size; - - if (knot_dname_find_labels(dname, 1) != 0) { - dbg_dname("Could not find labels in dname (new from wire).\n"); - knot_dname_free(&dname); - return NULL; - } - - dname->node = node; return dname; } /*----------------------------------------------------------------------------*/ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire, - size_t *pos, size_t size, - knot_node_t *node, - knot_dname_t *dname) + size_t *pos, size_t size) { - uint8_t name[KNOT_MAX_DNAME_LENGTH]; - uint8_t labels[KNOT_MAX_DNAME_LABELS]; - - short l = 0; - size_t i = 0, p = *pos; - int pointer_used = 0; - - while (p < size && wire[p] != 0) { - /* Check maximum number of labels (may overflow). */ - if (l == KNOT_MAX_DNAME_LABELS) { - return NULL; - } - labels[l] = i; - dbg_dname_detail("Next label (%d.) position: %zu\n", l, i); - - if (knot_wire_is_pointer(wire + p)) { - // pointer. - size_t ptr = knot_wire_get_pointer(wire + p); - - /* Check that the pointer points backwards - * otherwise it could result in infinite loop - */ - if (ptr >= p) { - return NULL; - } - - p = ptr; - - if (!pointer_used) { - *pos += 2; - pointer_used = 1; - } - if (p >= size) { - return NULL; - } - } else { - // label; first byte is label length - uint8_t length = *(wire + p); - /* Check label length (maximum 63 bytes allowed). */ - if (length > 63) { - return NULL; - } - /* Check if there's enough space. */ - if (i + length + 2 > KNOT_MAX_DNAME_LENGTH) { - return NULL; - } - //printf("Label %d (max %d), length: %u.\n", l, KNOT_MAX_DNAME_LABELS, length); - memcpy(name + i, wire + p, length + 1); - p += length + 1; - i += length + 1; - if (!pointer_used) { - *pos += length + 1; - } - ++l; - } - } - if (p >= size) { + const uint8_t *name = wire + *pos; + const uint8_t *endp = wire + size; + int parsed = knot_dname_wire_check(name, endp, wire); + if (parsed < 0) return NULL; - } - name[i] = 0; - if (!pointer_used) { - *pos += 1; - } - - /* Allocate if NULL. */ - if (dname == NULL) { - dname = knot_dname_new(); - if (dname) { - dname->name = (uint8_t *)malloc((i + 1) * sizeof(uint8_t)); - dname->labels = (uint8_t *)malloc((l + 1) * sizeof(uint8_t)); - } - } - - if (dname == NULL) { - ERR_ALLOC_FAILED; - return NULL; - } - - if (dname->name == NULL || dname->labels == NULL) { - ERR_ALLOC_FAILED; - knot_dname_free(&dname); - return NULL; - } - - memcpy(dname->name, name, i + 1); - memcpy(dname->labels, labels, l + 1); - dname->size = i + 1; - dname->label_count = l; - dname->node = node; + knot_dname_t *dname = knot_dname_new_from_wire(name, parsed); + if (dname) + *pos += parsed; return dname; } @@ -587,7 +206,6 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire, knot_dname_t *knot_dname_deep_copy(const knot_dname_t *dname) { - //return knot_dname_new_from_wire(dname->name, dname->size, dname->node); /* dname_new_from_wire() does not accept non-FQDN dnames, so we * do the copy by hand. It's faster anyway */ @@ -598,27 +216,15 @@ knot_dname_t *knot_dname_deep_copy(const knot_dname_t *dname) knot_dname_t *copy = knot_dname_new(); CHECK_ALLOC(copy, NULL); - copy->labels = (uint8_t *)(malloc(dname->label_count)); - - if (copy->labels == NULL) { - knot_dname_free(©); - return NULL; - } - copy->name = (uint8_t *)(malloc(dname->size)); if (copy->name == NULL) { knot_dname_free(©); return NULL; } - memcpy(copy->labels, dname->labels, dname->label_count); - copy->label_count = dname->label_count; - memcpy(copy->name, dname->name, dname->size); copy->size = dname->size; - copy->node = dname->node; - return copy; } @@ -705,14 +311,7 @@ char *knot_dname_to_str(const knot_dname_t *dname) int knot_dname_to_lower(knot_dname_t *dname) { - if (dname == NULL) { - return KNOT_EINVAL; - } - - for (int i = 0; i < dname->size; ++i) { - dname->name[i] = knot_tolower(dname->name[i]); - } - return KNOT_EOK; + return knot_dname_to_lower_copy(dname, (char*)dname->name, dname->size); } /*----------------------------------------------------------------------------*/ @@ -746,97 +345,6 @@ uint knot_dname_size(const knot_dname_t *dname) /*----------------------------------------------------------------------------*/ -uint8_t knot_dname_size_part(const knot_dname_t *dname, int labels) -{ - assert(labels < dname->label_count); - assert(dname->labels != NULL); - return (dname->labels[labels]); -} - -/*----------------------------------------------------------------------------*/ - -const struct knot_node *knot_dname_node(const knot_dname_t *dname) - -{ - return knot_dname_get_node(dname); -} - -/*----------------------------------------------------------------------------*/ - -struct knot_node *knot_dname_get_node(const knot_dname_t *dname) -{ - if (dname == NULL) { - return NULL; - } - - knot_node_t *node = dname->node; - - /* - * If the zone contains new zone contents (during an update), we should - * return new node. Check if the node has the new node set. If it does - * not, it means this is already the new node. If it has, return the - * new node. If the new node is empty, return NULL, as the node will be - * deleted later. - */ -dbg_dname_exec_detail( - dbg_dname_detail("Getting node from dname: node: %p, zone: %p\n", node, - knot_node_zone(node)); - if (node != NULL && knot_node_zone(node) != NULL - && knot_zone_contents(knot_node_zone(node)) != NULL) { - dbg_dname_detail("zone contents gen: %d, new node of the node: " - "%p, is empty: %d\n", - knot_zone_contents_gen_is_new(knot_zone_contents( - knot_node_zone(node))), - knot_node_new_node(node), - knot_node_new_node(node) - ? knot_node_is_empty(knot_node_new_node(node)) - : -1); - } -); - - if (node && knot_node_zone(node) - && knot_zone_contents(knot_node_zone(node)) - && knot_zone_contents_gen_is_new(knot_zone_contents( - knot_node_zone(node))) - && knot_node_new_node(node) != NULL) { - node = knot_node_get_new_node(node); - if (knot_node_is_empty(node)) { - node = NULL; - } - } - - return node; -} - -/*----------------------------------------------------------------------------*/ - -void knot_dname_set_node(knot_dname_t *dname, knot_node_t *node) -{ - dname->node = node; -} - -/*----------------------------------------------------------------------------*/ - -void knot_dname_update_node(knot_dname_t *dname) -{ -dbg_dname_exec_detail( - char *name = knot_dname_to_str(dname); - dbg_dname_detail("Updating node pointer in dname %p: %s. Before: %p\n", - dname, name, dname->node); - free(name); -); - - knot_node_update_ref(&dname->node); - dbg_dname_detail("After: %p\n", dname->node); - - if (knot_node_is_empty(dname->node)) { - dbg_dname_detail("Node is empty, setting to NULL.\n"); - dname->node = NULL; - } -} - -/*----------------------------------------------------------------------------*/ - int knot_dname_is_fqdn(const knot_dname_t *dname) { return (dname->name[dname->size - 1] == '\0'); @@ -846,10 +354,7 @@ int knot_dname_is_fqdn(const knot_dname_t *dname) knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname) { - if (dname == NULL || - /* Root domain. */ - ((knot_dname_label_count(dname) == 0) && - (knot_dname_is_fqdn(dname)))) { + if (dname == NULL || *knot_dname_name(dname) == '\0') { /* root */ return NULL; } @@ -858,25 +363,6 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname) return NULL; } - // last label, the result should be root domain - if (dname->label_count == 1) { - dbg_dname_verb("Chopping last label.\n"); - parent->label_count = 0; - - parent->name = (uint8_t *)malloc(1); - if (parent->name == NULL) { - ERR_ALLOC_FAILED; - knot_dname_free(&parent); - return NULL; - } - - *parent->name = 0; - - parent->size = 1; - - return parent; - } - parent->size = dname->size - dname->name[0] - 1; parent->name = (uint8_t *)malloc(parent->size); if (parent->name == NULL) { @@ -885,24 +371,7 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname) return NULL; } - parent->labels = (uint8_t *)malloc(dname->label_count - 1); - if (parent->labels == NULL) { - ERR_ALLOC_FAILED; - free(parent->name); - knot_dname_free(&parent); - return NULL; - } - memcpy(parent->name, &dname->name[dname->name[0] + 1], parent->size); - - - short first_label_length = dname->labels[1]; - - for (int i = 0; i < dname->label_count - 1; ++i) { - parent->labels[i] = dname->labels[i + 1] - first_label_length; - } - parent->label_count = dname->label_count - 1; - return parent; } @@ -910,24 +379,13 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname) void knot_dname_left_chop_no_copy(knot_dname_t *dname) { - // copy the name - if (dname->label_count > 1) { - short first_label_length = dname->labels[1]; - - memmove(dname->name, &dname->name[dname->labels[1]], - dname->size - first_label_length); - // adjust labels - for (int i = 0; i < dname->label_count - 1; ++i) { - dname->labels[i] = dname->labels[i + 1] - - first_label_length; - } - dname->label_count = dname->label_count - 1; - dname->size -= first_label_length; - } else { - dname->name[0] = '\0'; - dname->size = 1; - dname->label_count = 0; - } + uint8_t len = *knot_dname_name(dname); + if (len == 0) + return; + + /*! \todo this will work only with linearized names (as of now) */ + dname->size -= (len + 1); + memmove(dname->name, dname->name + len + 1, dname->size); } /*----------------------------------------------------------------------------*/ @@ -935,53 +393,32 @@ void knot_dname_left_chop_no_copy(knot_dname_t *dname) int knot_dname_is_subdomain(const knot_dname_t *sub, const knot_dname_t *domain) { -dbg_dname_exec_verb( - char *name1 = knot_dname_to_str(sub); - char *name2 = knot_dname_to_str(domain); - - dbg_dname_verb("Checking if %s is subdomain of %s\n", name1, name2); - free(name1); - free(name2); -); - - if (sub == domain) { + if (sub == domain) return 0; - } - // if one of the names is fqdn and the other is not - if ((sub->name[sub->size - 1] == '\0' - && domain->name[domain->size - 1] != '\0') - || (sub->name[sub->size - 1] != '\0' - && domain->name[domain->size - 1] == '\0')) { - return 0; - } + /* Count labels. */ + const uint8_t *sub_p = sub->name; + const uint8_t *domain_p = domain->name; + int sub_l = knot_dname_wire_labels(sub_p, NULL); + int domain_l = knot_dname_wire_labels(domain_p, NULL); - int l1 = sub->label_count; - int l2 = domain->label_count; - - dbg_dname_detail("Label counts: %d and %d\n", l1, l2); + /* Subdomain must have more labels as parent. */ + if (sub_l <= domain_l) + return 0; - if (l1 <= l2) { // if sub does not have more labes than domain - return 0; // it is not its subdomain - } + /* Align end-to-end to common suffix. */ + int common = knot_dname_align(&sub_p, sub_l, &domain_p, domain_l, NULL); - // compare labels from last to first - while (l1 > 0 && l2 > 0) { - dbg_dname_detail("Comparing labels %d and %d\n", - l1 - 1, l2 - 1); - dbg_dname_detail(" at offsets: %d and %d\n", - sub->labels[l1 - 1], domain->labels[l2 - 1]); - // if some labels do not match - if (knot_dname_compare_labels(&sub->name[sub->labels[--l1]], - &domain->name[domain->labels[--l2]], 0) - != 0) { - return 0; // sub is not a subdomain of domain - } // otherwise the labels are identical, continue with previous + /* Compare common suffix. */ + while(common > 0) { + /* Compare label. */ + if (!knot_label_is_equal(sub_p, domain_p)) + return 0; + /* Next label. */ + sub_p = knot_wire_next_label(sub_p, NULL); + domain_p = knot_wire_next_label(domain_p, NULL); + --common; } - - // if all labels matched, it should be subdomain (more labels) - assert(l1 > l2); - return 1; } @@ -999,20 +436,27 @@ int knot_dname_is_wildcard(const knot_dname_t *dname) int knot_dname_matched_labels(const knot_dname_t *dname1, const knot_dname_t *dname2) { - int l1 = dname1->label_count; - int l2 = dname2->label_count; + /* Count labels. */ + const uint8_t *d1 = dname1->name; + const uint8_t *d2 = dname2->name; + int l1 = knot_dname_wire_labels(d1, NULL); + int l2 = knot_dname_wire_labels(d2, NULL); - // compare labels from last to first + /* Align end-to-end to common suffix. */ + int common = knot_dname_align(&d1, l1, &d2, l2, NULL); + + /* Count longest chain leading to root label. */ int matched = 0; - while (l1 > 0 && l2 > 0) { - int res = knot_dname_compare_labels( - &dname1->name[dname1->labels[--l1]], - &dname2->name[dname2->labels[--l2]], 0); - if (res == 0) { + while (common > 0) { + if (knot_label_is_equal(d1, d2)) ++matched; - } else { - break; - } + else + matched = 0; /* Broken chain. */ + + /* Next label. */ + d1 = knot_wire_next_label(d1, NULL); + d2 = knot_wire_next_label(d2, NULL); + --common; } return matched; @@ -1020,24 +464,6 @@ int knot_dname_matched_labels(const knot_dname_t *dname1, /*----------------------------------------------------------------------------*/ -int knot_dname_label_count(const knot_dname_t *dname) -{ - return dname->label_count; -} - -/*----------------------------------------------------------------------------*/ - -uint8_t knot_dname_label_size(const knot_dname_t *dname, int i) -{ - assert(i >= 0); - assert(dname->size == 1 || i + 1 == dname->label_count - || dname->labels[i + 1] - dname->labels[i] - 1 - == dname->name[dname->labels[i]]); - return dname->name[dname->labels[i]]; -} - -/*----------------------------------------------------------------------------*/ - knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *dname, int size, const knot_dname_t *suffix) { @@ -1074,8 +500,6 @@ dbg_dname_exec_verb( dbg_dname_hex((char *)res->name, res->size); - knot_dname_find_labels(res, 1); - return res; } @@ -1089,9 +513,6 @@ void knot_dname_free(knot_dname_t **dname) free((*dname)->name); - free((*dname)->labels); - - // slab_free(*dname); free(*dname); *dname = NULL; @@ -1101,14 +522,14 @@ void knot_dname_free(knot_dname_t **dname) int knot_dname_compare(const knot_dname_t *d1, const knot_dname_t *d2) { - return knot_dname_cmp(d1, d2, 0); + return knot_dname_wire_cmp(d1, d2, NULL); } /*----------------------------------------------------------------------------*/ int knot_dname_compare_cs(const knot_dname_t *d1, const knot_dname_t *d2) { - return knot_dname_cmp(d1, d2, 1); + return knot_dname_wire_cmp(d1, d2, NULL); } int knot_dname_compare_non_canon(const knot_dname_t *d1, const knot_dname_t *d2) @@ -1130,22 +551,11 @@ knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2) return d1; } - if (knot_dname_is_fqdn(d1)) { - return NULL; - } - // allocate new space - uint8_t *new_dname = (uint8_t *)malloc(d1->size + d2->size); + size_t new_size = d1->size + d2->size - 1; /* Trim the d1 \0 label */ + uint8_t *new_dname = (uint8_t *)malloc(new_size); CHECK_ALLOC_LOG(new_dname, NULL); - uint8_t *new_labels = (uint8_t *)malloc(d1->label_count - + d2->label_count); - if (new_labels == NULL) { - ERR_ALLOC_FAILED; - free(new_dname); - return NULL; - } - dbg_dname_detail("1: copying %d bytes from adress %p to %p\n", d1->size, d1->name, new_dname); @@ -1154,24 +564,174 @@ knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2) dbg_dname_detail("2: copying %d bytes from adress %p to %p\n", d2->size, d2->name, new_dname + d1->size); - memcpy(new_dname + d1->size, d2->name, d2->size); - - // update labels - memcpy(new_labels, d1->labels, d1->label_count); - for (int i = 0; i < d2->label_count; ++i) { - new_labels[d1->label_count + i] = d2->labels[i] + d1->size; - } - - uint8_t *old_labels = d1->labels; - d1->labels = new_labels; - free(old_labels); - d1->label_count += d2->label_count; + /* Overwrite the d1 \0 label. */ + memcpy(new_dname + d1->size - 1, d2->name, d2->size); uint8_t *old_name = d1->name; d1->name = new_dname; free(old_name); - d1->size += d2->size; + d1->size = new_size; return d1; } + +int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp, + const uint8_t *pkt) +{ + if (name == NULL || name == endp) + return KNOT_EMALF; + + int wire_len = 0; /* Keep terminal label in advance. */ + int name_len = 0; + uint8_t is_compressed = 0; + uint8_t labels = 0; + + while (*name != '\0') { + + /* Check bounds (must have at least 2 octets remaining). */ + if (name + 2 > endp) + return KNOT_ESPACE; + + /* Reject more labels. */ + if (labels == KNOT_MAX_DNAME_LABELS - 1) + return KNOT_EMALF; + + if (knot_wire_is_pointer(name)) { + /* Check that the pointer points backwards + * otherwise it could result in infinite loop + */ + if (pkt == NULL) + return KNOT_EINVAL; + uint16_t ptr = knot_wire_get_pointer(name); + if (ptr >= (name - pkt)) + return KNOT_EMALF; + + name = pkt + ptr; /* Hop to compressed label */ + if (!is_compressed) { /* Measure compressed size only */ + wire_len += sizeof(uint16_t); + is_compressed = 1; + } + } else { + /* Check label length (maximum 63 bytes allowed). */ + if (*name > 63) + return KNOT_EMALF; + /* Check if there's enough space. */ + int lblen = *name + 1; + if (name_len + lblen > KNOT_MAX_DNAME_LENGTH) + return KNOT_EMALF; + /* Update wire size only for noncompressed part. */ + name_len += lblen; + if (!is_compressed) + wire_len += lblen; + /* Hop to next label. */ + name += lblen; + ++labels; + } + + /* Check bounds (must have at least 1 octet). */ + if (name + 1 > endp) + return KNOT_ESPACE; + } + + if (!is_compressed) /* Terminal label. */ + wire_len += 1; + + return wire_len; +} + +int knot_dname_wire_size(const uint8_t *name, const uint8_t *pkt) +{ + if (!name) + return KNOT_EINVAL; + + /* Seek first real label occurence. */ + while (knot_wire_is_pointer(name)) { + name = knot_wire_next_label((uint8_t *)name, (uint8_t *)pkt); + } + + int len = 1; /* Terminal label */ + while (*name != '\0') { + len += *name + 1; + name = knot_wire_next_label((uint8_t *)name, (uint8_t *)pkt); + } + + return len; +} + +int knot_dname_wire_labels(const uint8_t *name, const uint8_t *pkt) +{ + uint8_t count = 0; + while (*name != '\0') { + ++count; + name = knot_wire_next_label((uint8_t *)name, (uint8_t *)pkt); + if (!name) + return KNOT_EMALF; + } + return count; +} + +int knot_dname_align(const uint8_t **d1, uint8_t d1_labels, + const uint8_t **d2, uint8_t d2_labels, + uint8_t *wire) +{ + for (unsigned j = d1_labels; j < d2_labels; ++j) + *d2 = knot_wire_next_label(*d2, wire); + + for (unsigned j = d2_labels; j < d1_labels; ++j) + *d1 = knot_wire_next_label(*d1, wire); + + return (d1_labels < d2_labels) ? d1_labels : d2_labels; +} + +int knot_dname_wire_cmp(const knot_dname_t *d1, const knot_dname_t *d2, + const uint8_t *pkt) +{ + /*! \todo lf conversion should respect packet wire. */ + + /* Convert to lookup format. */ + unsigned buflen = DNAME_LFT_MAXLEN; + uint8_t d1_lf[DNAME_LFT_MAXLEN], d2_lf[DNAME_LFT_MAXLEN]; + if (dname_lf(d1_lf, d1, buflen) < 0 || dname_lf(d2_lf, d2, buflen) < 0) + return KNOT_EINVAL; + + /* Compare common part. */ + uint8_t common = d1_lf[0]; + if (common > d2_lf[0]) + common = d2_lf[0]; + int ret = memcmp(d1_lf+1, d2_lf+1, common); + if (ret != 0) + return ret; + + /* If they match, compare lengths. */ + if (d1_lf[0] < d2_lf[0]) + return -1; + if (d1_lf[0] > d2_lf[0]) + return 1; + return 0; +} + +int dname_lf(uint8_t *dst, const knot_dname_t *src, size_t maxlen) +{ + if (src->size > maxlen) + return KNOT_ESPACE; + *dst = (uint8_t)src->size; + /* need to save last \x00 for root dname */ + if (*dst > 1) + *dst -= 1; + *++dst = '\0'; + uint8_t* l = src->name; + uint8_t lstack[DNAME_LFT_MAXLEN]; + uint8_t *sp = lstack; + while(*l != 0) { /* build label stack */ + *sp++ = (l - src->name); + l += 1 + *l; + } + while(sp != lstack) { /* consume stack */ + l = src->name + *--sp; /* fetch rightmost label */ + memcpy(dst, l+1, *l); /* write label */ + dst += *l; + *dst++ = '\0'; /* label separator */ + } + return KNOT_EOK; +} diff --git a/src/libknot/dname.h b/src/libknot/dname.h index a872a4d87a61c9a27db052ce9a026ffe9e5832b9..71b17beacb990b01d941deeebbfb3846745faa3f 100644 --- a/src/libknot/dname.h +++ b/src/libknot/dname.h @@ -31,9 +31,6 @@ #include <string.h> #include <stdio.h> -struct knot_node; - -/*----------------------------------------------------------------------------*/ /*! * \brief Structure for representing a domain name. * @@ -43,28 +40,15 @@ struct knot_node; */ struct knot_dname { uint8_t *name; /*!< Wire format of the domain name. */ - uint8_t *labels; /*!< Array of labels positions in name. */ - struct knot_node *node; /*!< Zone node the domain name belongs to. */ uint32_t count; /*!< Reference counter. */ uint8_t size; /*!< Length of the domain name. */ - uint8_t label_count; /*!< Number of labels. */ }; typedef struct knot_dname knot_dname_t; -/*----------------------------------------------------------------------------*/ +#define DNAME_LFT_MAXLEN 255 /* maximum lookup format length */ -/*! - * \brief Creates empty dname structure (no name, no owner node). - * - * \note Newly created dname is referenced, caller is responsible for releasing - * it after use. - * - * \return Newly allocated and initialized dname structure. - * - * \todo Possibly useless. - */ -knot_dname_t *knot_dname_new(); +/*----------------------------------------------------------------------------*/ /*! * \brief Creates a dname structure from domain name given in presentation @@ -78,28 +62,11 @@ knot_dname_t *knot_dname_new(); * * \param name Domain name in presentation format (labels separated by dots). * \param size Size of the domain name (count of characters with all dots). - * \param node Zone node the domain name belongs to. Set to NULL if not - * applicable. * * \return Newly allocated and initialized dname structure representing the * given domain name. */ -knot_dname_t *knot_dname_new_from_str(const char *name, unsigned int size, - struct knot_node *node); - -/*! - * \brief Creates a dname structure from domain name possibly given in - * non-presentation format. - * - * Works the same as knot_dname_new_from_str but makes sure, that the name - * is terminated with a dot. - * - * \see knot_dname_new_from_str - * - */ -knot_dname_t *knot_dname_new_from_nonfqdn_str(const char *name, - unsigned int size, - struct knot_node *node); +knot_dname_t *knot_dname_new_from_str(const char *name, unsigned int size); /*! * \brief Creates a dname structure from domain name given in wire format. @@ -111,8 +78,6 @@ knot_dname_t *knot_dname_new_from_nonfqdn_str(const char *name, * * \param name Domain name in wire format. * \param size Size of the domain name in octets. - * \param node Zone node the domain name belongs to. Set to NULL if not - * applicable. * * \return Newly allocated and initialized dname structure representing the * given domain name. @@ -126,9 +91,7 @@ knot_dname_t *knot_dname_new_from_nonfqdn_str(const char *name, * \warning Actually, right now this function does not accept non-FQDN dnames. * For some reason there is a check for this. */ -knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, - unsigned int size, - struct knot_node *node); +knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, unsigned int size); /*! * \brief Parse dname from wire. @@ -136,16 +99,11 @@ knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, * \param wire Message in wire format. * \param pos Position of the domain name on wire. * \param size Domain name length. - * \param node Zone node the domain name belongs to. Set to NULL if not - * applicable. - * \param dname Destination dname (will allocate new when NULL). * * \return parsed domain name or NULL. */ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire, - size_t *pos, size_t size, - struct knot_node *node, - knot_dname_t *dname); + size_t *pos, size_t size); /*! * \brief Duplicates the given domain name. @@ -194,31 +152,6 @@ const uint8_t *knot_dname_name(const knot_dname_t *dname); */ unsigned int knot_dname_size(const knot_dname_t *dname); -/*! - * \brief Returns size of a part of domain name. - * - * \param dname Domain name. - * \param labels Count of labels to get the size of (counted from left). - * - * \return Size of first \a labels labels of \a dname, counted from left. - */ -uint8_t knot_dname_size_part(const knot_dname_t *dname, int labels); - -/*! - * \brief Returns the zone node the domain name belongs to. - * - * \param dname Domain name to get the zone node of. - * - * \return Zone node the domain name belongs to or NULL if none. - */ -const struct knot_node *knot_dname_node(const knot_dname_t *dname); - -struct knot_node *knot_dname_get_node(const knot_dname_t *dname); - -void knot_dname_update_node(knot_dname_t *dname); - -void knot_dname_set_node(knot_dname_t *dname, struct knot_node *node); - /*! * \brief Checks if the given domain name is a fully-qualified domain name. * @@ -242,13 +175,6 @@ int knot_dname_is_fqdn(const knot_dname_t *dname); */ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname); -/*! - * \brief Removes leftmost label from \a dname. - * - * \param dname Domain name to remove the first label from. - */ -void knot_dname_left_chop_no_copy(knot_dname_t *dname); - /*! * \brief Checks if one domain name is a subdomain of other. * @@ -281,28 +207,7 @@ int knot_dname_is_wildcard(const knot_dname_t *dname); * \return Number of labels common for the two domain names. */ int knot_dname_matched_labels(const knot_dname_t *dname1, - const knot_dname_t *dname2); - -/*! - * \brief Returns the number of labels in the domain name. - * - * \param dname Domain name to get the label count of. - * - * \return Number of labels in \a dname. - * - * \todo Find out if this counts the root label also. - */ -int knot_dname_label_count(const knot_dname_t *dname); - -/*! - * \brief Returns the size of the requested label in the domain name. - * - * \param dname Domain name to get the label size from. - * \param i Index of the label (0 is the leftmost label). - * - * \return Size of \a i-th label in \a dname (counted from left). - */ -uint8_t knot_dname_label_size(const knot_dname_t *dname, int i); + const knot_dname_t *dname2); /*! * \brief Replaces the suffix of given size in one domain name with other domain @@ -397,6 +302,67 @@ static inline void knot_dname_release(knot_dname_t *dname) { } } +/* ! New nocopy based API. + * \note Temporary, subject to name changes. + */ + +int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp, + const uint8_t *pkt); + +/*! Calculate wire size. + * \note Expects already checked name. + * \note pkt Supply if name uses dname compression, NULL otherwise. + */ +int knot_dname_wire_size(const uint8_t *name, const uint8_t *pkt); + +/*! Calculate label count. + * \note Expects already checked name. + */ +int knot_dname_wire_labels(const uint8_t *name, const uint8_t *pkt); + +/*! + * \brief Align name and reference to a common number of suffix labels. + */ +int knot_dname_align(const uint8_t **d1, uint8_t d1_labels, + const uint8_t **d2, uint8_t d2_labels, + uint8_t *wire); + +/*! + * \brief Compare domain name by labels. + * + * \todo No case insensitivity, flags... + * + * \param d1 Domain name. + * \param d2 Domain name. + * \param pkt Packet wire related to names (or NULL). + * \return + */ +int knot_dname_wire_cmp(const knot_dname_t *d1, const knot_dname_t *d2, + const uint8_t *pkt); + +/*! + * \brief Convert domain name from wire to lookup format. + * + * Formats names from rightmost label to the leftmost, separated by the lowest + * possible character (\x00). Sorting such formatted names also gives + * correct canonical order (for NSEC/NSEC3). + * + * Example: + * Name: lake.example.com. Wire: \x04lake\x07example\x03com\x00 + * Lookup format com\x00example\x00lake\x00 + * + * Maximum length of such a domain name is DNAME_LFT_MAXLEN characters. + * + * \param dst Memory to store converted name into. + * \param maxlen Maximum memory length. + * \param src Source domain name. + * + * \retval KNOT_EOK if successful + * \retval KNOT_ESPACE when not enough memory. + * \retval KNOT_EINVAL on invalid parameters + */ +int dname_lf(uint8_t *dst, const knot_dname_t *src, size_t maxlen); + #endif /* _KNOT_DNAME_H_ */ /*! @} */ diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c index 4a95240181d212ddd196250f90a6dbba55d37865..2c22663d48e3346271326f892d4d3b2fddeadd0d 100644 --- a/src/libknot/nameserver/name-server.c +++ b/src/libknot/nameserver/name-server.c @@ -432,8 +432,16 @@ dbg_ns_exec_verb( const knot_dname_t *cname = knot_rrset_rdata_cname_name(cname_rrset); dbg_ns_detail("CNAME name from RDATA: %p\n", cname); - // change the node to the node of that name - *node = knot_dname_node(cname); + + /* Attempt to find mentioned name in zone. */ + rcu_read_lock(); + const knot_zone_t *zone = resp->zone; + knot_zone_contents_t *contents = knot_zone_get_contents(zone); + const knot_node_t *encloser = NULL, *prev = NULL; + knot_zone_contents_find_dname(contents, cname, node, &encloser, &prev); + if (*node == NULL && encloser && encloser->wildcard_child) + *node = encloser->wildcard_child; + rcu_read_unlock(); dbg_ns_detail("This name's node: %p\n", *node); // save the new name which should be used for replacing wildcard @@ -639,7 +647,7 @@ dbg_ns_exec_verb( static int ns_put_additional_for_rrset(knot_packet_t *resp, const knot_rrset_t *rrset) { - const knot_node_t *node = NULL; + const knot_node_t *node = NULL, *encloser = NULL, *prev = NULL; int ret = 0; @@ -656,15 +664,15 @@ dbg_ns_exec_detail( free(name); ); assert(dname != NULL); - node = knot_dname_node(dname); - - dbg_ns_detail("Node saved in RDATA dname: %p\n", node); - if (node != NULL && node->owner != dname) { - // the stored node should be the wildcard covering the - // name - dbg_ns_detail("Node is wildcard.\n"); - assert(knot_dname_is_wildcard(knot_node_owner(node))); - } + + /* Attempt to find mentioned name in zone. */ + rcu_read_lock(); + const knot_zone_t *zone = resp->zone; + knot_zone_contents_t *contents = knot_zone_get_contents(zone); + knot_zone_contents_find_dname(contents, dname, &node, &encloser, &prev); + if (node == NULL && encloser && encloser->wildcard_child) + node = encloser->wildcard_child; + rcu_read_unlock(); knot_rrset_t *rrset_add; @@ -933,8 +941,8 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone, static knot_dname_t *ns_next_closer(const knot_dname_t *closest_encloser, const knot_dname_t *name) { - int ce_labels = knot_dname_label_count(closest_encloser); - int qname_labels = knot_dname_label_count(name); + int ce_labels = knot_dname_wire_labels(closest_encloser->name, NULL); + int qname_labels = knot_dname_wire_labels(name->name, NULL); assert(ce_labels < qname_labels); @@ -949,7 +957,9 @@ static knot_dname_t *ns_next_closer(const knot_dname_t *closest_encloser, } for (int i = 0; i < (qname_labels - ce_labels - 1); ++i) { - knot_dname_left_chop_no_copy(next_closer); + knot_dname_t *old_next_closer = next_closer; + next_closer = knot_dname_left_chop(next_closer); + knot_dname_free(&old_next_closer); } return next_closer; @@ -1163,7 +1173,7 @@ static knot_dname_t *ns_wildcard_child_name(const knot_dname_t *name) { assert(name != NULL); - knot_dname_t *wildcard = knot_dname_new_from_str("*", 1, NULL); + knot_dname_t *wildcard = knot_dname_new_from_str("*", 1); if (wildcard == NULL) { return NULL; } @@ -2011,9 +2021,9 @@ static int ns_dname_is_too_long(const knot_rrset_t *rrset, const knot_dname_t *qname) { // TODO: add function for getting DNAME target - if (knot_dname_label_count(qname) - - knot_dname_label_count(knot_rrset_owner(rrset)) - + knot_dname_label_count(knot_rrset_rdata_dname_target(rrset)) + if (knot_dname_wire_labels(qname->name, NULL) + - knot_dname_wire_labels(knot_rrset_owner(rrset)->name, NULL) + + knot_dname_wire_labels(knot_rrset_rdata_dname_target(rrset)->name, NULL) > KNOT_MAX_DNAME_LENGTH) { return 1; } else { @@ -2605,7 +2615,7 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig) // Clean the response structure dbg_ns_verb("Clearing response structure..\n"); - knot_response_clear(xfr->response, 0); + knot_response_clear(xfr->response); // increment the packet number ++xfr->packet_nr; @@ -2996,12 +3006,12 @@ static int ns_ixfr(knot_ns_xfr_t *xfr) /*----------------------------------------------------------------------------*/ static int knot_ns_prepare_response(knot_packet_t *query, knot_packet_t **resp, - size_t max_size, int copy_question) + size_t max_size) { assert(max_size >= 500); // initialize response packet structure - *resp = knot_packet_new_mm(KNOT_PACKET_PREALLOC_RESPONSE, &query->mm); + *resp = knot_packet_new_mm(&query->mm); if (*resp == NULL) { dbg_ns("Failed to create packet structure.\n"); return KNOT_ENOMEM; @@ -3015,7 +3025,7 @@ static int knot_ns_prepare_response(knot_packet_t *query, knot_packet_t **resp, return ret; } - ret = knot_response_init_from_query(*resp, query, copy_question); + ret = knot_response_init_from_query(*resp, query); if (ret != KNOT_EOK) { dbg_ns("Failed to init response structure.\n"); @@ -3056,7 +3066,7 @@ knot_nameserver_t *knot_ns_create() } // prepare empty response with SERVFAIL error - knot_packet_t *err = knot_packet_new(KNOT_PACKET_PREALLOC_NONE); + knot_packet_t *err = knot_packet_new(); if (err == NULL) { ERR_ALLOC_FAILED; free(ns); @@ -3350,8 +3360,7 @@ int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver, if (query->parsed > KNOT_WIRE_HEADER_SIZE + KNOT_WIRE_QUESTION_MIN_SIZE) { // in this case the whole question was parsed, append it - size_t question_size = 4 + knot_dname_size( - knot_packet_qname(query)); + size_t question_size = knot_packet_question_size(query); if (max_size > KNOT_WIRE_HEADER_SIZE + question_size) { /* @@ -3488,7 +3497,7 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver, resp_max_size = MAX_UDP_PAYLOAD; } - ret = knot_ns_prepare_response(query, resp, resp_max_size, 1); + ret = knot_ns_prepare_response(query, resp, resp_max_size); if (ret != KNOT_EOK) { return KNOT_ERROR; } @@ -3535,6 +3544,10 @@ dbg_ns_exec_verb( knot_zonedb_t *zonedb = rcu_dereference(nameserver->zone_db); *zone = ns_get_zone_for_qname(zonedb, qname, qtype); + /* Assign zone to packets. */ + query->zone = *zone; + (*resp)->zone = *zone; + return KNOT_EOK; } @@ -3627,11 +3640,15 @@ int knot_ns_prep_update_response(knot_nameserver_t *nameserver, resp_max_size = MAX_UDP_PAYLOAD; } - ret = knot_ns_prepare_response(query, resp, resp_max_size, 0); + ret = knot_ns_prepare_response(query, resp, resp_max_size); if (ret != KNOT_EOK) { return KNOT_ERROR; } + /* Trim question for DDNS answer. */ + knot_packet_set_size(query, KNOT_WIRE_HEADER_SIZE); + knot_wire_set_qdcount(query->wireformat, 0); + dbg_ns_verb("Query - parsed: %zu, total wire size: %zu\n", query->parsed, query->size); dbg_ns_detail("Opt RR: version: %d, payload: %d\n", @@ -3821,7 +3838,7 @@ dbg_ns_exec( int knot_ns_init_xfr_resp(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr) { int ret = KNOT_EOK; - knot_packet_t *resp = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE); + knot_packet_t *resp = knot_packet_new_mm(&xfr->query->mm); if (resp == NULL) { dbg_ns("Failed to create packet structure.\n"); /*! \todo xfr->wire is not NULL, will fail on assert! */ @@ -3836,7 +3853,7 @@ int knot_ns_init_xfr_resp(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr) resp->wireformat = xfr->wire; resp->max_size = xfr->wire_size; - ret = knot_response_init_from_query(resp, xfr->query, 1); + ret = knot_response_init_from_query(resp, xfr->query); if (ret != KNOT_EOK) { dbg_ns("Failed to init response structure.\n"); diff --git a/src/libknot/packet/packet.c b/src/libknot/packet/packet.c index f963b9d1861915f25b5ec55854ec9dde1b95f15b..6e1cbbb9801961e727aef7849e9731d51bba4b32 100644 --- a/src/libknot/packet/packet.c +++ b/src/libknot/packet/packet.c @@ -25,267 +25,33 @@ #include "util/wire.h" #include "tsig.h" -/*----------------------------------------------------------------------------*/ - -#define DEFAULT_RRCOUNT_QUERY(type) DEFAULT_##type##COUNT_QUERY -#define DEFAULT_RRCOUNT(type) DEFAULT_##type##COUNT - -#define DEFAULT_RRSET_COUNT(type, packet) \ - ((packet->prealloc_type == KNOT_PACKET_PREALLOC_NONE) \ - ? 0 \ - : (packet->prealloc_type == KNOT_PACKET_PREALLOC_QUERY) \ - ? DEFAULT_##type##_QUERY \ - : DEFAULT_##type) - /*----------------------------------------------------------------------------*/ /* Non-API functions */ /*----------------------------------------------------------------------------*/ -/*! - * \brief Sets all the pointers in the packet structure to the respective - * parts of the pre-allocated space. - */ -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 - pkt->question.qname = (knot_dname_t *)pos; - pos += PREALLOC_QNAME_DNAME; - - dbg_packet_detail("QNAME: %p\n", pkt->question.qname); - - pkt->question.qname->name = (uint8_t *)pos; - pos += PREALLOC_QNAME_NAME; - pkt->question.qname->labels = (uint8_t *)pos; - pos += PREALLOC_QNAME_LABELS; - - // then answer, authority and additional sections - if (DEFAULT_ANCOUNT == 0) { - pkt->answer = NULL; - } else { - 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 { - pkt->additional = (const knot_rrset_t **)pos; - pos += DEFAULT_ARCOUNT * sizeof(const knot_rrset_t *); - } - - dbg_packet_detail("Answer section: %p\n", pkt->answer); - dbg_packet_detail("Authority section: %p\n", pkt->authority); - dbg_packet_detail("Additional section: %p\n", pkt->additional); - - pkt->max_an_rrsets = DEFAULT_ANCOUNT; - pkt->max_ns_rrsets = DEFAULT_NSCOUNT; - pkt->max_ar_rrsets = DEFAULT_ARCOUNT; - - // 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 *); - pkt->wildcard_nodes.snames = (const knot_dname_t **)pos; - pos += DEFAULT_WILDCARD_NODES * sizeof(knot_dname_t *); - - dbg_packet_detail("Wildcard nodes: %p\n", pkt->wildcard_nodes.nodes); - dbg_packet_detail("Wildcard SNAMEs: %p\n", pkt->wildcard_nodes.snames); - - pkt->wildcard_nodes.default_count = DEFAULT_WILDCARD_NODES; - pkt->wildcard_nodes.max = DEFAULT_WILDCARD_NODES; - - pkt->tmp_rrsets = (const knot_rrset_t **)pos; - pos += DEFAULT_TMP_RRSETS * sizeof(const knot_rrset_t *); - - dbg_packet_detail("Tmp rrsets: %p\n", pkt->tmp_rrsets); - - pkt->tmp_rrsets_max = DEFAULT_TMP_RRSETS; - - assert((char *)pos == (char *)pkt + PREALLOC_RESPONSE); -} /*----------------------------------------------------------------------------*/ -/*! - * \brief Sets all the pointers in the packet structure to the respective - * parts of the pre-allocated space. - */ -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 - pkt->question.qname = (knot_dname_t *)pos; - pos += PREALLOC_QNAME_DNAME; - - dbg_packet_detail("QNAME: %p (%zu after start of packet)\n", - pkt->question.qname, - (void *)pkt->question.qname - (void *)pkt); - - pkt->question.qname->name = (uint8_t *)pos; - pos += PREALLOC_QNAME_NAME; - pkt->question.qname->labels = (uint8_t *)pos; - pos += PREALLOC_QNAME_LABELS; - - - // then answer, authority and additional sections - if (DEFAULT_ANCOUNT_QUERY == 0) { - pkt->answer = NULL; - } else { - 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 { - pkt->additional = (const knot_rrset_t **)pos; - pos += DEFAULT_ARCOUNT_QUERY * sizeof(const knot_rrset_t *); - } - - dbg_packet_detail("Answer section: %p\n", pkt->answer); - dbg_packet_detail("Authority section: %p\n", pkt->authority); - dbg_packet_detail("Additional section: %p\n", pkt->additional); - - pkt->max_an_rrsets = DEFAULT_ANCOUNT_QUERY; - pkt->max_ns_rrsets = DEFAULT_NSCOUNT_QUERY; - pkt->max_ar_rrsets = DEFAULT_ARCOUNT_QUERY; - - pkt->tmp_rrsets = (const knot_rrset_t **)pos; - pos += DEFAULT_TMP_RRSETS_QUERY * sizeof(const knot_rrset_t *); - - dbg_packet_detail("Tmp rrsets: %p\n", pkt->tmp_rrsets); - - pkt->tmp_rrsets_max = DEFAULT_TMP_RRSETS_QUERY; - - dbg_packet_detail("Allocated total: %u\n", PREALLOC_QUERY); - - assert(pos == (char *)pkt + PREALLOC_QUERY); -} /*----------------------------------------------------------------------------*/ /*! - * \brief Parses DNS header from the wire format. - * - * \note This function also adjusts the position (\a pos) and size of remaining - * bytes in the wire format (\a remaining) according to what was parsed - * (though it actually always parses the 12 bytes of the header). - * - * \param[in,out] pos Wire format to parse the header from. - * \param[in,out] remaining Remaining size of the wire format. - * \param[out] header Header structure to fill in. - * - * \retval KNOT_EOK - * \retval KNOT_EFEWDATA + * \brief Processes DNS Question entry from the wire format. */ -static int knot_packet_parse_header(const uint8_t *wire, size_t *pos, - size_t size, knot_header_t *header) +static int knot_packet_parse_question(knot_packet_t *pkt) { - assert(wire != NULL); - assert(pos != NULL); - assert(header != NULL); - - if (size - *pos < KNOT_WIRE_HEADER_SIZE) { - dbg_packet("Not enough data to parse header.\n"); - return KNOT_EFEWDATA; - } - - header->id = knot_wire_get_id(wire); - header->flags1 = knot_wire_get_flags1(wire); - header->flags2 = knot_wire_get_flags2(wire); + assert(pkt != NULL); - header->qdcount = knot_wire_get_qdcount(wire); - header->ancount = knot_wire_get_ancount(wire); - header->nscount = knot_wire_get_nscount(wire); - header->arcount = knot_wire_get_arcount(wire); + dbg_packet("Parsing Question starting on position %zu.\n", pkt->parsed); - *pos += KNOT_WIRE_HEADER_SIZE; - - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ -/*! - * \brief Parses DNS Question entry from the wire format. - * - * \note This function also adjusts the position (\a pos) and size of remaining - * bytes in the wire format (\a remaining) according to what was parsed. - * - * \param[in,out] pos Wire format to parse the Question from. - * \param[in,out] remaining Remaining size of the wire format. - * \param[out] question DNS Question structure to be filled. - * - * \retval KNOT_EOK - * \retval KNOT_EFEWDATA - * \retval KNOT_ENOMEM - */ -static int knot_packet_parse_question(const uint8_t *wire, size_t *pos, - size_t size, - knot_question_t *question, int alloc) -{ - assert(pos != NULL); - assert(wire != NULL); - assert(question != NULL); - - if (size - *pos < KNOT_WIRE_QUESTION_MIN_SIZE) { - dbg_packet("Not enough data to parse question.\n"); - return KNOT_EFEWDATA; // malformed - } - - dbg_packet("Parsing Question starting on position %zu.\n", *pos); - - // domain name must end with 0, so just search for 0 - int i = *pos; - while (i < size && wire[i] != 0) { - ++i; - } - - if (size - i - 1 < 4) { - dbg_packet("Not enough data to parse question.\n"); - return KNOT_EFEWDATA; // no 0 found or not enough data left - } + /* Process question. */ + int len = knot_dname_wire_check(pkt->wireformat + pkt->parsed, + pkt->wireformat + pkt->size, + pkt->wireformat); + if (len <= 0) + return KNOT_EMALF; - dbg_packet_verb("Parsing dname starting on position %zu and " - "%zu bytes long.\n", *pos, i - *pos + 1); - dbg_packet_verb("Alloc: %d\n", alloc); - if (alloc) { - question->qname = knot_dname_parse_from_wire(wire, pos, - i + 1, - NULL, NULL); - 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, - i + 1, - NULL, question->qname); - 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); - *pos += 4; + /*! \todo Question case should be preserved. */ + /* knot_dname_to_lower(question->qname); */ + pkt->parsed += len + 2 * sizeof(uint16_t); /* Class + Type */ + pkt->qname_size = len; return KNOT_EOK; } @@ -296,37 +62,24 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos, * * \param rrsets Space for RRSets. * \param max_count Size of the space available for the RRSets. - * \param default_max_count Size of the space pre-allocated for the RRSets when - * the response structure was initialized. - * \param step How much the space should be increased. * * \retval KNOT_EOK * \retval KNOT_ENOMEM */ -static int knot_packet_realloc_rrsets(const knot_rrset_t ***rrsets, - short *max_count, - short default_max_count, short step) +int knot_packet_realloc_rrsets(const knot_rrset_t ***rrsets, + short *max_count, + mm_ctx_t *mm) { - dbg_packet_verb("Max count: %d, default max count: %d\n", - *max_count, default_max_count); - int free_old = (*max_count) != default_max_count; - const knot_rrset_t **old = *rrsets; - - short new_max_count = *max_count + step; - const knot_rrset_t **new_rrsets = (const knot_rrset_t **)malloc( + short new_max_count = *max_count + RRSET_ALLOC_STEP; + const knot_rrset_t **new_rrsets = mm->alloc(mm->ctx, new_max_count * sizeof(knot_rrset_t *)); CHECK_ALLOC_LOG(new_rrsets, KNOT_ENOMEM); - - memset(new_rrsets, 0, new_max_count * sizeof(knot_rrset_t *)); memcpy(new_rrsets, *rrsets, (*max_count) * sizeof(knot_rrset_t *)); + mm->free(*rrsets); *rrsets = new_rrsets; *max_count = new_max_count; - if (free_old) { - free(old); - } - return KNOT_EOK; } @@ -410,8 +163,7 @@ static knot_rrset_t *knot_packet_parse_rr(const uint8_t *wire, size_t *pos, dbg_packet("Parsing RR from position: %zu, total size: %zu\n", *pos, size); - knot_dname_t *owner = knot_dname_parse_from_wire(wire, pos, size, - NULL, NULL); + knot_dname_t *owner = knot_dname_parse_from_wire(wire, pos, size); dbg_packet_detail("Created owner: %p, actual position: %zu\n", owner, *pos); if (owner == NULL) { @@ -490,8 +242,7 @@ static int knot_packet_add_rrset(knot_rrset_t *rrset, const knot_rrset_t ***rrsets, short *rrset_count, short *max_rrsets, - short default_rrsets, - const knot_packet_t *packet, + knot_packet_t *packet, knot_packet_flag_t flags) { assert(rrset != NULL); @@ -507,8 +258,8 @@ dbg_packet_exec_verb( ); if (*rrset_count == *max_rrsets - && knot_packet_realloc_rrsets(rrsets, max_rrsets, default_rrsets, - STEP_ANCOUNT) != KNOT_EOK) { + && knot_packet_realloc_rrsets(rrsets, max_rrsets, + &packet->mm) != KNOT_EOK) { return KNOT_ENOMEM; } @@ -557,7 +308,6 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos, uint16_t *parsed_rrs, const knot_rrset_t ***rrsets, short *rrset_count, short *max_rrsets, - short default_rrsets, knot_packet_t *packet, knot_packet_flag_t flags) { @@ -590,7 +340,7 @@ 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, flags); + max_rrsets, packet, flags); if (err < 0) { break; } else if (err == 1) { // merged, shallow data copy @@ -642,29 +392,13 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos, static void knot_packet_free_allocated_space(knot_packet_t *pkt) { dbg_packet_verb("Freeing additional space in packet.\n"); - if (pkt->prealloc_type == KNOT_PACKET_PREALLOC_NONE) { - dbg_packet_detail("Freeing QNAME.\n"); - knot_dname_release(pkt->question.qname); - } - - if (pkt->max_an_rrsets > DEFAULT_RRSET_COUNT(ANCOUNT, pkt)) { - free(pkt->answer); - } - if (pkt->max_ns_rrsets > DEFAULT_RRSET_COUNT(NSCOUNT, pkt)) { - free(pkt->authority); - } - if (pkt->max_ar_rrsets > DEFAULT_RRSET_COUNT(ARCOUNT, pkt)) { - free(pkt->additional); - } - - if (pkt->wildcard_nodes.max > pkt->wildcard_nodes.default_count) { - free(pkt->wildcard_nodes.nodes); - free(pkt->wildcard_nodes.snames); - } - if (pkt->tmp_rrsets_max > DEFAULT_RRSET_COUNT(TMP_RRSETS, pkt)) { - free(pkt->tmp_rrsets); - } + pkt->mm.free(pkt->answer); + pkt->mm.free(pkt->authority); + pkt->mm.free(pkt->additional); + pkt->mm.free(pkt->wildcard_nodes.nodes); + pkt->mm.free(pkt->wildcard_nodes.snames); + pkt->mm.free(pkt->tmp_rrsets); } /*----------------------------------------------------------------------------*/ @@ -684,9 +418,9 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, size_t *pos, dbg_packet_verb("Parsing Answer RRs...\n"); if ((err = knot_packet_parse_rrs(packet->wireformat, pos, - packet->size, packet->header.ancount, &packet->parsed_an, + packet->size, knot_wire_get_ancount(packet->wireformat), &packet->parsed_an, &packet->answer, &packet->an_rrsets, &packet->max_an_rrsets, - DEFAULT_RRSET_COUNT(ANCOUNT, packet), packet, flags)) != KNOT_EOK) { + packet, flags)) != KNOT_EOK) { return err; } @@ -697,9 +431,9 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, size_t *pos, dbg_packet_verb("Parsing Authority RRs...\n"); if ((err = knot_packet_parse_rrs(packet->wireformat, pos, - packet->size, packet->header.nscount, &packet->parsed_ns, + packet->size, knot_wire_get_nscount(packet->wireformat), &packet->parsed_ns, &packet->authority, &packet->ns_rrsets, &packet->max_ns_rrsets, - DEFAULT_RRSET_COUNT(NSCOUNT, packet), packet, flags)) != KNOT_EOK) { + packet, flags)) != KNOT_EOK) { return err; } @@ -710,9 +444,9 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, size_t *pos, dbg_packet_verb("Parsing Additional RRs...\n"); if ((err = knot_packet_parse_rrs(packet->wireformat, pos, - packet->size, packet->header.arcount, &packet->parsed_ar, + packet->size, knot_wire_get_arcount(packet->wireformat), &packet->parsed_ar, &packet->additional, &packet->ar_rrsets, &packet->max_ar_rrsets, - DEFAULT_RRSET_COUNT(ARCOUNT, packet), packet, flags)) != KNOT_EOK) { + packet, flags)) != KNOT_EOK) { return err; } @@ -755,42 +489,21 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet, size_t *pos, /* API functions */ /*----------------------------------------------------------------------------*/ -knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc) +knot_packet_t *knot_packet_new() { mm_ctx_t mm; mm_ctx_init(&mm); - return knot_packet_new_mm(prealloc, &mm); + return knot_packet_new_mm(&mm); } -knot_packet_t *knot_packet_new_mm(knot_packet_prealloc_type_t prealloc, mm_ctx_t *mm) +knot_packet_t *knot_packet_new_mm(mm_ctx_t *mm) { knot_packet_t *pkt = NULL; - void (*init_pointers)(knot_packet_t *pkt) = NULL; - size_t size = 0; - - switch (prealloc) { - case KNOT_PACKET_PREALLOC_NONE: - size = sizeof(knot_packet_t); - break; - case KNOT_PACKET_PREALLOC_QUERY: - size = PREALLOC_QUERY; - init_pointers = knot_packet_init_pointers_query; - break; - case KNOT_PACKET_PREALLOC_RESPONSE: - size = PREALLOC_RESPONSE; - init_pointers = knot_packet_init_pointers_response; - break; - } - - pkt = (knot_packet_t *)mm->alloc(mm->ctx, size); + + pkt = (knot_packet_t *)mm->alloc(mm->ctx, sizeof(knot_packet_t)); CHECK_ALLOC_LOG(pkt, NULL); - memset(pkt, 0, size); + memset(pkt, 0, sizeof(knot_packet_t)); memcpy(&pkt->mm, mm, sizeof(mm_ctx_t)); - if (init_pointers != NULL) { - init_pointers(pkt); - } - - pkt->prealloc_type = prealloc; // set EDNS version to not supported pkt->opt_rr.version = EDNS_NOT_SUPPORTED; @@ -804,52 +517,27 @@ int knot_packet_parse_from_wire(knot_packet_t *packet, const uint8_t *wireformat, size_t size, int question_only, knot_packet_flag_t flags) { - if (packet == NULL || wireformat == NULL) { + if (packet == NULL || wireformat == NULL || size < KNOT_WIRE_HEADER_SIZE) return KNOT_EINVAL; - } - int err; - // save the wireformat in the packet - // TODO: can we just save the pointer, or we have to copy the data?? + int err = KNOT_EOK; + assert(packet->wireformat == NULL); packet->wireformat = (uint8_t*)wireformat; packet->size = size; - packet->free_wireformat = 0; - - if (size < 2) { - return KNOT_EMALF; - } - - size_t pos = 0; - - dbg_packet_verb("Parsing wire format of packet (size %zu).\nHeader\n", - size); - if ((err = knot_packet_parse_header(wireformat, &pos, size, - &packet->header)) != KNOT_EOK) { - return err; - } - - packet->parsed = pos; - - dbg_packet_verb("Question (prealloc type: %d)...\n", - packet->prealloc_type); + packet->flags &= ~KNOT_PF_FREE_WIRE; + packet->parsed = KNOT_WIRE_HEADER_SIZE; - if (packet->header.qdcount > 1) { + uint16_t qdcount = knot_wire_get_qdcount(packet->wireformat); + if (qdcount == 1) { + if ((err = knot_packet_parse_question(packet)) != KNOT_EOK) + return err; + } else if (qdcount > 1) { dbg_packet("QDCOUNT larger than 1, FORMERR.\n"); return KNOT_EMALF; } - if (packet->header.qdcount == 1) { - if ((err = knot_packet_parse_question(wireformat, &pos, size, - &packet->question, packet->prealloc_type - == KNOT_PACKET_PREALLOC_NONE) - ) != KNOT_EOK) { - return err; - } - packet->parsed = pos; - } - dbg_packet_exec_detail( knot_packet_dump(packet); ); @@ -876,9 +564,9 @@ int knot_packet_parse_rest(knot_packet_t *packet, knot_packet_flag_t flags) return KNOT_EINVAL; } - if (packet->header.ancount == packet->parsed_an - && packet->header.nscount == packet->parsed_ns - && packet->header.arcount == packet->parsed_ar + if (knot_wire_get_ancount(packet->wireformat) == packet->parsed_an + && knot_wire_get_nscount(packet->wireformat) == packet->parsed_ns + && knot_wire_get_arcount(packet->wireformat) == packet->parsed_ar && packet->parsed == packet->size) { return KNOT_EOK; } @@ -906,8 +594,8 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet, *rr = NULL; if (packet->parsed >= packet->size) { - assert(packet->an_rrsets <= packet->header.ancount); - if (packet->parsed_an != packet->header.ancount) { + assert(packet->an_rrsets <= knot_wire_get_ancount(packet->wireformat)); + if (packet->parsed_an != knot_wire_get_ancount(packet->wireformat)) { dbg_packet("Parsed less RRs than expected.\n"); return KNOT_EMALF; } else { @@ -916,7 +604,7 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet, } } - if (packet->parsed_an == packet->header.ancount) { + if (packet->parsed_an == knot_wire_get_ancount(packet->wireformat)) { assert(packet->parsed < packet->size); //dbg_packet("Trailing garbage, ignoring...\n"); // there may be other data in the packet @@ -957,8 +645,8 @@ int knot_packet_parse_next_rr_additional(knot_packet_t *packet, *rr = NULL; if (packet->parsed >= packet->size) { - assert(packet->ar_rrsets <= packet->header.arcount); - if (packet->parsed_ar != packet->header.arcount) { + assert(packet->ar_rrsets <= knot_wire_get_arcount(packet->wireformat)); + if (packet->parsed_ar != knot_wire_get_arcount(packet->wireformat)) { dbg_packet("Parsed less RRs than expected.\n"); return KNOT_EMALF; } else { @@ -967,7 +655,7 @@ int knot_packet_parse_next_rr_additional(knot_packet_t *packet, } } - if (packet->parsed_ar == packet->header.arcount) { + if (packet->parsed_ar == knot_wire_get_arcount(packet->wireformat)) { assert(packet->parsed < packet->size); dbg_packet_verb("Trailing garbage, treating as malformed...\n"); return KNOT_EMALF; @@ -1011,8 +699,7 @@ size_t knot_packet_max_size(const knot_packet_t *packet) size_t knot_packet_question_size(const knot_packet_t *packet) { - return (KNOT_WIRE_HEADER_SIZE + 4 - + knot_dname_size(packet->question.qname)); + return KNOT_WIRE_HEADER_SIZE + packet->qname_size + 2 * sizeof(uint16_t); } /*----------------------------------------------------------------------------*/ @@ -1024,6 +711,16 @@ size_t knot_packet_parsed(const knot_packet_t *packet) /*----------------------------------------------------------------------------*/ +int knot_packet_set_size(knot_packet_t *packet, int size) +{ + if (packet == NULL || size > packet->max_size) + return KNOT_EINVAL; + + return packet->size = size; +} + +/*----------------------------------------------------------------------------*/ + int knot_packet_set_max_size(knot_packet_t *packet, int max_size) { if (packet == NULL || max_size <= 0) { @@ -1038,22 +735,17 @@ int knot_packet_set_max_size(knot_packet_t *packet, int max_size) return KNOT_ENOMEM; } - uint8_t *wire_old = packet->wireformat; - - memcpy(wire_new, packet->wireformat, packet->max_size); - packet->wireformat = wire_new; - - if (packet->max_size > 0 && packet->free_wireformat) { - if (packet->mm.free) - packet->mm.free(wire_old); + if (packet->max_size > 0) { + memcpy(wire_new, packet->wireformat, packet->max_size); + if (packet->flags & KNOT_PF_FREE_WIRE) + packet->mm.free(packet->wireformat); } - packet->free_wireformat = 1; + packet->wireformat = wire_new; + packet->max_size = max_size; + packet->flags |= KNOT_PF_FREE_WIRE; } - // set max size - packet->max_size = max_size; - return KNOT_EOK; } @@ -1062,18 +754,7 @@ int knot_packet_set_max_size(knot_packet_t *packet, int max_size) uint16_t knot_packet_id(const knot_packet_t *packet) { assert(packet != NULL); - return packet->header.id; -} - -/*----------------------------------------------------------------------------*/ - -void knot_packet_set_id(knot_packet_t *packet, uint16_t id) -{ - if (packet == NULL) { - return; - } - - packet->header.id = id; + return knot_wire_get_id(packet->wireformat); } /*----------------------------------------------------------------------------*/ @@ -1084,7 +765,7 @@ void knot_packet_set_random_id(knot_packet_t *packet) return; } - packet->header.id = knot_random_id(); + knot_wire_set_id(packet->wireformat, knot_random_id()); } /*----------------------------------------------------------------------------*/ @@ -1092,15 +773,8 @@ void knot_packet_set_random_id(knot_packet_t *packet) uint8_t knot_packet_opcode(const knot_packet_t *packet) { assert(packet != NULL); - return knot_wire_flags_get_opcode(packet->header.flags1); -} - -/*----------------------------------------------------------------------------*/ - -knot_question_t *knot_packet_question(knot_packet_t *packet) -{ - if (packet == NULL) return NULL; - return &packet->question; + uint8_t flags = knot_wire_get_flags1(packet->wireformat); + return knot_wire_flags_get_opcode(flags); } /*----------------------------------------------------------------------------*/ @@ -1111,7 +785,11 @@ const knot_dname_t *knot_packet_qname(const knot_packet_t *packet) return NULL; } - return packet->question.qname; + /*! \todo This will leak until dname API is finished, it's just placeholder + * to make it compile and work. + */ + const uint8_t *qname = packet->wireformat + KNOT_WIRE_HEADER_SIZE; + return knot_dname_new_from_wire(qname, knot_dname_wire_size(qname, NULL)); } /*----------------------------------------------------------------------------*/ @@ -1119,15 +797,8 @@ const knot_dname_t *knot_packet_qname(const knot_packet_t *packet) uint16_t knot_packet_qtype(const knot_packet_t *packet) { assert(packet != NULL); - return packet->question.qtype; -} - -/*----------------------------------------------------------------------------*/ - -void knot_packet_set_qtype(knot_packet_t *packet, uint16_t qtype) -{ - assert(packet != NULL); - packet->question.qtype = qtype; + unsigned off = KNOT_WIRE_HEADER_SIZE + packet->qname_size; + return knot_wire_read_u16(packet->wireformat + off); } /*----------------------------------------------------------------------------*/ @@ -1135,7 +806,8 @@ void knot_packet_set_qtype(knot_packet_t *packet, uint16_t qtype) uint16_t knot_packet_qclass(const knot_packet_t *packet) { assert(packet != NULL); - return packet->question.qclass; + unsigned off = KNOT_WIRE_HEADER_SIZE + packet->qname_size + sizeof(uint16_t); + return knot_wire_read_u16(packet->wireformat + off); } /*----------------------------------------------------------------------------*/ @@ -1146,7 +818,8 @@ int knot_packet_is_query(const knot_packet_t *packet) return KNOT_EINVAL; } - return (knot_wire_flags_get_qr(packet->header.flags1) == 0); + uint8_t flags = knot_wire_get_flags1(packet->wireformat); + return (knot_wire_flags_get_qr(flags) == 0); } /*----------------------------------------------------------------------------*/ @@ -1168,7 +841,8 @@ int knot_packet_rcode(const knot_packet_t *packet) return KNOT_EINVAL; } - return knot_wire_flags_get_rcode(packet->header.flags2); + uint8_t flags = knot_wire_get_flags2(packet->wireformat); + return knot_wire_flags_get_rcode(flags); } /*----------------------------------------------------------------------------*/ @@ -1179,7 +853,8 @@ int knot_packet_tc(const knot_packet_t *packet) return KNOT_EINVAL; } - return knot_wire_flags_get_tc(packet->header.flags1); + uint8_t flags = knot_wire_get_flags1(packet->wireformat); + return knot_wire_flags_get_tc(flags); } /*----------------------------------------------------------------------------*/ @@ -1190,7 +865,7 @@ int knot_packet_qdcount(const knot_packet_t *packet) return KNOT_EINVAL; } - return packet->header.qdcount; + return knot_wire_get_qdcount(packet->wireformat); } /*----------------------------------------------------------------------------*/ @@ -1201,7 +876,7 @@ int knot_packet_ancount(const knot_packet_t *packet) return KNOT_EINVAL; } - return packet->header.ancount; + return knot_wire_get_ancount(packet->wireformat); } /*----------------------------------------------------------------------------*/ @@ -1212,7 +887,7 @@ int knot_packet_nscount(const knot_packet_t *packet) return KNOT_EINVAL; } - return packet->header.nscount; + return knot_wire_get_nscount(packet->wireformat); } /*----------------------------------------------------------------------------*/ @@ -1223,7 +898,7 @@ int knot_packet_arcount(const knot_packet_t *packet) return KNOT_EINVAL; } - return packet->header.arcount; + return knot_wire_get_arcount(packet->wireformat); } /*----------------------------------------------------------------------------*/ @@ -1356,12 +1031,12 @@ int knot_packet_add_tmp_rrset(knot_packet_t *packet, return KNOT_EINVAL; } - if (packet->tmp_rrsets_count == packet->tmp_rrsets_max - && knot_packet_realloc_rrsets(&packet->tmp_rrsets, - &packet->tmp_rrsets_max, - DEFAULT_RRSET_COUNT(TMP_RRSETS, packet), - STEP_TMP_RRSETS) != KNOT_EOK) { - return KNOT_ENOMEM; + if (packet->tmp_rrsets_count == packet->tmp_rrsets_max) { + int ret = knot_packet_realloc_rrsets(&packet->tmp_rrsets, + &packet->tmp_rrsets_max, + &packet->mm); + if (ret != KNOT_EOK) + return ret; } packet->tmp_rrsets[packet->tmp_rrsets_count++] = tmp_rrset; @@ -1405,60 +1080,6 @@ dbg_packet_exec( /*----------------------------------------------------------------------------*/ -void knot_packet_header_to_wire(const knot_header_t *header, - uint8_t **pos, size_t *size) -{ - if (header == NULL || pos == NULL || *pos == NULL || size == NULL) { - return; - } - - knot_wire_set_id(*pos, header->id); - knot_wire_set_flags1(*pos, header->flags1); - knot_wire_set_flags2(*pos, header->flags2); - knot_wire_set_qdcount(*pos, header->qdcount); - knot_wire_set_ancount(*pos, header->ancount); - knot_wire_set_nscount(*pos, header->nscount); - knot_wire_set_arcount(*pos, header->arcount); - - *pos += KNOT_WIRE_HEADER_SIZE; - *size += KNOT_WIRE_HEADER_SIZE; -} - -/*----------------------------------------------------------------------------*/ - -int knot_packet_question_to_wire(knot_packet_t *packet) -{ - if (packet == NULL || packet->question.qname == NULL) { - return KNOT_EINVAL; - } - - if (packet->size > KNOT_WIRE_HEADER_SIZE) { - return KNOT_ERROR; - } - - // TODO: get rid of the numeric constants - size_t qsize = 4 + knot_dname_size(packet->question.qname); - if (qsize > packet->max_size - KNOT_WIRE_HEADER_SIZE) { - return KNOT_ESPACE; - } - - // create the wireformat of Question - uint8_t *pos = packet->wireformat + KNOT_WIRE_HEADER_SIZE; - memcpy(pos, knot_dname_name(packet->question.qname), - knot_dname_size(packet->question.qname)); - - pos += knot_dname_size(packet->question.qname); - knot_wire_write_u16(pos, packet->question.qtype); - pos += 2; - knot_wire_write_u16(pos, packet->question.qclass); - - packet->size += knot_dname_size(packet->question.qname) + 4; - - return KNOT_EOK; -} - -/*----------------------------------------------------------------------------*/ - int knot_packet_edns_to_wire(knot_packet_t *packet) { if (packet == NULL) { @@ -1469,7 +1090,7 @@ int knot_packet_edns_to_wire(knot_packet_t *packet) packet->wireformat + packet->size, packet->max_size - packet->size); - packet->header.arcount += 1; + knot_wire_add_arcount(packet->wireformat, 1); return KNOT_EOK; } @@ -1487,20 +1108,11 @@ int knot_packet_to_wire(knot_packet_t *packet, assert(packet->size <= packet->max_size); // if there are no additional RRSets, add EDNS OPT RR - if (packet->header.arcount == 0 + if (knot_wire_get_arcount(packet->wireformat) == 0 && packet->opt_rr.version != EDNS_NOT_SUPPORTED) { knot_packet_edns_to_wire(packet); } - // set QDCOUNT (in response it is already set, in query it is needed) - knot_wire_set_qdcount(packet->wireformat, packet->header.qdcount); - // set ANCOUNT to the packet - knot_wire_set_ancount(packet->wireformat, packet->header.ancount); - // set NSCOUNT to the packet - knot_wire_set_nscount(packet->wireformat, packet->header.nscount); - // set ARCOUNT to the packet - knot_wire_set_arcount(packet->wireformat, packet->header.arcount); - //assert(response->size == size); *wire = packet->wireformat; *wire_size = packet->size; @@ -1532,17 +1144,14 @@ void knot_packet_free(knot_packet_t **packet) knot_packet_free_allocated_space(*packet); // free the space for wireformat - if ((*packet)->wireformat != NULL && (*packet)->free_wireformat) { - if ((*packet)->mm.free) - (*packet)->mm.free((*packet)->wireformat); - } + if ((*packet)->flags & KNOT_PF_FREE_WIRE) + (*packet)->mm.free((*packet)->wireformat); // free EDNS options knot_edns_free_options(&(*packet)->opt_rr); dbg_packet("Freeing packet structure\n"); - if ((*packet)->mm.free) - (*packet)->mm.free(*packet); + (*packet)->mm.free(*packet); *packet = NULL; } @@ -1567,36 +1176,34 @@ void knot_packet_dump(const knot_packet_t *packet) } #ifdef KNOT_PACKET_DEBUG + uint8_t flags1 = knot_wire_get_flags1(packet->wireformat); + uint8_t flags2 = knot_wire_get_flags2(packet->wireformat); dbg_packet("DNS packet:\n-----------------------------\n"); dbg_packet("\nHeader:\n"); - dbg_packet(" ID: %u\n", packet->header.id); + dbg_packet(" ID: %u\n", knot_wire_get_id(packet->wireformat)); dbg_packet(" FLAGS: %s %s %s %s %s %s %s\n", - knot_wire_flags_get_qr(packet->header.flags1) ? "qr" : "", - knot_wire_flags_get_aa(packet->header.flags1) ? "aa" : "", - knot_wire_flags_get_tc(packet->header.flags1) ? "tc" : "", - knot_wire_flags_get_rd(packet->header.flags1) ? "rd" : "", - knot_wire_flags_get_ra(packet->header.flags2) ? "ra" : "", - knot_wire_flags_get_ad(packet->header.flags2) ? "ad" : "", - knot_wire_flags_get_cd(packet->header.flags2) ? "cd" : ""); - dbg_packet(" RCODE: %u\n", knot_wire_flags_get_rcode( - packet->header.flags2)); - dbg_packet(" OPCODE: %u\n", knot_wire_flags_get_opcode( - packet->header.flags1)); - dbg_packet(" QDCOUNT: %u\n", packet->header.qdcount); - dbg_packet(" ANCOUNT: %u\n", packet->header.ancount); - dbg_packet(" NSCOUNT: %u\n", packet->header.nscount); - dbg_packet(" ARCOUNT: %u\n", packet->header.arcount); + knot_wire_flags_get_qr(flags1) ? "qr" : "", + knot_wire_flags_get_aa(flags1) ? "aa" : "", + knot_wire_flags_get_tc(flags1) ? "tc" : "", + knot_wire_flags_get_rd(flags1) ? "rd" : "", + knot_wire_flags_get_ra(flags2) ? "ra" : "", + knot_wire_flags_get_ad(flags2) ? "ad" : "", + knot_wire_flags_get_cd(flags2) ? "cd" : ""); + dbg_packet(" RCODE: %u\n", knot_wire_flags_get_rcode(flags2)); + dbg_packet(" OPCODE: %u\n", knot_wire_flags_get_opcode(flags1)); + dbg_packet(" QDCOUNT: %u\n", knot_wire_get_qdcount(packet->wireformat)); + dbg_packet(" ANCOUNT: %u\n", knot_wire_get_ancount(packet->wireformat)); + dbg_packet(" NSCOUNT: %u\n", knot_wire_get_nscount(packet->wireformat)); + dbg_packet(" ARCOUNT: %u\n", knot_wire_get_arcount(packet->wireformat)); if (knot_packet_qdcount(packet) > 0) { dbg_packet("\nQuestion:\n"); - char *qname = knot_dname_to_str(packet->question.qname); + char *qname = knot_dname_to_str(knot_packet_qname(packet)); dbg_packet(" QNAME: %s\n", qname); free(qname); - 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(" QTYPE: %u\n", knot_packet_qtype(packet)); + dbg_packet(" QCLASS: %u\n", knot_packet_qclass(packet)); } dbg_packet("\nAnswer RRSets:\n"); diff --git a/src/libknot/packet/packet.h b/src/libknot/packet/packet.h index 0921fba430a8c3bc1fb37974543eb84da80f8a04..e86afc9e1bb1ad3ebaf395169d96ad92afb77cb4 100644 --- a/src/libknot/packet/packet.h +++ b/src/libknot/packet/packet.h @@ -38,50 +38,19 @@ /*----------------------------------------------------------------------------*/ +/* How many RRs pointers to alloc in one step. */ +#define RRSET_ALLOC_STEP 8 + struct knot_wildcard_nodes { const knot_node_t **nodes; /*!< Wildcard nodes from CNAME processing. */ const knot_dname_t **snames; /*!< SNAMEs related to the nodes. */ short count; /*!< Count of items in the previous arrays. */ short max; /*!< Capacity of the structure (allocated). */ - short default_count; }; typedef struct knot_wildcard_nodes knot_wildcard_nodes_t; /*----------------------------------------------------------------------------*/ -/*! - * \brief Structure representing the DNS packet header. - */ -struct knot_header { - uint16_t id; /*!< ID stored in host byte order. */ - uint8_t flags1; /*!< First octet of header flags. */ - uint8_t flags2; /*!< Second octet of header flags. */ - uint16_t qdcount; /*!< Number of Question RRs, in host byte order. */ - uint16_t ancount; /*!< Number of Answer RRs, in host byte order. */ - uint16_t nscount; /*!< Number of Authority RRs, in host byte order. */ - uint16_t arcount; /*!< Number of Additional RRs, in host byte order. */ -}; - -typedef struct knot_header knot_header_t; - -/*! - * \brief Structure representing one Question entry in the DNS packet. - */ -struct knot_question { - knot_dname_t *qname; /*!< Question domain name. */ - uint16_t qtype; /*!< Question TYPE. */ - uint16_t qclass; /*!< Question CLASS. */ -}; - -typedef struct knot_question knot_question_t; - -enum knot_packet_prealloc_type { - KNOT_PACKET_PREALLOC_NONE, - KNOT_PACKET_PREALLOC_QUERY, - KNOT_PACKET_PREALLOC_RESPONSE -}; - -typedef enum knot_packet_prealloc_type knot_packet_prealloc_type_t; /* Maximum number of compressed names. */ #define COMPR_MAXLEN 64 @@ -98,21 +67,8 @@ typedef struct { /*----------------------------------------------------------------------------*/ /*! * \brief Structure representing a DNS packet. - * - * \note QNAME, Answer, Authority and Additonal sections are by default put to - * preallocated space after the structure with default sizes. If the - * space is not enough, more space is allocated dynamically. */ struct knot_packet { - /*! \brief DNS header. */ - knot_header_t header; - - /*! - * \brief Question section. - * - * \note Only one Question is supported! - */ - knot_question_t question; const knot_rrset_t **answer; /*!< Answer RRSets. */ const knot_rrset_t **authority; /*!< Authority RRSets. */ @@ -130,12 +86,12 @@ struct knot_packet { uint8_t *wireformat; /*!< Wire format of the packet. */ - short free_wireformat; size_t parsed; uint16_t parsed_an; uint16_t parsed_ns; uint16_t parsed_ar; + uint8_t qname_size; /*!< QNAME size. */ size_t size; /*!< Current wire size of the packet. */ size_t max_size; /*!< Maximum allowed size of the packet. */ @@ -152,8 +108,6 @@ struct knot_packet { struct knot_packet *query; /*!< Associated query. */ - knot_packet_prealloc_type_t prealloc_type; - size_t tsig_size; /*!< Space to reserve for the TSIG RR. */ knot_rrset_t *tsig_rr; /*!< TSIG RR stored in the packet. */ uint16_t flags; /*!< Packet flags. */ @@ -169,88 +123,14 @@ typedef struct knot_packet knot_packet_t; * \brief Packet flags. */ enum { - KNOT_PF_NULL = 0 << 0, /*!< No flags. */ - KNOT_PF_QUERY = 1 << 0, /*!< Packet is query. */ - KNOT_PF_WILDCARD = 1 << 1, /*!< Query to wildcard name. */ - KNOT_PF_RESPONSE = 1 << 2 /*!< Packet is response. */ -}; - -/*! - * \brief Default sizes for response structure parts and steps for increasing - * them. - */ -enum { - DEFAULT_ANCOUNT = 6, /*!< Default count of Answer RRSets. */ - DEFAULT_NSCOUNT = 8, /*!< Default count of Authority RRSets. */ - DEFAULT_ARCOUNT = 28, /*!< Default count of Additional RRSets. */ - - DEFAULT_ANCOUNT_QUERY = 1, /*!< Default count of Answer RRSets. */ - DEFAULT_NSCOUNT_QUERY = 0, /*!< Default count of Authority RRSets. */ - DEFAULT_ARCOUNT_QUERY = 1, /*!< Default count of Additional RRSets. */ - /*! - * \brief Default count of all domain names in response. - * - * Used for compression table. - */ - DEFAULT_DOMAINS_IN_RESPONSE = 22, - - /*! \brief Default count of temporary RRSets stored in response. */ - DEFAULT_TMP_RRSETS = 5, - - /*! \brief Default count of wildcard nodes saved for later processing.*/ - DEFAULT_WILDCARD_NODES = 1, - - /*! \brief Default count of temporary RRSets stored in query. */ - DEFAULT_TMP_RRSETS_QUERY = 2, - - STEP_ANCOUNT = 6, /*!< Step for increasing space for Answer RRSets. */ - STEP_NSCOUNT = 8, /*!< Step for increasing space for Authority RRSets.*/ - STEP_ARCOUNT = 8,/*!< Step for increasing space for Additional RRSets.*/ - STEP_DOMAINS = 10, /*!< Step for resizing compression table. */ - STEP_TMP_RRSETS = 5, /*!< Step for increasing temorary RRSets count. */ - STEP_WILDCARD_NODES = 2 + KNOT_PF_NULL = 0 << 0, /*!< No flags. */ + KNOT_PF_QUERY = 1 << 0, /*!< Packet is query. */ + KNOT_PF_WILDCARD = 1 << 1, /*!< Query to wildcard name. */ + KNOT_PF_RESPONSE = 1 << 2, /*!< Packet is response. */ + KNOT_PF_FREE_WIRE = 1 << 3 /*!< Free wire. */ }; /*----------------------------------------------------------------------------*/ -#define PREALLOC_RRSETS(count) (count * sizeof(knot_rrset_t *)) - -/*! \brief Sizes for preallocated space in the response structure. */ -enum { - /*! \brief Size of the response structure itself. */ - PREALLOC_PACKET = sizeof(knot_packet_t), - /*! \brief Space for QNAME dname structure. */ - PREALLOC_QNAME_DNAME = sizeof(knot_dname_t), - /*! \brief Space for QNAME name (maximum domain name size). */ - PREALLOC_QNAME_NAME = 256, - /*! \brief Space for QNAME labels (maximum label count). */ - PREALLOC_QNAME_LABELS = 127, - /*! \brief Total space for QNAME. */ - PREALLOC_QNAME = PREALLOC_QNAME_DNAME - + PREALLOC_QNAME_NAME - + PREALLOC_QNAME_LABELS, - - PREALLOC_WC_NODES = - DEFAULT_WILDCARD_NODES * sizeof(knot_node_t *), - PREALLOC_WC_SNAMES = - DEFAULT_WILDCARD_NODES * sizeof(knot_dname_t *), - PREALLOC_WC = PREALLOC_WC_NODES + PREALLOC_WC_SNAMES, - - PREALLOC_QUERY = PREALLOC_PACKET - + PREALLOC_QNAME - + PREALLOC_RRSETS(DEFAULT_ANCOUNT_QUERY) - + PREALLOC_RRSETS(DEFAULT_NSCOUNT_QUERY) - + PREALLOC_RRSETS(DEFAULT_ARCOUNT_QUERY) - + PREALLOC_RRSETS(DEFAULT_TMP_RRSETS_QUERY), - - /*! \brief Total preallocated size for the response. */ - PREALLOC_RESPONSE = PREALLOC_PACKET - + PREALLOC_QNAME - + PREALLOC_RRSETS(DEFAULT_ANCOUNT) - + PREALLOC_RRSETS(DEFAULT_NSCOUNT) - + PREALLOC_RRSETS(DEFAULT_ARCOUNT) - + PREALLOC_WC - + PREALLOC_RRSETS(DEFAULT_TMP_RRSETS) -}; /*! \brief Flags which control packet parsing. */ typedef enum { @@ -264,18 +144,14 @@ typedef enum { /*! * \brief Creates new empty packet structure. * - * \param prealloc What space should be preallocated in the structure. - * * \return New packet structure or NULL if an error occured. */ -knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc); +knot_packet_t *knot_packet_new(); /*! * \brief Memory managed version of new packet create. - * - * See knot_packet_new() for info about parameters and output. */ -knot_packet_t *knot_packet_new_mm(knot_packet_prealloc_type_t prealloc, mm_ctx_t *mm); +knot_packet_t *knot_packet_new_mm(mm_ctx_t *mm); /*! * \brief Parses the DNS packet from wire format. @@ -335,9 +211,9 @@ size_t knot_packet_parsed(const knot_packet_t *packet); */ int knot_packet_set_max_size(knot_packet_t *packet, int max_size); -uint16_t knot_packet_id(const knot_packet_t *packet); +int knot_packet_set_size(knot_packet_t *packet, int size); -void knot_packet_set_id(knot_packet_t *packet, uint16_t id); +uint16_t knot_packet_id(const knot_packet_t *packet); void knot_packet_set_random_id(knot_packet_t *packet); @@ -350,15 +226,6 @@ void knot_packet_set_random_id(knot_packet_t *packet); */ uint8_t knot_packet_opcode(const knot_packet_t *packet); -/*! - * \brief Return question section from the packet. - * - * \param packet Packet instance. - * - * \return pointer to question section. - */ -knot_question_t *knot_packet_question(knot_packet_t *packet); - /*! * \brief Returns the QNAME from the packet. * @@ -515,19 +382,6 @@ int knot_packet_add_tmp_rrset(knot_packet_t *response, void knot_packet_free_tmp_rrsets(knot_packet_t *pkt); -/*! - * \brief Converts the header structure to wire format. - * - * \note This function also adjusts the position (\a pos) according to - * the size of the converted wire format. - * - * \param[in] header DNS header structure to convert. - * \param[out] pos Position where to put the converted header. The space has - * to be allocated before calling this function. - * \param[out] size Size of the wire format of the header in bytes. - */ -void knot_packet_header_to_wire(const knot_header_t *header, - uint8_t **pos, size_t *size); int knot_packet_question_to_wire(knot_packet_t *packet); @@ -577,6 +431,13 @@ void knot_packet_dump(const knot_packet_t *packet); */ int knot_packet_free_rrsets(knot_packet_t *packet); +/*! + * \brief (Temporary) realloc RRs array size. + */ +int knot_packet_realloc_rrsets(const knot_rrset_t ***rrsets, + short *max_count, + mm_ctx_t *mm); + #endif /* _KNOT_PACKET_H_ */ /*! @} */ diff --git a/src/libknot/packet/query.c b/src/libknot/packet/query.c index 4bededc9f113524ad015d75c14a290e4dc04e835..7fa19a406bf20cb1093b142fc478ae7149c95740 100644 --- a/src/libknot/packet/query.c +++ b/src/libknot/packet/query.c @@ -62,31 +62,45 @@ int knot_query_init(knot_packet_t *query) if (query == NULL) { return KNOT_EINVAL; } - // set the qr bit to 0 - knot_wire_flags_clear_qr(&query->header.flags1); - - uint8_t *pos = query->wireformat; - knot_packet_header_to_wire(&query->header, &pos, &query->size); + query->size = KNOT_WIRE_HEADER_SIZE; + memset(query->wireformat, 0, query->size); return KNOT_EOK; } /*----------------------------------------------------------------------------*/ int knot_query_set_question(knot_packet_t *query, - const knot_question_t *question) + const knot_dname_t *qname, + uint16_t qclass, uint16_t qtype) { - if (query == NULL || question == NULL) { + if (query == NULL || qname == NULL) { return KNOT_EINVAL; } - query->question.qname = question->qname; - query->question.qclass = question->qclass; - query->question.qtype = question->qtype; - query->header.qdcount = 1; + assert(query->size == KNOT_WIRE_HEADER_SIZE); + + /* Calculate question size. */ + uint8_t *dst = query->wireformat + KNOT_WIRE_HEADER_SIZE; + size_t qname_len = knot_dname_size(qname); + size_t qsize = 2 * sizeof(uint16_t) + qname_len; + if (KNOT_WIRE_HEADER_SIZE + qsize > query->max_size) { + return KNOT_ESPACE; + } + + /* Copy name wireformat and TYPE+CLASS. */ + memcpy(dst, knot_dname_name(qname), qname_len); + dst += qname_len; + knot_wire_write_u16(dst, qtype); + dst += sizeof(uint16_t); + knot_wire_write_u16(dst, qclass); - // convert the Question to wire format right away - return knot_packet_question_to_wire(query); + /* Update question count and sizes. */ + knot_wire_set_qdcount(query->wireformat, 1); + query->size += qsize; + query->qname_size = qname_len; + + return KNOT_EOK; } /*----------------------------------------------------------------------------*/ @@ -96,8 +110,7 @@ int knot_query_set_opcode(knot_packet_t *query, uint8_t opcode) if (query == NULL) { return KNOT_EINVAL; } - // set the OPCODE in the structure - knot_wire_flags_set_opcode(&query->header.flags1, opcode); + // set the OPCODE in the wire format knot_wire_set_opcode(query->wireformat, opcode); @@ -151,7 +164,7 @@ int knot_query_add_rrset_authority(knot_packet_t *query, } query->size += written; ++query->ns_rrsets; - ++query->header.nscount; + knot_wire_add_nscount(query->wireformat, 1); return KNOT_EOK; } diff --git a/src/libknot/packet/query.h b/src/libknot/packet/query.h index ee5418a2818a1f53cc01658016ca4389cd7aebf6..0c021731ce66cf9daa3337431b9a1f7df8dc4a5d 100644 --- a/src/libknot/packet/query.h +++ b/src/libknot/packet/query.h @@ -64,7 +64,8 @@ int knot_query_edns_supported(const knot_packet_t *query); int knot_query_init(knot_packet_t *query); int knot_query_set_question(knot_packet_t *query, - const knot_question_t *question); + const knot_dname_t *qname, + uint16_t qclass, uint16_t qtype); int knot_query_set_opcode(knot_packet_t *query, uint8_t opcode); diff --git a/src/libknot/packet/response.c b/src/libknot/packet/response.c index 015cdb11e78d308a4ebd2e214267663c70493e62..422454ecf8d6edc4893cae6ad3f30cae3b0a066b 100644 --- a/src/libknot/packet/response.c +++ b/src/libknot/packet/response.c @@ -33,7 +33,8 @@ * * Update current best score. */ -static bool knot_response_compr_score(uint8_t *n, uint8_t *p, uint8_t labels, +static bool knot_response_compr_score(const uint8_t *n, const uint8_t *p, + uint8_t labels, uint8_t *wire, knot_compr_ptr_t *match) { uint16_t score = 0; @@ -65,22 +66,6 @@ static bool knot_response_compr_score(uint8_t *n, uint8_t *p, uint8_t labels, return false; } -/*! - * \brief Align name and reference to a common number of suffix labels. - */ -static uint8_t knot_response_compr_align(uint8_t **name, uint8_t nlabels, - uint8_t **ref, uint8_t reflabels, - uint8_t *wire) -{ - for (unsigned j = nlabels; j < reflabels; ++j) - *ref = knot_wire_next_label(*ref, wire); - - for (unsigned j = reflabels; j < nlabels; ++j) - *name = knot_wire_next_label(*name, wire); - - return (nlabels < reflabels) ? nlabels : reflabels; -} - int knot_response_compress_dname(const knot_dname_t *dname, knot_compr_t *compr, uint8_t *dst, size_t max) { @@ -90,6 +75,7 @@ int knot_response_compress_dname(const knot_dname_t *dname, knot_compr_t *compr, /* Do not compress small dnames. */ uint8_t *name = dname->name; + unsigned name_labels = knot_dname_wire_labels(name, NULL); if (dname->size <= 2) { if (dname->size > max) return KNOT_ESPACE; @@ -103,28 +89,28 @@ int knot_response_compress_dname(const knot_dname_t *dname, knot_compr_t *compr, unsigned match_id = 0; knot_compr_ptr_t match = { 0, 0 }; for (; i < COMPR_MAXLEN && compr->table[i].off > 0; ++i) { - uint8_t *name = dname->name; - uint8_t *ref = compr->wire + compr->table[i].off; - lbcount = knot_response_compr_align(&name, dname->label_count, - &ref, compr->table[i].lbcount, - compr->wire); + const uint8_t *sample = dname->name; + const uint8_t *ref = compr->wire + compr->table[i].off; + lbcount = knot_dname_align(&sample, name_labels, + &ref, compr->table[i].lbcount, + compr->wire); - if (knot_response_compr_score(name, ref, lbcount, compr->wire, + if (knot_response_compr_score(sample, ref, lbcount, compr->wire, &match)) { match_id = i; - if (match.lbcount == dname->label_count) + if (match.lbcount == name_labels) break; /* Best match, break. */ } } /* Write non-matching prefix. */ unsigned written = 0; - for (unsigned j = match.lbcount; j < dname->label_count; ++j) { + for (unsigned j = match.lbcount; j < name_labels; ++j) { if (written + *name + 1 > max) return KNOT_ESPACE; memcpy(dst + written, name, *name + 1); written += *name + 1; - name = knot_wire_next_label(name, compr->wire); + name = (uint8_t *)knot_wire_next_label(name, compr->wire); } /* Write out pointer covering suffix. */ @@ -149,7 +135,7 @@ int knot_response_compress_dname(const knot_dname_t *dname, knot_compr_t *compr, } /* Do not insert if exceeds bounds or full match. */ - if (match.lbcount == dname->label_count || + if (match.lbcount == name_labels || compr->wire_pos > KNOT_WIRE_PTR_MAX) return written; @@ -163,7 +149,7 @@ int knot_response_compress_dname(const knot_dname_t *dname, knot_compr_t *compr, /* Store in dname table. */ if (compr->table[i].off == 0) { compr->table[i].off = (uint16_t)compr->wire_pos; - compr->table[i].lbcount = dname->label_count; + compr->table[i].lbcount = name_labels; } return written; @@ -227,50 +213,12 @@ dbg_response_exec( resp->size); } else if (tc) { dbg_response_verb("Setting TC bit.\n"); - knot_wire_flags_set_tc(&resp->header.flags1); knot_wire_set_tc(resp->wireformat); } return rr_count > 0 ? rr_count : ret; } -/*----------------------------------------------------------------------------*/ -/*! - * \brief Reallocate space for RRSets. - * - * \param rrsets Space for RRSets. - * \param max_count Size of the space available for the RRSets. - * \param default_max_count Size of the space pre-allocated for the RRSets when - * the response structure was initialized. - * \param step How much the space should be increased. - * - * \retval KNOT_EOK - * \retval KNOT_ENOMEM - */ -static int knot_response_realloc_rrsets(const knot_rrset_t ***rrsets, - short *max_count, - short default_max_count, short step) -{ - int free_old = (*max_count) != default_max_count; - const knot_rrset_t **old = *rrsets; - - short new_max_count = *max_count + step; - const knot_rrset_t **new_rrsets = (const knot_rrset_t **)malloc( - new_max_count * sizeof(knot_rrset_t *)); - CHECK_ALLOC_LOG(new_rrsets, KNOT_ENOMEM); - - memcpy(new_rrsets, *rrsets, (*max_count) * sizeof(knot_rrset_t *)); - - *rrsets = new_rrsets; - *max_count = new_max_count; - - if (free_old) { - free(old); - } - - return KNOT_EOK; -} - /*----------------------------------------------------------------------------*/ /*! * \brief Reallocate space for Wildcard nodes. @@ -281,40 +229,32 @@ static int knot_response_realloc_rrsets(const knot_rrset_t ***rrsets, static int knot_response_realloc_wc_nodes(const knot_node_t ***nodes, const knot_dname_t ***snames, short *max_count, - short default_max_count, short step) + mm_ctx_t *mm) { - dbg_packet_detail("Max count: %d, default max count: %d\n", - *max_count, default_max_count); - int free_old = (*max_count) != default_max_count; - - const knot_node_t **old_nodes = *nodes; - const knot_dname_t **old_snames = *snames; - short new_max_count = *max_count + step; + short new_max_count = *max_count + RRSET_ALLOC_STEP; - const knot_node_t **new_nodes = (const knot_node_t **)malloc( + const knot_node_t **new_nodes = mm->alloc(mm->ctx, new_max_count * sizeof(knot_node_t *)); CHECK_ALLOC_LOG(new_nodes, KNOT_ENOMEM); - const knot_dname_t **new_snames = (const knot_dname_t **)malloc( + const knot_dname_t **new_snames = mm->alloc(mm->ctx, new_max_count * sizeof(knot_dname_t *)); if (new_snames == NULL) { - free(new_nodes); + mm->free(new_nodes); return KNOT_ENOMEM; } memcpy(new_nodes, *nodes, (*max_count) * sizeof(knot_node_t *)); memcpy(new_snames, *snames, (*max_count) * sizeof(knot_dname_t *)); + mm->free(*nodes); + mm->free(*snames); + *nodes = new_nodes; *snames = new_snames; *max_count = new_max_count; - if (free_old) { - free(old_nodes); - free(old_snames); - } - return KNOT_EOK; } @@ -333,95 +273,63 @@ int knot_response_init(knot_packet_t *response) } // set the qr bit to 1 - knot_wire_flags_set_qr(&response->header.flags1); + memset(response->wireformat, 0, KNOT_WIRE_HEADER_SIZE); - uint8_t *pos = response->wireformat; - knot_packet_header_to_wire(&response->header, &pos, - &response->size); + uint8_t flags = knot_wire_get_flags1(response->wireformat); + knot_wire_flags_set_qr(&flags); + knot_wire_set_flags1(response->wireformat, flags); return KNOT_EOK; } /*----------------------------------------------------------------------------*/ -int knot_response_init_from_query(knot_packet_t *response, - knot_packet_t *query, - int copy_question) +int knot_response_init_from_query(knot_packet_t *response, knot_packet_t *query) { - if (response == NULL || query == NULL) { return KNOT_EINVAL; } - // copy the header from the query - memcpy(&response->header, &query->header, sizeof(knot_header_t)); - - /*! \todo Constant. */ - size_t to_copy = 12; - - if (copy_question) { - // copy the Question section (but do not copy the QNAME) - memcpy(&response->question, &query->question, - sizeof(knot_question_t)); - - /* Insert QNAME into compression table. */ - response->compression[0].off = KNOT_WIRE_HEADER_SIZE; - response->compression[0].lbcount = response->question.qname->label_count; - - - /*! \todo Constant. */ - to_copy += 4 + knot_dname_size(response->question.qname); - } else { - response->header.qdcount = 0; - knot_wire_set_qdcount(response->wireformat, 0); - } - - assert(response->max_size >= to_copy); + /* Header + question size. */ + size_t to_copy = knot_packet_question_size(query); + assert(to_copy <= response->max_size); if (response->wireformat != query->wireformat) { memcpy(response->wireformat, query->wireformat, to_copy); } - response->size = to_copy; - // set the qr bit to 1 - knot_wire_flags_set_qr(&response->header.flags1); - knot_wire_set_qr(response->wireformat); + /* Insert QNAME into compression table. */ + uint8_t *qname = response->wireformat + KNOT_WIRE_HEADER_SIZE; + response->compression[0].off = KNOT_WIRE_HEADER_SIZE; + response->compression[0].lbcount = knot_dname_wire_labels(qname, NULL); - // clear TC flag - knot_wire_flags_clear_tc(&response->header.flags1); + /* Update size and flags. */ + knot_wire_set_qdcount(response->wireformat, 1); + knot_wire_set_qr(response->wireformat); knot_wire_clear_tc(response->wireformat); - - // clear AD flag - knot_wire_flags_clear_ad(&response->header.flags2); - knot_wire_clear_ad(response->wireformat); - - // clear RA flag - knot_wire_flags_clear_ra(&response->header.flags2); knot_wire_clear_ad(response->wireformat); + knot_wire_clear_ra(response->wireformat); - // set counts to 0 - response->header.ancount = 0; + /* Reset RR counts */ knot_wire_set_ancount(response->wireformat, 0); - response->header.nscount = 0; knot_wire_set_nscount(response->wireformat, 0); - response->header.arcount = 0; knot_wire_set_arcount(response->wireformat, 0); response->query = query; - + response->size = to_copy; + response->qname_size = query->qname_size; return KNOT_EOK; } /*----------------------------------------------------------------------------*/ -void knot_response_clear(knot_packet_t *resp, int clear_question) +void knot_response_clear(knot_packet_t *resp) { if (resp == NULL) { return; } - resp->size = (clear_question) ? KNOT_WIRE_HEADER_SIZE - : KNOT_WIRE_HEADER_SIZE + 4 - + knot_dname_size(resp->question.qname); + /* Keep question. */ + resp->size = knot_packet_question_size(resp); resp->an_rrsets = 0; resp->ns_rrsets = 0; resp->ar_rrsets = 0; @@ -440,9 +348,9 @@ void knot_response_clear(knot_packet_t *resp, int clear_question) * the list of wildcard nodes should be cleared here. */ - resp->header.ancount = 0; - resp->header.nscount = 0; - resp->header.arcount = 0; + knot_wire_set_ancount(resp->wireformat, 0); + knot_wire_set_nscount(resp->wireformat, 0); + knot_wire_set_arcount(resp->wireformat, 0); } /*----------------------------------------------------------------------------*/ @@ -528,12 +436,12 @@ int knot_response_add_rrset_answer(knot_packet_t *response, } dbg_response_verb("add_rrset_answer()\n"); - assert(response->header.arcount == 0); - assert(response->header.nscount == 0); + assert(knot_wire_get_arcount(response->wireformat) == 0); + assert(knot_wire_get_nscount(response->wireformat) == 0); if (response->an_rrsets == response->max_an_rrsets - && knot_response_realloc_rrsets(&response->answer, - &response->max_an_rrsets, DEFAULT_ANCOUNT, STEP_ANCOUNT) + && knot_packet_realloc_rrsets(&response->answer, + &response->max_an_rrsets, &response->mm) != KNOT_EOK) { return KNOT_ENOMEM; } @@ -556,7 +464,7 @@ int knot_response_add_rrset_answer(knot_packet_t *response, rrset, tc); if (rrs >= 0) { - response->header.ancount += rrs; + knot_wire_add_ancount(response->wireformat, rrs); if (rotate) { // do round-robin rotation of the RRSet @@ -580,11 +488,11 @@ int knot_response_add_rrset_authority(knot_packet_t *response, return KNOT_EINVAL; } - assert(response->header.arcount == 0); + assert(knot_wire_get_arcount(response->wireformat) == 0); if (response->ns_rrsets == response->max_ns_rrsets - && knot_response_realloc_rrsets(&response->authority, - &response->max_ns_rrsets, DEFAULT_NSCOUNT, STEP_NSCOUNT) + && knot_packet_realloc_rrsets(&response->authority, + &response->max_ns_rrsets, &response->mm) != 0) { return KNOT_ENOMEM; } @@ -605,7 +513,7 @@ int knot_response_add_rrset_authority(knot_packet_t *response, rrset, tc); if (rrs >= 0) { - response->header.nscount += rrs; + knot_wire_add_nscount(response->wireformat, rrs); if (rotate) { // do round-robin rotation of the RRSet @@ -632,15 +540,15 @@ int knot_response_add_rrset_additional(knot_packet_t *response, int ret; // if this is the first additional RRSet, add EDNS OPT RR first - if (response->header.arcount == 0 + if (knot_wire_get_arcount(response->wireformat) == 0 && response->opt_rr.version != EDNS_NOT_SUPPORTED && (ret = knot_packet_edns_to_wire(response)) != KNOT_EOK) { return ret; } if (response->ar_rrsets == response->max_ar_rrsets - && knot_response_realloc_rrsets(&response->additional, - &response->max_ar_rrsets, DEFAULT_ARCOUNT, STEP_ARCOUNT) + && knot_packet_realloc_rrsets(&response->additional, + &response->max_ar_rrsets, &response->mm) != 0) { return KNOT_ENOMEM; } @@ -660,7 +568,7 @@ int knot_response_add_rrset_additional(knot_packet_t *response, tc); if (rrs >= 0) { - response->header.arcount += rrs; + knot_wire_add_arcount(response->wireformat, rrs); if (rotate) { // do round-robin rotation of the RRSet @@ -681,8 +589,9 @@ void knot_response_set_rcode(knot_packet_t *response, short rcode) return; } - knot_wire_flags_set_rcode(&response->header.flags2, rcode); - knot_wire_set_rcode(response->wireformat, rcode); + uint8_t flags = knot_wire_get_flags2(response->wireformat); + knot_wire_flags_set_rcode(&flags, rcode); + knot_wire_set_flags2(response->wireformat, flags); } /*----------------------------------------------------------------------------*/ @@ -693,7 +602,6 @@ void knot_response_set_aa(knot_packet_t *response) return; } - knot_wire_flags_set_aa(&response->header.flags1); knot_wire_set_aa(response->wireformat); } @@ -705,7 +613,6 @@ void knot_response_set_tc(knot_packet_t *response) return; } - knot_wire_flags_set_tc(&response->header.flags1); knot_wire_set_tc(response->wireformat); } @@ -736,8 +643,7 @@ int knot_response_add_wildcard_node(knot_packet_t *response, && knot_response_realloc_wc_nodes(&response->wildcard_nodes.nodes, &response->wildcard_nodes.snames, &response->wildcard_nodes.max, - DEFAULT_WILDCARD_NODES, - STEP_WILDCARD_NODES) != KNOT_EOK) { + &response->mm) != KNOT_EOK) { return KNOT_ENOMEM; } diff --git a/src/libknot/packet/response.h b/src/libknot/packet/response.h index b68ca45d852478602a9bc50a6ac68628ecb59133..7bd1887a80090c4f1b058dc9587bb38e72367c87 100644 --- a/src/libknot/packet/response.h +++ b/src/libknot/packet/response.h @@ -105,9 +105,7 @@ int knot_response_init(knot_packet_t *response); * * \retval KNOT_EOK */ -int knot_response_init_from_query(knot_packet_t *response, - knot_packet_t *query, - int copy_question); +int knot_response_init_from_query(knot_packet_t *response, knot_packet_t *query); /*! * \brief Clears the response structure for reuse. @@ -119,7 +117,7 @@ int knot_response_init_from_query(knot_packet_t *response, * * \todo Replace the use of this function with something else maybe? */ -void knot_response_clear(knot_packet_t *resp, int clear_question); +void knot_response_clear(knot_packet_t *resp); /*! * \brief Sets the OPT RR of the response. diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c index c8c7fe75264c7d86aa9e1579c8bf2f9b28045ec1..6cadd1106d7bfd07832423fa8fa3be3e14ffb8ee 100644 --- a/src/libknot/rrset-dump.c +++ b/src/libknot/rrset-dump.c @@ -846,7 +846,7 @@ static void wire_dname_to_str(rrset_dump_params_t *p) } while (label_len > 0); // Create dname. - dname = knot_dname_new_from_wire(p->in - in_len, in_len, NULL); + dname = knot_dname_new_from_wire(p->in - in_len, in_len); if (dname == NULL) { return; } diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c index 34614f7cd8e54d217dafdfeda3f24dfcaf020d07..b22982974b9035bedd659c50c41b02584ccdf5b1 100644 --- a/src/libknot/rrset.c +++ b/src/libknot/rrset.c @@ -696,7 +696,7 @@ static int rrset_deserialize_rr(knot_rrset_t *rrset, size_t rdata_pos, stream_offset += 1; knot_dname_t *dname = knot_dname_new_from_wire(stream + stream_offset, - dname_size, NULL); + dname_size); if (dname == NULL) { return KNOT_ERROR; } @@ -1208,7 +1208,7 @@ int knot_rrset_rdata_from_wire_one(knot_rrset_t *rrset, if (descriptor_item_is_dname(item)) { pos2 = *pos; knot_dname_t *dname = knot_dname_parse_from_wire( - wire, &pos2, total_size, NULL, NULL); + wire, &pos2, total_size); if (dname == NULL) { return KNOT_EMALF; } @@ -2320,7 +2320,7 @@ int rrset_deserialize(uint8_t *stream, size_t *stream_size, uint8_t owner_size = *(stream + offset); offset += 1; knot_dname_t *owner = knot_dname_new_from_wire(stream + offset, - owner_size, NULL); + owner_size); assert(owner); offset += owner_size; /* Read type. */ diff --git a/src/libknot/sign/key.c b/src/libknot/sign/key.c index d721e642d7fa3c34ba264147cd32ac6047b239fb..1fc821eb29778591a0c0eaa690560c154c8522b6 100644 --- a/src/libknot/sign/key.c +++ b/src/libknot/sign/key.c @@ -139,8 +139,7 @@ static int get_key_info_from_public_key(const char *filename, free(buffer); knot_dname_t *owner = knot_dname_new_from_wire(scanner->r_owner, - scanner->r_owner_length, - NULL); + scanner->r_owner_length); if (!owner) { scanner_free(scanner); return KNOT_ENOMEM; @@ -517,8 +516,7 @@ static int knot_tsig_create_key_from_args(knot_dname_t *name, int algorithm, int knot_tsig_create_key(const char *name, int algorithm, const char *b64secret, knot_tsig_key_t *key) { - knot_dname_t *dname; - dname = knot_dname_new_from_nonfqdn_str(name, strlen(name), NULL); + knot_dname_t *dname = knot_dname_new_from_str(name, strlen(name)); if (!dname) return KNOT_ENOMEM; diff --git a/src/libknot/sign/sig0.c b/src/libknot/sign/sig0.c index d1f1ea93cce18eb18e13e971202e6291e8e8cc69..4ac37d64e9b8fed5f4cd80a94ba7067189b357ef 100644 --- a/src/libknot/sign/sig0.c +++ b/src/libknot/sign/sig0.c @@ -38,7 +38,7 @@ */ static knot_rrset_t *sig0_create_rrset(void) { - knot_dname_t *root = knot_dname_new_from_str(".", 1, NULL); + knot_dname_t *root = knot_dname_new_from_str(".", 1); uint32_t ttl = 0; knot_rrset_t *sig_record = knot_rrset_new(root, KNOT_RRTYPE_SIG, KNOT_CLASS_ANY, ttl); diff --git a/src/libknot/tsig.c b/src/libknot/tsig.c index fd5970985951738b31c06c9e1cc3ee183b53177c..46964a27a293d72a2ead31948b0e829e45ae1e82 100644 --- a/src/libknot/tsig.c +++ b/src/libknot/tsig.c @@ -160,7 +160,7 @@ int tsig_rdata_set_alg_name(knot_rrset_t *tsig, knot_dname_t *alg_name) int tsig_rdata_set_alg(knot_rrset_t *tsig, knot_tsig_algorithm_t alg) { const char *s = tsig_alg_to_str(alg); - knot_dname_t *alg_name = knot_dname_new_from_str(s, strlen(s), NULL); + knot_dname_t *alg_name = knot_dname_new_from_str(s, strlen(s)); int ret = tsig_rdata_set_alg_name(tsig, alg_name); knot_dname_release(alg_name); return ret; diff --git a/src/libknot/updates/xfr-in.c b/src/libknot/updates/xfr-in.c index ab9172dc449bd4868ff20764097503ccb0eda324..febc73acbde415d4ad821aed7a7b5a752dd1c7b9 100644 --- a/src/libknot/updates/xfr-in.c +++ b/src/libknot/updates/xfr-in.c @@ -43,7 +43,7 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype, uint16_t qclass, knot_ns_xfr_t *xfr, size_t *size, const knot_rrset_t *soa, int use_tsig) { - knot_packet_t *pkt = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); + knot_packet_t *pkt = knot_packet_new(); CHECK_ALLOC_LOG(pkt, KNOT_ENOMEM); /*! \todo Get rid of the numeric constant. */ @@ -59,23 +59,10 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype, return KNOT_ERROR; } - knot_question_t question; - - /* Retain qname until the question is freed. */ - knot_dname_retain(qname); - /* Set random query ID. */ knot_packet_set_random_id(pkt); - knot_wire_set_id(pkt->wireformat, pkt->header.id); - - // this is ugly!! - question.qname = (knot_dname_t *)qname; - question.qtype = qtype; - question.qclass = qclass; - - rc = knot_query_set_question(pkt, &question); + rc = knot_query_set_question(pkt, qname, qclass, qtype); if (rc != KNOT_EOK) { - knot_dname_release(question.qname); knot_packet_free(&pkt); return KNOT_ERROR; } @@ -99,7 +86,6 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype, rc = knot_packet_to_wire(pkt, &wire, &wire_size); if (rc != KNOT_EOK) { dbg_xfrin("Failed to write packet to wire.\n"); - knot_dname_release(question.qname); knot_packet_free(&pkt); return KNOT_ERROR; } @@ -141,9 +127,6 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype, knot_packet_free(&pkt); - /* Release qname. */ - knot_dname_release(question.qname); - return KNOT_EOK; } @@ -452,8 +435,7 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr) /*! \todo Should TC bit be checked? */ - knot_packet_t *packet = - knot_packet_new(KNOT_PACKET_PREALLOC_NONE); + knot_packet_t *packet = knot_packet_new(); if (packet == NULL) { dbg_xfrin("Could not create packet structure.\n"); return KNOT_ENOMEM; @@ -886,7 +868,7 @@ static int xfrin_parse_first_rr(knot_packet_t **packet, const uint8_t *pkt, assert(packet != NULL); assert(rr != NULL); - *packet = knot_packet_new(KNOT_PACKET_PREALLOC_NONE); + *packet = knot_packet_new(); if (*packet == NULL) { dbg_xfrin("Could not create packet structure.\n"); return KNOT_ENOMEM; @@ -2449,17 +2431,6 @@ static void xfrin_zone_contents_free2(knot_zone_contents_t **contents) /*----------------------------------------------------------------------------*/ -static void xfrin_cleanup_old_nodes(knot_node_t *node, void *data) -{ - UNUSED(data); - assert(node != NULL); - - knot_node_set_new_node(node, NULL); - knot_dname_set_node(knot_node_get_owner(node), node); -} - -/*----------------------------------------------------------------------------*/ - static void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents, knot_zone_contents_t **new_contents) { @@ -2471,18 +2442,6 @@ static void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents, // destroy the shallow copy of zone xfrin_zone_contents_free2(new_contents); } - - if (old_contents != NULL) { - // cleanup old zone tree - reset pointers to new node to NULL - // also set pointers from dnames to old nodes - knot_zone_contents_tree_apply_inorder(old_contents, - xfrin_cleanup_old_nodes, - NULL); - - knot_zone_contents_nsec3_apply_inorder(old_contents, - xfrin_cleanup_old_nodes, - NULL); - } } /*----------------------------------------------------------------------------*/ @@ -3241,56 +3200,6 @@ int xfrin_apply_changesets(knot_zone_t *zone, /*----------------------------------------------------------------------------*/ -static int xfrin_switch_node_in_rdata(knot_dname_t **dname, void *data) -{ - UNUSED(data); - if (dname == NULL || *dname == NULL) { - return KNOT_EINVAL; - } - - if ((*dname)->node != NULL) { - knot_dname_update_node(*dname); - } - - return KNOT_EOK; -} - -static void xfrin_switch_node_in_rrset(knot_rrset_t *rrset) -{ - if (rrset == NULL) { - return; - } - - if (rrset->rrsigs) { - xfrin_switch_node_in_rrset(rrset->rrsigs); - } - - if (rrset->owner->node != NULL) { - knot_dname_update_node(rrset->owner); - } - - rrset_dnames_apply(rrset, xfrin_switch_node_in_rdata, NULL); -} - -static void xfrin_switch_node_in_node(knot_node_t **node, void *data) -{ - UNUSED(data); - if (node == NULL || *node == NULL) { - return; - } - - if ((*node)->owner->node != NULL) { - knot_dname_update_node((*node)->owner); - } - - knot_rrset_t **rr_array = knot_node_get_rrsets_no_copy(*node); - for (uint16_t i = 0; i < (*node)->rrset_count; ++i) { - xfrin_switch_node_in_rrset(rr_array[i]); - } -} - -/*----------------------------------------------------------------------------*/ - int xfrin_switch_zone(knot_zone_t *zone, knot_zone_contents_t *new_contents, int transfer_type) @@ -3310,17 +3219,6 @@ int xfrin_switch_zone(knot_zone_t *zone, dbg_xfrin_verb("Old contents: %p, apex: %p, new apex: %p\n", old, (old) ? old->apex : NULL, new_contents->apex); - // switch pointers in domain names, now only the new zone is used - if (transfer_type == XFR_TYPE_IIN || transfer_type == XFR_TYPE_UPDATE) { - /* Switch node references in owner DNAMEs and RDATA dnames. */ - int ret = knot_zone_tree_apply(new_contents->nodes, - xfrin_switch_node_in_node, NULL); - assert(ret == KNOT_EOK); - ret = knot_zone_tree_apply(new_contents->nsec3_nodes, - xfrin_switch_node_in_node, NULL); - assert(ret == KNOT_EOK); - } - // set generation to old, so that the flags may be used in next transfer // and we do not search for new nodes anymore knot_zone_contents_set_gen_old(new_contents); diff --git a/src/libknot/util/debug.c b/src/libknot/util/debug.c index 9f8d8527fc443b5c9fd2c5b866bb45cc58280f4b..97c9e5af4c28c1d4a1b36b63dbc188ebc7ebfbfc 100644 --- a/src/libknot/util/debug.c +++ b/src/libknot/util/debug.c @@ -44,10 +44,7 @@ void knot_node_dump(knot_node_t *node) name = knot_dname_to_str(node->owner); dbg_node_detail("owner: %s\n", name); free(name); - dbg_node_detail("labels: "); - hex_print(node->owner->labels, node->owner->label_count); dbg_node_detail("node: %p\n", node); - dbg_node_detail("node (in node's owner): %p\n", node->owner->node); if (knot_node_is_deleg_point(node)) { dbg_node_detail("delegation point\n"); diff --git a/src/libknot/util/wire.h b/src/libknot/util/wire.h index e2f283de7b57bbecef837dbfeb8cb156dba15c3c..80588a689dec8036a1b111fe206b1b46fa03880e 100644 --- a/src/libknot/util/wire.h +++ b/src/libknot/util/wire.h @@ -148,6 +148,15 @@ static inline void knot_wire_set_qdcount(uint8_t *packet, uint16_t qdcount) knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT, qdcount); } +/*! + * \brief Adds to QDCOUNT. + */ +static inline void knot_wire_add_qdcount(uint8_t *packet, int16_t n) +{ + knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT, + knot_wire_get_qdcount(packet) + n); +} + /*! * \brief Returns the ANCOUNT (count of Answer entries) from wire format of * the packet. @@ -173,6 +182,15 @@ static inline void knot_wire_set_ancount(uint8_t *packet, uint16_t ancount) knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT, ancount); } +/*! + * \brief Adds to ANCOUNT. + */ +static inline void knot_wire_add_ancount(uint8_t *packet, int16_t n) +{ + knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT, + knot_wire_get_ancount(packet) + n); +} + /*! * \brief Returns the NSCOUNT (count of Authority entries) from wire format of * the packet. @@ -198,6 +216,15 @@ static inline void knot_wire_set_nscount(uint8_t *packet, uint16_t nscount) knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT, nscount); } +/*! + * \brief Adds to NSCOUNT. + */ +static inline void knot_wire_add_nscount(uint8_t *packet, int16_t n) +{ + knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT, + knot_wire_get_nscount(packet) + n); +} + /*! * \brief Returns the ARCOUNT (count of Additional entries) from wire format of * the packet. @@ -223,6 +250,15 @@ static inline void knot_wire_set_arcount(uint8_t *packet, uint16_t arcount) knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT, arcount); } +/*! + * \brief Adds to ARCOUNT. + */ +static inline void knot_wire_add_arcount(uint8_t *packet, int16_t n) +{ + knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT, + knot_wire_get_arcount(packet) + n); +} + /* * Packet header flags manipulation functions. */ @@ -919,10 +955,12 @@ static inline uint16_t knot_wire_get_pointer(const uint8_t *pos) return (knot_wire_read_u16(pos) - KNOT_WIRE_PTR_BASE); // Return offset. } -static inline uint8_t *knot_wire_next_label(uint8_t *lp, uint8_t *wire) +static inline const uint8_t *knot_wire_next_label(const uint8_t *lp, const uint8_t *wire) { lp = lp + (lp[0] + sizeof(uint8_t)); if (knot_wire_is_pointer(lp)) { + if (!wire) + return NULL; lp = wire + knot_wire_get_pointer(lp); } return lp; diff --git a/src/libknot/zone/node.c b/src/libknot/zone/node.c index 59eea304193096e160055f8dc741d22f51f6d4fd..cd358f7528be13676b98b26272fa7187cbabd8cc 100644 --- a/src/libknot/zone/node.c +++ b/src/libknot/zone/node.c @@ -707,13 +707,6 @@ void knot_node_free(knot_node_t **node) (*node)->rrset_count = 0; } - // set owner's node pointer to NULL, but only if the 'node' does - // not point to the owner's node - if (node != &(*node)->owner->node - && knot_dname_node(knot_node_owner(*node)) == *node) { - knot_dname_set_node((*node)->owner, NULL); - } - knot_dname_release((*node)->owner); free(*node); diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c index e9dfff0311b0e9732da7de2d595c3866a89c9df1..3375590c578e34bd2d383ceaa7883946ff5b7e15 100644 --- a/src/libknot/zone/zone-contents.c +++ b/src/libknot/zone/zone-contents.c @@ -134,7 +134,7 @@ static const knot_node_t *knot_zone_contents_find_wildcard_child( assert(zone != NULL); assert(closest_encloser != NULL); - knot_dname_t *tmp = knot_dname_new_from_str("*", 1, NULL); + knot_dname_t *tmp = knot_dname_new_from_str("*", 1); CHECK_ALLOC(tmp, NULL); knot_dname_t *wildcard = knot_dname_cat(tmp, knot_node_owner( @@ -213,71 +213,7 @@ static void knot_zone_contents_adjust_rdata_dname(knot_zone_contents_t *zone, knot_node_t *node, knot_dname_t **in_dname) { -// const knot_node_t *old_dname_node = (*in_dname)->node; knot_zone_contents_insert_dname_into_table(in_dname, lookup_tree); -// assert((*in_dname)->node == old_dname_node || old_dname_node == NULL); - - knot_dname_t *dname = *in_dname; - /* - * The case when dname.node is already set is handled here. - * No use to check it later. - */ - if (knot_dname_node(dname) != NULL - || !knot_dname_is_subdomain(dname, knot_node_owner( - knot_zone_contents_apex(zone)))) { - // The name's node is either already set - // or the name does not belong to the zone - dbg_zone_detail("Name's node either set or the name " - "does not belong to the zone (%p).\n", - knot_dname_node(dname)); - return; - } - - const knot_node_t *n = NULL; - const knot_node_t *closest_encloser = NULL; - const knot_node_t *prev = NULL; - - int ret = knot_zone_contents_find_dname(zone, dname, &n, - &closest_encloser, &prev); - - if (ret == KNOT_EINVAL || ret == KNOT_EBADZONE) { - // TODO: do some cleanup if needed - dbg_zone_detail("Failed to find the name in zone: %s\n", - knot_strerror(ret)); - return; - } - - assert(ret != KNOT_ZONE_NAME_FOUND || n == closest_encloser); - - if (ret != KNOT_ZONE_NAME_FOUND && (closest_encloser != NULL)) { - /*! - * \note There is no need to set closer encloser to the - * name. We may find the possible wildcard child - * right away. - * Having the closest encloser saved in the dname - * would disrupt the query processing algorithms - * anyway. - */ - - dbg_zone_verb("Trying to find wildcard child.\n"); - - n = knot_zone_contents_find_wildcard_child(zone, - closest_encloser); - - if (n != NULL) { - knot_dname_set_node(dname, (knot_node_t *)n); - dbg_zone_exec_detail( - char *name = knot_dname_to_str( - knot_node_owner(n)); - char *name2 = knot_dname_to_str(dname); - dbg_zone_detail("Set wildcard node %s " - "to RDATA dname %s.\n", - name, name2); - free(name); - free(name2); - ); - } - } } /*----------------------------------------------------------------------------*/ @@ -391,11 +327,6 @@ static int knot_zone_contents_adjust_node(knot_node_t *node, knot_zone_contents_insert_dname_into_table(&node->owner, lookup_tree); // assert(node->owner->node == old_dname_node || old_dname_node == NULL); - // assure that owner has proper node - if (knot_dname_node(knot_node_owner(node)) == NULL) { - knot_dname_set_node(knot_node_get_owner(node), node); - } - // check if this node is not a wildcard child of its parent if (knot_dname_is_wildcard(knot_node_owner(node))) { assert(knot_node_parent(node) != NULL); @@ -554,11 +485,6 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree( return; } - // assure that owner has proper node - if (knot_dname_node(knot_node_owner(node)) == NULL) { - knot_dname_set_node(knot_node_get_owner(node), node); - } - /* * We assume, that NSEC3 nodes have none DNAMEs in their RDATA and * that node owners are all unique. \todo Harmful? @@ -660,7 +586,7 @@ dbg_zone_exec_verb( ); /* Will be returned to caller, make sure it is released after use. */ - *nsec3_name = knot_dname_new_from_str((char *)name_b32, size, NULL); + *nsec3_name = knot_dname_new_from_str((char *)name_b32, size); free(name_b32); @@ -933,8 +859,7 @@ dbg_zone_exec_detail( knot_dname_left_chop(knot_node_owner(node)); if(chopped == NULL) { /* Root domain and root domain only. */ - assert(node->owner && node->owner->labels && - node->owner->labels[0] == 0); + assert(node->owner && *node->owner->name == '\0'); return KNOT_EOK; } @@ -1439,8 +1364,8 @@ dbg_zone_detail("Search function returned %d, node %s (%p) and prev: %s (%p)\n", int matched_labels = knot_dname_matched_labels( knot_node_owner((*closest_encloser)), name); - while (matched_labels < knot_dname_label_count( - knot_node_owner((*closest_encloser)))) { + while (matched_labels < knot_dname_wire_labels( + knot_node_owner((*closest_encloser))->name, NULL)) { (*closest_encloser) = knot_node_parent((*closest_encloser)); assert(*closest_encloser); @@ -2217,7 +2142,7 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node, // if direct child if (knot_dname_is_subdomain(node_owner, parent_owner) && knot_dname_matched_labels(node_owner, parent_owner) - == knot_dname_label_count(parent_owner)) { + == knot_dname_wire_labels(parent_owner->name, NULL)) { // check the parent pointer const knot_node_t *parent = knot_node_parent(node); @@ -2272,29 +2197,6 @@ typedef struct find_dname_data { /*----------------------------------------------------------------------------*/ -static void knot_zc_integrity_check_owner(const knot_node_t *node, - check_data_t *check_data, - const char *name) -{ - // check node stored in owner - const knot_node_t *owner_node = - knot_dname_node(knot_node_owner(node)); - if (owner_node != node) { - char *name2 = (owner_node != NULL) - ? knot_dname_to_str(knot_node_owner(owner_node)) - : "none"; - fprintf(stderr, "Wrong owner's node: node %s, owner's node %s" - "\n", name, name2); - if (owner_node != NULL) { - free(name2); - } - - ++check_data->errors; - } -} - -/*----------------------------------------------------------------------------*/ - static void knot_zc_integrity_check_node(knot_node_t *node, void *data) { assert(node != NULL); @@ -2315,9 +2217,6 @@ static void knot_zc_integrity_check_node(knot_node_t *node, void *data) // & wildcard child knot_zc_integrity_check_parent(node, check_data, name); - // check owner - knot_zc_integrity_check_owner(node, check_data, name); - /*! \todo Check NSEC3 node. */ free(name); @@ -2347,9 +2246,6 @@ static void knot_zc_integrity_check_nsec3(knot_node_t *node, void *data) ++check_data->errors; } - // check owner - knot_zc_integrity_check_owner(node, check_data, name); - free(name); } diff --git a/src/libknot/zone/zone-tree.c b/src/libknot/zone/zone-tree.c index 27cdf5f22339c64156ea93421145eb5ad8ac2eb8..c31c6dc51c301155f3818fc303492d69a963f314 100644 --- a/src/libknot/zone/zone-tree.c +++ b/src/libknot/zone/zone-tree.c @@ -27,53 +27,6 @@ /* Non-API functions */ /*----------------------------------------------------------------------------*/ -#define DNAME_LFT_MAXLEN 255 /* maximum lookup format length */ - -/*! - * \brief Convert domain name from wire to lookup format. - * - * Formats names from rightmost label to the leftmost, separated by the lowest - * possible character (\x00). Sorting such formatted names also gives - * correct canonical order (for NSEC/NSEC3). - * - * Example: - * Name: lake.example.com. Wire: \x04lake\x07example\x03com\x00 - * Lookup format com\x00example\x00lake\x00 - * - * Maximum length of such a domain name is DNAME_LFT_MAXLEN characters. - * - * \param dst Memory to store converted name into. - * \param maxlen Maximum memory length. - * \param src Source domain name. - * - * \retval KNOT_EOK if successful - * \retval KNOT_ESPACE when not enough memory. - * \retval KNOT_EINVAL on invalid parameters - */ -static int dname_lf(uint8_t *dst, const knot_dname_t *src, size_t maxlen) { - if (src->size > maxlen) - return KNOT_ESPACE; - *dst = (uint8_t)src->size; - /* need to save last \x00 for root dname */ - if (*dst > 1) - *dst -= 1; - *++dst = '\0'; - uint8_t* l = src->name; - uint8_t lstack[DNAME_LFT_MAXLEN]; - uint8_t *sp = lstack; - while(*l != 0) { /* build label stack */ - *sp++ = (l - src->name); - l += 1 + *l; - } - while(sp != lstack) { /* consume stack */ - l = src->name + *--sp; /* fetch rightmost label */ - memcpy(dst, l+1, *l); /* write label */ - dst += *l; - *dst++ = '\0'; /* label separator */ - } - return KNOT_EOK; -} - static value_t knot_zone_node_copy(value_t v) { return v; diff --git a/src/tests/knot/conf_tests.c b/src/tests/knot/conf_tests.c index 0904a4e2a7ea83916a437bbc7b50d62929ba4265..84ace6f17f488763a3a73fb42c7c787fc537a432 100644 --- a/src/tests/knot/conf_tests.c +++ b/src/tests/knot/conf_tests.c @@ -128,7 +128,7 @@ static int conf_tests_run(int argc, char *argv[]) // Test 21: Load key dname const char *sample_str = "key0.example.net"; knot_dname_t *sample = knot_dname_new_from_str(sample_str, - strlen(sample_str), 0); + strlen(sample_str)); if (conf->key_count > 0) { knot_tsig_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k; ok(knot_dname_compare(sample, k->name) == 0, diff --git a/src/tests/knot/rrl_tests.c b/src/tests/knot/rrl_tests.c index e7d26dd3b8fad976f3360f80ba936db48cd2034b..46c60ff33f9d0f2c16f128bea656cc747c6d9923 100644 --- a/src/tests/knot/rrl_tests.c +++ b/src/tests/knot/rrl_tests.c @@ -120,24 +120,22 @@ static int rrl_tests_count(int argc, char *argv[]) static int rrl_tests_run(int argc, char *argv[]) { /* Prepare query. */ - knot_question_t qst; - qst.qclass = KNOT_CLASS_IN; - qst.qtype = KNOT_RRTYPE_A; - qst.qname = knot_dname_new_from_str("beef.", 5, NULL); - knot_packet_t *query = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY); - knot_query_init(query); + knot_packet_t *query = knot_packet_new(); if (knot_packet_set_max_size(query, 512) < 0) { - knot_dname_free(&qst.qname); knot_packet_free(&query); return KNOT_ERROR; /* Fatal */ } - int ret = knot_query_set_question(query, &qst); + knot_query_init(query); + + knot_dname_t *qname = knot_dname_new_from_str("beef.", 5); + int ret = knot_query_set_question(query, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A); + knot_dname_free(&qname); if (ret != KNOT_EOK) { - knot_dname_free(&qst.qname); knot_packet_free(&query); return KNOT_ERROR; /* Fatal */ } + /* Prepare response */ knot_nameserver_t *ns = knot_ns_create(); uint8_t rbuf[65535]; @@ -148,7 +146,7 @@ static int rrl_tests_run(int argc, char *argv[]) rrl_req_t rq; rq.w = rbuf; rq.len = rlen; - rq.qst = &qst; + rq.query = query; rq.flags = 0; /* 1. create rrl table */ @@ -165,7 +163,7 @@ static int rrl_tests_run(int argc, char *argv[]) ok(ret == KNOT_EOK, "rrl: setlocks"); /* 4. N unlimited requests. */ - knot_dname_t *apex = knot_dname_new_from_str("rrl.", 4, NULL); + knot_dname_t *apex = knot_dname_new_from_str("rrl.", 4); knot_zone_t *zone = knot_zone_new(knot_node_new(apex, NULL, 0)); sockaddr_t addr; sockaddr_t addr6; @@ -220,7 +218,6 @@ static int rrl_tests_run(int argc, char *argv[]) ok(rd.passed, "rrl: hashtable is ~ consistent"); #endif - knot_dname_release(qst.qname); knot_dname_release(apex); knot_zone_deep_free(&zone); knot_ns_destroy(&ns); diff --git a/src/tests/libknot/dname_tests.c b/src/tests/libknot/dname_tests.c index 73ca67de9647df7a8133d922fb8836bf36e1fbe1..bb37d2e94593de8460efada10a4ac881e9f0827e 100644 --- a/src/tests/libknot/dname_tests.c +++ b/src/tests/libknot/dname_tests.c @@ -20,18 +20,8 @@ /* Test dname_parse_from_wire */ static int test_fw(size_t l, const char *w) { - size_t p = 0; - knot_dname_t *d = NULL; - d = knot_dname_parse_from_wire((const uint8_t*)w, &p, l, NULL, NULL); - int ret = (d != NULL); -// d = knot_dname_new_from_wire((const uint8_t*)w, l, 0); -// if (d) { -// for(unsigned i = 0; i < d->label_count; ++i) { -// diag("%d", knot_dname_label_size(d, i)); -// } -// } - knot_dname_free(&d); - return ret; + const uint8_t *np = (const uint8_t *)w + l; + return knot_dname_wire_check((const uint8_t *)w, np, NULL) > 0; } static int dname_tests_count(int argc, char *argv[]); @@ -45,12 +35,15 @@ unit_api dname_tests_api = { static int dname_tests_count(int argc, char *argv[]) { - return 8; + return 21; } static int dname_tests_run(int argc, char *argv[]) { - const char *w = NULL; + knot_dname_t *d = NULL, *d2 = NULL; + const char *w = NULL, *t = NULL; + unsigned len = 0; + size_t pos = 0; /* 1. NULL wire */ ok(!test_fw(0, NULL), "parsing NULL dname"); @@ -80,5 +73,84 @@ static int dname_tests_run(int argc, char *argv[]) w = "\x20\x68\x6d\x6e\x63\x62\x67\x61\x61\x61\x61\x65\x72\x6b\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x67\x6e\x69\x64\x68\x62\x61\x61\x61\x61\x65\x6c\x64\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x61\x63\x6f\x63\x64\x62\x61\x61\x61\x61\x65\x6b\x72\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x69\x62\x63\x6d\x6a\x6f\x61\x61\x61\x61\x65\x72\x6a\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x6f\x6c\x6e\x6c\x67\x68\x61\x61\x61\x61\x65\x73\x72\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x6a\x6b\x64\x66\x66\x67\x61\x61\x61\x61\x65\x6c\x68\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x67\x67\x6c\x70\x70\x61\x61\x61\x61\x61\x65\x73\x72\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x65\x6b\x6c\x67\x70\x66\x61\x61\x61\x61\x65\x6c\x68\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x0\x21\x42\x63\x84\xa5\xc6\xe7\x8\xa\xd\x11\x73\x3\x6e\x69\x63\x2\x43\x5a"; ok(!test_fw(277, w), "parsing invalid label (spec. case 1)"); - return 0; + /* 9. parse from string (correct) .*/ + len = 10; + w = "\x04""abcd""\x03""efg"; + t = "abcd.efg"; + d = knot_dname_new_from_str(t, strlen(t)); + ok(d && d->size == len && memcmp(d->name, w, len) == 0, + "dname_fromstr: parsed correct non-FQDN name"); + knot_dname_free(&d); + + /* 10. parse FQDN from string (correct) .*/ + t = "abcd.efg."; + d = knot_dname_new_from_str(t, strlen(t)); + ok(d && d->size == len && memcmp(d->name, w, len) == 0, + "dname_fromstr: parsed correct FQDN name"); + knot_dname_free(&d); + + /* 11. parse name from string (incorrect) .*/ + t = ".."; + d = knot_dname_new_from_str(t, strlen(t)); + ok(d == NULL, "dname_fromstr: parsed incorrect name"); + + /* 12. equal name is subdomain */ + t = "ab.cd.ef"; + d2 = knot_dname_new_from_str(t, strlen(t)); + t = "ab.cd.ef"; + d = knot_dname_new_from_str(t, strlen(t)); + ok(!knot_dname_is_subdomain(d, d2), "dname_subdomain: equal name"); + knot_dname_free(&d); + + /* 13. true subdomain */ + t = "0.ab.cd.ef"; + d = knot_dname_new_from_str(t, strlen(t)); + ok(knot_dname_is_subdomain(d, d2), "dname_subdomain: true subdomain"); + knot_dname_free(&d); + + /* 14. not subdomain */ + t = "cd.ef"; + d = knot_dname_new_from_str(t, strlen(t)); + ok(!knot_dname_is_subdomain(d, d2), "dname_subdomain: not subdomain"); + knot_dname_free(&d); + + /* 15. root subdomain */ + t = "."; + d = knot_dname_new_from_str(t, strlen(t)); + ok(knot_dname_is_subdomain(d2, d), "dname_subdomain: root subdomain"); + knot_dname_free(&d); + knot_dname_free(&d2); + + /* 16-17. dname cat (valid) */ + w = "\x03""cat"; + len = 5; + d = knot_dname_new_from_wire((const uint8_t *)w, len); + t = "*"; + d2 = knot_dname_new_from_str(t, strlen(t)); + d2 = knot_dname_cat(d2, d); + t = "\x01""*""\x03""cat"; + len = 2 + 4 + 1; + ok (d2 && len == d2->size, "dname_cat: valid concatenation size"); + ok(memcmp(d2->name, t, len) == 0, "dname_cat: valid concatenation"); + knot_dname_free(&d); + knot_dname_free(&d2); + + /* 18-19. parse from wire (valid) */ + t = "\x04""abcd""\x03""efg"; + len = 10; + pos = 0; + d = knot_dname_parse_from_wire((const uint8_t *)t, &pos, len); + ok(d != NULL, "dname_parse: valid name"); + cmp_ok(pos, "==", len, "dname_parse: valid name (parsed length)"); + knot_dname_free(&d); + + /* 20-21. parse from wire (invalid) */ + t = "\x08""dddd"; + len = 5; + pos = 0; + d = knot_dname_parse_from_wire((const uint8_t *)t, &pos, len); + ok(d == NULL, "dname_parse: bad name"); + cmp_ok(pos, "==", 0, "dname_parse: bad name (parsed length)"); + + done_testing(); } diff --git a/src/tests/libknot/rrset_tests.c b/src/tests/libknot/rrset_tests.c index d140681017bf7d023b6bbcdbfd5b732165e16353..a8c9932eb12c3073c4e3ac1f320776ad1cb14a4d 100644 --- a/src/tests/libknot/rrset_tests.c +++ b/src/tests/libknot/rrset_tests.c @@ -170,8 +170,7 @@ static void create_test_dnames() for (int i = 0; i < TEST_DNAME_COUNT; i++) { test_dnames[i] = knot_dname_new_from_str(test_dname_strings[i], - strlen(test_dname_strings[i]), - NULL); + strlen(test_dname_strings[i])); } } diff --git a/src/tests/libknot/sign_tests.c b/src/tests/libknot/sign_tests.c index 6b77218bf08bb9774a4a91d137b927d6a64d4295..1a7864d734317a93c804cecfe27112b6eba14b48 100644 --- a/src/tests/libknot/sign_tests.c +++ b/src/tests/libknot/sign_tests.c @@ -208,8 +208,7 @@ static int sign_tests_run(int argc, char *argv[]) knot_tsig_key_t tsig_key; const char *owner = "shared.example.com."; knot_dname_t *name = knot_dname_new_from_str(owner, - strlen(owner), - NULL); + strlen(owner)); result = knot_tsig_key_from_params(¶ms, &tsig_key); ok(result == KNOT_EINVAL, diff --git a/src/tests/libknot/ztree_tests.c b/src/tests/libknot/ztree_tests.c index 53506af7b6530a3c8c85c015dda897d836f5cc60..4d322ac1bcf405e1ef3a5ff0b75e34309ea530d3 100644 --- a/src/tests/libknot/ztree_tests.c +++ b/src/tests/libknot/ztree_tests.c @@ -24,10 +24,10 @@ static knot_node_t NODE[NCOUNT]; static knot_dname_t* ORDER[NCOUNT]; static void ztree_init_data() { - NAME[0] = knot_dname_new_from_str(".", 1, NULL); - NAME[1] = knot_dname_new_from_str("master.ac.", 10, NULL); - NAME[2] = knot_dname_new_from_str("ac.", 3, NULL); - NAME[3] = knot_dname_new_from_str("ns.", 3, NULL); + NAME[0] = knot_dname_new_from_str(".", 1); + NAME[1] = knot_dname_new_from_str("master.ac.", 10); + NAME[2] = knot_dname_new_from_str("ac.", 3); + NAME[3] = knot_dname_new_from_str("ns.", 3); knot_dname_t *order[NCOUNT] = { NAME[0], NAME[2], NAME[1], NAME[3] @@ -37,7 +37,6 @@ static void ztree_init_data() for (unsigned i = 0; i < NCOUNT; ++i) { memset(NODE + i, 0, sizeof(knot_node_t)); NODE[i].owner = NAME[i]; - NAME[i]->node = NODE + i; NODE[i].prev = NODE + ((NCOUNT + i - 1) % NCOUNT); NODE[i].rrset_count = 1; /* required for ordered search */ } @@ -120,7 +119,7 @@ static int ztree_tests_run(int argc, char *argv[]) passed = 1; node = NULL; const knot_node_t *prev = NULL; - knot_dname_t *tmp_dn = knot_dname_new_from_str("z.ac.", 5, NULL); + knot_dname_t *tmp_dn = knot_dname_new_from_str("z.ac.", 5); knot_zone_tree_find_less_or_equal(t, tmp_dn, &node, &prev); knot_dname_free(&tmp_dn); ok(prev == NODE + 1, "ztree: ordered lookup"); diff --git a/src/tests/xfr_tests.c b/src/tests/xfr_tests.c index fee09f2680d8e44d98da2f3199e1d5468f6bff87..e278c531fe81e5dc1d600d195fc53f43f7c0c4e2 100644 --- a/src/tests/xfr_tests.c +++ b/src/tests/xfr_tests.c @@ -319,7 +319,7 @@ int main(int argc, char **argv) if (zone == NULL) sig_integrity_check = 0; if (sig_integrity_check) { log_server_info("Starting integrity check of zone: %s\n", zone); - knot_dname_t* zdn = knot_dname_new_from_str(zone, strlen(zone), NULL); + knot_dname_t* zdn = knot_dname_new_from_str(zone, strlen(zone)); assert(zdn); knot_zone_t *z = knot_zonedb_find_zone(server->nameserver->zone_db, zdn); int ic_ret = knot_zone_contents_integrity_check(z->contents); diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c index 0a9c1a9f2889575735a71b0cc734e28eb5fae070..38a6482b6f91f7ee795ca4e5c52c941d76822d67 100644 --- a/src/utils/common/exec.c +++ b/src/utils/common/exec.c @@ -101,8 +101,10 @@ static void print_header(const knot_packet_t *packet, const style_t *style) ";; Flags:%1s; " "ZONE: %u; PREREQ: %u; UPDATE: %u; ADDITIONAL: %u\n", opcode_str, rcode_str, knot_packet_id(packet), - flags, packet->header.qdcount, packet->header.ancount, - packet->header.nscount, packet->header.arcount); + flags, knot_wire_get_qdcount(packet->wireformat), + knot_wire_get_ancount(packet->wireformat), + knot_wire_get_nscount(packet->wireformat), + knot_wire_get_arcount(packet->wireformat)); break; default: @@ -110,8 +112,10 @@ static void print_header(const knot_packet_t *packet, const style_t *style) ";; Flags:%1s; " "QUERY: %u; ANSWER: %u; AUTHORITY: %u; ADDITIONAL: %u\n", opcode_str, rcode_str, knot_packet_id(packet), - flags, packet->header.qdcount, packet->header.ancount, - packet->header.nscount, packet->header.arcount); + flags, knot_wire_get_qdcount(packet->wireformat), + knot_wire_get_ancount(packet->wireformat), + knot_wire_get_nscount(packet->wireformat), + knot_wire_get_arcount(packet->wireformat)); break; } } @@ -316,7 +320,7 @@ static void print_section_host(const knot_rrset_t **rrsets, } static void print_error_host(const uint8_t code, - const knot_question_t *question) + const knot_packet_t *packet) { const char *rcode_str = "NULL"; char type[32] = "NULL"; @@ -324,12 +328,12 @@ static void print_error_host(const uint8_t code, knot_lookup_table_t *rcode; - owner = knot_dname_to_str(question->qname); + owner = knot_dname_to_str(knot_packet_qname(packet)); rcode = knot_lookup_by_id(knot_rcode_names, code); if (rcode != NULL) { rcode_str = rcode->name; } - knot_rrtype_to_string(question->qtype, type, sizeof(type)); + knot_rrtype_to_string(knot_packet_qtype(packet), type, sizeof(type)); if (code == KNOT_RCODE_NOERROR) { printf("Host %s has no %s record\n", owner, type); @@ -340,11 +344,10 @@ static void print_error_host(const uint8_t code, free(owner); } -knot_packet_t* create_empty_packet(const knot_packet_prealloc_type_t type, - const size_t max_size) +knot_packet_t* create_empty_packet(const size_t max_size) { // Create packet skeleton. - knot_packet_t *packet = knot_packet_new(type); + knot_packet_t *packet = knot_packet_new(); if (packet == NULL) { DBG_NULL; return NULL; @@ -362,7 +365,7 @@ knot_packet_t* create_empty_packet(const knot_packet_prealloc_type_t type, return packet; } -void print_header_xfr(const knot_question_t *question, const style_t *style) +void print_header_xfr(const knot_packet_t *packet, const style_t *style) { if (style == NULL) { DBG_NULL; @@ -371,7 +374,7 @@ void print_header_xfr(const knot_question_t *question, const style_t *style) char xfr[16] = "AXFR"; - switch (question->qtype) { + switch (knot_packet_qtype(packet)) { case KNOT_RRTYPE_AXFR: break; case KNOT_RRTYPE_IXFR: @@ -382,7 +385,7 @@ void print_header_xfr(const knot_question_t *question, const style_t *style) } if (style->show_header) { - char *owner = knot_dname_to_str(question->qname); + char *owner = knot_dname_to_str(knot_packet_qname(packet)); if (owner != NULL) { printf("\n;; %s for %s\n", xfr, owner); free(owner); @@ -398,20 +401,21 @@ void print_data_xfr(const knot_packet_t *packet, return; } + uint16_t ancount = knot_wire_get_ancount(packet->wireformat); switch (style->format) { case FORMAT_DIG: - print_section_dig(packet->answer, packet->header.ancount,style); + print_section_dig(packet->answer, ancount,style); break; case FORMAT_HOST: - print_section_host(packet->answer, packet->header.ancount, style); + print_section_host(packet->answer, ancount, style); break; case FORMAT_FULL: - print_section_full(packet->answer, packet->header.ancount, style); + print_section_full(packet->answer, ancount, style); // Print TSIG record if any. if (style->show_additional) { print_section_full(packet->additional, - packet->header.arcount, + knot_wire_get_arcount(packet->wireformat), style); } break; @@ -449,7 +453,11 @@ void print_packet(const knot_packet_t *packet, return; } - uint16_t additionals = packet->header.arcount; + uint8_t rcode = knot_wire_get_rcode(packet->wireformat); + uint16_t qdcount = knot_wire_get_qdcount(packet->wireformat); + uint16_t ancount = knot_wire_get_ancount(packet->wireformat); + uint16_t arcount = knot_wire_get_arcount(packet->wireformat); + uint16_t nscount = knot_wire_get_nscount(packet->wireformat); // Print packet information header. if (style->show_header) { @@ -463,83 +471,82 @@ void print_packet(const knot_packet_t *packet, print_opt_section(&packet->opt_rr); } - additionals--; + arcount--; } // Print DNS sections. switch (style->format) { case FORMAT_DIG: - if (packet->header.ancount > 0) { - print_section_dig(packet->answer, packet->header.ancount, + if (ancount > 0) { + print_section_dig(packet->answer, ancount, style); } break; case FORMAT_HOST: - if (packet->header.ancount > 0) { - print_section_host(packet->answer, packet->header.ancount, + if (ancount > 0) { + print_section_host(packet->answer, ancount, style); } else { - uint8_t rcode = knot_wire_get_rcode(packet->wireformat); - print_error_host(rcode, &packet->question); + print_error_host(rcode, packet); } break; case FORMAT_NSUPDATE: - if (style->show_question && packet->header.qdcount > 0) { + if (style->show_question && qdcount > 0) { printf("\n;; ZONE SECTION:\n;; "); - print_section_question(packet->question.qname, - packet->question.qclass, - packet->question.qtype, + print_section_question(knot_packet_qname(packet), + knot_packet_qclass(packet), + knot_packet_qtype(packet), style); } - if (style->show_answer && packet->header.ancount > 0) { + if (style->show_answer && ancount > 0) { printf("\n;; PREREQUISITE SECTION:\n"); print_section_full(packet->answer, - packet->header.ancount, + ancount, style); } - if (style->show_authority && packet->header.nscount > 0) { + if (style->show_authority && nscount > 0) { printf("\n;; UPDATE SECTION:\n"); print_section_full(packet->authority, - packet->header.nscount, + nscount, style); } - if (style->show_additional && additionals > 0) { + if (style->show_additional && arcount > 0) { printf("\n;; ADDITIONAL DATA:\n"); print_section_full(packet->additional, - packet->header.arcount, + arcount, style); } break; case FORMAT_FULL: - if (style->show_question && packet->header.qdcount > 0) { + if (style->show_question && qdcount > 0) { printf("\n;; QUESTION SECTION:\n;; "); - print_section_question(packet->question.qname, - packet->question.qclass, - packet->question.qtype, + print_section_question(knot_packet_qname(packet), + knot_packet_qclass(packet), + knot_packet_qtype(packet), style); } - if (style->show_answer && packet->header.ancount > 0) { + if (style->show_answer && ancount > 0) { printf("\n;; ANSWER SECTION:\n"); print_section_full(packet->answer, - packet->header.ancount, + ancount, style); } - if (style->show_authority && packet->header.nscount > 0) { + if (style->show_authority && nscount > 0) { printf("\n;; AUTHORITY SECTION:\n"); print_section_full(packet->authority, - packet->header.nscount, + nscount, style); } - if (style->show_additional && additionals > 0) { + if (style->show_additional && arcount > 0) { printf("\n;; ADDITIONAL SECTION:\n"); print_section_full(packet->additional, - packet->header.arcount, + arcount, style); } break; diff --git a/src/utils/common/exec.h b/src/utils/common/exec.h index 63189e12527d0ba8b2532625b6628d486c4209ed..00d969c0df5d01298643738489426d73b04032e9 100644 --- a/src/utils/common/exec.h +++ b/src/utils/common/exec.h @@ -42,22 +42,20 @@ typedef struct { /*! * \brief Allocates empty packet and sets packet size and random id. * - * \param type Packet preallocation type. * \param max_size Maximal packet size. * * \retval packet if success. * \retval NULL if error. */ -knot_packet_t* create_empty_packet(const knot_packet_prealloc_type_t type, - const size_t max_size); +knot_packet_t* create_empty_packet(const size_t max_size); /*! * \brief Prints information header for transfer. * - * \param question Packet question section. + * \param packet Parsed packet. * \param style Style of the output. */ -void print_header_xfr(const knot_question_t *question, const style_t *style); +void print_header_xfr(const knot_packet_t *packet, const style_t *style); /*! * \brief Prints answer section for 1 transfer message. diff --git a/src/utils/common/params.c b/src/utils/common/params.c index 56dc662132381c14fc8f2a29491a025dc82ef5d5..3c50885c3e488d11f4d24fb07397b099cfa687fd 100644 --- a/src/utils/common/params.c +++ b/src/utils/common/params.c @@ -344,7 +344,7 @@ int params_parse_tsig(const char *value, knot_key_params_t *key_params) } /* Set key name and secret. */ - key_params->name = knot_dname_new_from_nonfqdn_str(k, strlen(k), NULL); + key_params->name = knot_dname_new_from_str(k, strlen(k)); key_params->secret = strdup(s); DBG("%s: parsed name '%s'\n", __func__, k); diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c index 8a13e96303c99b30d69679066f85fa7ce08d8742..d7aa30b94483dfc262ad164ebcb7677a05734df4 100644 --- a/src/utils/dig/dig_exec.c +++ b/src/utils/dig/dig_exec.c @@ -35,7 +35,6 @@ static knot_packet_t* create_query_packet(const query_t *query, uint8_t **data, size_t *data_len) { - knot_question_t q; knot_packet_t *packet; // Set packet buffer size. @@ -52,7 +51,7 @@ static knot_packet_t* create_query_packet(const query_t *query, } // Create packet skeleton. - packet = create_empty_packet(KNOT_PACKET_PREALLOC_NONE, max_size); + packet = create_empty_packet(max_size); if (packet == NULL) { return NULL; } @@ -80,20 +79,19 @@ static knot_packet_t* create_query_packet(const query_t *query, knot_wire_set_cd(packet->wireformat); } - // Fill auxiliary question structure. - q.qclass = query->class_num; - q.qtype = query->type_num; - q.qname = knot_dname_new_from_str(query->owner, strlen(query->owner), 0); - if (q.qname == NULL) { + // Create QNAME from string. + knot_dname_t *qname = knot_dname_new_from_str(query->owner, + strlen(query->owner)); + if (qname == NULL) { knot_packet_free(&packet); return NULL; } // Set packet question. - if (knot_query_set_question(packet, &q) != KNOT_EOK) { - // It's necessary to release q.qname by hand as it isn't - // connected with the packet yet. - knot_dname_release(q.qname); + int ret = knot_query_set_question(packet, qname, + query->class_num, query->type_num); + if (ret != KNOT_EOK) { + knot_dname_free(&qname); knot_packet_free(&packet); return NULL; } @@ -103,13 +101,13 @@ static knot_packet_t* create_query_packet(const query_t *query, // SOA rdata in wireformat. uint8_t wire[22] = { 0x0 }; size_t pos = 0; - int ret; // Create rrset with SOA record. - knot_rrset_t *soa = knot_rrset_new(q.qname, + knot_rrset_t *soa = knot_rrset_new(qname, KNOT_RRTYPE_SOA, query->class_num, 0); + knot_dname_free(&qname); /* Won't be needed anymore. */ if (soa == NULL) { knot_packet_free(&packet); return NULL; @@ -217,16 +215,16 @@ static bool check_reply_id(const knot_packet_t *reply, static void check_reply_question(const knot_packet_t *reply, const knot_packet_t *query) { - if (reply->header.qdcount < 1) { + if (knot_wire_get_qdcount(reply->wireformat) < 1) { WARN("response doesn't have question section\n"); return; } - int name_diff = knot_dname_compare_cs(reply->question.qname, - query->question.qname); + int name_diff = knot_dname_compare_cs(knot_packet_qname(reply), + knot_packet_qname(query)); - if (reply->question.qclass != query->question.qclass || - reply->question.qtype != query->question.qtype || + if (knot_packet_qclass(reply) != knot_packet_qclass(query) || + knot_packet_qtype(reply) != knot_packet_qtype(query) || name_diff != 0) { WARN("query/response question sections are different\n"); return; @@ -235,7 +233,7 @@ static void check_reply_question(const knot_packet_t *reply, static int64_t first_serial_check(const knot_packet_t *reply) { - if (reply->header.ancount <= 0) { + if (knot_wire_get_ancount(reply->wireformat) <= 0) { return -1; } @@ -250,11 +248,11 @@ static int64_t first_serial_check(const knot_packet_t *reply) static bool last_serial_check(const uint32_t serial, const knot_packet_t *reply) { - if (reply->header.ancount <= 0) { + if (knot_wire_get_ancount(reply->wireformat) <= 0) { return false; } - const knot_rrset_t *last = *(reply->answer + reply->header.ancount - 1); + const knot_rrset_t *last = *(reply->answer + knot_wire_get_ancount(reply->wireformat) - 1); if (last->type != KNOT_RRTYPE_SOA) { return false; @@ -321,7 +319,7 @@ static int process_query_packet(const knot_packet_t *query, gettimeofday(&t_end, NULL); // Create reply packet structure to fill up. - reply = knot_packet_new(KNOT_PACKET_PREALLOC_NONE); + reply = knot_packet_new(); if (reply == NULL) { net_close(net); return -1; @@ -527,7 +525,7 @@ static int process_packet_xfr(const knot_packet_t *query, } // Print leading transfer information. - print_header_xfr(&query->question, style); + print_header_xfr(query, style); // Loop over reply messages unless first and last SOA serials differ. while (true) { @@ -539,7 +537,7 @@ static int process_packet_xfr(const knot_packet_t *query, } // Create reply packet structure to fill up. - reply = knot_packet_new(KNOT_PACKET_PREALLOC_NONE); + reply = knot_packet_new(); if (reply == NULL) { net_close(net); return -1; @@ -609,7 +607,7 @@ static int process_packet_xfr(const knot_packet_t *query, } msg_count++; - rr_count += reply->header.ancount; + rr_count += knot_wire_get_ancount(reply->wireformat); total_len += in_len; // Print reply packet. diff --git a/src/utils/nsupdate/nsupdate_exec.c b/src/utils/nsupdate/nsupdate_exec.c index 705e7c01ecdb825b4c76c19eb743f745390896f9..a68dc959e9c8be7ce3a2cb3c691c906e6a4a5998 100644 --- a/src/utils/nsupdate/nsupdate_exec.c +++ b/src/utils/nsupdate/nsupdate_exec.c @@ -128,7 +128,7 @@ enum { }; static int dname_isvalid(const char *lp, size_t len) { - knot_dname_t *dn = knot_dname_new_from_str(lp, len, NULL); + knot_dname_t *dn = knot_dname_new_from_str(lp, len); if (dn == NULL) { return 0; } @@ -164,7 +164,7 @@ static int parse_partial_rr(scanner_t *s, const char *lp, unsigned flags) { /* Extract owner. */ size_t len = strcspn(lp, SEP_CHARS); - knot_dname_t *owner = knot_dname_new_from_str(lp, len, NULL); + knot_dname_t *owner = knot_dname_new_from_str(lp, len); if (owner == NULL) { return KNOT_EPARSEFAIL; } @@ -172,8 +172,7 @@ static int parse_partial_rr(scanner_t *s, const char *lp, unsigned flags) { /* ISC nsupdate doesn't do this, but it seems right to me. */ if (!knot_dname_is_fqdn(owner)) { knot_dname_t* suf = knot_dname_new_from_wire(s->zone_origin, - s->zone_origin_length, - NULL); + s->zone_origin_length); if (suf == NULL) { knot_dname_free(&owner); return KNOT_ENOMEM; @@ -301,23 +300,21 @@ static int pkt_append(nsupdate_params_t *p, int sect) { /* Check packet state first. */ int ret = KNOT_EOK; + knot_dname_t * qname = NULL; scanner_t *s = p->rrp; if (!p->pkt) { - p->pkt = create_empty_packet(KNOT_PACKET_PREALLOC_RESPONSE, - MAX_PACKET_SIZE); - knot_question_t q; - q.qclass = p->class_num; - q.qtype = p->type_num; - q.qname = knot_dname_new_from_nonfqdn_str(p->zone, strlen(p->zone), NULL); - ret = knot_query_set_question(p->pkt, &q); - if (ret != KNOT_EOK) { + p->pkt = create_empty_packet(MAX_PACKET_SIZE); + qname = knot_dname_new_from_str(p->zone, strlen(p->zone)); + ret = knot_query_set_question(p->pkt, qname, p->class_num, p->type_num); + knot_dname_free(&qname); + if (ret != KNOT_EOK) return ret; - } + knot_query_set_opcode(p->pkt, KNOT_OPCODE_UPDATE); } /* Form a rrset. */ - knot_dname_t *o = knot_dname_new_from_wire(s->r_owner, s->r_owner_length, NULL); + knot_dname_t *o = knot_dname_new_from_wire(s->r_owner, s->r_owner_length); if (!o) { DBG("%s: failed to create dname - %s\n", __func__, knot_strerror(ret)); @@ -729,8 +726,6 @@ int cmd_send(const char* lp, nsupdate_params_t *params) } /* Clear sent packet. */ - knot_question_t *q = knot_packet_question(params->pkt); - knot_dname_release(q->qname); knot_packet_free_rrsets(params->pkt); knot_packet_free(¶ms->pkt); @@ -746,7 +741,7 @@ int cmd_send(const char* lp, nsupdate_params_t *params) } /* Parse response. */ - params->resp = knot_packet_new(KNOT_PACKET_PREALLOC_NONE); + params->resp = knot_packet_new(); if (!params->resp) { free_sign_context(&sign_ctx); return KNOT_ENOMEM;