mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-10 00:32:54 -05:00
Merge pull request #563 from NLnetLabs/bugfix/general-edns-options3
Better positioning of general EDNS option handling: revisited V2
This commit is contained in:
commit
c47e98a659
18 changed files with 240 additions and 224 deletions
|
|
@ -519,7 +519,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
|||
sldns_buffer_set_limit(buf, lim);
|
||||
return 0;
|
||||
}
|
||||
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
|
||||
if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) !=
|
||||
LDNS_RCODE_NOERROR) {
|
||||
sldns_buffer_set_limit(buf, lim);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -449,7 +449,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
* Then check if it needs validation, if so, this routine fails,
|
||||
* so that iterator can prime and validator can verify rrsets.
|
||||
*/
|
||||
struct edns_data edns_bak;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
int secure = 0;
|
||||
time_t timenow = *worker->env.now;
|
||||
|
|
@ -508,7 +507,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
}
|
||||
}
|
||||
/* return this delegation from the cache */
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
|
|
@ -518,15 +516,13 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
worker->env.now_tv))
|
||||
return 0;
|
||||
msg->rep->flags |= BIT_QR|BIT_RA;
|
||||
if(!apply_edns_options(edns, &edns_bak, worker->env.cfg,
|
||||
repinfo->c, worker->scratchpad) ||
|
||||
!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
|
||||
if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
|
||||
repinfo->c->buffer, 0, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
|
||||
worker->env.now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
}
|
||||
|
|
@ -604,7 +600,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
struct reply_info* rep, uint16_t id, uint16_t flags,
|
||||
struct comm_reply* repinfo, struct edns_data* edns)
|
||||
{
|
||||
struct edns_data edns_bak;
|
||||
time_t timenow = *worker->env.now;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
struct reply_info* encode_rep = rep;
|
||||
|
|
@ -685,7 +680,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
}
|
||||
} else *is_secure_answer = 0;
|
||||
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
|
|
@ -722,15 +716,13 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
if(!*partial_repp)
|
||||
goto bail_out;
|
||||
}
|
||||
} else if(!apply_edns_options(edns, &edns_bak, worker->env.cfg,
|
||||
repinfo->c, worker->scratchpad) ||
|
||||
!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
} else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
|
||||
worker->env.now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
}
|
||||
|
|
@ -796,7 +788,7 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
|
|||
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
|
||||
LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad,
|
||||
worker->env.now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
sldns_buffer_clear(pkt);
|
||||
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */
|
||||
sldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA));
|
||||
|
|
@ -1011,7 +1003,6 @@ answer_notify(struct worker* w, struct query_info* qinfo,
|
|||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
edns->opt_list = NULL;
|
||||
error_encode(pkt, rcode, qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(pkt),
|
||||
sldns_buffer_read_u16_at(pkt, 2), edns);
|
||||
|
|
@ -1248,7 +1239,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
}
|
||||
goto send_reply;
|
||||
}
|
||||
if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) {
|
||||
if((ret=parse_edns_from_query_pkt(c->buffer, &edns, worker->env.cfg, c,
|
||||
worker->scratchpad)) != 0) {
|
||||
struct edns_data reply_edns;
|
||||
verbose(VERB_ALGO, "worker parse edns: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
|
|
@ -1263,13 +1255,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
goto send_reply;
|
||||
}
|
||||
if(edns.edns_present) {
|
||||
struct edns_option* edns_opt;
|
||||
if(edns.edns_version != 0) {
|
||||
edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4);
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits &= EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
verbose(VERB_ALGO, "query with bad edns version.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
|
|
@ -1289,26 +1282,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
edns.udp_size = NORMAL_UDP_SIZE;
|
||||
}
|
||||
if(c->type != comm_udp) {
|
||||
edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE);
|
||||
if(edns_opt && edns_opt->opt_len > 0) {
|
||||
edns.ext_rcode = 0;
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits &= EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
verbose(VERB_ALGO, "query with bad edns keepalive.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
error_encode(c->buffer, LDNS_RCODE_FORMERR, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
if(sldns_buffer_capacity(c->buffer) >=
|
||||
sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(edns.udp_size > worker->daemon->cfg->max_udp_size &&
|
||||
c->type == comm_udp) {
|
||||
|
|
@ -1460,7 +1433,7 @@ lookup_cache:
|
|||
* this is a two-pass operation, and lookup_qinfo is different for
|
||||
* each pass. We should still pass the original qinfo to
|
||||
* answer_from_cache(), however, since it's used to build the reply. */
|
||||
if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) {
|
||||
if(!edns_bypass_cache_stage(edns.opt_list_in, &worker->env)) {
|
||||
is_expired_answer = 0;
|
||||
is_secure_answer = 0;
|
||||
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
|
|
|
|||
|
|
@ -3852,15 +3852,15 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
goto handle_it;
|
||||
}
|
||||
/* edns is not examined, but removed from message to help cache */
|
||||
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
|
||||
if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) !=
|
||||
LDNS_RCODE_NOERROR) {
|
||||
iq->parse_failures++;
|
||||
goto handle_it;
|
||||
}
|
||||
|
||||
/* Copy the edns options we may got from the back end */
|
||||
if(edns.opt_list) {
|
||||
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list,
|
||||
if(edns.opt_list_in) {
|
||||
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in,
|
||||
qstate->region);
|
||||
if(!qstate->edns_opts_back_in) {
|
||||
log_err("out of memory on incoming message");
|
||||
|
|
|
|||
|
|
@ -600,7 +600,9 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
|
|||
edns->ext_rcode = 0;
|
||||
edns->edns_version = 0;
|
||||
edns->bits = EDNS_DO;
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_in = NULL;
|
||||
edns->opt_list_out = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
edns->padding_block_size = 0;
|
||||
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
|
||||
edns->udp_size = (uint16_t)sldns_buffer_capacity(
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
|
|||
return 0;
|
||||
}
|
||||
/* edns is not examined, but removed from message to help cache */
|
||||
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
|
||||
if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) !=
|
||||
LDNS_RCODE_NOERROR)
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -3518,7 +3518,7 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env,
|
|||
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||
rcode, edns, repinfo, temp, env->now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(buf, rcode|BIT_AA, qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
|
|
@ -5358,7 +5358,9 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
|||
edns.ext_rcode = 0;
|
||||
edns.edns_version = 0;
|
||||
edns.bits = EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
if(sldns_buffer_capacity(buf) < 65535)
|
||||
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
|
||||
|
|
@ -6547,7 +6549,9 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
|||
edns.ext_rcode = 0;
|
||||
edns.edns_version = 0;
|
||||
edns.bits = EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
if(sldns_buffer_capacity(buf) < 65535)
|
||||
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
|
||||
|
|
@ -8322,7 +8326,9 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
|
|||
edns.ext_rcode = 0;
|
||||
edns.edns_version = 0;
|
||||
edns.bits = EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
if(sldns_buffer_capacity(buf) < 65535)
|
||||
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
|
||||
else edns.udp_size = 65535;
|
||||
|
|
|
|||
|
|
@ -1299,7 +1299,7 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
|
|||
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||
rcode, edns, repinfo, temp, env->now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
|
|
@ -505,7 +505,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
|
|
@ -514,14 +514,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
/* copy the edns options we got from the front */
|
||||
if(edns->opt_list) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list,
|
||||
if(edns->opt_list_in) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
|
||||
s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
|
|
@ -594,7 +594,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
servfail_mem:
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
|
|
@ -609,7 +609,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
|
||||
int timeout = mesh->env->cfg->serve_expired?
|
||||
mesh->env->cfg->serve_expired_client_timeout:0;
|
||||
int was_detached = 0;
|
||||
|
|
@ -632,8 +632,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
}
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
if(edns->opt_list) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list,
|
||||
if(edns->opt_list_in) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
|
||||
s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
return 0;
|
||||
|
|
@ -1145,11 +1145,11 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, NULL, m->s.region, start_time))
|
||||
r->edns.opt_list = NULL;
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, NULL, m->s.region, start_time))
|
||||
r->edns.opt_list = NULL;
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
}
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL,
|
||||
|
|
@ -1217,9 +1217,6 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
/* Copy the client's EDNS for later restore, to make sure the edns
|
||||
* compare is with the correct edns options. */
|
||||
struct edns_data edns_bak = r->edns;
|
||||
/* briefly set the replylist to null in case the
|
||||
* meshsendreply calls tcpreqinfo sendreply that
|
||||
* comm_point_drops because of size, and then the
|
||||
|
|
@ -1269,8 +1266,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
prev->edns.edns_present == r->edns.edns_present &&
|
||||
prev->edns.bits == r->edns.bits &&
|
||||
prev->edns.udp_size == r->edns.udp_size &&
|
||||
edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list)
|
||||
== 0) {
|
||||
edns_opt_list_compare(prev->edns.opt_list_out, r->edns.opt_list_out) == 0 &&
|
||||
edns_opt_list_compare(prev->edns.opt_list_inplace_cb_out, r->edns.opt_list_inplace_cb_out) == 0
|
||||
) {
|
||||
/* if the previous reply is identical to this one, fix ID */
|
||||
if(prev_buffer != r_buffer)
|
||||
sldns_buffer_copy(r_buffer, prev_buffer);
|
||||
|
|
@ -1286,11 +1284,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
r->edns.opt_list = NULL;
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
r->edns.opt_list = NULL;
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
}
|
||||
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
|
||||
r->qflags, &r->edns);
|
||||
|
|
@ -1307,9 +1305,6 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
m->s.qinfo.local_alias = r->local_alias;
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) ||
|
||||
!apply_edns_options(&r->edns, &edns_bak,
|
||||
m->s.env->cfg, r->query_reply.c,
|
||||
m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r_buffer, 0, 1, m->s.env->scratch,
|
||||
udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO),
|
||||
|
|
@ -1317,11 +1312,10 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||
{
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
r->edns.opt_list = NULL;
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
&m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
r->edns = edns_bak;
|
||||
m->reply_list = NULL;
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
m->reply_list = rlist;
|
||||
|
|
@ -1509,12 +1503,15 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
|||
r->cb = cb;
|
||||
r->cb_arg = cb_arg;
|
||||
r->edns = *edns;
|
||||
if(edns->opt_list) {
|
||||
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
|
||||
s->s.region);
|
||||
if(!r->edns.opt_list)
|
||||
return 0;
|
||||
}
|
||||
if(edns->opt_list_in && !(r->edns.opt_list_in =
|
||||
edns_opt_copy_region(edns->opt_list_in, s->s.region)))
|
||||
return 0;
|
||||
if(edns->opt_list_out && !(r->edns.opt_list_out =
|
||||
edns_opt_copy_region(edns->opt_list_out, s->s.region)))
|
||||
return 0;
|
||||
if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out =
|
||||
edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region)))
|
||||
return 0;
|
||||
r->qid = qid;
|
||||
r->qflags = qflags;
|
||||
r->next = s->cb_list;
|
||||
|
|
@ -1533,12 +1530,15 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
|||
return 0;
|
||||
r->query_reply = *rep;
|
||||
r->edns = *edns;
|
||||
if(edns->opt_list) {
|
||||
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
|
||||
s->s.region);
|
||||
if(!r->edns.opt_list)
|
||||
return 0;
|
||||
}
|
||||
if(edns->opt_list_in && !(r->edns.opt_list_in =
|
||||
edns_opt_copy_region(edns->opt_list_in, s->s.region)))
|
||||
return 0;
|
||||
if(edns->opt_list_out && !(r->edns.opt_list_out =
|
||||
edns_opt_copy_region(edns->opt_list_out, s->s.region)))
|
||||
return 0;
|
||||
if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out =
|
||||
edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region)))
|
||||
return 0;
|
||||
r->qid = qid;
|
||||
r->qflags = qflags;
|
||||
r->start_time = *s->s.env->now_tv;
|
||||
|
|
|
|||
|
|
@ -2709,7 +2709,9 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
|
|||
edns.edns_present = 1;
|
||||
edns.ext_rcode = 0;
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.opt_list = sq->opt_list;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = sq->opt_list;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
|
||||
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
|
||||
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
|
||||
|
|
@ -2732,8 +2734,8 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
|
|||
padding_option.opt_code = LDNS_EDNS_PADDING;
|
||||
padding_option.opt_len = 0;
|
||||
padding_option.opt_data = NULL;
|
||||
padding_option.next = edns.opt_list;
|
||||
edns.opt_list = &padding_option;
|
||||
padding_option.next = edns.opt_list_out;
|
||||
edns.opt_list_out = &padding_option;
|
||||
edns.padding_block_size = sq->padding_block_size;
|
||||
}
|
||||
attach_edns_record(buff, &edns);
|
||||
|
|
|
|||
|
|
@ -1244,7 +1244,9 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
|||
client_string_addr->string_len,
|
||||
client_string_addr->string, qstate->region);
|
||||
}
|
||||
edns.opt_list = qstate->edns_opts_back_out;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = qstate->edns_opts_back_out;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
attach_edns_record(pend->buffer, &edns);
|
||||
}
|
||||
memcpy(&pend->addr, addr, addrlen);
|
||||
|
|
|
|||
|
|
@ -796,7 +796,10 @@ calc_edns_field_size(struct edns_data* edns)
|
|||
struct edns_option* opt;
|
||||
if(!edns || !edns->edns_present)
|
||||
return 0;
|
||||
for(opt = edns->opt_list; opt; opt = opt->next) {
|
||||
for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) {
|
||||
rdatalen += 4 + opt->opt_len;
|
||||
}
|
||||
for(opt = edns->opt_list_out; opt; opt = opt->next) {
|
||||
rdatalen += 4 + opt->opt_len;
|
||||
}
|
||||
/* domain root '.' + type + class + ttl + rdatalen */
|
||||
|
|
@ -827,7 +830,17 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns,
|
|||
rdatapos = sldns_buffer_position(pkt);
|
||||
sldns_buffer_write_u16(pkt, 0); /* rdatalen */
|
||||
/* write rdata */
|
||||
for(opt=edns->opt_list; opt; opt=opt->next) {
|
||||
for(opt=edns->opt_list_inplace_cb_out; opt; opt=opt->next) {
|
||||
if (opt->opt_code == LDNS_EDNS_PADDING) {
|
||||
padding_option = opt;
|
||||
continue;
|
||||
}
|
||||
sldns_buffer_write_u16(pkt, opt->opt_code);
|
||||
sldns_buffer_write_u16(pkt, opt->opt_len);
|
||||
if(opt->opt_len != 0)
|
||||
sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
|
||||
}
|
||||
for(opt=edns->opt_list_out; opt; opt=opt->next) {
|
||||
if (opt->opt_code == LDNS_EDNS_PADDING) {
|
||||
padding_option = opt;
|
||||
continue;
|
||||
|
|
@ -860,8 +873,7 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns,
|
|||
sldns_buffer_skip(pkt, pad_sz);
|
||||
}
|
||||
}
|
||||
if(edns->opt_list)
|
||||
sldns_buffer_write_u16_at(pkt, rdatapos,
|
||||
sldns_buffer_write_u16_at(pkt, rdatapos,
|
||||
sldns_buffer_position(pkt)-rdatapos-2);
|
||||
sldns_buffer_flip(pkt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,12 @@
|
|||
* Routines for message parsing a packet buffer to a descriptive structure.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/regional.h"
|
||||
#include "sldns/rrdef.h"
|
||||
|
|
@ -938,11 +940,40 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
edns_opt_list_append_keepalive(struct edns_option** list, int msec,
|
||||
struct regional* region)
|
||||
{
|
||||
uint8_t data[2]; /* For keepalive value */
|
||||
data[0] = (uint8_t)((msec >> 8) & 0xff);
|
||||
data[1] = (uint8_t)(msec & 0xff);
|
||||
return edns_opt_list_append(list, LDNS_EDNS_KEEPALIVE, sizeof(data),
|
||||
data, region);
|
||||
}
|
||||
|
||||
/** parse EDNS options from EDNS wireformat rdata */
|
||||
static int
|
||||
parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
|
||||
struct edns_data* edns, struct regional* region)
|
||||
parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
|
||||
struct edns_data* edns, struct config_file* cfg, struct comm_point* c,
|
||||
struct regional* region)
|
||||
{
|
||||
/* To respond with a Keepalive option, the client connection must have
|
||||
* received one message with a TCP Keepalive EDNS option, and that
|
||||
* option must have 0 length data. Subsequent messages sent on that
|
||||
* connection will have a TCP Keepalive option.
|
||||
*
|
||||
* In the if-statement below, the option is added unsolicited. This
|
||||
* means that the client has sent an KEEPALIVE option earlier. We know
|
||||
* here this is true, because c->tcp_keepalive is set.
|
||||
*/
|
||||
if (cfg && cfg->do_tcp_keepalive && c && c->type != comm_udp && c->tcp_keepalive) {
|
||||
if(!edns_opt_list_append_keepalive(&edns->opt_list_out,
|
||||
c->tcp_timeout_msec / 100, region)) {
|
||||
log_err("out of memory");
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* while still more options, and have code+len to read */
|
||||
/* ignores partial content (i.e. rdata len 3) */
|
||||
while(rdata_len >= 4) {
|
||||
|
|
@ -952,20 +983,81 @@ parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
|
|||
rdata_len -= 4;
|
||||
if(opt_len > rdata_len)
|
||||
break; /* option code partial */
|
||||
if(!edns_opt_append(edns, region, opt_code, opt_len,
|
||||
rdata_ptr)) {
|
||||
|
||||
/* handle parse time edns options here */
|
||||
switch(opt_code) {
|
||||
case LDNS_EDNS_NSID:
|
||||
if (!cfg || !cfg->nsid)
|
||||
break;
|
||||
if(!edns_opt_list_append(&edns->opt_list_out,
|
||||
LDNS_EDNS_NSID, cfg->nsid_len,
|
||||
cfg->nsid, region)) {
|
||||
log_err("out of memory");
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDNS_EDNS_KEEPALIVE:
|
||||
/* To respond with a Keepalive option, the client
|
||||
* connection must have received one message with a TCP
|
||||
* Keepalive EDNS option, and that option must have 0
|
||||
* length data. Subsequent messages sent on that
|
||||
* connection will have a TCP Keepalive option.
|
||||
*
|
||||
* This should be the first time the client sends this
|
||||
* option, so c->tcp_keepalive is not set.
|
||||
* Besides adding the reply KEEPALIVE option,
|
||||
* c->tcp_keepalive will be set so that the
|
||||
* option will be added unsolicited in subsequent
|
||||
* responses (see the comment above the if-statement
|
||||
* at the start of this function).
|
||||
*/
|
||||
if (!cfg || !cfg->do_tcp_keepalive || !c ||
|
||||
c->type == comm_udp || c->tcp_keepalive)
|
||||
break;
|
||||
if(opt_len) {
|
||||
verbose(VERB_ALGO, "query with bad edns keepalive.");
|
||||
return LDNS_RCODE_FORMERR;
|
||||
}
|
||||
if(!edns_opt_list_append_keepalive(&edns->opt_list_out,
|
||||
c->tcp_timeout_msec / 100,
|
||||
region)) {
|
||||
log_err("out of memory");
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
c->tcp_keepalive = 1;
|
||||
break;
|
||||
|
||||
case LDNS_EDNS_PADDING:
|
||||
if(!cfg || !cfg->pad_responses ||
|
||||
!c || c->type != comm_tcp ||!c->ssl)
|
||||
break;
|
||||
if(!edns_opt_list_append(&edns->opt_list_out,
|
||||
LDNS_EDNS_PADDING,
|
||||
0, NULL, region)) {
|
||||
log_err("out of memory");
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
edns->padding_block_size = cfg->pad_responses_block_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!edns_opt_list_append(&edns->opt_list_in,
|
||||
opt_code, opt_len, rdata_ptr, region)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
rdata_ptr += opt_len;
|
||||
rdata_len -= opt_len;
|
||||
}
|
||||
return 1;
|
||||
return LDNS_RCODE_NOERROR;
|
||||
}
|
||||
|
||||
int
|
||||
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
|
||||
struct regional* region)
|
||||
parse_extract_edns_from_response_msg(struct msg_parse* msg,
|
||||
struct edns_data* edns, struct regional* region)
|
||||
{
|
||||
struct rrset_parse* rrset = msg->rrset_first;
|
||||
struct rrset_parse* prev = 0;
|
||||
|
|
@ -1019,18 +1111,35 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
|
|||
edns->edns_version = found->rr_last->ttl_data[1];
|
||||
edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]);
|
||||
edns->udp_size = ntohs(found->rrset_class);
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_in = NULL;
|
||||
edns->opt_list_out = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
edns->padding_block_size = 0;
|
||||
|
||||
/* take the options */
|
||||
rdata_len = found->rr_first->size-2;
|
||||
rdata_ptr = found->rr_first->ttl_data+6;
|
||||
if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
|
||||
return 0;
|
||||
|
||||
/* while still more options, and have code+len to read */
|
||||
/* ignores partial content (i.e. rdata len 3) */
|
||||
while(rdata_len >= 4) {
|
||||
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
|
||||
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
|
||||
rdata_ptr += 4;
|
||||
rdata_len -= 4;
|
||||
if(opt_len > rdata_len)
|
||||
break; /* option code partial */
|
||||
|
||||
if(!edns_opt_list_append(&edns->opt_list_in,
|
||||
opt_code, opt_len, rdata_ptr, region)) {
|
||||
log_err("out of memory");
|
||||
break;
|
||||
}
|
||||
rdata_ptr += opt_len;
|
||||
rdata_len -= opt_len;
|
||||
}
|
||||
/* ignore rrsigs */
|
||||
|
||||
return 0;
|
||||
return LDNS_RCODE_NOERROR;
|
||||
}
|
||||
|
||||
/** skip RR in packet */
|
||||
|
|
@ -1060,8 +1169,8 @@ skip_pkt_rrs(sldns_buffer* pkt, int num)
|
|||
}
|
||||
|
||||
int
|
||||
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
|
||||
struct regional* region)
|
||||
parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns,
|
||||
struct config_file* cfg, struct comm_point* c, struct regional* region)
|
||||
{
|
||||
size_t rdata_len;
|
||||
uint8_t* rdata_ptr;
|
||||
|
|
@ -1093,7 +1202,9 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
|
|||
edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */
|
||||
edns->edns_version = sldns_buffer_read_u8(pkt);
|
||||
edns->bits = sldns_buffer_read_u16(pkt);
|
||||
edns->opt_list = NULL;
|
||||
edns->opt_list_in = NULL;
|
||||
edns->opt_list_out = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
edns->padding_block_size = 0;
|
||||
|
||||
/* take the options */
|
||||
|
|
@ -1101,12 +1212,9 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
|
|||
if(sldns_buffer_remaining(pkt) < rdata_len)
|
||||
return LDNS_RCODE_FORMERR;
|
||||
rdata_ptr = sldns_buffer_current(pkt);
|
||||
if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
|
||||
/* ignore rrsigs */
|
||||
|
||||
return 0;
|
||||
return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg,
|
||||
c, region);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ struct rrset_parse;
|
|||
struct rr_parse;
|
||||
struct regional;
|
||||
struct edns_option;
|
||||
struct config_file;
|
||||
struct comm_point;
|
||||
|
||||
/** number of buckets in parse rrset hash table. Must be power of 2. */
|
||||
#define PARSE_TABLE_SIZE 32
|
||||
|
|
@ -225,8 +227,15 @@ struct edns_data {
|
|||
uint16_t bits;
|
||||
/** UDP reassembly size. */
|
||||
uint16_t udp_size;
|
||||
/** rdata element list, or NULL if none */
|
||||
struct edns_option* opt_list;
|
||||
/** rdata element list of options of an incoming packet created at
|
||||
* parse time, or NULL if none */
|
||||
struct edns_option* opt_list_in;
|
||||
/** rdata element list of options to encode for outgoing packets,
|
||||
* or NULL if none */
|
||||
struct edns_option* opt_list_out;
|
||||
/** rdata element list of outgoing edns options from modules
|
||||
* or NULL if none */
|
||||
struct edns_option* opt_list_inplace_cb_out;
|
||||
/** block size to pad */
|
||||
uint16_t padding_block_size;
|
||||
};
|
||||
|
|
@ -281,8 +290,8 @@ int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg,
|
|||
* @return: 0 on success. or an RCODE on an error.
|
||||
* RCODE formerr if OPT in wrong section, and so on.
|
||||
*/
|
||||
int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
|
||||
struct regional* region);
|
||||
int parse_extract_edns_from_response_msg(struct msg_parse* msg,
|
||||
struct edns_data* edns, struct regional* region);
|
||||
|
||||
/**
|
||||
* If EDNS data follows a query section, extract it and initialize edns struct.
|
||||
|
|
@ -290,12 +299,14 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
|
|||
* section. At end, right after EDNS data or no movement if failed.
|
||||
* @param edns: the edns data allocated by the caller. Does not have to be
|
||||
* initialised.
|
||||
* @param cfg: the configuration (with nsid value etc.)
|
||||
* @param c: commpoint to determine transport (if needed)
|
||||
* @param region: region to alloc results in (edns option contents)
|
||||
* @return: 0 on success, or an RCODE on error.
|
||||
* RCODE formerr if OPT is badly formatted and so on.
|
||||
*/
|
||||
int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
|
||||
struct regional* region);
|
||||
int parse_edns_from_query_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
|
||||
struct config_file* cfg, struct comm_point* c, struct regional* region);
|
||||
|
||||
/**
|
||||
* Calculate hash value for rrset in packet.
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
|
|||
if((ret = parse_packet(pkt, msg, region)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
if((ret = parse_extract_edns(msg, edns, region)) != 0)
|
||||
if((ret = parse_extract_edns_from_response_msg(msg, edns, region)) != 0)
|
||||
return ret;
|
||||
|
||||
/* parse OK, allocate return structures */
|
||||
|
|
@ -989,34 +989,6 @@ parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region,
|
|||
return rep;
|
||||
}
|
||||
|
||||
int edns_opt_append(struct edns_data* edns, struct regional* region,
|
||||
uint16_t code, size_t len, uint8_t* data)
|
||||
{
|
||||
struct edns_option** prevp;
|
||||
struct edns_option* opt;
|
||||
|
||||
/* allocate new element */
|
||||
opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
|
||||
if(!opt)
|
||||
return 0;
|
||||
opt->next = NULL;
|
||||
opt->opt_code = code;
|
||||
opt->opt_len = len;
|
||||
opt->opt_data = NULL;
|
||||
if(len > 0) {
|
||||
opt->opt_data = regional_alloc_init(region, data, len);
|
||||
if(!opt->opt_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* append at end of list */
|
||||
prevp = &edns->opt_list;
|
||||
while(*prevp != NULL)
|
||||
prevp = &((*prevp)->next);
|
||||
*prevp = opt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
uint8_t* data, struct regional* region)
|
||||
{
|
||||
|
|
@ -1097,7 +1069,7 @@ static int inplace_cb_reply_call_generic(
|
|||
(void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep,
|
||||
rcode, edns, &opt_list_out, repinfo, region, start_time, cb->id, cb->cb_arg);
|
||||
}
|
||||
edns->opt_list = opt_list_out;
|
||||
edns->opt_list_inplace_cb_out = opt_list_out;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -518,18 +518,6 @@ void log_reply_info(enum verbosity_value v, struct query_info *qinf,
|
|||
void log_query_info(enum verbosity_value v, const char* str,
|
||||
struct query_info* qinf);
|
||||
|
||||
/**
|
||||
* Append edns option to edns data structure
|
||||
* @param edns: the edns data structure to append the edns option to.
|
||||
* @param region: region to allocate the new edns option.
|
||||
* @param code: the edns option's code.
|
||||
* @param len: the edns option's length.
|
||||
* @param data: the edns option's data.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int edns_opt_append(struct edns_data* edns, struct regional* region,
|
||||
uint16_t code, size_t len, uint8_t* data);
|
||||
|
||||
/**
|
||||
* Append edns option to edns option list
|
||||
* @param list: the edns option list to append the edns option to.
|
||||
|
|
|
|||
50
util/edns.c
50
util/edns.c
|
|
@ -128,53 +128,3 @@ edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
|
|||
return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
|
||||
}
|
||||
|
||||
static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in,
|
||||
struct comm_point* c, struct regional* region)
|
||||
{
|
||||
if(c->type == comm_udp)
|
||||
return 1;
|
||||
|
||||
/* To respond with a Keepalive option, the client connection
|
||||
* must have received one message with a TCP Keepalive EDNS option,
|
||||
* and that option must have 0 length data. Subsequent messages
|
||||
* sent on that connection will have a TCP Keepalive option.
|
||||
*/
|
||||
if(c->tcp_keepalive ||
|
||||
edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_KEEPALIVE)) {
|
||||
int keepalive = c->tcp_timeout_msec / 100;
|
||||
uint8_t data[2];
|
||||
data[0] = (uint8_t)((keepalive >> 8) & 0xff);
|
||||
data[1] = (uint8_t)(keepalive & 0xff);
|
||||
if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_KEEPALIVE,
|
||||
sizeof(data), data, region))
|
||||
return 0;
|
||||
c->tcp_keepalive = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in,
|
||||
struct config_file* cfg, struct comm_point* c, struct regional* region)
|
||||
{
|
||||
if(cfg->do_tcp_keepalive &&
|
||||
!edns_keepalive(edns_out, edns_in, c, region))
|
||||
return 0;
|
||||
|
||||
if (cfg->nsid && edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_NSID)
|
||||
&& !edns_opt_list_append(&edns_out->opt_list,
|
||||
LDNS_EDNS_NSID, cfg->nsid_len, cfg->nsid, region))
|
||||
return 0;
|
||||
|
||||
if(!cfg->pad_responses || c->type != comm_tcp || !c->ssl
|
||||
|| !edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_PADDING)) {
|
||||
; /* pass */
|
||||
}
|
||||
|
||||
else if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_PADDING
|
||||
, 0, NULL, region))
|
||||
return 0;
|
||||
else
|
||||
edns_out->padding_block_size = cfg->pad_responses_block_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
12
util/edns.h
12
util/edns.h
|
|
@ -106,16 +106,4 @@ struct edns_string_addr*
|
|||
edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Apply common EDNS options.
|
||||
*
|
||||
* @param edns_out: initialised edns information with outbound edns.
|
||||
* @param edns_in: initialised edns information with received edns.
|
||||
* @param cfg: configuration.
|
||||
* @param c: comm channel.
|
||||
* @param region: the region to allocate the edns options in.
|
||||
*/
|
||||
int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in,
|
||||
struct config_file* cfg, struct comm_point* c, struct regional* region);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2377,7 +2377,9 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
|
|||
edns.ext_rcode = 0;
|
||||
edns.edns_version = 0;
|
||||
edns.bits = EDNS_DO;
|
||||
edns.opt_list = NULL;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
if(sldns_buffer_capacity(buf) < 65535)
|
||||
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
|
||||
|
|
|
|||
Loading…
Reference in a new issue