diff --git a/src/Makefile.in b/src/Makefile.in index b17cf7a3..574a08bf 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -62,7 +62,7 @@ srcdir = @srcdir@ VPATH = @srcdir@ CC=@CC@ -CFLAGS=@CFLAGS@ -Wall -I$(srcdir) -I. -std=c99 +CFLAGS=@CFLAGS@ -Wall -I$(srcdir) -I. -std=c99 -D_POSIX_C_SOURCE=200112L LDFLAGS=@LDFLAGS@ @LIBS@ EXTENSION_LIBEVENT_LIB=@EXTENSION_LIBEVENT_LIB@ diff --git a/src/context.c b/src/context.c index 1ac934d8..74bb545d 100755 --- a/src/context.c +++ b/src/context.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "config.h" #include "context.h" @@ -63,10 +64,6 @@ getdns_return_t create_local_hosts(struct getdns_context *context); getdns_return_t destroy_local_hosts(struct getdns_context *context); static struct getdns_list *create_default_root_servers(void); static getdns_return_t add_ip_str(struct getdns_dict *); -static struct getdns_dict *create_ipaddr_dict_from_rdf(struct getdns_context *, - ldns_rdf *); -static struct getdns_list *create_from_ldns_list(struct getdns_context *, - ldns_rdf **, size_t); static getdns_return_t set_os_defaults(struct getdns_context *); static int transaction_id_cmp(const void *, const void *); static int timeout_cmp(const void *, const void *); @@ -92,7 +89,7 @@ static getdns_return_t set_ldns_dns_transport(struct getdns_context* context, static void set_ldns_edns_maximum_udp_payload_size(struct getdns_context*, uint16_t); static getdns_return_t set_ldns_nameservers(struct getdns_context*, - struct getdns_list * upstreams); + getdns_upstreams *upstreams); /* Stuff to make it compile pedantically */ #define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code; @@ -295,65 +292,53 @@ filechg_check(struct getdns_context *context, struct filechg *fchg) return fchg->changes; } /* filechg */ -static struct getdns_dict * -create_ipaddr_dict_from_rdf(struct getdns_context *context, ldns_rdf * rdf) +static size_t +upstream_addr_len(struct getdns_upstream *upstream) { - ldns_rdf_type rt = ldns_rdf_get_type(rdf); - size_t sz = ldns_rdf_size(rdf); - struct 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, - GETDNS_STR_IPV4); - } else { - getdns_dict_util_set_string(result, GETDNS_STR_ADDRESS_TYPE, - GETDNS_STR_IPV6); - } - /* set data */ - struct getdns_bindata data_bin = { sz, ldns_rdf_data(rdf) }; - getdns_dict_set_bindata(result, GETDNS_STR_ADDRESS_DATA, &data_bin); - add_ip_str(result); - return result; + return upstream->addr.ss_family == AF_INET ? 4 : 16; } -static struct getdns_list * -create_from_ldns_list(struct getdns_context *context, ldns_rdf ** ldns_list, - size_t count) +static uint8_t* +upstream_addr(struct getdns_upstream *upstream) { - size_t i = 0; - size_t idx = 0; - 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)) { - case LDNS_RDF_TYPE_A: - case LDNS_RDF_TYPE_AAAA: - { - struct getdns_dict *ipaddr = - create_ipaddr_dict_from_rdf(context, rdf); - getdns_list_add_item(result, &idx); - getdns_list_set_dict(result, idx, ipaddr); - getdns_dict_destroy(ipaddr); - } - break; + return upstream->addr.ss_family == AF_INET + ? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr + : (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr; +} - case LDNS_RDF_TYPE_DNAME: - { - struct getdns_bindata item; - char *srch = ldns_rdf2str(rdf); - item.size = strlen(srch) + 1; - item.data = (uint8_t *) srch; - getdns_list_add_item(result, &idx); - getdns_list_set_bindata(result, idx, &item); - free(srch); - } - break; +static in_port_t +upstream_port(struct getdns_upstream *upstream) +{ + return ntohs(upstream->addr.ss_family == AF_INET + ? ((struct sockaddr_in *)&upstream->addr)->sin_port + : ((struct sockaddr_in6*)&upstream->addr)->sin6_port); +} - default: - break; - } - } - return result; +static uint32_t * +upstream_scope_id(struct getdns_upstream *upstream) +{ + return upstream->addr.ss_family == AF_INET ? NULL + : (upstream_addr(upstream)[0] == 0xFE && + (upstream_addr(upstream)[1] & 0xC0) == 0x80 ? + &((struct sockaddr_in6*)&upstream->addr)->sin6_scope_id : NULL); +} + +void +upstream_ntop_buf(struct getdns_upstream *upstream, char *buf, size_t len) +{ + /* Also possible but prints scope_id by name (nor parsed by unbound) + * + * getnameinfo((struct sockaddr *)&upstream->addr, upstream->addr_len, + * buf, len, NULL, 0, NI_NUMERICHOST) + */ + (void) inet_ntop(upstream->addr.ss_family, upstream_addr(upstream), + buf, len); + if (upstream_scope_id(upstream)) + (void) snprintf(buf + strlen(buf), len - strlen(buf), + "%%%d", (int)*upstream_scope_id(upstream)); + if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0) + (void) snprintf(buf + strlen(buf), len - strlen(buf), + "@%d", (int)upstream_port(upstream)); } /*---------------------------------------- set_os_defaults @@ -363,16 +348,20 @@ create_from_ldns_list(struct getdns_context *context, ldns_rdf ** ldns_list, static getdns_return_t set_os_defaults(struct getdns_context *context) { - ldns_resolver *lr = NULL; - ldns_rdf **rdf_list; - size_t rdf_list_sz; + FILE *in; + char line[1024], domain[1024]; + char *parse, *token, prev_ch; + size_t upstreams_limit = 10, length; + struct getdns_bindata bindata; + struct addrinfo hints; + struct addrinfo *result; + struct getdns_upstream *upstream; + struct getdns_dict *addr; + int s; - if (ldns_resolver_new_frm_file(&lr, NULL) != LDNS_STATUS_OK) - return GETDNS_RETURN_GENERIC_ERROR; - - if(context->fchg_resolvconf == NULL) - { - context->fchg_resolvconf = GETDNS_MALLOC(context->my_mf, struct filechg); + if(context->fchg_resolvconf == NULL) { + context->fchg_resolvconf = + GETDNS_MALLOC(context->my_mf, struct filechg); if(context->fchg_resolvconf == NULL) return GETDNS_RETURN_MEMORY_ERROR; context->fchg_resolvconf->fn = "/etc/resolv.conf"; @@ -382,22 +371,130 @@ set_os_defaults(struct getdns_context *context) } filechg_check(context, context->fchg_resolvconf); - rdf_list = ldns_resolver_nameservers(lr); - rdf_list_sz = ldns_resolver_nameserver_count(lr); - if (rdf_list_sz > 0) { - context->upstream_list = - create_from_ldns_list(context, rdf_list, rdf_list_sz); - } + context->upstream_list = getdns_list_create_with_context(context); + context->suffix = getdns_list_create_with_context(context); + context->upstreams = (void *) GETDNS_XMALLOC(context->mf, char, + sizeof(getdns_upstreams) + + sizeof(struct getdns_upstream) * upstreams_limit); + context->upstreams->mf = context->mf; + context->upstreams->referenced = 1; + context->upstreams->count = 0; - 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(context, rdf_list, - rdf_list_sz); - } - ldns_resolver_deep_free(lr); + in = fopen(context->fchg_resolvconf->fn, "r"); + if (!in) + return GETDNS_RETURN_GOOD; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = 0; /* Datagram socket */ + hints.ai_flags = AI_NUMERICHOST; /* No reverse name lookups */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; - return GETDNS_RETURN_GOOD; + *domain = 0; + while (fgets(line, (int)sizeof(line), in)) { + line[sizeof(line)-1] = 0; + /* parse = line + strspn(line, " \t"); */ /* No leading whitespace */ + parse = line; + + if (strncmp(parse, "domain", 6) == 0) { + parse += 6; + parse += strspn(parse, " \t"); + if (*parse == 0 || *parse == '#') continue; + token = parse + strcspn(parse, " \t\r\n"); + *token = 0; + + (void) strcpy(domain, parse); + + } else if (strncmp(parse, "search", 6) == 0) { + parse += 6; + do { + parse += strspn(parse, " \t"); + if (*parse == '#' || *parse == '\n') break; + token = parse + strcspn(parse, " \t\r\n"); + prev_ch = *token; + *token = 0; + + bindata.data = (uint8_t *)parse; + bindata.size = strlen(parse) + 1; + (void) getdns_list_get_length( + context->suffix, &length); + (void) getdns_list_set_bindata( + context->suffix, length, &bindata); + + *token = prev_ch; + parse = token; + } while (*parse); + + } else if (strncmp(parse, "nameserver", 10) != 0) + continue; + + parse += 10; + parse += strspn(parse, " \t"); + if (*parse == 0 || *parse == '#') continue; + token = parse + strcspn(parse, " \t\r\n"); + *token = 0; + + if ((s = getaddrinfo(parse, "53", &hints, &result))) + continue; + + /* No lookups, so maximal 1 result */ + if (! result) continue; + + /* Grow array when needed */ + if (context->upstreams->count == upstreams_limit) { + upstreams_limit *= 2; + context->upstreams = (void *) GETDNS_XREALLOC( + context->mf, context->upstreams, char, + sizeof(getdns_upstreams) + + sizeof(struct getdns_upstream) * upstreams_limit); + } + + upstream = &context->upstreams-> + upstreams[context->upstreams->count++]; + upstream->rtt = 1; + upstream->tcp_fd = -1; + upstream->addr_len = result->ai_addrlen; + (void) memcpy(&upstream->addr, + result->ai_addr, result->ai_addrlen); + freeaddrinfo(result); + + /***************************************************** + * Add to context->upstream_list too. + * TODO: remove this after async stub is finished. + */ + addr = getdns_dict_create_with_context(context); + bindata.size = upstream_addr_len(upstream); + bindata.data = upstream_addr(upstream); + (void) getdns_dict_set_int( + addr, "port", upstream_port(upstream)); + (void) getdns_dict_set_bindata(addr, "address_data", &bindata); + if ((parse = strchr(parse, '%'))) { + parse += 1; + bindata.size = strlen(parse) + 1; + bindata.data = (uint8_t *)parse; + (void) getdns_dict_set_bindata( + addr, "scope_id", &bindata); + } + (void) getdns_list_get_length(context->upstream_list, &length); + (void) getdns_list_set_dict( + context->upstream_list, length, addr); + + getdns_dict_destroy(addr); + /* + *****************************************************/ + } + fclose(in); + + (void) getdns_list_get_length(context->suffix, &length); + if (length == 0 && *domain != 0) { + bindata.data = (uint8_t *)domain; + bindata.size = strlen(domain) + 1; + (void) getdns_list_set_bindata(context->suffix, 0, &bindata); + } + return GETDNS_RETURN_GOOD; } /* set_os_defaults */ /* compare of transaction ids in DESCENDING order @@ -696,6 +793,9 @@ getdns_context_destroy(struct getdns_context *context) GETDNS_FREE(context->my_mf, context->local_hosts); } + if (--context->upstreams->referenced == 0) + GETDNS_FREE(context->upstreams->mf, context->upstreams); + GETDNS_FREE(context->my_mf, context); } /* getdns_context_destroy */ @@ -788,7 +888,7 @@ rebuild_ldns_res(struct getdns_context* context) { return result; /* We need to set up the upstream recursive servers from the context */ - result = set_ldns_nameservers(context, context->upstream_list); + result = set_ldns_nameservers(context, context->upstreams); if (result != GETDNS_RETURN_GOOD) return result; @@ -1406,35 +1506,20 @@ getdns_cancel_callback(struct getdns_context *context, } /* getdns_cancel_callback */ static getdns_return_t -ub_setup_stub(struct ub_ctx *ctx, struct getdns_list * upstreams) +ub_setup_stub(struct ub_ctx *ctx, getdns_upstreams *upstreams) { + getdns_return_t r = GETDNS_RETURN_GOOD; size_t i; - size_t count; - struct getdns_dict *dict; - struct getdns_bindata *address_string; - getdns_return_t r; + struct getdns_upstream *upstream; + char addr[1024]; - r = getdns_list_get_length(upstreams, &count); - if (r != GETDNS_RETURN_GOOD) - return r; - - if (count == 0) - return GETDNS_RETURN_BAD_CONTEXT; - - /* reset forwarding servers */ (void) ub_ctx_set_fwd(ctx, NULL); - for (i = 0; i < count; ++i) { - r = getdns_list_get_dict(upstreams, i, &dict); - if (r != GETDNS_RETURN_GOOD) - break; - - r = getdns_dict_get_bindata(dict, GETDNS_STR_ADDRESS_STRING, - &address_string); - if (r != GETDNS_RETURN_GOOD) - break; - - (void) ub_ctx_set_fwd(ctx, (char *)address_string->data); + for (i = 0; i < upstreams->count; i++) { + upstream = &upstreams->upstreams[i]; + upstream_ntop_buf(upstream, addr, 1024); + ub_ctx_set_fwd(ctx, addr); } + /* Allow lookups of: */ /* - localhost */ @@ -1496,41 +1581,24 @@ ub_setup_stub(struct ub_ctx *ctx, struct getdns_list * upstreams) static getdns_return_t set_ldns_nameservers(struct getdns_context *context, - struct getdns_list * upstreams) + getdns_upstreams *upstreams) { + getdns_return_t r = GETDNS_RETURN_GOOD; size_t i; - size_t count; - struct getdns_dict *dict; - struct getdns_bindata *address_string; - char *address_type = NULL; - ldns_rdf* ns_rdf = NULL; - getdns_return_t r; + struct getdns_upstream *upstream; + ldns_rdf *pop, *ns_rdf; + uint16_t port = 53; - r = getdns_list_get_length(upstreams, &count); - if (r != GETDNS_RETURN_GOOD) - return r; - - if (count == 0 || context->ldns_res == NULL) + if (context->ldns_res == NULL) return GETDNS_RETURN_BAD_CONTEXT; /* remove current list of nameservers from resolver */ - ldns_rdf *pop; while((pop = ldns_resolver_pop_nameserver(context->ldns_res))) { ldns_rdf_deep_free(pop); } - for (i = 0; i < count; ++i) { - r = getdns_list_get_dict(upstreams, i, &dict); - if (r != GETDNS_RETURN_GOOD) - break; - r = getdns_dict_get_bindata(dict, GETDNS_STR_ADDRESS_STRING, - &address_string); - if (r != GETDNS_RETURN_GOOD) - break; - r = getdns_dict_util_get_string(dict, GETDNS_STR_ADDRESS_TYPE, - &address_type); - if (r != GETDNS_RETURN_GOOD) - break; + for (i = 0; i < upstreams->count; i++) { + upstream = &upstreams->upstreams[i]; /* TODO: PROBLEM! The upstream list is implemented such that there is both * an IP address and a port in the bindata for each nameserver. Unbound @@ -1540,42 +1608,16 @@ set_ldns_nameservers(struct getdns_context *context, * nameserver in the list. Wrong, but this will support the test scripts * in the short term which rely on being able to set a port for a single * nameserver. */ - char *address_char = (char *)address_string->data; - char *port_char = NULL; - char *at_symbol_position = strchr(address_char, '@'); - if (at_symbol_position != NULL) { - int ip_length = at_symbol_position - address_char; - int port_length = strlen(address_char) - ip_length; - address_char = (char*) malloc(ip_length + 1); - memcpy(address_char, (char *)address_string->data, ip_length); - address_char[ip_length] = '\0'; - port_char = (char*) malloc(port_length); - memcpy(port_char, (char *)(address_string->data + ip_length + 1), port_length); - port_char[port_length] = '\0'; - } - - if (strncmp(GETDNS_STR_IPV4, address_type, - strlen(GETDNS_STR_IPV4)) == 0) { - ns_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, - address_char); - } else if (strncmp(GETDNS_STR_IPV6, address_type, - strlen(GETDNS_STR_IPV6)) == 0) { - ns_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, - address_char); - } + + ns_rdf = ldns_sockaddr_storage2rdf(&upstream->addr, &port); if (ns_rdf == NULL) return GETDNS_RETURN_GENERIC_ERROR; ldns_resolver_push_nameserver(context->ldns_res, ns_rdf); ldns_rdf_deep_free(ns_rdf); - - if (at_symbol_position != NULL) { - ldns_resolver_set_port(context->ldns_res, atoi(port_char)); - free(port_char); - free(address_char); - } } - return GETDNS_RETURN_GOOD; + ldns_resolver_set_port(context->ldns_res, port); + return r; } static getdns_return_t @@ -1592,7 +1634,7 @@ priv_getdns_ns_dns_setup(struct getdns_context *context) /* We get away with just setting up ldns here here because sync mode * always hits this method because at the moment all sync calls use DNS * namespace */ - r = ub_setup_stub(context->unbound_ctx, context->upstream_list); + r = ub_setup_stub(context->unbound_ctx, context->upstreams); if (r != GETDNS_RETURN_GOOD) return r; return rebuild_ldns_res(context); diff --git a/src/context.h b/src/context.h index ad7f6597..3b121947 100755 --- a/src/context.h +++ b/src/context.h @@ -66,8 +66,21 @@ struct filechg { struct stat *prevstat; }; -struct getdns_context { +struct getdns_upstream { + socklen_t addr_len; + struct sockaddr_storage addr; + int tcp_fd; + int rtt; +}; +typedef struct getdns_upstreams { + struct mem_funcs mf; + size_t referenced; + size_t count; + struct getdns_upstream upstreams[]; +} getdns_upstreams; + +struct getdns_context { /* Context values */ getdns_resolution_t resolution_type; getdns_namespace_t *namespaces; @@ -79,19 +92,19 @@ struct getdns_context { struct getdns_list *suffix; struct getdns_list *dnssec_trust_anchors; struct getdns_list *upstream_list; - getdns_transport_t dns_transport; - uint16_t limit_outstanding_queries; - uint32_t dnssec_allowed_skew; + getdns_transport_t dns_transport; + uint16_t limit_outstanding_queries; + uint32_t dnssec_allowed_skew; uint8_t edns_extended_rcode; uint8_t edns_version; uint8_t edns_do_bit; - uint16_t edns_maximum_udp_payload_size; + uint16_t edns_maximum_udp_payload_size; getdns_update_callback update_callback; - int processing; - int destroying; + int processing; + int destroying; struct mem_funcs mf; struct mem_funcs my_mf; @@ -102,7 +115,7 @@ struct getdns_context { /* A tree to hold local host information*/ struct ldns_rbtree_t *local_hosts; int has_ta; /* No DNSSEC without trust anchor */ - int return_dnssec_status; + int return_dnssec_status; /* which resolution type the contexts are configured for * 0 means nothing set @@ -114,25 +127,25 @@ struct getdns_context { */ struct ldns_rbtree_t *outbound_requests; - /* - * Event loop extension functions - * These structs are static and should never be freed - * since they are just a collection of function pointers - */ - getdns_eventloop_extension* extension; - /* - * Extension data that will be freed by the functions - * in the extension struct - */ - void* extension_data; + /* + * Event loop extension functions + * These structs are static and should never be freed + * since they are just a collection of function pointers + */ + getdns_eventloop_extension* extension; + /* + * Extension data that will be freed by the functions + * in the extension struct + */ + void* extension_data; - /* - * Timeout info one tree to manage timeout data - * keyed by transaction id. Second to manage by - * timeout time (ascending) - */ - struct ldns_rbtree_t *timeouts_by_id; - struct ldns_rbtree_t *timeouts_by_time; + /* + * Timeout info one tree to manage timeout data + * keyed by transaction id. Second to manage by + * timeout time (ascending) + */ + struct ldns_rbtree_t *timeouts_by_id; + struct ldns_rbtree_t *timeouts_by_time; /* * state data used to detect changes to the system config files @@ -140,6 +153,7 @@ struct getdns_context { struct filechg *fchg_resolvconf; struct filechg *fchg_hosts; + getdns_upstreams *upstreams; }; /* getdns_context */ /** internal functions **/ diff --git a/src/stub.c b/src/stub.c index ac28154c..67a86ad1 100644 --- a/src/stub.c +++ b/src/stub.c @@ -47,11 +47,13 @@ typedef struct stub_resolver { struct getdns_event_base *base; - getdns_context *context; - const char *name; - uint16_t request_type; - getdns_dict *extensions; - gldns_buffer *response; + getdns_context *context; + getdns_upstreams *upstreams; + const char *name; + uint16_t request_type; + getdns_dict *extensions; + gldns_buffer *response; + size_t request_pkt_len; uint8_t *request_pkt; @@ -74,9 +76,6 @@ cb_udp_request(int fd, short bits, void *arg) gldns_buffer_remaining(resolver->response), 0, NULL, NULL); -#if STUBDEBUG - fprintf(stderr, "read: %d\n", read); -#endif if (read == -1 || read == 0) return; @@ -91,69 +90,37 @@ cb_udp_request(int fd, short bits, void *arg) free(str); } while(0); #endif - (void) getdns_event_base_loopexit(resolver->base, NULL); + + if (--resolver->upstreams->referenced == 0) + GETDNS_FREE(resolver->upstreams->mf, resolver->upstreams); + GETDNS_FREE(resolver->context->mf, resolver); } static getdns_return_t query_ns(stub_resolver *resolver) { - size_t n_upstreams; - getdns_return_t r; - getdns_dict *upstream; - getdns_bindata *address_data; - uint32_t port = 53; - - struct sockaddr_in dst4; - struct sockaddr_in6 dst6; + struct getdns_upstream *upstream; ssize_t sent; - struct getdns_event *ev; assert(resolver); - r = getdns_list_get_length( - resolver->context->upstream_list, &n_upstreams); - if (r) return r; - - r = getdns_list_get_dict( - resolver->context->upstream_list, resolver->ns_index, &upstream); - if (r) return r; - - r = getdns_dict_get_bindata(upstream, "address_data", &address_data); - if (r) return r; - - (void) getdns_dict_get_int(upstream, "port", &port); - -#if STUBDEBUG - fprintf(stderr, "upstream: %s\n", getdns_pretty_print_dict(upstream)); -#endif + if (resolver->ns_index >= resolver->upstreams->count) + return GETDNS_RETURN_GENERIC_ERROR; + upstream = &resolver->upstreams->upstreams[resolver->ns_index]; /* TODO: Try next upstream if something is not right with this one * Also later on... for example when socket returns -1 */ /* TODO: Check how to connect first (udp or tcp) */ - resolver->sockfd = socket(address_data->size == 4 ? AF_INET : AF_INET6, - SOCK_DGRAM, IPPROTO_UDP); - if (address_data->size == 4) { - memset(&dst4, 0, sizeof(struct sockaddr_in)); - dst4.sin_family = AF_INET; - dst4.sin_port = (in_port_t)htons((uint16_t)port); - memcpy(&dst4.sin_addr, address_data->data, 4); - sent = sendto(resolver->sockfd, - resolver->request_pkt, resolver->request_pkt_len, 0, - (struct sockaddr *)&dst4, sizeof(dst4)); - } else { - memset(&dst6, 0, sizeof(struct sockaddr_in6)); - dst6.sin6_family = AF_INET; - dst6.sin6_port = (in_port_t)htons((uint16_t)port); - memcpy(&dst6.sin6_addr, address_data->data, 16); - sent = sendto(resolver->sockfd, - resolver->request_pkt, resolver->request_pkt_len, 0, - (struct sockaddr *)&dst6, sizeof(dst6)); - } + resolver->sockfd = socket(upstream->addr.ss_family, SOCK_DGRAM, + IPPROTO_UDP); + sent = sendto(resolver->sockfd, + resolver->request_pkt, resolver->request_pkt_len, 0, + (struct sockaddr *)&upstream->addr, upstream->addr_len); if (sent == -1 || sent != resolver->request_pkt_len) return GETDNS_RETURN_GENERIC_ERROR; @@ -179,6 +146,8 @@ getdns_stub_dns_query_async(struct getdns_event_base *base, resolver->base = base; resolver->context = context; + resolver->upstreams = context->upstreams; + resolver->upstreams->referenced++; resolver->name = name; resolver->request_type = request_type; resolver->extensions = extensions; @@ -199,8 +168,11 @@ getdns_stub_dns_query_async(struct getdns_event_base *base, #endif resolver->ns_index = 0; r = query_ns(resolver); - if (r) + if (r) { + if (--resolver->upstreams->referenced == 0) + GETDNS_FREE(resolver->upstreams->mf, resolver->upstreams); GETDNS_FREE(context->mf, resolver); + } return r; } diff --git a/src/sync.c b/src/sync.c index 9342489e..81d04e1e 100755 --- a/src/sync.c +++ b/src/sync.c @@ -82,10 +82,6 @@ static getdns_return_t submit_request_sync_rec( static getdns_return_t submit_request_sync_stub( getdns_dns_req* req, uint64_t *timeout) { - uint8_t *pkt; - size_t pkt_len; - char *str; - ldns_rdf *qname; getdns_network_req *netreq = req->first_req; uint16_t qflags = 0;