From: Yuri Schaeffer Date: Thu, 21 Mar 2013 15:10:53 +0000 (+0000) Subject: more straightforward way of managing edns communication X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c24e0c16b8a1ee32e584fa25025fae62ab994cb7;p=thirdparty%2Funbound.git more straightforward way of managing edns communication git-svn-id: file:///svn/unbound/branches/edns-subnet@2867 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index d3860ffce..22819e598 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1282,7 +1282,7 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, addrlen, zone, zonelen, worker_handle_service_reply, e, worker->back->udp_buff #ifdef CLIENT_SUBNET - , &q->edns_out + , &q->edns_server_out #endif ); if(!e->qsent) { diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index d1101c173..91bf9593e 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -73,30 +73,28 @@ void cp_edns_bad_response(struct edns_data* target, struct edns_data* source) 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; } @@ -106,29 +104,31 @@ enum module_ext_state eval_response(struct module_qstate* qstate) /* 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; @@ -141,7 +141,6 @@ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, 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]; @@ -151,20 +150,18 @@ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, 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. */ @@ -223,7 +220,6 @@ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, /* 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; } diff --git a/iterator/iterator.c b/iterator/iterator.c index 8885832a6..f0f9ef427 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1934,8 +1934,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, } #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, @@ -2740,7 +2740,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, } 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 @@ -2751,7 +2751,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, 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) diff --git a/libunbound/libworker.c b/libunbound/libworker.c index 2bad0ba60..d6c28b424 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -752,7 +752,7 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, addrlen, zone, zonelen, libworker_handle_service_reply, e, w->back->udp_buff #ifdef CLIENT_SUBNET - , &q->edns_out + , &q->edns_server_out #endif ); diff --git a/services/mesh.c b/services/mesh.c index 43474101f..bcb3d447d 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -128,31 +128,21 @@ timeval_smaller(const struct timeval* x, const struct timeval* y) /** Returns a==b: 0, ab: 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 @@ -183,7 +173,7 @@ mesh_state_compare(const void* ap, const void* bp) 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); @@ -425,7 +415,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* 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) { @@ -624,10 +614,6 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo, 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; imesh->mods.num; i++) { mstate->s.minfo[i] = NULL; @@ -964,12 +950,12 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, 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; @@ -1047,7 +1033,8 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh, 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); diff --git a/validator/validator.c b/validator/validator.c index 139511c5d..c90e57ebc 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -1985,8 +1985,8 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, #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 /* store results in cache */ if(qstate->query_flags&BIT_RD) {