diff --git a/src/context.c b/src/context.c index 10827863..cd58aaac 100644 --- a/src/context.c +++ b/src/context.c @@ -43,11 +43,13 @@ #include "util-internal.h" /* Private functions */ -static uint16_t *create_default_namespaces(); +static uint16_t *create_default_namespaces(getdns_context_t context); static struct getdns_list *create_default_root_servers(); static getdns_return_t add_ip_str(getdns_dict *); -static struct getdns_dict *create_ipaddr_dict_from_rdf(ldns_rdf *); -static struct getdns_list *create_from_ldns_list(ldns_rdf **, size_t); +static struct getdns_dict *create_ipaddr_dict_from_rdf(getdns_context_t, + ldns_rdf *); +static struct getdns_list *create_from_ldns_list(getdns_context_t, + ldns_rdf **, size_t); static getdns_return_t set_os_defaults(getdns_context_t); static int transaction_id_cmp(const void *, const void *); static void set_ub_string_opt(getdns_context_t, char *, char *); @@ -64,9 +66,9 @@ static void cancel_dns_req(getdns_dns_req *); * TODO: Determine from OS */ static uint16_t * -create_default_namespaces() +create_default_namespaces(getdns_context_t context) { - uint16_t *result = malloc(2 * sizeof(uint16_t)); + uint16_t *result = GETDNS_XMALLOC(context, uint16_t, 2); result[0] = GETDNS_CONTEXT_NAMESPACE_LOCALNAMES; result[1] = GETDNS_CONTEXT_NAMESPACE_DNS; return result; @@ -117,11 +119,11 @@ add_ip_str(getdns_dict * ip) } static struct getdns_dict * -create_ipaddr_dict_from_rdf(ldns_rdf * rdf) +create_ipaddr_dict_from_rdf(getdns_context_t context, ldns_rdf * rdf) { ldns_rdf_type rt = ldns_rdf_get_type(rdf); size_t sz = ldns_rdf_size(rdf); - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); /* set type */ if (rt == LDNS_RDF_TYPE_A) { getdns_dict_util_set_string(result, GETDNS_STR_ADDRESS_TYPE, @@ -138,11 +140,12 @@ create_ipaddr_dict_from_rdf(ldns_rdf * rdf) } static struct getdns_list * -create_from_ldns_list(ldns_rdf ** ldns_list, size_t count) +create_from_ldns_list(getdns_context_t context, ldns_rdf ** ldns_list, + size_t count) { size_t i = 0; size_t idx = 0; - struct getdns_list *result = getdns_list_create(); + struct getdns_list *result = getdns_list_create_with_context(context); for (i = 0; i < count; ++i) { ldns_rdf *rdf = ldns_list[i]; switch (ldns_rdf_get_type(rdf)) { @@ -150,7 +153,7 @@ create_from_ldns_list(ldns_rdf ** ldns_list, size_t count) case LDNS_RDF_TYPE_AAAA: { getdns_dict *ipaddr = - create_ipaddr_dict_from_rdf(rdf); + create_ipaddr_dict_from_rdf(context, rdf); getdns_list_add_item(result, &idx); getdns_list_set_dict(result, idx, ipaddr); getdns_dict_destroy(ipaddr); @@ -161,7 +164,7 @@ create_from_ldns_list(ldns_rdf ** ldns_list, size_t count) { getdns_bindata item; char *srch = ldns_rdf2str(rdf); - item.size = strlen(srch); + item.size = strlen(srch) + 1; item.data = (uint8_t *) srch; getdns_list_add_item(result, &idx); getdns_list_set_bindata(result, idx, &item); @@ -187,12 +190,13 @@ set_os_defaults(getdns_context_t context) size_t rdf_list_sz = ldns_resolver_nameserver_count(lr); if (rdf_list_sz > 0) { context->upstream_list = - create_from_ldns_list(rdf_list, rdf_list_sz); + create_from_ldns_list(context, rdf_list, rdf_list_sz); } rdf_list = ldns_resolver_searchlist(lr); rdf_list_sz = ldns_resolver_searchlist_count(lr); if (rdf_list_sz > 0) { - context->suffix = create_from_ldns_list(rdf_list, rdf_list_sz); + context->suffix = create_from_ldns_list(context, rdf_list, + rdf_list_sz); } /** cleanup **/ ldns_resolver_deep_free(lr); @@ -229,24 +233,28 @@ transaction_id_cmp(const void *id1, const void *id2) * Call this to initialize the context that is used in other getdns calls. */ getdns_return_t -getdns_context_create(getdns_context_t * context, int set_from_os) +getdns_context_create_with_memory_functions(getdns_context_t * context, + int set_from_os, + void *(*malloc)(size_t), + void *(*realloc)(void *, size_t), + void (*free)(void *) + ) { getdns_context_t result = NULL; - if (context == NULL) { + if (!context || !malloc || !realloc || !free) return GETDNS_RETURN_GENERIC_ERROR; - } /** default init **/ - result = malloc(sizeof(struct getdns_context_t)); + result = (*malloc)(sizeof(struct getdns_context_t)); if (!result) { return GETDNS_RETURN_GENERIC_ERROR; } result->update_callback = NULL; - result->memory_allocator = malloc; - result->memory_deallocator = free; - result->memory_reallocator = realloc; + result->malloc = malloc; + result->realloc = realloc; + result->free = free; result->event_base_sync = event_base_new(); result->unbound_sync = ub_ctx_create_event(result->event_base_sync); @@ -259,7 +267,7 @@ getdns_context_create(getdns_context_t * context, int set_from_os) result->outbound_requests = ldns_rbtree_create(transaction_id_cmp); result->resolution_type = GETDNS_CONTEXT_RECURSING; - result->namespaces = create_default_namespaces(); + result->namespaces = create_default_namespaces(result); result->timeout = 5000; result->follow_redirects = GETDNS_CONTEXT_FOLLOW_REDIRECTS; @@ -292,6 +300,19 @@ getdns_context_create(getdns_context_t * context, int set_from_os) return GETDNS_RETURN_GOOD; } /* getdns_context_create */ +/* + * getdns_context_create + * + * Call this to initialize the context that is used in other getdns calls. + */ +getdns_return_t +getdns_context_create(getdns_context_t * context, int set_from_os) +{ + return getdns_context_create_with_memory_functions(context, + set_from_os, malloc, realloc, free); +} /* getdns_context_create */ + + /* * getdns_context_destroy * @@ -304,9 +325,9 @@ getdns_context_destroy(getdns_context_t context) if (context == NULL) { return; } - if (context->namespaces) { - context->memory_deallocator(context->namespaces); - } + if (context->namespaces) + GETDNS_FREE(context, context->namespaces); + getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->suffix); getdns_list_destroy(context->dnssec_trust_anchors); @@ -320,7 +341,7 @@ getdns_context_destroy(getdns_context_t context) ldns_rbtree_free(context->outbound_requests); - free(context); + GETDNS_FREE(context, context); return; } /* getdns_context_destroy */ @@ -416,18 +437,18 @@ getdns_return_t getdns_context_set_namespaces(getdns_context_t context, size_t namespace_count, uint16_t * namespaces) { - size_t namespaces_size; if (namespace_count == 0 || namespaces == NULL) { return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } /** clean up old namespaces **/ - context->memory_deallocator(context->namespaces); + GETDNS_FREE(context, context->namespaces); /** duplicate **/ - namespaces_size = namespace_count * sizeof(uint16_t); - context->namespaces = context->memory_allocator(namespaces_size); - memcpy(context->namespaces, namespaces, namespaces_size); + context->namespaces = GETDNS_XMALLOC(context, uint16_t, + namespace_count); + memcpy(context->namespaces, namespaces, + namespace_count * sizeof(uint16_t)); dispatch_updated(context, GETDNS_CONTEXT_CODE_NAMESPACES); @@ -759,46 +780,31 @@ getdns_context_set_edns_do_bit(getdns_context_t context, uint8_t value) } /* getdns_context_set_edns_do_bit */ /* - * getdns_context_set_memory_allocator + * getdns_context_set_memory_functions * */ getdns_return_t -getdns_context_set_memory_allocator(getdns_context_t context, - void (*value) (size_t somesize) +getdns_context_set_memory_functions(getdns_context_t context, + void *(*malloc) (size_t), + void *(*realloc) (void *, size_t), + void (*free) (void *) ) { - UNUSED_PARAM(context); - UNUSED_PARAM(value); - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; -} /* getdns_context_set_memory_allocator */ + if (!context) + return GETDNS_RETURN_BAD_CONTEXT; -/* - * getdns_context_set_memory_deallocator - * - */ -getdns_return_t -getdns_context_set_memory_deallocator(getdns_context_t context, - void (*value) (void *) - ) -{ - UNUSED_PARAM(context); - UNUSED_PARAM(value); - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; -} /* getdns_context_set_memory_deallocator */ + if (!malloc || !realloc || !free) + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + + context->malloc = malloc; + context->realloc = realloc; + context->free = free; + + dispatch_updated(context, GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS); + + return GETDNS_RETURN_GOOD; +} /* getdns_context_set_memory_functions*/ -/* - * getdns_context_set_memory_reallocator - * - */ -getdns_return_t -getdns_context_set_memory_reallocator(getdns_context_t context, - void (*value) (void *) - ) -{ - UNUSED_PARAM(context); - UNUSED_PARAM(value); - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; -} /* getdns_context_set_memory_reallocator */ /* * getdns_extension_set_libevent_base @@ -864,7 +870,7 @@ getdns_context_cancel_request(getdns_context_t context, user_pointer = req->user_pointer; /* clean up */ - context->memory_deallocator(node); + GETDNS_FREE(context, node); dns_req_free(req); /* fire callback */ @@ -949,7 +955,7 @@ getdns_context_track_outbound_request(getdns_dns_req * req) return GETDNS_RETURN_GENERIC_ERROR; } getdns_context_t context = req->context; - ldns_rbnode_t *node = context->memory_allocator(sizeof(ldns_rbnode_t)); + ldns_rbnode_t *node = GETDNS_MALLOC(context, ldns_rbnode_t); if (!node) { return GETDNS_RETURN_GENERIC_ERROR; } @@ -957,7 +963,7 @@ getdns_context_track_outbound_request(getdns_dns_req * req) node->data = req; if (!ldns_rbtree_insert(context->outbound_requests, node)) { /* free the node */ - context->memory_deallocator(node); + GETDNS_FREE(context, node); return GETDNS_RETURN_GENERIC_ERROR; } return GETDNS_RETURN_GOOD; @@ -973,9 +979,52 @@ getdns_context_clear_outbound_request(getdns_dns_req * req) ldns_rbnode_t *node = ldns_rbtree_delete(context->outbound_requests, &(req->trans_id)); if (node) { - context->memory_deallocator(node); + GETDNS_FREE(context, node); } return GETDNS_RETURN_GOOD; } +char * +getdns_strdup(getdns_context_t context, const char *s) +{ + size_t sz = strlen(s) + 1; + char *r = GETDNS_XMALLOC(context, char, sz); + if (r) + return memcpy(r, s, sz); + else + return NULL; +} + +struct getdns_bindata * +getdns_bindata_copy(getdns_context_t context, + const struct getdns_bindata *src) +{ + struct getdns_bindata *dst; + + if (!src) + return NULL; + + dst = GETDNS_MALLOC(context, struct getdns_bindata); + if (!dst) + return NULL; + + dst->size = src->size; + dst->data = GETDNS_XMALLOC(context, uint8_t, src->size); + if (!dst->data) { + GETDNS_FREE(context, dst); + return NULL; + } + (void) memcpy(dst->data, src->data, src->size); + return dst; +} + +void +getdns_bindata_destroy(getdns_context_t context, + struct getdns_bindata *bindata) +{ + if (!bindata) + return; + GETDNS_FREE(context, bindata->data); + GETDNS_FREE(context, bindata); +} /* getdns_context.c */ diff --git a/src/context.h b/src/context.h index a131516b..53fc793b 100644 --- a/src/context.h +++ b/src/context.h @@ -62,9 +62,9 @@ struct getdns_context_t uint8_t edns_do_bit; getdns_update_callback update_callback; - getdns_memory_allocator memory_allocator; - getdns_memory_deallocator memory_deallocator; - getdns_memory_reallocator memory_reallocator; + getdns_memory_allocator malloc; + getdns_memory_reallocator realloc; + getdns_memory_deallocator free; /* Event loop for sync requests */ struct event_base *event_base_sync; @@ -87,6 +87,19 @@ struct getdns_context_t struct ldns_rbtree_t *outbound_requests; }; +#define GETDNS_XMALLOC(context, type, count) \ + ((context) ? ((type *) (*(context)->malloc)((count) * sizeof(type))) \ + : ((type *) malloc((count) * sizeof(type)))) +#define GETDNS_MALLOC(context, type) \ + GETDNS_XMALLOC(context, type, 1) +#define GETDNS_XREALLOC(context, ptr, type, count) \ + ((context) ? ((type *) (*(context)->realloc)((ptr), (count) * sizeof(type))) \ + : ((type *) realloc((ptr), (count) * sizeof(type)))) +#define GETDNS_REALLOC(context, ptr, type) \ + GETDNS_XREALLOC(context, ptr, type, 1); +#define GETDNS_FREE(context, ptr) \ + ((context) ? ((*(context)->free)(ptr)) : free(ptr)) + /** internal functions **/ /** * Sets up the unbound contexts with stub or recursive behavior @@ -105,4 +118,12 @@ getdns_return_t getdns_context_clear_outbound_request(struct getdns_dns_req getdns_return_t getdns_context_cancel_request(getdns_context_t context, getdns_transaction_t transaction_id, int fire_callback); +char *getdns_strdup(getdns_context_t, const char *str); + +struct getdns_bindata *getdns_bindata_copy(getdns_context_t, + const struct getdns_bindata *src); + +void getdns_bindata_destroy(getdns_context_t context, + struct getdns_bindata *bindata); + #endif /* _GETDNS_CONTEXT_H_ */ diff --git a/src/dict.c b/src/dict.c index 1d81e34e..4804fbce 100644 --- a/src/dict.c +++ b/src/dict.c @@ -37,6 +37,7 @@ #include #include +#include "context.h" #include "dict.h" /*---------------------------------------- getdns_dict_find */ @@ -51,23 +52,20 @@ struct getdns_dict_item * getdns_dict_find(struct getdns_dict *dict, char *key, bool addifnotfnd) { - struct getdns_dict_item *item = NULL; + struct getdns_dict_item *item; - if (dict != NULL && key != NULL) { - item = - (struct getdns_dict_item *) ldns_rbtree_search(&(dict-> - root), key); - if (addifnotfnd == true && item == NULL) { - /* tsearch will add a node automatically for us */ - item = - (struct getdns_dict_item *) malloc(sizeof(struct - getdns_dict_item)); - item->node.key = strdup(key); - item->dtype = t_invalid; - item->data.n = 0; - ldns_rbtree_insert(&(dict->root), - (ldns_rbnode_t *) item); - } + if (!dict || !key) + return NULL; + + item = (struct getdns_dict_item *) + ldns_rbtree_search(&(dict->root), key); + + if (!item && addifnotfnd) { + /* tsearch will add a node automatically for us */ + item = GETDNS_MALLOC(dict->context, struct getdns_dict_item); + item->node.key = getdns_strdup(dict->context, key); + item->data.n = 0; + ldns_rbtree_insert(&(dict->root), (ldns_rbnode_t *) item); } return item; } /* getdns_dict_find */ @@ -77,27 +75,25 @@ getdns_dict_find(struct getdns_dict *dict, char *key, bool addifnotfnd) getdns_return_t getdns_dict_get_names(struct getdns_dict * dict, struct getdns_list ** answer) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; struct getdns_dict_item *item; size_t index; + struct getdns_bindata bindata; - if (dict != NULL && answer != NULL) { - *answer = getdns_list_create(); + if (!dict || !answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(dict->root)) - { - if (getdns_list_add_item(*answer, - &index) == GETDNS_RETURN_GOOD) { - struct getdns_bindata bindata; - bindata.size = strlen(item->node.key); - bindata.data = (void *) item->node.key; - getdns_list_set_bindata(*answer, index, - &bindata); - } - } - retval = GETDNS_RETURN_GOOD; + *answer = getdns_list_create_with_context(dict->context); + if (!*answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(dict->root)) { + if (getdns_list_add_item(*answer, &index) != GETDNS_RETURN_GOOD) + continue; + bindata.size = strlen(item->node.key) + 1; + bindata.data = (void *) item->node.key; + getdns_list_set_bindata(*answer, index, &bindata); } - return retval; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_names */ /*---------------------------------------- getdns_dict_get_data_type */ @@ -106,17 +102,16 @@ getdns_dict_get_data_type(struct getdns_dict * dict, char *name, getdns_data_type * answer) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (dict != NULL && name != NULL && answer != NULL) { - item = getdns_dict_find(dict, name, false); - if (item != NULL) { - *answer = item->dtype; - retval = GETDNS_RETURN_GOOD; - } - } + if (!dict || !name || !answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - return retval; + item = getdns_dict_find(dict, name, false); + if (!item) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + *answer = item->dtype; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_data_type */ /*---------------------------------------- getdns_dict_get_dict */ @@ -125,21 +120,16 @@ getdns_dict_get_dict(struct getdns_dict * dict, char *name, struct getdns_dict ** answer) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (dict != NULL && name != NULL && answer != NULL) { - item = getdns_dict_find(dict, name, false); - if (item != NULL) { - if (item->dtype != t_dict) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = item->data.dict; - retval = GETDNS_RETURN_GOOD; - } - } - } + if (!dict || !name || !answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - return retval; + item = getdns_dict_find(dict, name, false); + if (!item || item->dtype != t_dict) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + *answer = item->data.dict; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_dict */ /*---------------------------------------- getdns_dict_get_list */ @@ -148,21 +138,16 @@ getdns_dict_get_list(struct getdns_dict * dict, char *name, struct getdns_list ** answer) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (dict != NULL && name != NULL && answer != NULL) { - item = getdns_dict_find(dict, name, false); - if (item != NULL) { - if (item->dtype != t_list) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = item->data.list; - retval = GETDNS_RETURN_GOOD; - } - } - } + if (!dict || !name || !answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - return retval; + item = getdns_dict_find(dict, name, false); + if (!item || item->dtype != t_list) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + *answer = item->data.list; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_list */ /*---------------------------------------- getdns_dict_get_bindata */ @@ -171,21 +156,16 @@ getdns_dict_get_bindata(struct getdns_dict * dict, char *name, struct getdns_bindata ** answer) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (dict != NULL && name != NULL && answer != NULL) { - item = getdns_dict_find(dict, name, false); - if (item != NULL) { - if (item->dtype != t_bindata) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = item->data.bindata; - retval = GETDNS_RETURN_GOOD; - } - } - } + if (!dict || !name || !answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - return retval; + item = getdns_dict_find(dict, name, false); + if (!item || item->dtype != t_bindata) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + *answer = item->data.bindata; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_bindata */ /*---------------------------------------- getdns_dict_get_int */ @@ -193,34 +173,40 @@ getdns_return_t getdns_dict_get_int(struct getdns_dict * dict, char *name, uint32_t * answer) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (dict != NULL && name != NULL && answer != NULL) { - item = getdns_dict_find(dict, name, false); - if (item != NULL) { - if (item->dtype != t_int) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = item->data.n; - retval = GETDNS_RETURN_GOOD; - } - } - } + if (!dict || !name || !answer) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - return retval; + item = getdns_dict_find(dict, name, false); + if (!item || item->dtype != t_int) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + *answer = item->data.n; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_int */ +/*-------------------------- getdns_dict_create_with_context */ +struct getdns_dict * +getdns_dict_create_with_context(getdns_context_t context) +{ + struct getdns_dict *dict; + + dict = GETDNS_MALLOC(context, struct getdns_dict); + if (!dict) + return NULL; + + dict->context = context; + ldns_rbtree_init(&(dict->root), (int (*)(const void *, + const void *)) strcmp); + return dict; +} /* getdns_dict_create_with_context */ + /*---------------------------------------- getdns_dict_create */ struct getdns_dict * getdns_dict_create() { - struct getdns_dict *dict; - - dict = (struct getdns_dict *) malloc(sizeof(struct getdns_dict)); - ldns_rbtree_init(&(dict->root), (int (*)(const void *, - const void *)) strcmp); - return dict; -} /* getdns_dict_create */ + return getdns_dict_create_with_context(NULL); +} /* getdns_dict_create */ /*---------------------------------------- getdns_dict_copy */ /** @@ -236,39 +222,48 @@ getdns_dict_copy(struct getdns_dict * srcdict, struct getdns_dict ** dstdict) { struct getdns_dict_item *item; char *key; + getdns_return_t retval; - if (dstdict == NULL) + if (!dstdict) return GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (srcdict == NULL) { + + if (!srcdict) { *dstdict = NULL; return GETDNS_RETURN_GOOD; } - *dstdict = getdns_dict_create(); + *dstdict = getdns_dict_create_with_context(srcdict->context); + if (!*dstdict) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + retval = GETDNS_RETURN_GOOD; LDNS_RBTREE_FOR(item, struct getdns_dict_item *, &(srcdict->root)) { key = (char *) item->node.key; switch (item->dtype) { case t_bindata: - getdns_dict_set_bindata(*dstdict, key, + retval = getdns_dict_set_bindata(*dstdict, key, item->data.bindata); break; case t_dict: - getdns_dict_set_dict(*dstdict, key, item->data.dict); + retval = getdns_dict_set_dict(*dstdict, key, + item->data.dict); break; case t_int: - getdns_dict_set_int(*dstdict, key, item->data.n); + retval = getdns_dict_set_int(*dstdict, key, + item->data.n); break; case t_list: - getdns_dict_set_list(*dstdict, key, item->data.list); - break; - - case t_invalid: - default: - // TODO: this is a fault of some kind, for now ignore it + retval = getdns_dict_set_list(*dstdict, key, + item->data.list); break; } + if (retval != GETDNS_RETURN_GOOD) { + getdns_dict_destroy(*dstdict);; + *dstdict = NULL; + return retval; + } } return GETDNS_RETURN_GOOD; } /* getdns_dict_copy */ @@ -282,36 +277,40 @@ getdns_dict_copy(struct getdns_dict * srcdict, struct getdns_dict ** dstdict) void getdns_dict_item_free(ldns_rbnode_t * node, void *arg) { - (void) arg; struct getdns_dict_item *item = (struct getdns_dict_item *) node; - if (item != NULL) { - if (item->dtype == t_bindata) { - if (item->data.bindata->size > 0) - free(item->data.bindata->data); - free(item->data.bindata); - } else if (item->dtype == t_dict) { - getdns_dict_destroy(item->data.dict); - } else if (item->dtype == t_list) { - getdns_list_destroy(item->data.list); - } + getdns_context_t context = (getdns_context_t)arg; - if (item->node.key != NULL) - free((char *) item->node.key); - free(item); + if (!item) + return; + + switch (item->dtype) { + case t_bindata: + getdns_bindata_destroy(context, item->data.bindata); + break; + case t_dict: + getdns_dict_destroy(item->data.dict); + break; + case t_list: + getdns_list_destroy(item->data.list); + break; + default: + break; } + if (item->node.key) + GETDNS_FREE(context, (void *)item->node.key); + GETDNS_FREE(context, item); } /* getdns_dict_item_free */ /*---------------------------------------- getdns_dict_destroy */ void getdns_dict_destroy(struct getdns_dict *dict) { - if (dict != NULL) { - ldns_traverse_postorder(&(dict->root), getdns_dict_item_free, - NULL); - free(dict); - } + if (!dict) + return; - return; + ldns_traverse_postorder(&(dict->root), + getdns_dict_item_free, dict->context); + GETDNS_FREE(dict->context, dict); } /* getdns_dict_destroy */ /*---------------------------------------- getdns_dict_set_dict */ @@ -321,21 +320,23 @@ getdns_dict_set_dict(struct getdns_dict * dict, char *name, { struct getdns_dict_item *item; struct getdns_dict *newdict; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; + getdns_return_t retval; - if (dict != NULL && name != NULL) { - item = getdns_dict_find(dict, name, true); - if (item != NULL) { - retval = getdns_dict_copy(child_dict, &newdict); - if (retval == GETDNS_RETURN_GOOD) { - item->dtype = t_dict; - item->data.dict = newdict; - } else - item->dtype = t_invalid; - } + if (!dict || !name) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + retval = getdns_dict_copy(child_dict, &newdict); + if (retval != GETDNS_RETURN_GOOD) + return retval; + + item = getdns_dict_find(dict, name, true); + if (!item) { + getdns_dict_destroy(newdict); + return GETDNS_RETURN_NO_SUCH_DICT_NAME; } - - return retval; + item->dtype = t_dict; + item->data.dict = newdict; + return GETDNS_RETURN_GOOD; } /* getdns_dict_set_dict */ /*---------------------------------------- getdns_dict_set_list */ @@ -345,21 +346,23 @@ getdns_dict_set_list(struct getdns_dict * dict, char *name, { struct getdns_dict_item *item; struct getdns_list *newlist; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; + getdns_return_t retval; - if (dict != NULL && name != NULL) { - item = getdns_dict_find(dict, name, true); - if (item != NULL) { - retval = getdns_list_copy(child_list, &newlist); - if (retval == GETDNS_RETURN_GOOD) { - item->dtype = t_list; - item->data.list = newlist; - } else - item->dtype = t_invalid; - } + if (!dict || !name) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + retval = getdns_list_copy(child_list, &newlist); + if (retval != GETDNS_RETURN_GOOD) + return retval; + + item = getdns_dict_find(dict, name, true); + if (!item) { + getdns_list_destroy(newlist); + return GETDNS_RETURN_NO_SUCH_DICT_NAME; } - - return retval; + item->dtype = t_list; + item->data.list = newlist; + return GETDNS_RETURN_GOOD; } /* getdns_dict_set_list */ /*---------------------------------------- getdns_dict_set_bindata */ @@ -368,31 +371,23 @@ getdns_dict_set_bindata(struct getdns_dict * dict, char *name, struct getdns_bindata * child_bindata) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; + struct getdns_bindata *newbindata; - if (dict != NULL && name != NULL && child_bindata != NULL) { - item = getdns_dict_find(dict, name, true); - if (item != NULL) { - item->dtype = t_bindata; - item->data.bindata = - (struct getdns_bindata *) malloc(sizeof(struct - getdns_bindata)); - if (item->data.bindata != NULL) { - item->data.bindata->data = - (void *) malloc(child_bindata->size); - if (item->data.bindata->data != NULL) { - item->data.bindata->size = - child_bindata->size; - memcpy(item->data.bindata->data, - child_bindata->data, - child_bindata->size); - retval = GETDNS_RETURN_GOOD; - } - } - } + if (!dict || !name || !child_bindata) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + newbindata = getdns_bindata_copy(dict->context, child_bindata); + if (!newbindata) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + item = getdns_dict_find(dict, name, true); + if (!item) { + getdns_bindata_destroy(dict->context, newbindata); + return GETDNS_RETURN_NO_SUCH_DICT_NAME; } - - return retval; + item->dtype = t_bindata; + item->data.bindata = newbindata; + return GETDNS_RETURN_GOOD; } /* getdns_dict_set_bindata */ /*---------------------------------------- getdns_dict_set_int */ @@ -401,18 +396,17 @@ getdns_dict_set_int(struct getdns_dict * dict, char *name, uint32_t child_uint32) { struct getdns_dict_item *item; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_DICT_NAME; - if (dict != NULL && name != NULL) { - item = getdns_dict_find(dict, name, true); - if (item != NULL) { - item->dtype = t_int; - item->data.n = child_uint32; - retval = GETDNS_RETURN_GOOD; - } - } + if (!dict || !name) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; - return retval; + item = getdns_dict_find(dict, name, true); + if (!item) + return GETDNS_RETURN_NO_SUCH_DICT_NAME; + + item->dtype = t_int; + item->data.n = child_uint32; + return GETDNS_RETURN_GOOD; } /* getdns_dict_set_int */ /*---------------------------------------- getdns_pp_dict */ @@ -550,9 +544,8 @@ getdns_pp_list(ldns_buffer * buf, size_t indent, struct getdns_list *list) return -1; break; - case t_invalid: default: - if (ldns_buffer_printf(buf, " ") < 0) + if (ldns_buffer_printf(buf, " ") < 0) return -1; } i++; @@ -631,9 +624,8 @@ getdns_pp_dict(ldns_buffer * buf, size_t indent, struct getdns_dict *dict) return -1; break; - case t_invalid: default: - if (ldns_buffer_printf(buf, " ") < 0) + if (ldns_buffer_printf(buf, " ") < 0) return -1; } i++; @@ -660,9 +652,8 @@ getdns_pretty_print_dict(struct getdns_dict *dict) ldns_buffer *buf; char *ret; - if (!dict) { + if (!dict) return NULL; - } buf = ldns_buffer_new(100); if (!buf) diff --git a/src/dict.h b/src/dict.h index e8c80e1c..5f5afae2 100644 --- a/src/dict.h +++ b/src/dict.h @@ -66,6 +66,7 @@ struct getdns_dict_item struct getdns_dict { ldns_rbtree_t root; + getdns_context_t context; }; #endif diff --git a/src/example/example_all_functions.c b/src/example/example_all_functions.c index 8d824a73..c8706acb 100644 --- a/src/example/example_all_functions.c +++ b/src/example/example_all_functions.c @@ -39,10 +39,19 @@ uint8_t *uint8ptrarg; uint16_t *uint16ptrarg; uint32_t *uint32ptrarg; void *arrayarg; -void +void * allocfunctionarg(size_t foo) { UNUSED_PARAM(foo); + return NULL; +} + +void * +reallocfunctionarg(void *foo, size_t bar) +{ + UNUSED_PARAM(foo); + UNUSED_PARAM(bar); + return NULL; } void @@ -80,16 +89,16 @@ main() retregular = getdns_cancel_callback(contextarg, txidarg); retregular = getdns_general_sync(contextarg, - charstararg, uint16arg, dictarg, uint32ptrarg, &dictarg); + charstararg, uint16arg, dictarg, &dictarg); retregular = getdns_address_sync(contextarg, - charstararg, dictarg, uint32ptrarg, &dictarg); + charstararg, dictarg, &dictarg); retregular = getdns_hostname_sync(contextarg, - dictarg, dictarg, uint32ptrarg, &dictarg); + dictarg, dictarg, &dictarg); retregular = getdns_service_sync(contextarg, - charstararg, dictarg, uint32ptrarg, &dictarg); + charstararg, dictarg, &dictarg); getdns_free_sync_request_memory(dictarg); @@ -179,14 +188,8 @@ main() retregular = getdns_context_set_edns_do_bit(contextarg, uint8arg); - retregular = getdns_context_set_memory_allocator(contextarg, - allocfunctionarg); - - retregular = getdns_context_set_memory_deallocator(contextarg, - deallocfunctionarg); - - retregular = getdns_context_set_memory_reallocator(contextarg, - deallocfunctionarg); + retregular = getdns_context_set_memory_functions(contextarg, + allocfunctionarg, reallocfunctionarg, deallocfunctionarg); getdns_list_destroy(listarg); getdns_dict_destroy(dictarg); diff --git a/src/example/example_synchronous.c b/src/example/example_synchronous.c index 4d070ad2..16d0bb45 100644 --- a/src/example/example_synchronous.c +++ b/src/example/example_synchronous.c @@ -110,8 +110,8 @@ main() } /* Clean up */ - getdns_context_destroy(this_context); getdns_free_sync_request_memory(this_response); + getdns_context_destroy(this_context); exit(EXIT_SUCCESS); } /* main */ diff --git a/src/general.c b/src/general.c index 5a7b48de..8f4f1e39 100644 --- a/src/general.c +++ b/src/general.c @@ -340,7 +340,7 @@ getdns_address(getdns_context_t context, { int cleanup_extensions = 0; if (!extensions) { - extensions = getdns_dict_create(); + extensions = getdns_dict_create_with_context(context); cleanup_extensions = 1; } getdns_dict_set_int(extensions, diff --git a/src/getdns/getdns.h b/src/getdns/getdns.h index 96977ed9..67f57ca2 100644 --- a/src/getdns/getdns.h +++ b/src/getdns/getdns.h @@ -169,13 +169,9 @@ struct event_base; #define GETDNS_CONTEXT_CODE_EDNS_DO_BIT_TEXT Change related to getdns_context_set_edns_do_bit #define GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW 614 #define GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW_TEXT Change related to getdns_context_set_dnssec_allowed_skew -#define GETDNS_CONTEXT_CODE_MEMORY_ALLOCATOR 615 -#define GETDNS_CONTEXT_CODE_MEMORY_ALLOCATOR_TEXT Change related to getdns_context_set_memory_allocator -#define GETDNS_CONTEXT_CODE_MEMORY_DEALLOCATOR 616 -#define GETDNS_CONTEXT_CODE_MEMORY_DEALLOCATOR_TEXT Change related to getdns_context_set_memory_deallocator -#define GETDNS_CONTEXT_CODE_MEMORY_REALLOCATOR 617 -#define GETDNS_CONTEXT_CODE_MEMORY_REALLOCATOR_TEXT Change related to getdns_context_set_memory_reallocator -#define GETDNS_CONTEXT_CODE_TIMEOUT 618 +#define GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS 615 +#define GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS_TEXT Change related to getdns_context_set_memory_functions +#define GETDNS_CONTEXT_CODE_TIMEOUT 616 #define GETDNS_CONTEXT_CODE_TIMEOUT_TEXT Change related to getdns_context_set_timeout /** @} */ @@ -376,7 +372,7 @@ typedef uint64_t getdns_transaction_t; */ typedef enum getdns_data_type { - t_dict, t_list, t_int, t_bindata, t_invalid + t_dict, t_list, t_int, t_bindata } getdns_data_type; typedef struct getdns_bindata { @@ -420,7 +416,7 @@ getdns_return_t getdns_list_get_length(struct getdns_list *list, * private function (API users should not be calling this), this uses library * routines to make a copy of the list - would be faster to make the copy directly * caller must ensure that dstlist points to unallocated storage - the address will - * be overwritten by a new list via a call to getdns_list_create() + * be overwritten by a new list via a call to getdns_list_create(context) * @param srclist pointer to list to copy * @param dstlist pointer to pointer to list to receive the copy (will be allocated) * @return GETDNS_RETURN_GOOD on success @@ -562,6 +558,7 @@ getdns_return_t getdns_dict_get_int(struct getdns_dict *this_dict, char *name, * @return pointer to an allocated list, NULL if insufficient memory */ struct getdns_list *getdns_list_create(); +struct getdns_list *getdns_list_create_with_context(getdns_context_t context); /** * free memory allocated to the list (also frees all children of the list) * note that lists and bindata retrieved from the list via the getdns_list_get_* @@ -617,6 +614,7 @@ getdns_return_t getdns_list_set_int(struct getdns_list *list, size_t index, * @return pointer to an allocated dictionary, NULL if insufficient memory */ struct getdns_dict *getdns_dict_create(); +struct getdns_dict *getdns_dict_create_with_context(getdns_context_t context); /** * private function used to make a copy of a dict structure, the caller is responsible @@ -702,6 +700,14 @@ getdns_service(getdns_context_t context, void *userarg, getdns_transaction_t * transaction_id, getdns_callback_t callbackfn); +getdns_return_t getdns_context_create_with_memory_functions( + getdns_context_t * context, + int set_from_os, + void *(*malloc) (size_t), + void *(*realloc) (void *, size_t), + void (*free) (void *) + ); + getdns_return_t getdns_context_create(getdns_context_t * context, int set_from_os); @@ -871,18 +877,10 @@ getdns_return_t getdns_context_set_edns_do_bit(getdns_context_t context, uint8_t value); getdns_return_t -getdns_context_set_memory_allocator(getdns_context_t context, - void (*value) (size_t somesize) - ); - -getdns_return_t -getdns_context_set_memory_deallocator(getdns_context_t context, - void (*value) (void *) - ); - -getdns_return_t -getdns_context_set_memory_reallocator(getdns_context_t context, - void (*value) (void *) +getdns_context_set_memory_functions(getdns_context_t context, + void *(*malloc) (size_t), + void *(*realloc) (void *, size_t), + void (*free) (void *) ); /* Extension - refactor to abstract async evt loop */ diff --git a/src/list.c b/src/list.c index 176f8ade..8e069db4 100644 --- a/src/list.c +++ b/src/list.c @@ -35,20 +35,18 @@ */ #include +#include "context.h" #include "list.h" /*---------------------------------------- getdns_list_get_length */ getdns_return_t getdns_list_get_length(struct getdns_list * list, size_t * answer) { - int retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + if (!list || !answer) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (list != NULL && answer != NULL) { - retval = GETDNS_RETURN_GOOD; - *answer = list->numinuse; - } - - return retval; + *answer = list->numinuse; + return GETDNS_RETURN_GOOD;; } /* getdns_list_get_length */ /*---------------------------------------- getdns_list_get_data_type */ @@ -56,13 +54,11 @@ getdns_return_t getdns_list_get_data_type(struct getdns_list * list, size_t index, getdns_data_type * answer) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + if (!list || index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (list != NULL && index < list->numinuse) { - *answer = list->items[index].dtype; - retval = GETDNS_RETURN_GOOD; - } - return retval; + *answer = list->items[index].dtype; + return GETDNS_RETURN_GOOD; } /* getdns_list_get_data_type */ /*---------------------------------------- getdns_list_get_dict */ @@ -70,18 +66,14 @@ getdns_return_t getdns_list_get_dict(struct getdns_list * list, size_t index, struct getdns_dict ** answer) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + if (!list || index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (list != NULL && index < list->numinuse) { - if (list->items[index].dtype != t_dict) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = list->items[index].data.dict; - retval = GETDNS_RETURN_GOOD; - } - } + if (list->items[index].dtype != t_dict) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; - return retval; + *answer = list->items[index].data.dict; + return GETDNS_RETURN_GOOD; } /* getdns_list_get_dict */ /*---------------------------------------- getdns_list_get_list */ @@ -89,18 +81,15 @@ getdns_return_t getdns_list_get_list(struct getdns_list * list, size_t index, struct getdns_list ** answer) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (list != NULL && index < list->numinuse) { - if (list->items[index].dtype != t_list) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = list->items[index].data.list; - retval = GETDNS_RETURN_GOOD; - } - } + if (!list || index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - return retval; + if (list->items[index].dtype != t_list) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; + + *answer = list->items[index].data.list; + return GETDNS_RETURN_GOOD; } /* getdns_list_get_list */ /*---------------------------------------- getdns_list_get_bindata */ @@ -108,36 +97,28 @@ getdns_return_t getdns_list_get_bindata(struct getdns_list * list, size_t index, struct getdns_bindata ** answer) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + if (!list || index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (list->items[index].dtype != t_bindata) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; - if (list != NULL && index < list->numinuse) { - if (list->items[index].dtype != t_bindata) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = list->items[index].data.bindata; - retval = GETDNS_RETURN_GOOD; - } - } - - return retval; + *answer = list->items[index].data.bindata; + return GETDNS_RETURN_GOOD; } /* getdns_list_get_bindata */ /*---------------------------------------- getdns_list_get_int */ getdns_return_t getdns_list_get_int(struct getdns_list * list, size_t index, uint32_t * answer) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + if (!list || index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (list != NULL && index < list->numinuse) { - if (list->items[index].dtype != t_int) - retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED; - else { - *answer = list->items[index].data.n; - retval = GETDNS_RETURN_GOOD; - } - } + if (list->items[index].dtype != t_int) + return GETDNS_RETURN_WRONG_TYPE_REQUESTED; - return retval; + *answer = list->items[index].data.n; + return GETDNS_RETURN_GOOD; } /* getdns_list_get_int */ /*---------------------------------------- getdns_list_realloc */ @@ -149,31 +130,29 @@ getdns_list_get_int(struct getdns_list * list, size_t index, uint32_t * answer) * @return GETDNS_RETURN_GOOD on success, GETDNS_RETURN_GENERIC_ERROR if out of memory */ getdns_return_t -getdns_list_realloc(struct getdns_list * list) +getdns_list_realloc(struct getdns_list *list) { - getdns_return_t retval = GETDNS_RETURN_GENERIC_ERROR; - int i; struct getdns_list_item *newlist; + int i; - if (list != NULL) { - newlist = - (struct getdns_list_item *) realloc(list->items, - (list->numalloc + - GETDNS_LIST_BLOCKSZ) * - sizeof(struct getdns_list_item)); - if (newlist != NULL) { - list->items = newlist; - for (i = list->numalloc; - i < list->numalloc + GETDNS_LIST_BLOCKSZ; i++) { - list->items[i].inuse = false; - list->items[i].dtype = t_invalid; - } - list->numalloc += GETDNS_LIST_BLOCKSZ; - retval = GETDNS_RETURN_GOOD; - } + if (!list) + return GETDNS_RETURN_GENERIC_ERROR; + + newlist = GETDNS_XREALLOC(list->context, list->items, + struct getdns_list_item, + list->numalloc + GETDNS_LIST_BLOCKSZ); + if (!newlist) + return GETDNS_RETURN_GENERIC_ERROR; + + list->items = newlist; + list->numalloc += GETDNS_LIST_BLOCKSZ; + /* + for (i = list->numalloc - GETDNS_LIST_BLOCKSZ; i < list->numalloc; i++) { + list->items[i].dtype = t_int; + list->items[i].data.n = 0; } - - return retval; + */ + return GETDNS_RETURN_GOOD; } /* getdns_list_realloc */ /*---------------------------------------- getdns_list_copy */ @@ -182,98 +161,82 @@ getdns_list_copy(struct getdns_list * srclist, struct getdns_list ** dstlist) { int i; size_t index; - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + getdns_return_t retval; - if (srclist != NULL && dstlist != NULL) { - *dstlist = getdns_list_create(); - if (*dstlist != NULL) { - retval = GETDNS_RETURN_GOOD; - for (i = 0; i < srclist->numinuse; i++) { - if (getdns_list_add_item(*dstlist, - &index) == GETDNS_RETURN_GOOD) { - (*dstlist)->items[index].inuse = true; - (*dstlist)->items[index].dtype = - srclist->items[i].dtype; + if (!dstlist) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (srclist->items[i].dtype == t_int) - (*dstlist)->items[index].data. - n = - srclist->items[i].data.n; - else if (srclist->items[i].dtype == - t_list) - retval = - getdns_list_copy(srclist-> - items[index].data.list, - &((*dstlist)->items[i]. - data.list)); - else if (srclist->items[i].dtype == - t_bindata) { - (*dstlist)->items[i].data. - bindata = - (struct getdns_bindata *) - malloc(sizeof - (getdns_bindata)); - (*dstlist)->items[i].data. - bindata->size = - srclist->items[i].data. - bindata->size; - (*dstlist)->items[i].data. - bindata->data = (uint8_t *) - malloc(srclist->items[i]. - data.bindata->size); - if ((*dstlist)->items[i].data. - bindata->data != NULL) - memcpy((*dstlist)-> - items[i].data. - bindata->data, - srclist->items[i]. - data.bindata->data, - srclist->items[i]. - data.bindata-> - size); - else - retval = - GETDNS_RETURN_GENERIC_ERROR; - } else if (srclist->items[i].dtype == - t_dict) { - retval = - getdns_dict_copy(srclist-> - items[index].data.dict, - &((*dstlist)->items[i]. - data.dict)); - } - } else { - retval = GETDNS_RETURN_GENERIC_ERROR; - getdns_list_destroy(*dstlist); - *dstlist = NULL; - } - - if (retval != GETDNS_RETURN_GOOD) - break; - } - } else - retval = GETDNS_RETURN_GENERIC_ERROR; + if (!srclist) { + *dstlist = NULL; + return GETDNS_RETURN_GOOD; } + *dstlist = getdns_list_create_with_context(srclist->context); + if (!dstlist) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; - return retval; + for (i = 0; i < srclist->numinuse; i++) { + retval = getdns_list_add_item(*dstlist, &index); + if (retval != GETDNS_RETURN_GOOD) { + getdns_list_destroy(*dstlist); + *dstlist = NULL; + return retval; + } + switch (srclist->items[i].dtype) { + case t_int: + retval = getdns_list_set_int(*dstlist, index, + srclist->items[i].data.n); + break; + + case t_list: + retval =getdns_list_set_list(*dstlist, index, + srclist->items[i].data.list); + break; + + case t_bindata: + retval = getdns_list_set_bindata(*dstlist, index, + srclist->items[i].data.bindata); + break; + + case t_dict: + retval = getdns_list_set_dict(*dstlist, index, + srclist->items[i].data.dict); + break; + } + if (retval != GETDNS_RETURN_GOOD) { + getdns_list_destroy(*dstlist); + *dstlist = NULL; + return retval; + } + } + return GETDNS_RETURN_GOOD; } /* getdns_list_copy */ +/*-------------------------- getdns_list_create_with_context */ +struct getdns_list * +getdns_list_create_with_context(getdns_context_t context) +{ + struct getdns_list *list; + + list = GETDNS_MALLOC(context, struct getdns_list); + if (!list) + return NULL; + + list->context = context; + list->numalloc = 0; + list->numinuse = 0; + list->items = NULL; + if (getdns_list_realloc(list) != GETDNS_RETURN_GOOD) { + getdns_list_destroy(list); + return NULL; + } + return list; +} /* getdns_list_create_with_context */ + /*---------------------------------------- getdns_list_create */ struct getdns_list * getdns_list_create() { - struct getdns_list *list = NULL; - - list = (struct getdns_list *) malloc(sizeof(struct getdns_list)); - if (list != NULL) { - list->numalloc = 0; - list->numinuse = 0; - list->items = NULL; - - getdns_list_realloc(list); - } - - return list; + return getdns_list_create_with_context(NULL); } /* getdns_list_create */ /*---------------------------------------- getdns_list_destroy */ @@ -282,48 +245,51 @@ getdns_list_destroy(struct getdns_list *list) { int i; - if (list != NULL) { - if (list->items != NULL) { - for (i = 0; i < list->numinuse; i++) { - if (list->items[i].dtype == t_list) { - if (list->items[i].dtype == t_list) - getdns_list_destroy(list-> - items[i].data.list); - } else if (list->items[i].dtype == t_bindata) { - if (list->items[i].data.bindata->size > - 0) - free(list->items[i].data. - bindata->data); - free(list->items[i].data.bindata); - } else if (list->items[i].dtype == t_dict) { - getdns_dict_destroy(list->items[i]. - data.dict); - } - } - free(list->items); + if (!list) + return; + + for (i = 0; i < list->numinuse; i++) { + switch (list->items[i].dtype) { + case t_dict: + getdns_dict_destroy(list->items[i].data.dict); + break; + + case t_list: + getdns_list_destroy(list->items[i].data.list); + break; + + case t_bindata: + getdns_bindata_destroy(list->context, + list->items[i].data.bindata); + break; + + default: + break; } - free(list); } + + if (list->items) + GETDNS_FREE(list->context, list->items); + GETDNS_FREE(list->context, list); } /* getdns_list_destroy */ /*---------------------------------------- getdns_list_add_item */ getdns_return_t getdns_list_add_item(struct getdns_list *list, size_t * index) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; - if (list != NULL && index != NULL) { - if (list->numalloc == list->numinuse) - retval = getdns_list_realloc(list); - else - retval = GETDNS_RETURN_GOOD; + getdns_return_t retval; - if (retval == GETDNS_RETURN_GOOD) { - *index = list->numinuse; - list->items[*index].inuse = true; - list->numinuse++; - } + if (!list || !index) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (list->numalloc == list->numinuse) { + retval = getdns_list_realloc(list); + if (retval != GETDNS_RETURN_GOOD) + return retval; } - return retval; + *index = list->numinuse; + list->numinuse++; + return GETDNS_RETURN_GOOD; } /* getdns_list_add_item */ /*---------------------------------------- getdns_list_set_dict */ @@ -331,85 +297,106 @@ getdns_return_t getdns_list_set_dict(struct getdns_list * list, size_t index, struct getdns_dict * child_dict) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + struct getdns_dict *newdict; + getdns_return_t retval; - if (list != NULL && child_dict != NULL) { - if (list->numinuse > index) { - list->items[index].dtype = t_dict; - retval = - getdns_dict_copy(child_dict, - &(list->items[index].data.dict)); - } + if (!list || !child_dict) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + retval = getdns_dict_copy(child_dict, &newdict); + if (retval != GETDNS_RETURN_GOOD) + return retval; + + if (index == list->numinuse) { + retval = getdns_list_add_item(list, &index); + if (retval != GETDNS_RETURN_GOOD) + return retval; } - - return retval; + list->items[index].dtype = t_dict; + list->items[index].data.dict = newdict; + return GETDNS_RETURN_GOOD; } /* getdns_list_set_dict */ -/*---------------------------------------- getdns_set_list */ +/*---------------------------------------- getdns_list_set_list */ getdns_return_t getdns_list_set_list(struct getdns_list * list, size_t index, struct getdns_list * child_list) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + struct getdns_list *newlist; + getdns_return_t retval; - if (list != NULL && child_list != NULL) { - if (list->numinuse > index) { - list->items[index].dtype = t_list; - retval = - getdns_list_copy(child_list, - &(list->items[index].data.list)); - } + if (!list || !child_list) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + retval = getdns_list_copy(child_list, &newlist); + if (retval != GETDNS_RETURN_GOOD) + return retval; + + if (index == list->numinuse) { + retval = getdns_list_add_item(list, &index); + if (retval != GETDNS_RETURN_GOOD) + return retval; } - - return retval; -} /* getdns_set_list */ + list->items[index].dtype = t_list; + list->items[index].data.list = newlist; + return GETDNS_RETURN_GOOD; +} /* getdns_list_set_list */ /*---------------------------------------- getdns_list_set_bindata */ getdns_return_t getdns_list_set_bindata(struct getdns_list * list, size_t index, struct getdns_bindata * child_bindata) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + struct getdns_bindata *newbindata; + getdns_return_t retval; - if (list != NULL && child_bindata != NULL) { - if (list->numinuse > index) { - list->items[index].dtype = t_bindata; - list->items[index].data.bindata = - (struct getdns_bindata *) - malloc(sizeof(struct getdns_bindata)); - if (list->items[index].data.bindata != NULL) { - list->items[index].data.bindata->size = - child_bindata->size; - list->items[index].data.bindata->data = - (uint8_t *) malloc(child_bindata->size * - sizeof(uint8_t)); - memcpy(list->items[index].data.bindata->data, - child_bindata->data, child_bindata->size); - retval = GETDNS_RETURN_GOOD; - } else - retval = GETDNS_RETURN_GENERIC_ERROR; - } + if (!list || !child_bindata) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + newbindata = getdns_bindata_copy(list->context, child_bindata); + if (!newbindata) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (index == list->numinuse) { + retval = getdns_list_add_item(list, &index); + if (retval != GETDNS_RETURN_GOOD) + return retval; } - - return retval; + list->items[index].dtype = t_bindata; + list->items[index].data.bindata = newbindata; + return GETDNS_RETURN_GOOD; } /* getdns_list_set_bindata */ /*---------------------------------------- getdns_list_set_int */ getdns_return_t getdns_list_set_int(struct getdns_list * list, size_t index, - uint32_t child_uint32) + uint32_t child_int) { - getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM; + getdns_return_t retval; - if (list != NULL) { - if (list->numinuse > index) { - list->items[index].dtype = t_int; - list->items[index].data.n = child_uint32; - retval = GETDNS_RETURN_GOOD; - } + if (!list) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (index >= list->numinuse) + return GETDNS_RETURN_NO_SUCH_LIST_ITEM; + + if (index == list->numinuse) { + retval = getdns_list_add_item(list, &index); + if (retval != GETDNS_RETURN_GOOD) + return retval; } - - return retval; + list->items[index].dtype = t_int; + list->items[index].data.n = child_int; + return GETDNS_RETURN_GOOD; } /* getdns_list_set_int */ - /* getdns_list.c */ + diff --git a/src/list.h b/src/list.h index 2da5b541..54cc9233 100644 --- a/src/list.h +++ b/src/list.h @@ -39,7 +39,6 @@ */ struct getdns_list_item { - int inuse; getdns_data_type dtype; union { @@ -64,6 +63,7 @@ struct getdns_list int numalloc; int numinuse; struct getdns_list_item *items; + getdns_context_t context; }; #endif diff --git a/src/request-internal.c b/src/request-internal.c index f0d93062..c7bee15f 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -39,8 +39,8 @@ #include /* useful macros */ -#define gd_malloc(sz) context->memory_allocator(sz) -#define gd_free(ptr) context->memory_deallocator(ptr) +#define gd_malloc(sz) context->malloc(sz) +#define gd_free(ptr) context->free(ptr) void network_req_free(getdns_network_req * net_req) diff --git a/src/sync.c b/src/sync.c index d812bb27..de265b04 100644 --- a/src/sync.c +++ b/src/sync.c @@ -83,7 +83,7 @@ getdns_address_sync(getdns_context_t context, { int cleanup_extensions = 0; if (!extensions) { - extensions = getdns_dict_create(); + extensions = getdns_dict_create_with_context(context); cleanup_extensions = 1; } getdns_dict_set_int(extensions, diff --git a/src/test/tests_dict.c b/src/test/tests_dict.c index 58a0133b..7e2ed8b8 100644 --- a/src/test/tests_dict.c +++ b/src/test/tests_dict.c @@ -271,13 +271,13 @@ tst_getnames(void) printf("t_int, value=%d\n", ansint); break; - case t_invalid: - printf("data type invalid"); - break; - case t_list: printf("NOTIMPLEMENTED"); break; + + default: + printf("data type invalid"); + break; } } @@ -493,7 +493,7 @@ tst_copy(void) dict1 = getdns_dict_create(); getdns_dict_copy(dict1, &dict2); getdns_dict_destroy(dict2); - getdns_dict_copy(NULL, &dict1); + /* getdns_dict_copy(NULL, &dict1); */ tstmsg_case_msg("dict1 populate"); @@ -502,7 +502,7 @@ tst_copy(void) getdns_dict_set_int(dict1, "quz", 62); dictstr = getdns_pretty_print_dict(dict1); - printf("%s", dictstr); + printf("%s\n", dictstr); free(dictstr); tstmsg_case_msg("getdns_dict_copy(dict1, &dict2)"); @@ -510,7 +510,7 @@ tst_copy(void) getdns_dict_copy(dict1, &dict2); dictstr = getdns_pretty_print_dict(dict2); - printf("%s", dictstr); + printf("%s\n", dictstr); free(dictstr); getdns_dict_destroy(dict1); diff --git a/src/test/tests_list.c b/src/test/tests_list.c index 8a6b9b07..9e0dcbd0 100644 --- a/src/test/tests_list.c +++ b/src/test/tests_list.c @@ -104,8 +104,7 @@ tst_bindatasetget(void) new_bindata = (struct getdns_bindata *) malloc(sizeof(struct getdns_bindata)); new_bindata->size = strlen("foobar") + 1; - new_bindata->data = (uint8_t *) strdup("foobar"); - new_bindata->data[strlen("foobar")] = '\0'; + new_bindata->data = (uint8_t *) "foobar"; getdns_list_add_item(list, &index); getdns_list_set_bindata(list, index, new_bindata); @@ -403,6 +402,7 @@ tst_create(void) i, (int) index, retval); tstmsg_case_msg(msg); } + getdns_list_set_int(list, index, 0); } } @@ -413,7 +413,7 @@ tst_create(void) tstmsg_case_msg("getdns_list_get_length()"); retval = getdns_list_get_length(NULL, &index); - sprintf(msg, "NUll, &i, retval = %d", retval); + sprintf(msg, "NUll, %i, retval = %d", (int)index, retval); tstmsg_case_msg(msg); retval = getdns_list_get_length(NULL, NULL); diff --git a/src/test/tests_stub_sync.c b/src/test/tests_stub_sync.c index e0cdca22..b5ac0733 100644 --- a/src/test/tests_stub_sync.c +++ b/src/test/tests_stub_sync.c @@ -57,10 +57,8 @@ main() getdns_context_set_resolution_type(this_context, GETDNS_CONTEXT_STUB); getdns_dict *response = NULL; - uint32_t responseLen = 0; getdns_return_t ret = - getdns_address_sync(this_context, "www.google.com", NULL, - &responseLen, &response); + getdns_address_sync(this_context, "www.google.com", NULL, &response); if (ret != GETDNS_RETURN_GOOD || response == NULL) { fprintf(stderr, "Address sync returned error.\n"); @@ -70,8 +68,7 @@ main() getdns_dict_destroy(response); ret = - getdns_service_sync(this_context, "www.google.com", NULL, - &responseLen, &response); + getdns_service_sync(this_context, "www.google.com", NULL, &response); if (ret != GETDNS_RETURN_GOOD || response == NULL) { fprintf(stderr, "Service sync returned error.\n"); exit(EXIT_FAILURE); diff --git a/src/util-internal.c b/src/util-internal.c index 1d12147f..8667b8f6 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -127,14 +127,15 @@ dict_to_sockaddr(getdns_dict * ns, struct sockaddr_storage * output) } getdns_return_t -sockaddr_to_dict(struct sockaddr_storage * address, getdns_dict ** output) +sockaddr_to_dict(getdns_context_t context, struct sockaddr_storage *address, + getdns_dict ** output) { if (!output || !address) { return GETDNS_RETURN_GENERIC_ERROR; } getdns_bindata addr_data; *output = NULL; - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); if (address->ss_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *) address; getdns_dict_util_set_string(result, GETDNS_STR_ADDRESS_TYPE, @@ -172,11 +173,11 @@ convert_rdf_to_str(ldns_rdf * rdf) /* create the header dict */ static getdns_dict * -create_reply_header_dict(ldns_pkt * reply) +create_reply_header_dict(getdns_context_t context, ldns_pkt * reply) { /* { "id": 23456, "qr": 1, "opcode": 0, ... }, */ int r = 0; - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); if (!result) { return NULL; } @@ -196,13 +197,13 @@ create_reply_header_dict(ldns_pkt * reply) } static getdns_dict * -create_reply_question_dict(ldns_pkt * reply) +create_reply_question_dict(getdns_context_t context, ldns_pkt * reply) { /* { "qname": , "qtype": 1, "qclass": 1 } */ int r = 0; ldns_rr *question = NULL; char *qname; - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); if (!result) { return NULL; } @@ -227,7 +228,7 @@ create_reply_question_dict(ldns_pkt * reply) } static getdns_dict * -create_dict_from_rdf(ldns_rdf * rdf) +create_dict_from_rdf(getdns_context_t context, ldns_rdf * rdf) { /* * create a dict w/ rdata_raw and special fields if needed @@ -239,7 +240,7 @@ create_dict_from_rdf(ldns_rdf * rdf) */ int r = 0; getdns_bindata rbin = { ldns_rdf_size(rdf), ldns_rdf_data(rdf) }; - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); r |= getdns_dict_set_bindata(result, GETDNS_STR_KEY_RDATA_RAW, &rbin); if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_AAAA) { r |= getdns_dict_set_bindata(result, GETDNS_STR_KEY_V6_ADDR, @@ -256,7 +257,7 @@ create_dict_from_rdf(ldns_rdf * rdf) } static getdns_dict * -create_dict_from_rr(ldns_rr * rr) +create_dict_from_rr(getdns_context_t context, ldns_rr * rr) { /* * { @@ -273,7 +274,7 @@ create_dict_from_rr(ldns_rr * rr) */ int r = 0; char *name = NULL; - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); size_t rd_count = ldns_rr_rd_count(rr); ldns_rdf *owner = ldns_rr_owner(rr); r |= getdns_dict_set_int(result, GETDNS_STR_KEY_TYPE, @@ -293,7 +294,8 @@ create_dict_from_rr(ldns_rr * rr) } /* create rdatas */ if (rd_count >= 1) { - getdns_dict *rdata = create_dict_from_rdf(ldns_rr_rdf(rr, 0)); + getdns_dict *rdata = create_dict_from_rdf(context, + ldns_rr_rdf(rr, 0)); r |= getdns_dict_set_dict(result, GETDNS_STR_KEY_RDATA, rdata); getdns_dict_destroy(rdata); } @@ -310,15 +312,15 @@ create_dict_from_rr(ldns_rr * rr) returns a list of objects where each object is a result from create_dict_from_rr */ static getdns_list * -create_list_from_rr_list(ldns_rr_list * rr_list) +create_list_from_rr_list(getdns_context_t context, ldns_rr_list * rr_list) { size_t i = 0; size_t idx = 0; int r = 0; - getdns_list *result = getdns_list_create(); + getdns_list *result = getdns_list_create_with_context(context); for (i = 0; i < ldns_rr_list_rr_count(rr_list); ++i) { ldns_rr *rr = ldns_rr_list_rr(rr_list, i); - getdns_dict *rrdict = create_dict_from_rr(rr); + getdns_dict *rrdict = create_dict_from_rr(context, rr); r |= getdns_list_add_item(result, &idx); r |= getdns_list_set_dict(result, idx, rrdict); getdns_dict_destroy(rrdict); @@ -357,7 +359,8 @@ add_only_addresses(getdns_list * addrs, ldns_rr_list * rr_list) } static getdns_dict * -create_reply_dict(getdns_network_req * req, getdns_list * just_addrs) +create_reply_dict(getdns_context_t context, getdns_network_req * req, + getdns_list * just_addrs) { /* turn a packet into this glorious structure * @@ -406,23 +409,23 @@ create_reply_dict(getdns_network_req * req, getdns_list * just_addrs) getdns_list *sublist = NULL; char *name = NULL; - getdns_dict *result = getdns_dict_create(); + getdns_dict *result = getdns_dict_create_with_context(context); if (!result) { return NULL; } /* header */ - subdict = create_reply_header_dict(reply); + subdict = create_reply_header_dict(context, reply); r |= getdns_dict_set_dict(result, GETDNS_STR_KEY_HEADER, subdict); getdns_dict_destroy(subdict); /* question */ - subdict = create_reply_question_dict(reply); + subdict = create_reply_question_dict(context, reply); r |= getdns_dict_set_dict(result, GETDNS_STR_KEY_QUESTION, subdict); getdns_dict_destroy(subdict); /* answers */ rr_list = ldns_pkt_answer(reply); - sublist = create_list_from_rr_list(rr_list); + sublist = create_list_from_rr_list(context, rr_list); r |= getdns_dict_set_list(result, GETDNS_STR_KEY_ANSWER, sublist); getdns_list_destroy(sublist); if ((req->request_type == GETDNS_RRTYPE_A || @@ -434,13 +437,13 @@ create_reply_dict(getdns_network_req * req, getdns_list * just_addrs) /* authority */ rr_list = ldns_pkt_authority(reply); - sublist = create_list_from_rr_list(rr_list); + sublist = create_list_from_rr_list(context, rr_list); r |= getdns_dict_set_list(result, GETDNS_STR_KEY_AUTHORITY, sublist); getdns_list_destroy(sublist); /* additional */ rr_list = ldns_pkt_additional(reply); - sublist = create_list_from_rr_list(rr_list); + sublist = create_list_from_rr_list(context, rr_list); r |= getdns_dict_set_list(result, GETDNS_STR_KEY_ADDITIONAL, sublist); getdns_list_destroy(sublist); @@ -478,10 +481,12 @@ get_canonical_name(const char *name) getdns_dict * create_getdns_response(struct getdns_dns_req * completed_request) { - getdns_dict *result = getdns_dict_create(); - getdns_list *replies_full = getdns_list_create(); + getdns_dict *result = getdns_dict_create_with_context(completed_request->context); + getdns_list *replies_full = getdns_list_create_with_context( + completed_request->context); getdns_list *just_addrs = NULL; - getdns_list *replies_tree = getdns_list_create(); + getdns_list *replies_tree = getdns_list_create_with_context( + completed_request->context); getdns_network_req *netreq = completed_request->first_req; char *canonical_name = NULL; @@ -490,7 +495,8 @@ create_getdns_response(struct getdns_dns_req * completed_request) if (completed_request->first_req->request_class == GETDNS_RRTYPE_A || completed_request->first_req->request_class == GETDNS_RRTYPE_AAAA) { - just_addrs = getdns_list_create(); + just_addrs = getdns_list_create_with_context( + completed_request->context); } r |= getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS, @@ -511,7 +517,8 @@ create_getdns_response(struct getdns_dns_req * completed_request) ldns_pkt2wire(&(full_data.data), pkt, &(full_data.size)); size_t idx = 0; /* reply tree */ - getdns_dict *reply = create_reply_dict(netreq, just_addrs); + getdns_dict *reply = create_reply_dict( + completed_request->context, netreq, just_addrs); r |= getdns_list_add_item(replies_tree, &idx); r |= getdns_list_set_dict(replies_tree, idx, reply); getdns_dict_destroy(reply); diff --git a/src/util-internal.h b/src/util-internal.h index 5fac211f..94214c61 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -46,8 +46,8 @@ struct getdns_dns_req; /* convert an ip address dict to a sock storage */ getdns_return_t dict_to_sockaddr(getdns_dict * ns, struct sockaddr_storage *output); -getdns_return_t sockaddr_to_dict(struct sockaddr_storage *sockaddr, - getdns_dict ** output); +getdns_return_t sockaddr_to_dict(getdns_context_t context, + struct sockaddr_storage *sockaddr, getdns_dict ** output); getdns_dict *create_getdns_response(struct getdns_dns_req *completed_request);