From: Yuri Schaeffer Date: Mon, 6 Aug 2012 15:37:51 +0000 (+0000) Subject: setup for appending subnet option in outbound replies and queries X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8471f2f0381ba73530de065c9bc9a0792d81675f;p=thirdparty%2Funbound.git setup for appending subnet option in outbound replies and queries git-svn-id: file:///svn/unbound/branches/edns-subnet@2742 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index 832278fc3..6d6993afb 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -475,6 +475,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + edns->subnet_option_add = 0; error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, &msg->qinfo, id, flags, edns); regional_free_all(worker->scratchpad); @@ -503,6 +504,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + edns->subnet_option_add = 0; msg->rep->flags |= BIT_QR|BIT_RA; if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags, repinfo->c->buffer, 0, 1, worker->scratchpad, @@ -561,6 +563,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + edns->subnet_option_add = 0; error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, qinfo, id, flags, edns); rrset_array_unlock_touch(worker->env.rrset_cache, @@ -592,6 +595,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + edns->subnet_option_add = 0; if(!reply_info_answer_encode(qinfo, rep, id, flags, repinfo->c->buffer, timenow, 1, worker->scratchpad, udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { @@ -665,6 +669,7 @@ chaos_replystr(ldns_buffer* pkt, const char* str, struct edns_data* edns) edns->edns_version = EDNS_ADVERTISED_VERSION; edns->udp_size = EDNS_ADVERTISED_SIZE; edns->bits &= EDNS_DO; + edns->subnet_option_add = 0; attach_edns_record(pkt, edns); } @@ -816,6 +821,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits &= EDNS_DO; + edns.subnet_option_add = 0; verbose(VERB_ALGO, "query with bad edns version."); log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo, diff --git a/services/localzone.c b/services/localzone.c index 98d69433e..6a166e257 100644 --- a/services/localzone.c +++ b/services/localzone.c @@ -1010,6 +1010,7 @@ local_encode(struct query_info* qinfo, struct edns_data* edns, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + edns->subnet_option_add = 0; if(!reply_info_answer_encode(qinfo, &rep, *(uint16_t*)ldns_buffer_begin(buf), ldns_buffer_read_u16_at(buf, 2), diff --git a/services/mesh.c b/services/mesh.c index f6fd288ad..6d16412ab 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -783,6 +783,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; r->edns.bits &= EDNS_DO; + r->edns.subnet_option_add = 0; if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid, r->qflags, r->buf, 0, 1, m->s.env->scratch, udp_size, &r->edns, @@ -854,6 +855,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; r->edns.bits &= EDNS_DO; + r->edns.subnet_option_add = 0; m->s.qinfo.qname = r->qname; if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid, r->qflags, r->query_reply.c->buffer, 0, 1, diff --git a/services/outside_network.c b/services/outside_network.c index 24d65db39..3ee3e47a3 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1323,6 +1323,7 @@ serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns) edns.edns_present = 1; edns.ext_rcode = 0; edns.edns_version = EDNS_ADVERTISED_VERSION; + edns.subnet_option_add = 0; if(sq->status == serviced_query_UDP_EDNS_FRAG) { if(addr_is_ip6(&sq->addr, sq->addrlen)) { if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE) diff --git a/util/config_file.c b/util/config_file.c index 6ab0c4a2c..1e05a9ae7 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -1091,6 +1091,7 @@ config_apply(struct config_file* config) MAX_TTL = (uint32_t)config->max_ttl; MIN_TTL = (uint32_t)config->min_ttl; EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size; + EDNS_SUBNET_OPC = (uint16_t)config->client_subnet_opc; MINIMAL_RESPONSES = config->minimal_responses; RRSET_ROUNDROBIN = config->rrset_roundrobin; log_set_time_asc(config->log_time_ascii); diff --git a/util/data/msgencode.c b/util/data/msgencode.c index 157796deb..c7cd60a96 100644 --- a/util/data/msgencode.c +++ b/util/data/msgencode.c @@ -728,7 +728,8 @@ calc_edns_field_size(struct edns_data* edns) void attach_edns_record(ldns_buffer* pkt, struct edns_data* edns) { - size_t len; + size_t len, sn_octs, sn_octs_remainder; + int i; if(!edns || !edns->edns_present) return; /* inc additional count */ @@ -744,7 +745,29 @@ attach_edns_record(ldns_buffer* pkt, struct edns_data* edns) ldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */ ldns_buffer_write_u8(pkt, edns->edns_version); ldns_buffer_write_u16(pkt, edns->bits); - ldns_buffer_write_u16(pkt, 0); /* rdatalen */ + /* YBS: do vandergaast hier! */ + if(edns->subnet_option_add) { + assert(edns.addr_fam == 0x01 || edns.addr_fam == 0x02); + assert(edns.addr_fam != 0x01 || edns->subnet_source_mask <= 32); + assert(edns.addr_fam != 0x02 || edns->subnet_source_mask <= 128); //ipv6 addr fam? + + sn_octs = edns->subnet_source_mask / 8; + sn_octs_remainder = !!(edns->subnet_source_mask % 8); + + ldns_buffer_write_u16(pkt, sn_octs + sn_octs_remainder + 4 + 4); /* rdatalen */ + ldns_buffer_write_u16(pkt, EDNS_SUBNET_OPC); /* opc */ + ldns_buffer_write_u16(pkt, sn_octs + sn_octs_remainder + 4); /* datalen */ + ldns_buffer_write_u16(pkt, edns->subnet_addr_fam); /* addr fam */ + ldns_buffer_write_u8(pkt, edns->subnet_source_mask); /* source mask */ + ldns_buffer_write_u8(pkt, edns->subnet_scope_mask); /* scope mask */ + + for(i = 0; isubnet_addr[i]); + if(sn_octs_remainder) + ldns_buffer_write_u8(pkt, edns->subnet_addr[sn_octs] & + ~(1<<(8-(edns->subnet_source_mask % 8))-1)); + } else ldns_buffer_write_u16(pkt, 0); /* rdatalen */ + /* //YBS: do vandergaast hier! */ ldns_buffer_flip(pkt); } diff --git a/util/data/msgparse.h b/util/data/msgparse.h index 830d68e16..85c51289a 100644 --- a/util/data/msgparse.h +++ b/util/data/msgparse.h @@ -211,6 +211,13 @@ struct edns_data { uint16_t bits; /** UDP reassembly size. */ uint16_t udp_size; + // YBS add vandergaast here + int subnet_option_add; + uint16_t subnet_addr_fam; + uint8_t subnet_source_mask; + uint8_t subnet_scope_mask; + uint8_t subnet_addr[16]; + // YBS add vandergaast here }; /** diff --git a/util/net_help.c b/util/net_help.c index 6be5fcc31..2a8713c3d 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -52,6 +52,8 @@ #define MAX_ADDR_STRLEN 128 /* characters */ /** default value for EDNS ADVERTISED size */ uint16_t EDNS_ADVERTISED_SIZE = 4096; +/** YBS: opcode for edns subnet option, is TBD. */ +uint16_t EDNS_SUBNET_OPC = 0x50fa; /** minimal responses when positive answer: default is no */ int MINIMAL_RESPONSES = 0; diff --git a/util/net_help.h b/util/net_help.h index e0c0ebea1..f8a3da998 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -81,6 +81,8 @@ struct regional; #define EDNS_ADVERTISED_VERSION 0 /** Advertised size of EDNS capabilities */ extern uint16_t EDNS_ADVERTISED_SIZE; +/** YBS: opcode for edns subnet option, is TBD. */ +extern uint16_t EDNS_SUBNET_OPC; /** bits for EDNS bitfield */ #define EDNS_DO 0x8000 /* Dnssec Ok */ /** byte size of ip4 address */