mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- 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
This commit is contained in:
parent
3904c2be9a
commit
031caba9c0
15 changed files with 186 additions and 61 deletions
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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().
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
int edns_opt_list_equal(struct edns_option* p, struct edns_option* q);
|
||||
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_compare(struct edns_option* p, struct edns_option* q);
|
||||
|
||||
#endif /* UTIL_DATA_MSGREPLY_H */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue