From: Wouter Wijngaards Date: Tue, 31 May 2016 16:55:22 +0000 (+0000) Subject: - and also generic edns options for upstream messages (and replies). X-Git-Tag: release-1.5.9rc1~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=031caba9c06bbd65e194c78489f14c944cb85761;p=thirdparty%2Funbound.git - and also generic edns options for upstream messages (and replies). after parse use edns_opt_find(edns.opt_list, LDNS_EDNS_NSID), to insert use edns_opt_append(edns, region, code, len, bindata) on the opt_list passed to send_query, or in edns_opt_inplace_reply. git-svn-id: file:///svn/unbound/trunk@3742 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index b08474fb1..84c004ed6 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1370,8 +1370,9 @@ worker_delete(struct worker* worker) struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec, - int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* q) + int nocaps, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, struct module_qstate* q) { struct worker* worker = q->env->worker; struct outbound_entry* e = (struct outbound_entry*)regional_alloc( @@ -1381,8 +1382,8 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, e->qstate = q; e->qsent = outnet_serviced_query(worker->back, qname, qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps, - q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, - addrlen, zone, zonelen, worker_handle_service_reply, e, + q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list, + addr, addrlen, zone, zonelen, worker_handle_service_reply, e, worker->back->udp_buff); if(!e->qsent) { return NULL; @@ -1427,7 +1428,8 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname), size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), + int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list), + struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) { diff --git a/doc/Changelog b/doc/Changelog index 6293ce7aa..a6bce071c 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,10 @@ network service account, from Mario Turschmann. - compat strsep implementation. - generic edns option parse and store code. + - and also generic edns options for upstream messages (and replies). + after parse use edns_opt_find(edns.opt_list, LDNS_EDNS_NSID), + to insert use edns_opt_append(edns, region, code, len, bindata) on + the opt_list passed to send_query, or in edns_opt_inplace_reply. 30 May 2016: Wouter - Fix time in case answer comes from cache in ub_resolve_event(). diff --git a/iterator/iterator.c b/iterator/iterator.c index bcce7e6fc..139cae4ba 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1786,6 +1786,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, int tf_policy; struct delegpt_addr* target; struct outbound_entry* outq; + /* EDNS options to set on outgoing packet */ + struct edns_option* opt_list = NULL; /* NOTE: a request will encounter this state for each target it * needs to send a query to. That is, at least one per referral, @@ -2103,8 +2105,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env, &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( - ie, iq), &target->addr, target->addrlen, iq->dp->name, - iq->dp->namelen, qstate); + ie, iq), opt_list, &target->addr, target->addrlen, + iq->dp->name, iq->dp->namelen, qstate); if(!outq) { log_addr(VERB_DETAIL, "error sending query to auth server", &target->addr, target->addrlen); diff --git a/libunbound/libworker.c b/libunbound/libworker.c index 8129f8c01..3065bede4 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -822,9 +822,9 @@ void libworker_alloc_cleanup(void* arg) struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, - int want_dnssec, int nocaps, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - struct module_qstate* q) + int want_dnssec, int nocaps, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, struct module_qstate* q) { struct libworker* w = (struct libworker*)q->env->worker; struct outbound_entry* e = (struct outbound_entry*)regional_alloc( @@ -834,9 +834,9 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, e->qstate = q; e->qsent = outnet_serviced_query(w->back, qname, qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps, - q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, - addrlen, zone, zonelen, libworker_handle_service_reply, e, - w->back->udp_buff); + q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list, + addr, addrlen, zone, zonelen, libworker_handle_service_reply, + e, w->back->udp_buff); if(!e->qsent) { return NULL; } @@ -955,7 +955,8 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), + int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list), + struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) { diff --git a/libunbound/worker.h b/libunbound/worker.h index a53150199..b8d8dd88a 100644 --- a/libunbound/worker.h +++ b/libunbound/worker.h @@ -48,6 +48,7 @@ struct comm_reply; struct comm_point; struct module_qstate; struct tube; +struct edns_option; /** * Worker service routine to send serviced queries to authoritative servers. @@ -59,6 +60,7 @@ struct tube; * @param dnssec: if set, EDNS record will have DO bit set. * @param want_dnssec: signatures needed. * @param nocaps: ignore capsforid(if in config), do not perturb qname. + * @param opt_list: EDNS options on outgoing packet. * @param addr: where to. * @param addrlen: length of addr. * @param zone: delegation point name. @@ -69,9 +71,9 @@ struct tube; */ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, - int want_dnssec, int nocaps, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - struct module_qstate* q); + int want_dnssec, int nocaps, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, struct module_qstate* q); /** process incoming replies from the network */ int libworker_handle_reply(struct comm_point* c, void* arg, int error, @@ -114,6 +116,7 @@ void worker_sighandler(int sig, void* arg); * @param dnssec: if set, EDNS record will have DO bit set. * @param want_dnssec: signatures needed. * @param nocaps: ignore capsforid(if in config), do not perturb qname. + * @param opt_list: EDNS options on outgoing packet. * @param addr: where to. * @param addrlen: length of addr. * @param zone: wireformat dname of the zone. @@ -124,9 +127,9 @@ void worker_sighandler(int sig, void* arg); */ struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, - int want_dnssec, int nocaps, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - struct module_qstate* q); + int want_dnssec, int nocaps, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, struct module_qstate* q); /** * process control messages from the main thread. Frees the control diff --git a/services/mesh.c b/services/mesh.c index 2df5ad62f..8f74cbe82 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -865,7 +865,8 @@ 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_equal(prev->edns.opt_list, r->edns.opt_list)) { + edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list) + == 0) { /* if the previous reply is identical to this one, fix ID */ if(prev->query_reply.c->buffer != r->query_reply.c->buffer) sldns_buffer_copy(r->query_reply.c->buffer, diff --git a/services/outside_network.c b/services/outside_network.c index 56f46f42e..d9e34f469 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -122,6 +122,8 @@ serviced_cmp(const void* key1, const void* key2) } if((r = query_dname_compare(q1->qbuf+10, q2->qbuf+10)) != 0) return r; + if((r = edns_opt_list_compare(q1->opt_list, q2->opt_list)) != 0) + return r; return sockaddr_cmp(&q1->addr, q1->addrlen, &q2->addr, q2->addrlen); } @@ -757,6 +759,7 @@ serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg)) struct service_callback* p = sq->cblist, *np; free(sq->qbuf); free(sq->zone); + edns_opt_list_free(sq->opt_list); while(p) { np = p->next; free(p); @@ -1219,7 +1222,8 @@ serviced_gen_query(sldns_buffer* buff, uint8_t* qname, size_t qnamelen, /** lookup serviced query in serviced query rbtree */ static struct serviced_query* lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec, - struct sockaddr_storage* addr, socklen_t addrlen) + struct sockaddr_storage* addr, socklen_t addrlen, + struct edns_option* opt_list) { struct serviced_query key; key.node.key = &key; @@ -1229,6 +1233,7 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec, memcpy(&key.addr, addr, addrlen); key.addrlen = addrlen; key.outnet = outnet; + key.opt_list = opt_list; return (struct serviced_query*)rbtree_search(outnet->serviced, &key); } @@ -1237,7 +1242,7 @@ static struct serviced_query* serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int qtype) + size_t zonelen, int qtype, struct edns_option* opt_list) { struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq)); #ifdef UNBOUND_DEBUG @@ -1267,6 +1272,16 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, sq->ssl_upstream = ssl_upstream; memcpy(&sq->addr, addr, addrlen); sq->addrlen = addrlen; + sq->opt_list = NULL; + if(opt_list) { + sq->opt_list = edns_opt_copy_alloc(opt_list); + if(!sq->opt_list) { + free(sq->zone); + free(sq->qbuf); + free(sq); + return NULL; + } + } sq->outnet = outnet; sq->cblist = NULL; sq->pending = NULL; @@ -1394,9 +1409,7 @@ 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; - /* insert EDNS options here for upstream messages, - * stored from sq */ - edns.opt_list = NULL; + edns.opt_list = sq->opt_list; if(sq->status == serviced_query_UDP_EDNS_FRAG) { if(addr_is_ip6(&sq->addr, sq->addrlen)) { if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE) @@ -1919,15 +1932,15 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec, int nocaps, - int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - comm_point_callback_t* callback, void* callback_arg, + int tcp_upstream, int ssl_upstream, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, comm_point_callback_t* callback, void* callback_arg, sldns_buffer* buff) { struct serviced_query* sq; struct service_callback* cb; serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags); - sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen); + sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen, opt_list); /* duplicate entries are included in the callback list, because * there is a counterpart registration by our caller that needs to * be doubly-removed (with callbacks perhaps). */ @@ -1937,7 +1950,7 @@ outnet_serviced_query(struct outside_network* outnet, /* make new serviced query entry */ sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps, tcp_upstream, ssl_upstream, addr, addrlen, zone, - zonelen, (int)qtype); + zonelen, (int)qtype, opt_list); if(!sq) { free(cb); return NULL; diff --git a/services/outside_network.h b/services/outside_network.h index 36f798d3b..9a3270ee1 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -58,6 +58,7 @@ struct port_if; struct sldns_buffer; struct serviced_query; struct dt_env; +struct edns_option; /** * Send queries to outside servers and wait for answers from servers. @@ -367,6 +368,8 @@ struct serviced_query { int last_rtt; /** do we know edns probe status already, for UDP_EDNS queries */ int edns_lame_known; + /** edns options to use for sending upstream packet */ + struct edns_option* opt_list; /** outside network this is part of */ struct outside_network* outnet; /** list of interested parties that need callback on results. */ @@ -477,6 +480,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p); * @param nocaps: ignore use_caps_for_id and use unperturbed qname. * @param tcp_upstream: use TCP for upstream queries. * @param ssl_upstream: use SSL for upstream queries. + * @param opt_list: pass edns option list (deep copied into serviced query) + * these options are set on the outgoing packets. * @param callback: callback function. * @param callback_arg: user argument to callback function. * @param addr: to which server to send the query. @@ -492,9 +497,9 @@ void pending_delete(struct outside_network* outnet, struct pending* p); struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec, int nocaps, - int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - comm_point_callback_t* callback, void* callback_arg, + int tcp_upstream, int ssl_upstream, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, comm_point_callback_t* callback, void* callback_arg, struct sldns_buffer* buff); /** diff --git a/smallapp/worker_cb.c b/smallapp/worker_cb.c index 8193bec1b..6ed95ac01 100644 --- a/smallapp/worker_cb.c +++ b/smallapp/worker_cb.c @@ -103,7 +103,8 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), + int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list), + struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) { @@ -135,7 +136,8 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname), size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), + int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list), + struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) { diff --git a/testcode/fake_event.c b/testcode/fake_event.c index d50f8b03c..1578b7ddc 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1039,9 +1039,9 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), int ATTR_UNUSED(tcp_upstream), - int ATTR_UNUSED(ssl_upstream), struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - comm_point_callback_t* callback, void* callback_arg, + int ATTR_UNUSED(ssl_upstream), struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, comm_point_callback_t* callback, void* callback_arg, sldns_buffer* ATTR_UNUSED(buff)) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; @@ -1077,7 +1077,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits = 0; - edns.opt_list = NULL; + edns.opt_list = opt_list; if(dnssec) edns.bits = EDNS_DO; attach_edns_record(pend->buffer, &edns); diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 4cfc37d71..f8a24918d 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -923,22 +923,89 @@ struct edns_option* edns_opt_copy_region(struct edns_option* list, return result; } -int edns_opt_list_equal(struct edns_option* p, struct edns_option* q) +int edns_opt_compare(struct edns_option* p, struct edns_option* q) +{ + if(!p && !q) return 0; + if(!p) return -1; + if(!q) return 1; + log_assert(p && q); + if(p->opt_code != q->opt_code) + return (int)q->opt_code - (int)p->opt_code; + if(p->opt_len != q->opt_len) + return (int)q->opt_len - (int)p->opt_len; + if(p->opt_len != 0) + return memcmp(p->opt_data, q->opt_data, p->opt_len); + return 0; +} + +int edns_opt_list_compare(struct edns_option* p, struct edns_option* q) { + int r; while(p && q) { - /* compare elements */ - if(p->opt_code != q->opt_code || - p->opt_len != q->opt_len) - return 0; - if(p->opt_len > 0 && q->opt_len > 0) { - if(memcmp(p->opt_data, q->opt_data, p->opt_len) != 0) - return 0; - } - + r = edns_opt_compare(p, q); + if(r != 0) + return r; p = p->next; q = q->next; } - if(p || q) - return 0; /* uneven length lists */ - return 1; + if(p || q) { + /* uneven length lists */ + if(p) return 1; + if(q) return -1; + } + return 0; +} + +void edns_opt_list_free(struct edns_option* list) +{ + struct edns_option* n; + while(list) { + free(list->opt_data); + n = list->next; + free(list); + list = n; + } +} + +struct edns_option* edns_opt_copy_alloc(struct edns_option* list) +{ + struct edns_option* result = NULL, *cur = NULL, *s; + while(list) { + /* copy edns option structure */ + s = memdup(list, sizeof(*list)); + if(!s) { + edns_opt_list_free(result); + return NULL; + } + s->next = NULL; + + /* copy option data */ + if(s->opt_data) { + s->opt_data = memdup(s->opt_data, s->opt_len); + if(!s->opt_data) { + edns_opt_list_free(result); + return NULL; + } + } + + /* link into list */ + if(cur) + cur->next = s; + else result = s; + cur = s; + + /* examine next element */ + list = list->next; + } + return result; +} + +struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code) +{ + struct edns_option* p; + for(p=list; p; p=p->next) { + if(p->opt_code == code) + return p; + } + return NULL; } diff --git a/util/data/msgreply.h b/util/data/msgreply.h index 32a822706..b542b75e6 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -443,6 +443,14 @@ void log_query_info(enum verbosity_value v, const char* str, int edns_opt_append(struct edns_data* edns, struct regional* region, uint16_t code, size_t len, uint8_t* data); +/** + * Find edns option in edns list + * @param list: list of edns options (eg. edns.opt_list) + * @param code: opt code to find. + * @return NULL or the edns_option element. + */ +struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code); + /** * Transform edns data structure from query structure into reply structure. * In place transform, for errors and cache replies. @@ -462,8 +470,23 @@ struct edns_option* edns_opt_copy_region(struct edns_option* list, struct regional* region); /** - * See if edns option lists are equal, also order and contents of options. + * Copy edns option list allocated with malloc + */ +struct edns_option* edns_opt_copy_alloc(struct edns_option* list); + +/** + * Free edns option list allocated with malloc + */ +void edns_opt_list_free(struct edns_option* list); + +/** + * Compare an edns option. (not entire list). Also compares contents. + */ +int edns_opt_compare(struct edns_option* p, struct edns_option* q); + +/** + * Compare edns option lists, also the order and contents of edns-options. */ -int edns_opt_list_equal(struct edns_option* p, struct edns_option* q); +int edns_opt_list_compare(struct edns_option* p, struct edns_option* q); #endif /* UTIL_DATA_MSGREPLY_H */ diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 63d0b8b6f..80a23f203 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -267,8 +267,8 @@ int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec, int nocaps, - struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, + struct edns_option* opt_list, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, struct module_qstate* q)) { if(fptr == &worker_send_query) return 1; diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index 10de5d816..98ca21bb9 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -212,7 +212,7 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr); int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec, int nocaps, - struct sockaddr_storage* addr, socklen_t addrlen, + struct edns_option*, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, struct module_qstate* q)); diff --git a/util/module.h b/util/module.h index b9dde36e2..c3ce8a40e 100644 --- a/util/module.h +++ b/util/module.h @@ -214,6 +214,8 @@ struct module_env { * EDNS, the answer is likely to be useless for this domain. * @param nocaps: do not use caps_for_id, use the qname as given. * (ignored if caps_for_id is disabled). + * @param opt_list: set these EDNS options on the outgoing packet. + * or NULL if none (the list is deep-copied). * @param addr: where to. * @param addrlen: length of addr. * @param zone: delegation point name. @@ -226,9 +228,9 @@ struct module_env { */ struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, - int want_dnssec, int nocaps, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, - struct module_qstate* q); + int want_dnssec, int nocaps, struct edns_option* opt_list, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* zone, size_t zonelen, struct module_qstate* q); /** * Detach-subqueries.