enum module_ext_state eval_response(struct module_qstate* qstate)
{
- if (!qstate->edns_out.subnet_sent) {
- if (qstate->edns_in.subnet_validdata)
+ if (!qstate->edns_server_out.subnet_sent) {
+ if (qstate->edns_server_in.subnet_validdata)
verbose(VERB_QUERY, "subnet: received spurious data");
- if (qstate->edns_out.subnet_downstream) {
+ if (qstate->edns_client_in.subnet_downstream) {
/* Copy question back to client */
- qstate->edns_to_client = &qstate->edns_in;
- cp_edns_bad_response(qstate->edns_to_client,
- qstate->edns_from_client);
+ cp_edns_bad_response(&qstate->edns_client_out,
+ &qstate->edns_client_in);
}
return module_finished;
}
/* subnet sent but nothing came back */
- if (!qstate->edns_in.subnet_validdata) {
+ if (!qstate->edns_server_in.subnet_validdata) {
/** The authority indicated no support for vandergaast. As a
* consequence the answer ended up in the regular cache. It
* is still usefull to put it in the vandergaast cache for
* when a client explicitly asks for subnet specific answer. */
verbose(VERB_QUERY, "subnet: Authority indicates no support");
// TODO PUT IT IN OUR SPECIAL CACHE
- if (qstate->edns_out.subnet_downstream) {
- qstate->edns_to_client = &qstate->edns_in;
- cp_edns_bad_response(qstate->edns_to_client,
- qstate->edns_from_client);
+ if (qstate->edns_client_in.subnet_downstream) {
+ cp_edns_bad_response(&qstate->edns_client_out,
+ &qstate->edns_client_in);
}
return module_finished;
}
/* can we accept response? */
size_t sn_octs, remainder;
- sn_octs = qstate->edns_out.subnet_source_mask / 8;
+ sn_octs = qstate->edns_server_out.subnet_source_mask / 8;
assert(sn_octs <= INET6_SIZE); /* Enforced by msgparse */
- remainder = 8 - (size_t)(qstate->edns_out.subnet_source_mask % 8);
- if(qstate->edns_out.subnet_addr_fam != qstate->edns_in.subnet_addr_fam ||
- qstate->edns_out.subnet_source_mask != qstate->edns_in.subnet_source_mask ||
- memcmp(qstate->edns_out.subnet_addr, qstate->edns_in.subnet_addr, sn_octs) != 0 ||
- (qstate->edns_out.subnet_addr[sn_octs]^qstate->edns_in.subnet_addr[sn_octs])>>remainder) {
+ remainder = 8 - (size_t)(qstate->edns_server_out.subnet_source_mask % 8);
+ if(qstate->edns_server_out.subnet_addr_fam != qstate->edns_server_in.subnet_addr_fam ||
+ qstate->edns_server_out.subnet_source_mask != qstate->edns_server_in.subnet_source_mask ||
+ memcmp(qstate->edns_server_out.subnet_addr, qstate->edns_server_in.subnet_addr, sn_octs) != 0 ||
+ //YBS should this just be equal?
+ (qstate->edns_server_out.subnet_addr[sn_octs]^qstate->edns_server_in.subnet_addr[sn_octs])>>remainder) {
/* we can not, restart query without option */
verbose(VERB_QUERY, "subnet: forged data");
- qstate->edns_out.subnet_validdata = 0;
- qstate->edns_out.subnet_sent = 0;
+ qstate->edns_server_out.subnet_validdata = 0;
+ qstate->edns_server_out.subnet_sent = 0;
return module_wait_module;
}
/* TODO PUT IT IN OUR SPECIAL CACHE */
- if (qstate->edns_out.subnet_downstream) {
+ if (qstate->edns_client_in.subnet_downstream) {
/* Client wants to see the answer, echo option back
* and adjust the scope. */
- qstate->edns_to_client = qstate->edns_from_client;
+ memcpy(&qstate->edns_client_out, &qstate->edns_client_in,
+ sizeof(qstate->edns_client_in));
verbose(VERB_QUERY, "subnet: attach");
- qstate->edns_to_client->subnet_scope_mask =
- qstate->edns_in.subnet_scope_mask;
+ qstate->edns_client_out.subnet_scope_mask =
+ qstate->edns_server_in.subnet_scope_mask;
}
verbose(VERB_QUERY, "subnet: done");
return module_finished;
void* cachehit;
int max_mask;
#endif
- struct edns_data* edns_from_client;
struct subnet_env* sne = (struct subnet_env*)qstate->env->modinfo[id];
struct subnet_qstate* snq = (struct subnet_qstate*)qstate->minfo[id];
log_query_info(VERB_QUERY, "subnet operate: query", &qstate->qinfo);
if(event == module_event_new) {
- edns_from_client = qstate->edns_from_client;
-
- if(!edns_from_client || !edns_from_client->subnet_validdata) {
+ if(!qstate->edns_client_in.subnet_validdata) {
/* No clients are interested in result or we could not
* parse it, we don't do client subnet */
- qstate->edns_out.subnet_validdata = 0;
+ qstate->edns_server_out.subnet_validdata = 0;
verbose(VERB_ALGO, "subnet: pass to next module");
qstate->ext_state[id] = module_wait_module;
return;
}
/* copy information from client request to upstream query */
- memcpy(&qstate->edns_out, edns_from_client, sizeof(struct edns_data));
- qstate->edns_out.subnet_scope_mask = 0;
- qstate->edns_out.subnet_sent = 0;
+ memcpy(&qstate->edns_server_out, &qstate->edns_client_in, sizeof(struct edns_data));
+ qstate->edns_server_out.subnet_scope_mask = 0;
+ qstate->edns_server_out.subnet_sent = 0;
#if 0
while(1) {
/* cache returns valid answer with largest mask. */
/* Query handed back by next module, we have a 'final' answer */
if(event == module_event_moddone) {
verbose(VERB_QUERY, "subnet: done");
- qstate->edns_to_client = NULL;
qstate->ext_state[id] = eval_response(qstate);
return;
}
}
#ifdef CLIENT_SUBNET
/* Do not cache, we asked for and got subnet option */
- if(!qstate->edns_in.subnet_validdata ||
- !qstate->edns_out.subnet_sent) {
+ if(!qstate->edns_server_in.subnet_validdata ||
+ !qstate->edns_server_out.subnet_sent) {
#endif
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
}
memset(prs, 0, sizeof(*prs));
#ifdef CLIENT_SUBNET
- memset(&qstate->edns_in, 0, sizeof(qstate->edns_in));
+ memset(&qstate->edns_server_in, 0, sizeof(qstate->edns_server_in));
#else
memset(&edns, 0, sizeof(edns));
#endif
goto handle_it;
}
#ifdef CLIENT_SUBNET
- if(parse_extract_edns(prs, &qstate->edns_in) != LDNS_RCODE_NOERROR)
+ if(parse_extract_edns(prs, &qstate->edns_server_in) != LDNS_RCODE_NOERROR)
#else
/* edns is not examined, but removed from message to help cache */
if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
/** Returns a==b: 0, a<b: positive, a>b: negative */
int subnet_compare(struct edns_data *a, struct edns_data *b)
{
- if (!a) {
- if (b) return 1;
- return 0;
- } else {
- if (!b) return -1;
- /* crude way:
- * return memcmp(b, a, sizeof(struct edns_data)); */
-
- if ( a->edns_present && !b->edns_present) return -1;
- if (!a->edns_present && !b->edns_present) return 0;
- if (!a->edns_present && b->edns_present) return 1;
+ if ( a->edns_present && !b->edns_present) return -1;
+ if (!a->edns_present && !b->edns_present) return 0;
+ if (!a->edns_present && b->edns_present) return 1;
- if ( a->subnet_validdata && !b->subnet_validdata) return -1;
- if (!a->subnet_validdata && !b->subnet_validdata) return 0;
- if (!a->subnet_validdata && b->subnet_validdata) return 1;
-
- if (a->subnet_addr_fam != b->subnet_addr_fam) {
- return b->subnet_addr_fam - a->subnet_addr_fam;
- }
- if (a->subnet_source_mask != b->subnet_source_mask) {
- return b->subnet_source_mask - a->subnet_source_mask;
- }
- return memcmp(b->subnet_addr, a->subnet_addr, INET6_SIZE);
-
+ if ( a->subnet_validdata && !b->subnet_validdata) return -1;
+ if (!a->subnet_validdata && !b->subnet_validdata) return 0;
+ if (!a->subnet_validdata && b->subnet_validdata) return 1;
+
+ if (a->subnet_addr_fam != b->subnet_addr_fam) {
+ return b->subnet_addr_fam - a->subnet_addr_fam;
}
+ if (a->subnet_source_mask != b->subnet_source_mask) {
+ return b->subnet_source_mask - a->subnet_source_mask;
+ }
+ return memcmp(b->subnet_addr, a->subnet_addr, INET6_SIZE);
}
#endif
return 1;
#ifdef CLIENT_SUBNET
- r = subnet_compare(a->s.edns_from_client, b->s.edns_from_client);
+ r = subnet_compare(&a->s.edns_client_in, &b->s.edns_client_in);
if (r != 0) return r;
#endif
return query_info_compare(&a->s.qinfo, &b->s.qinfo);
}
#endif /* INET6 */
}
- s->s.edns_from_client = edns;
+ memcpy(&s->s.edns_client_in, edns, sizeof(struct edns_data));
#endif /* CLIENT_SUBNET */
/* update statistics */
if(was_detached) {
mstate->s.env = env;
mstate->s.mesh_info = mstate;
mstate->s.prefetch_leeway = 0;
-#ifdef CLIENT_SUBNET
- mstate->s.edns_from_client = NULL;
- mstate->s.edns_to_client = NULL;
-#endif
/* init modules */
for(i=0; i<env->mesh->mods.num; i++) {
mstate->s.minfo[i] = NULL;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
#ifdef CLIENT_SUBNET
- if(m->s.edns_to_client && m->s.edns_to_client->subnet_validdata) {
+ if(m->s.edns_client_out.subnet_validdata) {
r->edns.subnet_validdata = 1;
- r->edns.subnet_addr_fam = m->s.edns_to_client->subnet_addr_fam;
- r->edns.subnet_source_mask = m->s.edns_to_client->subnet_source_mask;
- r->edns.subnet_scope_mask = m->s.edns_to_client->subnet_scope_mask;
- memcpy(r->edns.subnet_addr, m->s.edns_to_client->subnet_addr, INET6_SIZE);
+ r->edns.subnet_addr_fam = m->s.edns_client_out.subnet_addr_fam;
+ r->edns.subnet_source_mask = m->s.edns_client_out.subnet_source_mask;
+ r->edns.subnet_scope_mask = m->s.edns_client_out.subnet_scope_mask;
+ memcpy(r->edns.subnet_addr, m->s.edns_client_out.subnet_addr, INET6_SIZE);
} else r->edns.subnet_validdata = 0;
#endif
m->s.qinfo.qname = r->qname;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
#ifdef CLIENT_SUBNET
- key.s.edns_from_client = NULL; /* is used in subnet cmp function */
+ key.s.edns_client_in.edns_present = 0;
+ key.s.edns_client_in.subnet_validdata = 0;
#endif
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);