edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns);
regional_free_all(worker->scratchpad);
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 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,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns);
rrset_array_unlock_touch(worker->env.rrset_cache,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 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)) {
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->bits &= EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 0;
attach_edns_record(pkt, edns);
}
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.bits &= EDNS_DO;
- edns.subnet_option_add = 0;
+ edns.subnet_option = 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,
edns->ext_rcode = 0;
edns->edns_version = 0;
edns->bits = EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 0;
if(ldns_buffer_capacity(w->back->udp_buff) < 65535)
edns->udp_size = (uint16_t)ldns_buffer_capacity(
w->back->udp_buff);
if(!e->qsent) {
return NULL;
}
- if(e->qstate->mesh_info->reply_list)
- e->qsent->client = &e->qstate->mesh_info->reply_list->query_reply;
+ e->qsent->mesh_info = e->qstate->mesh_info;
return e;
}
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
- edns->subnet_option_add = 0;
+ edns->subnet_option = 0;
if(!reply_info_answer_encode(qinfo, &rep,
*(uint16_t*)ldns_buffer_begin(buf),
ldns_buffer_read_u16_at(buf, 2),
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
- r->edns.subnet_option_add = 0;
+ r->edns.subnet_option = 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,
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
- r->edns.subnet_option_add = 0;
+ r->edns.subnet_option = 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,
/** true if replies have been sent out (at end for alignment) */
uint8_t replies_sent;
+
+ /* YBS */
+ int subnet_option_expect;
+ uint16_t subnet_addr_fam;
+ uint8_t subnet_source_mask;
+ uint8_t subnet_addr[16];
};
/**
sq->status = serviced_initial;
sq->retry = 0;
sq->to_be_deleted = 0;
- sq->client = NULL;
+ sq->mesh_info = NULL;
#ifdef UNBOUND_DEBUG
ins =
#endif
edns.edns_version = EDNS_ADVERTISED_VERSION;
/* If this query has an interested client and the upstream
* target is in the whitelist, add the edns subnet option. */
- edns.subnet_option_add = sq->client && upstream_lookup(
- sq->outnet->edns_subnet_upstreams, &sq->addr, sq->addrlen);
- if(edns.subnet_option_add) {
- ss = &sq->client->addr;
+ edns.subnet_option = sq->mesh_info->reply_list &&
+ upstream_lookup(sq->outnet->edns_subnet_upstreams,
+ &sq->addr, sq->addrlen);
+ if(edns.subnet_option) {
+ ss = &sq->mesh_info->reply_list->query_reply.addr;
if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
edns.subnet_addr_fam = IANA_ADDRFAM_IP4;
sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
}
#endif
edns.subnet_scope_mask = 0;
+ //YBS add addr,fam,mask to mesh.
+ sq->mesh_info->subnet_option_expect = 1;
+ sq->mesh_info->subnet_addr_fam = edns.subnet_addr_fam;
+ sq->mesh_info->subnet_source_mask = edns.subnet_source_mask;
+ memcpy(sq->mesh_info->subnet_addr, (uint8_t *)sinaddr, INET6_SIZE);
}
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
{
struct serviced_query* sq;
struct service_callback* cb;
- struct mesh_reply* reply_list;
serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags);
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen);
/* duplicate entries are inclded in the callback list, because
}
/* Is this a client initiated query? Make clients available
* to serviced query. */
- reply_list = ((struct outbound_entry*)callback_arg)
- ->qstate->mesh_info->reply_list;
- if(reply_list)
- sq->client = &reply_list->query_reply;
+ sq->mesh_info = ((struct outbound_entry*)callback_arg)
+ ->qstate->mesh_info;
/* perform first network action */
if(outnet->do_udp && !(tcp_upstream || ssl_upstream)) {
/** the UDP or TCP query that is pending, see status which */
void* pending;
/** Clients initiating lookup. Not owned by serviced_query */
- struct comm_reply *client;
+ struct mesh_state *mesh_info;
};
/**
memcpy(&pend->addr, (struct sockaddr_storage*)&target_addr,
sizeof(struct sockaddr_storage));
pend->addrlen = 16;
- edns.subnet_option_add = pend->client && upstream_lookup(
+ edns.subnet_option = pend->client && upstream_lookup(
outnet->edns_subnet_upstreams, &pend->addr, pend->addrlen);
- if(edns.subnet_option_add) {
+ if(edns.subnet_option) {
ss = &pend->client->addr;
if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
edns.subnet_addr_fam = IANA_ADDRFAM_IP4;
edns.edns_present = 1;
edns.bits = EDNS_DO;
edns.udp_size = 4096;
- edns.subnet_option_add = 0;
+ edns.subnet_option = 0;
attach_edns_record(buf, &edns);
}
ldns_buffer_write_u8(pkt, edns->edns_version);
ldns_buffer_write_u16(pkt, edns->bits);
/* Add edns-subnet option to record */
- if(edns->subnet_option_add) {
+ if(edns->subnet_option) {
assert(edns->subnet_addr_fam == IANA_ADDRFAM_IP4 ||
edns->subnet_addr_fam == IANA_ADDRFAM_IP6);
assert(edns->subnet_addr_fam != IANA_ADDRFAM_IP4 ||
es.udp_size = EDNS_ADVERTISED_SIZE;
es.ext_rcode = 0;
es.bits &= EDNS_DO;
- es.subnet_option_add = 0;
+ es.subnet_option = 0;
if(ldns_buffer_limit(buf) + calc_edns_field_size(&es) >
edns->udp_size)
return;
#include "util/data/packed_rrset.h"
#include "util/storage/lookup3.h"
#include "util/regional.h"
+#include "util/net_help.h"
/** smart comparison of (compressed, valid) dnames from packet */
static int
return 0;
}
+void
+parse_ednsdata(uint8_t* data, struct edns_data* edns)
+{
+ int edns_datalen, opt_opc, opt_len, opt_start;
+ edns->subnet_option = 0;
+ /* Parse EDNS data field */
+ edns_datalen = ldns_read_uint16(data);
+ if(edns_datalen < 4) return;
+ /* iterate trough all options */
+ opt_start = 0;
+ while(opt_start + 4 <= edns_datalen) { /* opcode + len must fit */
+ opt_opc = ldns_read_uint16(&data[2 + opt_start]);
+ opt_len = ldns_read_uint16(&data[4 + opt_start]);
+ /* Option does not fit in remaining data */
+ if(opt_start + 4 + opt_len > edns_datalen) return;
+ opt_start += 4;
+ if(opt_opc == EDNS_SUBNET_OPC) {
+ if(opt_len < 4) break;
+ edns->subnet_addr_fam = ldns_read_uint16(data + 2 + opt_start);
+ edns->subnet_source_mask = data[4 + opt_start];
+ edns->subnet_scope_mask = data[5 + opt_start];
+ /* remaing bytes indicate address */
+ if(opt_len - 4 > INET6_SIZE || opt_len == 0) break;
+ memset(edns->subnet_addr, 0, INET6_SIZE);
+ memcpy(edns->subnet_addr, data + 6 + opt_start, opt_len - 4);
+ edns->subnet_option = 1;
+ break;
+ } else { /* Unknown opcode */
+ verbose(VERB_QUERY, "Unknow EDNS option %x", opt_opc);
+ }
+ opt_start += opt_len;
+ }
+}
+
int
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
{
/* take the data ! */
edns->edns_present = 1;
+ edns->udp_size = ntohs(found->rrset_class);
edns->ext_rcode = found->rr_last->ttl_data[0];
edns->edns_version = found->rr_last->ttl_data[1];
edns->bits = ldns_read_uint16(&found->rr_last->ttl_data[2]);
- edns->udp_size = ntohs(found->rrset_class);
- edns->subnet_option_add = 0; //YBS do some actual parsing here
- /* ignore rdata and rrsigs */
+ parse_ednsdata(found->rr_last->ttl_data + 4, edns);
return 0;
}
edns->ext_rcode = ldns_buffer_read_u8(pkt); /* ttl used for bits */
edns->edns_version = ldns_buffer_read_u8(pkt);
edns->bits = ldns_buffer_read_u16(pkt);
- /* ignore rdata and rrsigs */
+ parse_ednsdata(ldns_buffer_current(pkt), edns);
return 0;
}
uint16_t bits;
/** UDP reassembly size. */
uint16_t udp_size;
- int subnet_option_add;
+ int subnet_option; /*YBS*/
uint16_t subnet_addr_fam;
uint8_t subnet_source_mask;
uint8_t subnet_scope_mask;
edns.ext_rcode = 0;
edns.edns_version = 0;
edns.bits = EDNS_DO;
- edns.subnet_option_add = 0;
+ edns.subnet_option = 0;
if(ldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)ldns_buffer_capacity(buf);
else edns.udp_size = 65535;