edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- edns->opt_list = NULL;
+ edns->opt_list_in = NULL;
+ edns->opt_list_out = NULL;
edns->opt_list_modules_out = NULL;
error_encode(pkt, rcode, qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(pkt),
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_modules_out = NULL;
edns.padding_block_size = 0;
verbose(VERB_ALGO, "query with bad edns version.");
edns.udp_size = NORMAL_UDP_SIZE;
}
if(c->type != comm_udp) {
- edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE);
+ /* @TODO reuse what we found at parse time */
+ edns_opt = edns_opt_list_find(edns.opt_list_in, 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;
+ edns.opt_list_in = NULL;
+ edns.opt_list_out = NULL;
edns.opt_list_modules_out = NULL;
verbose(VERB_ALGO, "query with bad edns keepalive.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
* 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));
}
/* 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");
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_modules_out = NULL;
edns->padding_block_size = 0;
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
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_modules_out = NULL;
edns.padding_block_size = 0;
if(sldns_buffer_capacity(buf) < 65535)
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_modules_out = NULL;
edns.padding_block_size = 0;
if(sldns_buffer_capacity(buf) < 65535)
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_modules_out = NULL;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
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;
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");
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;
}
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;
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_modules_out, r->edns.opt_list_modules_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);
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,
+ if(edns->opt_list_in || edns->opt_list_out || edns->opt_list_modules_out) {
+ r->edns.opt_list_in = edns_opt_copy_region(edns->opt_list_in,
s->s.region);
- if(!r->edns.opt_list)
+ if(!r->edns.opt_list_in)
+ return 0;
+ r->edns.opt_list_out = edns_opt_copy_region(edns->opt_list_out,
+ s->s.region);
+ if(!r->edns.opt_list_out)
+ return 0;
+ r->edns.opt_list_modules_out = edns_opt_copy_region(edns->opt_list_modules_out,
+ s->s.region);
+ if(!r->edns.opt_list_modules_out)
return 0;
}
r->qid = qid;
return 0;
r->query_reply = *rep;
r->edns = *edns;
- if(edns->opt_list) {
- r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
+ if(edns->opt_list_in || edns->opt_list_out || edns->opt_list_modules_out) {
+ r->edns.opt_list_in = edns_opt_copy_region(edns->opt_list_in,
+ s->s.region);
+ if(!r->edns.opt_list_in)
+ return 0;
+ r->edns.opt_list_out = edns_opt_copy_region(edns->opt_list_out,
+ s->s.region);
+ if(!r->edns.opt_list_out)
+ return 0;
+ r->edns.opt_list_modules_out = edns_opt_copy_region(edns->opt_list_modules_out,
s->s.region);
- if(!r->edns.opt_list)
+ if(!r->edns.opt_list_modules_out)
return 0;
}
r->qid = qid;
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_modules_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)
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);
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_modules_out = NULL;
attach_edns_record(pend->buffer, &edns);
}
memcpy(&pend->addr, addr, addrlen);
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_modules_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 */
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_modules_out; opt; opt=opt->next) {
+ 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;
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);
}
rdata_len -= 4;
if(opt_len > rdata_len)
break; /* option code partial */
- if(!edns_opt_append(edns, region, opt_code, opt_len,
- rdata_ptr)) {
+ if(!edns_opt_list_append(&edns->opt_list_in, opt_code, opt_len,
+ rdata_ptr, region)) {
log_err("out of memory");
return 0;
}
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_modules_out = NULL;
edns->padding_block_size = 0;
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_modules_out = NULL;
edns->padding_block_size = 0;
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_modules_out;
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)
{
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.
* 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)) {
+ edns_opt_list_find(edns_in->opt_list_in, 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,
+ if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_KEEPALIVE,
sizeof(data), data, region))
return 0;
c->tcp_keepalive = 1;
!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,
+ if (cfg->nsid && edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_NSID)
+ && !edns_opt_list_append(&edns_out->opt_list_out,
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)) {
+ || !edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_PADDING)) {
; /* pass */
}
- else if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_PADDING
+ else if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_PADDING
, 0, NULL, region))
return 0;
else
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_modules_out = NULL;
edns.padding_block_size = 0;
if(sldns_buffer_capacity(buf) < 65535)