diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index af4ffe5f..725bc6ce 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -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; diff --git a/daemon/worker.c b/daemon/worker.c index 8880cac1..5d2483cd 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1239,7 +1239,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, } goto send_reply; } - if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->env.cfg, c, + 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."); diff --git a/iterator/iterator.c b/iterator/iterator.c index 64a0602d..55d53da6 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -3852,7 +3852,7 @@ 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; diff --git a/pythonmod/pythonmod_utils.c b/pythonmod/pythonmod_utils.c index 21a16bbe..34a20ba7 100644 --- a/pythonmod/pythonmod_utils.c +++ b/pythonmod/pythonmod_utils.c @@ -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; diff --git a/util/data/msgparse.c b/util/data/msgparse.c index fcf2f232..415973cd 100644 --- a/util/data/msgparse.c +++ b/util/data/msgparse.c @@ -953,7 +953,7 @@ edns_opt_list_append_keepalive(struct edns_option** list, int msec, /** parse EDNS options from EDNS wireformat rdata */ static int -parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len, +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) { @@ -1044,8 +1044,8 @@ parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len, } 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; @@ -1107,11 +1107,26 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, /* 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, NULL, NULL, region)) - return LDNS_RCODE_NOERROR; + /* 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 LDNS_RCODE_NOERROR; } @@ -1142,7 +1157,7 @@ skip_pkt_rrs(sldns_buffer* pkt, int num) } int -parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns, +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; @@ -1186,7 +1201,8 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns, return LDNS_RCODE_FORMERR; rdata_ptr = sldns_buffer_current(pkt); /* ignore rrsigs */ - return parse_edns_options(rdata_ptr, rdata_len, edns, cfg, c, region); + return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg, + c, region); } void diff --git a/util/data/msgparse.h b/util/data/msgparse.h index 0c70d3b1..4c0559a7 100644 --- a/util/data/msgparse.h +++ b/util/data/msgparse.h @@ -290,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. @@ -305,7 +305,7 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, * @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, +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); /** diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 5fb28a9e..ec46e472 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -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 */