2013-08-15 11:33:05 -05:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* /brief getdns contect management functions
|
|
|
|
*
|
|
|
|
* This is the meat of the API
|
|
|
|
* Originally taken from the getdns API description pseudo implementation.
|
|
|
|
*
|
|
|
|
*/
|
2013-11-04 17:37:54 -06:00
|
|
|
/*
|
2014-02-25 07:12:33 -06:00
|
|
|
* Copyright (c) 2013, NLnet Labs, Verisign, Inc.
|
2013-11-04 17:37:54 -06:00
|
|
|
* All rights reserved.
|
2014-01-21 14:31:22 -06:00
|
|
|
*
|
2013-11-04 17:37:54 -06:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2014-02-25 07:23:19 -06:00
|
|
|
* * Neither the names of the copyright holders nor the
|
2013-11-04 17:37:54 -06:00
|
|
|
* names of its contributors may be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
2013-08-15 11:33:05 -05:00
|
|
|
*
|
2013-11-04 17:37:54 -06:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
|
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2013-08-15 11:33:05 -05:00
|
|
|
*/
|
|
|
|
|
2013-11-30 06:53:57 -06:00
|
|
|
#include "config.h"
|
2013-08-15 11:33:05 -05:00
|
|
|
#include "types-internal.h"
|
|
|
|
#include "util-internal.h"
|
2014-10-07 08:52:41 -05:00
|
|
|
#include "gldns/rrdef.h"
|
2013-08-15 11:33:05 -05:00
|
|
|
|
2015-01-29 05:30:40 -06:00
|
|
|
static void
|
|
|
|
network_req_cleanup(getdns_network_req *net_req)
|
2013-11-05 14:03:44 -06:00
|
|
|
{
|
2015-01-29 05:30:40 -06:00
|
|
|
assert(net_req);
|
|
|
|
|
|
|
|
if (net_req->result)
|
2013-11-05 14:03:44 -06:00
|
|
|
ldns_pkt_free(net_req->result);
|
2015-01-29 05:30:40 -06:00
|
|
|
|
|
|
|
if (net_req->response && net_req->response != net_req->wire_data)
|
|
|
|
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
2013-08-15 11:33:05 -05:00
|
|
|
}
|
|
|
|
|
2015-01-29 05:30:40 -06:00
|
|
|
static void
|
|
|
|
network_req_init(getdns_network_req *net_req,
|
|
|
|
getdns_dns_req *owner, uint16_t request_type,
|
|
|
|
uint16_t request_class, size_t wire_data_sz)
|
2013-11-05 14:03:44 -06:00
|
|
|
{
|
|
|
|
net_req->result = NULL;
|
|
|
|
|
|
|
|
net_req->request_type = request_type;
|
|
|
|
net_req->request_class = request_class;
|
|
|
|
net_req->unbound_id = -1;
|
|
|
|
net_req->state = NET_REQ_NOT_SENT;
|
|
|
|
net_req->owner = owner;
|
|
|
|
|
2014-10-15 16:57:24 -05:00
|
|
|
net_req->upstream = NULL;
|
2014-10-17 17:25:41 -05:00
|
|
|
net_req->fd = -1;
|
|
|
|
memset(&net_req->event, 0, sizeof(net_req->event));
|
|
|
|
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
2014-10-23 08:17:54 -05:00
|
|
|
net_req->query_id = 0;
|
|
|
|
net_req->max_udp_payload_size = 0;
|
2014-10-18 07:32:55 -05:00
|
|
|
net_req->write_queue_tail = NULL;
|
2015-01-29 05:30:40 -06:00
|
|
|
|
|
|
|
net_req->wire_data_sz = wire_data_sz;
|
|
|
|
net_req->response = NULL;
|
2013-08-15 11:33:05 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 14:03:44 -06:00
|
|
|
void
|
|
|
|
dns_req_free(getdns_dns_req * req)
|
|
|
|
{
|
2015-01-29 05:30:40 -06:00
|
|
|
getdns_network_req **net_req;
|
2013-11-05 14:03:44 -06:00
|
|
|
if (!req) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free extensions */
|
|
|
|
getdns_dict_destroy(req->extensions);
|
|
|
|
|
2014-10-15 08:12:16 -05:00
|
|
|
if (req->upstreams && --req->upstreams->referenced == 0)
|
|
|
|
GETDNS_FREE(req->upstreams->mf, req->upstreams);
|
|
|
|
|
2015-01-29 05:30:40 -06:00
|
|
|
/* cleanup network requests */
|
|
|
|
for (net_req = req->netreqs; *net_req; net_req++)
|
|
|
|
network_req_cleanup(*net_req);
|
2013-11-05 14:03:44 -06:00
|
|
|
|
2015-01-29 05:30:40 -06:00
|
|
|
/* clear timeout event */
|
2014-10-13 17:14:25 -05:00
|
|
|
if (req->timeout.timeout_cb) {
|
|
|
|
req->loop->vmt->clear(req->loop, &req->timeout);
|
|
|
|
req->timeout.timeout_cb = NULL;
|
|
|
|
}
|
2013-11-05 14:03:44 -06:00
|
|
|
|
|
|
|
/* free strduped name */
|
2014-02-20 16:35:27 -06:00
|
|
|
GETDNS_FREE(req->my_mf, req->name);
|
|
|
|
GETDNS_FREE(req->my_mf, req);
|
2013-08-15 11:33:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* create a new dns req to be submitted */
|
2013-11-05 14:03:44 -06:00
|
|
|
getdns_dns_req *
|
2015-01-29 05:30:40 -06:00
|
|
|
dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|
|
|
const char *name, uint16_t request_type, getdns_dict *extensions)
|
2013-11-05 14:03:44 -06:00
|
|
|
{
|
|
|
|
|
|
|
|
getdns_dns_req *result = NULL;
|
2014-10-07 08:52:41 -05:00
|
|
|
uint32_t klass = GLDNS_RR_CLASS_IN;
|
2015-01-29 05:30:40 -06:00
|
|
|
size_t edns_maximum_udp_payload_size =
|
|
|
|
getdns_get_maximum_udp_payload_size(context, extensions, NULL);
|
|
|
|
int a_aaaa_query =
|
|
|
|
is_extension_set(extensions, "return_both_v4_and_v6") &&
|
|
|
|
( request_type == GETDNS_RRTYPE_A ||
|
|
|
|
request_type == GETDNS_RRTYPE_AAAA );
|
|
|
|
/* Reserve for the buffer at least one more byte
|
|
|
|
* (to test for udp overflow) (hence the + 1),
|
|
|
|
* And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
|
|
|
|
*/
|
|
|
|
size_t netreq_sz = ( sizeof(getdns_network_req)
|
|
|
|
+ edns_maximum_udp_payload_size + 1 + 7) / 8 * 8;
|
|
|
|
size_t dnsreq_base_sz = ( sizeof(getdns_dns_req)
|
|
|
|
+ (a_aaaa_query ? 3 : 2)
|
|
|
|
* sizeof(getdns_network_req *));
|
|
|
|
uint8_t *region;
|
|
|
|
|
|
|
|
if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
|
|
|
|
dnsreq_base_sz + (a_aaaa_query ? 2 : 1) * netreq_sz)))
|
2013-11-05 14:03:44 -06:00
|
|
|
return NULL;
|
2015-01-29 05:30:40 -06:00
|
|
|
|
|
|
|
result = (getdns_dns_req *)region;
|
|
|
|
result->netreqs[0] = (getdns_network_req *)(region + dnsreq_base_sz);
|
|
|
|
if (a_aaaa_query) {
|
|
|
|
result->netreqs[1] = (getdns_network_req *)
|
|
|
|
(region + dnsreq_base_sz + netreq_sz);
|
|
|
|
result->netreqs[2] = NULL;
|
|
|
|
} else
|
|
|
|
result->netreqs[1] = NULL;
|
|
|
|
|
2014-10-07 08:52:41 -05:00
|
|
|
result->my_mf = context->mf;
|
2014-02-20 16:35:27 -06:00
|
|
|
result->name = getdns_strdup(&(result->my_mf), name);
|
2013-11-05 14:03:44 -06:00
|
|
|
result->context = context;
|
2014-10-13 17:14:25 -05:00
|
|
|
result->loop = loop;
|
2013-11-05 14:03:44 -06:00
|
|
|
result->canceled = 0;
|
2014-10-15 08:12:16 -05:00
|
|
|
result->trans_id = (uint64_t)(((intptr_t) result) ^ ldns_get_random());
|
2013-11-05 14:03:44 -06:00
|
|
|
|
|
|
|
getdns_dict_copy(extensions, &result->extensions);
|
2014-10-07 08:52:41 -05:00
|
|
|
result->return_dnssec_status = context->return_dnssec_status;
|
2013-11-05 14:03:44 -06:00
|
|
|
|
|
|
|
/* will be set by caller */
|
|
|
|
result->user_pointer = NULL;
|
|
|
|
result->user_callback = NULL;
|
2014-10-08 08:42:33 -05:00
|
|
|
memset(&result->timeout, 0, sizeof(result->timeout));
|
2013-11-05 14:03:44 -06:00
|
|
|
|
2014-05-21 09:50:01 -05:00
|
|
|
/* check the specify_class extension */
|
2014-10-07 08:52:41 -05:00
|
|
|
(void) getdns_dict_get_int(extensions, "specify_class", &klass);
|
2014-05-21 09:50:01 -05:00
|
|
|
|
2014-10-15 08:12:16 -05:00
|
|
|
result->upstreams = context->upstreams;
|
|
|
|
if (result->upstreams)
|
|
|
|
result->upstreams->referenced++;
|
|
|
|
|
2015-01-29 05:30:40 -06:00
|
|
|
network_req_init(result->netreqs[0], result, request_type,
|
|
|
|
klass, netreq_sz - sizeof(getdns_network_req));
|
2013-11-05 14:03:44 -06:00
|
|
|
|
2015-01-29 05:30:40 -06:00
|
|
|
if (a_aaaa_query)
|
|
|
|
network_req_init(result->netreqs[1], result,
|
|
|
|
( request_type == GETDNS_RRTYPE_A
|
|
|
|
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ),
|
|
|
|
klass, netreq_sz - sizeof(getdns_network_req));
|
2013-11-05 14:03:44 -06:00
|
|
|
|
|
|
|
return result;
|
2013-08-15 11:33:05 -05:00
|
|
|
}
|