mirror of https://github.com/getdnsapi/getdns.git
First query append
This commit is contained in:
parent
54498cd556
commit
89b6c04d4f
|
@ -104,7 +104,7 @@ getdns_port_str_array[] = {
|
|||
GETDNS_STR_PORT_DNS_OVER_TLS
|
||||
};
|
||||
|
||||
static uint8_t no_suffixes[] = { 0, 0 };
|
||||
static const uint8_t no_suffixes[] = { 1, 0 };
|
||||
|
||||
/* Private functions */
|
||||
static getdns_return_t create_default_namespaces(struct getdns_context *context);
|
||||
|
@ -1181,7 +1181,7 @@ getdns_context_destroy(struct getdns_context *context)
|
|||
unlink(context->root_servers_fn);
|
||||
|
||||
if (context->suffixes && context->suffixes != no_suffixes)
|
||||
GETDNS_FREE(context->mf, context->suffixes);
|
||||
GETDNS_FREE(context->mf, (void *)context->suffixes);
|
||||
|
||||
if (context->trust_anchors &&
|
||||
context->trust_anchors != context->trust_anchors_spc)
|
||||
|
@ -1830,7 +1830,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value)
|
|||
|
||||
if (value == NULL) {
|
||||
if (context->suffixes && context->suffixes != no_suffixes)
|
||||
GETDNS_FREE(context->mf, context->suffixes);
|
||||
GETDNS_FREE(context->mf, (void *)context->suffixes);
|
||||
|
||||
context->suffixes = no_suffixes;
|
||||
context->suffixes_len = sizeof(no_suffixes);
|
||||
|
@ -1890,7 +1890,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value)
|
|||
return r;
|
||||
}
|
||||
if (context->suffixes && context->suffixes != no_suffixes)
|
||||
GETDNS_FREE(context->mf, context->suffixes);
|
||||
GETDNS_FREE(context->mf, (void *)context->suffixes);
|
||||
|
||||
context->suffixes = suffixes;
|
||||
context->suffixes_len = suffixes_len;
|
||||
|
@ -3248,7 +3248,7 @@ getdns_return_t
|
|||
getdns_context_get_suffix(getdns_context *context, getdns_list **value)
|
||||
{
|
||||
size_t dname_len;
|
||||
uint8_t *dname;
|
||||
const uint8_t *dname;
|
||||
char name[1024];
|
||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||
getdns_list *list;
|
||||
|
@ -3263,7 +3263,7 @@ getdns_context_get_suffix(getdns_context *context, getdns_list **value)
|
|||
dname_len = context->suffixes[0];
|
||||
dname = context->suffixes + 1;
|
||||
while (dname_len && *dname) {
|
||||
if (! gldns_wire2str_dname_buf(
|
||||
if (! gldns_wire2str_dname_buf((UNCONST_UINT8_p)
|
||||
dname, dname_len, name, sizeof(name))) {
|
||||
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
break;
|
||||
|
|
|
@ -183,7 +183,7 @@ struct getdns_context {
|
|||
* length bytes contains the length of the following dname.
|
||||
* The last dname should be the zero byte.
|
||||
*/
|
||||
uint8_t *suffixes;
|
||||
const uint8_t *suffixes;
|
||||
/* Length of all suffixes in the suffix buffer */
|
||||
size_t suffixes_len;
|
||||
uint8_t *trust_anchors;
|
||||
|
|
|
@ -3269,7 +3269,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
|
|||
, netreq->response, netreq->response_len
|
||||
, netreq->owner->name
|
||||
, netreq->request_type
|
||||
, netreq->request_class
|
||||
, netreq->owner->request_class
|
||||
, netreq
|
||||
);
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ _getdns_submit_netreq(getdns_network_req *netreq)
|
|||
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
return ub_resolve_async(dns_req->context->unbound_ctx,
|
||||
name, netreq->request_type, netreq->request_class,
|
||||
name, netreq->request_type, netreq->owner->request_class,
|
||||
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||
#else
|
||||
|
|
|
@ -112,15 +112,13 @@ network_req_cleanup(getdns_network_req *net_req)
|
|||
|
||||
static int
|
||||
network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||
const char *name, uint16_t request_type, uint16_t request_class,
|
||||
int dnssec_extension_set, int with_opt,
|
||||
uint16_t request_type, int dnssec_extension_set, int with_opt,
|
||||
int edns_maximum_udp_payload_size,
|
||||
uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
|
||||
uint16_t opt_options_size, size_t noptions, getdns_list *options,
|
||||
size_t wire_data_sz, size_t max_query_sz)
|
||||
{
|
||||
uint8_t *buf;
|
||||
size_t dname_len;
|
||||
getdns_dict *option;
|
||||
uint32_t option_code;
|
||||
getdns_bindata *option_data;
|
||||
|
@ -128,7 +126,6 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
int r = 0;
|
||||
|
||||
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;
|
||||
|
@ -138,10 +135,10 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
|
||||
net_req->upstream = NULL;
|
||||
net_req->fd = -1;
|
||||
net_req->transport_count = owner->context->dns_transport_count;
|
||||
net_req->transport_count = owner->context->dns_transport_count;
|
||||
net_req->transport_current = 0;
|
||||
memcpy(net_req->transports, owner->context->dns_transports,
|
||||
net_req->transport_count * sizeof(getdns_transport_list_t));
|
||||
memcpy(net_req->transports, owner->context->dns_transports,
|
||||
net_req->transport_count * sizeof(getdns_transport_list_t));
|
||||
net_req->tls_auth_min = owner->context->tls_auth_min;
|
||||
memset(&net_req->event, 0, sizeof(net_req->event));
|
||||
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
||||
|
@ -161,72 +158,69 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
net_req->debug_udp = 0;
|
||||
|
||||
net_req->wire_data_sz = wire_data_sz;
|
||||
if (max_query_sz) {
|
||||
/* first two bytes will contain query length (for tcp) */
|
||||
buf = net_req->query = net_req->wire_data + 2;
|
||||
|
||||
gldns_write_uint16(buf + 2, 0); /* reset all flags */
|
||||
GLDNS_RD_SET(buf);
|
||||
if (dnssec_extension_set) /* We will do validation ourselves */
|
||||
GLDNS_CD_SET(buf);
|
||||
GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
|
||||
gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
|
||||
gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
|
||||
gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
|
||||
gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
|
||||
|
||||
buf += GLDNS_HEADER_SIZE;
|
||||
dname_len = max_query_sz - GLDNS_HEADER_SIZE;
|
||||
if ((r = gldns_str2wire_dname_buf(name, buf, &dname_len))) {
|
||||
net_req->opt = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
buf += dname_len;
|
||||
|
||||
gldns_write_uint16(buf, request_type);
|
||||
gldns_write_uint16(buf + 2, request_class);
|
||||
buf += 4;
|
||||
|
||||
if (with_opt) {
|
||||
net_req->opt = buf;
|
||||
buf[0] = 0; /* dname for . */
|
||||
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
|
||||
gldns_write_uint16(net_req->opt + 3,
|
||||
net_req->max_udp_payload_size);
|
||||
buf[5] = edns_extended_rcode;
|
||||
buf[6] = edns_version;
|
||||
buf[7] = edns_do_bit ? 0x80 : 0;
|
||||
buf[8] = 0;
|
||||
gldns_write_uint16(buf + 9, opt_options_size);
|
||||
buf += 11;
|
||||
for (i = 0; i < noptions; i++) {
|
||||
if (getdns_list_get_dict(options, i, &option))
|
||||
continue;
|
||||
if (getdns_dict_get_int(
|
||||
option, "option_code", &option_code))
|
||||
continue;
|
||||
if (getdns_dict_get_bindata(
|
||||
option, "option_data", &option_data))
|
||||
continue;
|
||||
|
||||
gldns_write_uint16(buf, (uint16_t) option_code);
|
||||
gldns_write_uint16(buf + 2,
|
||||
(uint16_t) option_data->size);
|
||||
(void) memcpy(buf + 4, option_data->data,
|
||||
option_data->size);
|
||||
|
||||
buf += option_data->size + 4;
|
||||
}
|
||||
} else
|
||||
net_req->opt = NULL;
|
||||
net_req->response = buf;
|
||||
gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
|
||||
} else {
|
||||
if (max_query_sz == 0) {
|
||||
net_req->query = NULL;
|
||||
net_req->opt = NULL;
|
||||
net_req->response = net_req->wire_data;
|
||||
return r;
|
||||
}
|
||||
/* first two bytes will contain query length (for tcp) */
|
||||
buf = net_req->query = net_req->wire_data + 2;
|
||||
|
||||
gldns_write_uint16(buf + 2, 0); /* reset all flags */
|
||||
GLDNS_RD_SET(buf);
|
||||
if (dnssec_extension_set) /* We will do validation ourselves */
|
||||
GLDNS_CD_SET(buf);
|
||||
GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
|
||||
gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
|
||||
gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
|
||||
gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
|
||||
gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
|
||||
|
||||
buf += GLDNS_HEADER_SIZE;
|
||||
memcpy(buf, owner->name, owner->name_len);
|
||||
buf += owner->name_len;
|
||||
|
||||
gldns_write_uint16(buf, request_type);
|
||||
gldns_write_uint16(buf + 2, owner->request_class);
|
||||
buf += 4;
|
||||
|
||||
if (with_opt) {
|
||||
net_req->opt = buf;
|
||||
buf[0] = 0; /* dname for . */
|
||||
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
|
||||
gldns_write_uint16(net_req->opt + 3,
|
||||
net_req->max_udp_payload_size);
|
||||
buf[5] = edns_extended_rcode;
|
||||
buf[6] = edns_version;
|
||||
buf[7] = edns_do_bit ? 0x80 : 0;
|
||||
buf[8] = 0;
|
||||
gldns_write_uint16(buf + 9, opt_options_size);
|
||||
buf += 11;
|
||||
for (i = 0; i < noptions; i++) {
|
||||
if (getdns_list_get_dict(options, i, &option))
|
||||
continue;
|
||||
if (getdns_dict_get_int(
|
||||
option, "option_code", &option_code))
|
||||
continue;
|
||||
if (getdns_dict_get_bindata(
|
||||
option, "option_data", &option_data))
|
||||
continue;
|
||||
|
||||
gldns_write_uint16(buf, (uint16_t) option_code);
|
||||
gldns_write_uint16(buf + 2,
|
||||
(uint16_t) option_data->size);
|
||||
(void) memcpy(buf + 4, option_data->data,
|
||||
option_data->size);
|
||||
|
||||
buf += option_data->size + 4;
|
||||
}
|
||||
} else
|
||||
net_req->opt = NULL;
|
||||
|
||||
net_req->response = buf;
|
||||
gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -583,6 +577,8 @@ _getdns_dns_req_free(getdns_dns_req * req)
|
|||
GETDNS_FREE(req->my_mf, req);
|
||||
}
|
||||
|
||||
static const uint8_t no_suffixes[] = { 1, 0 };
|
||||
|
||||
/* create a new dns req to be submitted */
|
||||
getdns_dns_req *
|
||||
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||
|
@ -647,7 +643,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
* And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
|
||||
*/
|
||||
size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
|
||||
uint8_t *region;
|
||||
uint8_t *region, *suffixes;
|
||||
|
||||
if (extensions == dnssec_ok_checking_disabled ||
|
||||
extensions == dnssec_ok_checking_disabled_roadblock_avoidance ||
|
||||
|
@ -719,7 +715,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
;
|
||||
}
|
||||
max_query_sz = ( GLDNS_HEADER_SIZE
|
||||
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
|
||||
+ 256 + 4 /* dname maximum 255 bytes (256 with mdns)*/
|
||||
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
||||
+ MAXIMUM_UPSTREAM_OPTION_SPACE
|
||||
+ MAXIMUM_TSIG_SPACE
|
||||
|
@ -734,6 +730,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
+ max_query_sz + max_response_sz + 7 ) / 8 * 8;
|
||||
dnsreq_base_sz = (( sizeof(getdns_dns_req)
|
||||
+ (a_aaaa_query ? 3 : 2) * sizeof(getdns_network_req*)
|
||||
+ context->suffixes_len
|
||||
) + 7) / 8 * 8;
|
||||
|
||||
if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
|
||||
|
@ -751,11 +748,51 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
|
||||
result->my_mf = context->mf;
|
||||
|
||||
suffixes = region + dnsreq_base_sz - context->suffixes_len;
|
||||
assert(context->suffixes);
|
||||
assert(context->suffixes_len);
|
||||
memcpy(suffixes, context->suffixes, context->suffixes_len);
|
||||
|
||||
result->append_name = context->append_name;
|
||||
if (!strlen(name) || name[strlen(name)-1] == '.' ||
|
||||
result->append_name == GETDNS_APPEND_NAME_NEVER) {
|
||||
/* Absolute query string, no appending */
|
||||
result->suffix_len = no_suffixes[0];
|
||||
result->suffix = no_suffixes + 1;
|
||||
result->suffix_appended = 1;
|
||||
} else {
|
||||
result->suffix_len = suffixes[0];
|
||||
result->suffix = suffixes + 1;
|
||||
result->suffix_appended = 0;
|
||||
}
|
||||
result->name_len = sizeof(result->name);
|
||||
if (gldns_str2wire_dname_buf(name, result->name, &result->name_len)) {
|
||||
GETDNS_FREE(result->my_mf, result);
|
||||
return NULL;
|
||||
}
|
||||
if (result->append_name == GETDNS_APPEND_NAME_ALWAYS) {
|
||||
for (
|
||||
; result->suffix_len > 1 && *result->suffix
|
||||
; result->suffix += result->suffix_len
|
||||
, result->suffix_len = *result->suffix++) {
|
||||
|
||||
if (result->suffix_len + result->name_len - 1 <
|
||||
sizeof(result->name)) {
|
||||
memcpy(result->name + result->name_len - 1,
|
||||
result->suffix, result->suffix_len);
|
||||
result->name_len += result->suffix_len - 1;
|
||||
result->suffix_appended = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (result->append_name ==
|
||||
GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE &&
|
||||
result->name[result->name[0]+1] != 0) {
|
||||
/* We have multiple labels, no appending */
|
||||
result->suffix_len = no_suffixes[0];
|
||||
result->suffix = no_suffixes + 1;
|
||||
result->suffix_appended = 1;
|
||||
}
|
||||
result->context = context;
|
||||
result->loop = loop;
|
||||
result->canceled = 0;
|
||||
|
@ -781,23 +818,23 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
|
||||
/* check the specify_class extension */
|
||||
(void) getdns_dict_get_int(extensions, "specify_class", &klass);
|
||||
result->request_class = klass;
|
||||
|
||||
result->upstreams = context->upstreams;
|
||||
if (result->upstreams)
|
||||
result->upstreams->referenced++;
|
||||
|
||||
network_req_init(result->netreqs[0], result,
|
||||
name, request_type, klass,
|
||||
dnssec_extension_set, with_opt,
|
||||
request_type, dnssec_extension_set, with_opt,
|
||||
edns_maximum_udp_payload_size,
|
||||
edns_extended_rcode, edns_version, edns_do_bit,
|
||||
opt_options_size, noptions, options,
|
||||
netreq_sz - sizeof(getdns_network_req), max_query_sz);
|
||||
|
||||
if (a_aaaa_query)
|
||||
network_req_init(result->netreqs[1], result, name,
|
||||
network_req_init(result->netreqs[1], result,
|
||||
( request_type == GETDNS_RRTYPE_A
|
||||
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ), klass,
|
||||
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ),
|
||||
dnssec_extension_set, with_opt,
|
||||
edns_maximum_udp_payload_size,
|
||||
edns_extended_rcode, edns_version, edns_do_bit,
|
||||
|
|
|
@ -203,9 +203,6 @@ typedef struct getdns_network_req
|
|||
/* request type */
|
||||
uint16_t request_type;
|
||||
|
||||
/* request class */
|
||||
uint16_t request_class;
|
||||
|
||||
/* dnssec status */
|
||||
int dnssec_status;
|
||||
|
||||
|
@ -282,6 +279,13 @@ typedef struct getdns_dns_req {
|
|||
uint8_t name[256];
|
||||
size_t name_len;
|
||||
|
||||
getdns_append_name_t append_name;
|
||||
const uint8_t *suffix;
|
||||
size_t suffix_len;
|
||||
int suffix_appended;
|
||||
|
||||
uint16_t request_class;
|
||||
|
||||
/* canceled flag */
|
||||
int canceled;
|
||||
|
||||
|
|
|
@ -1035,7 +1035,7 @@ getdns_apply_network_result(getdns_network_req* netreq,
|
|||
, netreq->request_type);
|
||||
gldns_write_uint16( netreq->response + GLDNS_HEADER_SIZE
|
||||
+ netreq->owner->name_len + 2
|
||||
, netreq->request_class);
|
||||
, netreq->owner->request_class);
|
||||
|
||||
netreq->response_len = GLDNS_HEADER_SIZE + netreq->owner->name_len + 4;
|
||||
|
||||
|
|
Loading…
Reference in New Issue