aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/services/outside_network.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/services/outside_network.c')
-rw-r--r--contrib/unbound/services/outside_network.c310
1 files changed, 201 insertions, 109 deletions
diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c
index a7e5fa3ad583..2b7f7d0a2f21 100644
--- a/contrib/unbound/services/outside_network.c
+++ b/contrib/unbound/services/outside_network.c
@@ -86,10 +86,6 @@ static void serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
static int randomize_and_send_udp(struct pending* pend, sldns_buffer* packet,
int timeout);
-/** remove waiting tcp from the outnet waiting list */
-static void waiting_list_remove(struct outside_network* outnet,
- struct waiting_tcp* w);
-
/** select a DNS ID for a TCP stream */
static uint16_t tcp_select_id(struct outside_network* outnet,
struct reuse_tcp* reuse);
@@ -266,12 +262,14 @@ pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s)
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int
-outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp)
+outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
+ int tcp_mss, int dscp, int nodelay)
{
int s;
int af;
char* err;
-#ifdef SO_REUSEADDR
+#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT) \
+ || defined(TCP_NODELAY)
int on = 1;
#endif
#ifdef INET6
@@ -317,7 +315,25 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss,
" setsockopt(TCP_MAXSEG) unsupported");
#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
}
-
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ if(setsockopt(s, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+ verbose(VERB_ALGO, "outgoing tcp:"
+ " setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed");
+ }
+#endif /* IP_BIND_ADDRESS_NO_PORT */
+ if(nodelay) {
+#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
+ if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+ verbose(VERB_ALGO, "outgoing tcp:"
+ " setsockopt(.. TCP_NODELAY ..) failed");
+ }
+#else
+ verbose(VERB_ALGO, "outgoing tcp:"
+ " setsockopt(.. TCP_NODELAY ..) unsupported");
+#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */
+ }
return s;
}
@@ -366,7 +382,8 @@ log_reuse_tcp(enum verbosity_value v, const char* msg, struct reuse_tcp* reuse)
}
/** pop the first element from the writewait list */
-static struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse)
+struct waiting_tcp*
+reuse_write_wait_pop(struct reuse_tcp* reuse)
{
struct waiting_tcp* w = reuse->write_wait_first;
if(!w)
@@ -384,8 +401,8 @@ static struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse)
}
/** remove the element from the writewait list */
-static void reuse_write_wait_remove(struct reuse_tcp* reuse,
- struct waiting_tcp* w)
+void
+reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w)
{
log_assert(w);
log_assert(w->write_wait_queued);
@@ -409,8 +426,8 @@ static void reuse_write_wait_remove(struct reuse_tcp* reuse,
}
/** push the element after the last on the writewait list */
-static void reuse_write_wait_push_back(struct reuse_tcp* reuse,
- struct waiting_tcp* w)
+void
+reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w)
{
if(!w) return;
log_assert(!w->write_wait_queued);
@@ -421,7 +438,9 @@ static void reuse_write_wait_push_back(struct reuse_tcp* reuse,
w->write_wait_prev = reuse->write_wait_last;
} else {
reuse->write_wait_first = w;
+ w->write_wait_prev = NULL;
}
+ w->write_wait_next = NULL;
reuse->write_wait_last = w;
w->write_wait_queued = 1;
}
@@ -545,9 +564,28 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
log_assert(&key_p.reuse != (struct reuse_tcp*)result);
log_assert(&key_p != ((struct reuse_tcp*)result)->pending);
}
+
+ /* It is possible that we search for something before the first element
+ * in the tree. Replace a null pointer with the first element.
+ */
+ if (!result) {
+ verbose(VERB_CLIENT, "reuse_tcp_find: taking first");
+ result = rbtree_first(&outnet->tcp_reuse);
+ }
+
/* not found, return null */
if(!result || result == RBTREE_NULL)
return NULL;
+
+ /* It is possible that we got the previous address, but that the
+ * address we are looking for is in the tree. If the address we got
+ * is less than the address we are looking, then take the next entry.
+ */
+ if (reuse_cmp_addrportssl(result->key, &key_p.reuse) < 0) {
+ verbose(VERB_CLIENT, "reuse_tcp_find: key too low");
+ result = rbtree_next(result);
+ }
+
verbose(VERB_CLIENT, "reuse_tcp_find check inexact match");
/* inexact match, find one of possibly several connections to the
* same destination address, with the correct port, ssl, and
@@ -615,8 +653,18 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
log_assert(w->addrlen > 0);
pend->c->tcp_do_toggle_rw = 0;
pend->c->tcp_do_close = 0;
+
+ /* Consistency check, if we have ssl_upstream but no sslctx, then
+ * log an error and return failure.
+ */
+ if (w->ssl_upstream && !w->outnet->sslctx) {
+ log_err("SSL upstream requested but no SSL context");
+ return 0;
+ }
+
/* open socket */
- s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
+ s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss,
+ w->outnet->ip_dscp, w->ssl_upstream);
if(s == -1)
return 0;
@@ -715,12 +763,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
pend->next_free = NULL;
pend->query = w;
pend->reuse.outnet = w->outnet;
- pend->c->repinfo.addrlen = w->addrlen;
+ pend->c->repinfo.remote_addrlen = w->addrlen;
pend->c->tcp_more_read_again = &pend->reuse.cp_more_read_again;
pend->c->tcp_more_write_again = &pend->reuse.cp_more_write_again;
pend->reuse.cp_more_read_again = 0;
pend->reuse.cp_more_write_again = 0;
- memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen);
+ memcpy(&pend->c->repinfo.remote_addr, &w->addr, w->addrlen);
pend->reuse.pending = pend;
/* Remove from tree in case the is_ssl will be different and causes the
@@ -804,20 +852,50 @@ reuse_tcp_lru_snip(struct outside_network* outnet)
return reuse;
}
-/** call callback on waiting_tcp, if not NULL */
-static void
-waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error,
- struct comm_reply* reply_info)
+/** remove waiting tcp from the outnet waiting list */
+void
+outnet_waiting_tcp_list_remove(struct outside_network* outnet, struct waiting_tcp* w)
{
- if(w && w->cb) {
- fptr_ok(fptr_whitelist_pending_tcp(w->cb));
- (void)(*w->cb)(c, w->cb_arg, error, reply_info);
+ struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL;
+ w->on_tcp_waiting_list = 0;
+ while(p) {
+ if(p == w) {
+ /* remove w */
+ if(prev)
+ prev->next_waiting = w->next_waiting;
+ else outnet->tcp_wait_first = w->next_waiting;
+ if(outnet->tcp_wait_last == w)
+ outnet->tcp_wait_last = prev;
+ w->next_waiting = NULL;
+ return;
+ }
+ prev = p;
+ p = p->next_waiting;
}
+ /* outnet_waiting_tcp_list_remove is currently called only with items
+ * that are already in the waiting list. */
+ log_assert(0);
+}
+
+/** pop the first waiting tcp from the outnet waiting list */
+struct waiting_tcp*
+outnet_waiting_tcp_list_pop(struct outside_network* outnet)
+{
+ struct waiting_tcp* w = outnet->tcp_wait_first;
+ if(!outnet->tcp_wait_first) return NULL;
+ log_assert(w->on_tcp_waiting_list);
+ outnet->tcp_wait_first = w->next_waiting;
+ if(outnet->tcp_wait_last == w)
+ outnet->tcp_wait_last = NULL;
+ w->on_tcp_waiting_list = 0;
+ w->next_waiting = NULL;
+ return w;
}
/** add waiting_tcp element to the outnet tcp waiting list */
-static void
-outnet_add_tcp_waiting(struct outside_network* outnet, struct waiting_tcp* w)
+void
+outnet_waiting_tcp_list_add(struct outside_network* outnet,
+ struct waiting_tcp* w, int set_timer)
{
struct timeval tv;
log_assert(!w->on_tcp_waiting_list);
@@ -829,16 +907,18 @@ outnet_add_tcp_waiting(struct outside_network* outnet, struct waiting_tcp* w)
else outnet->tcp_wait_first = w;
outnet->tcp_wait_last = w;
w->on_tcp_waiting_list = 1;
+ if(set_timer) {
#ifndef S_SPLINT_S
- tv.tv_sec = w->timeout/1000;
- tv.tv_usec = (w->timeout%1000)*1000;
+ tv.tv_sec = w->timeout/1000;
+ tv.tv_usec = (w->timeout%1000)*1000;
#endif
- comm_timer_set(w->timer, &tv);
+ comm_timer_set(w->timer, &tv);
+ }
}
/** add waiting_tcp element as first to the outnet tcp waiting list */
-static void
-outnet_add_tcp_waiting_first(struct outside_network* outnet,
+void
+outnet_waiting_tcp_list_add_first(struct outside_network* outnet,
struct waiting_tcp* w, int reset_timer)
{
struct timeval tv;
@@ -863,6 +943,17 @@ outnet_add_tcp_waiting_first(struct outside_network* outnet,
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
}
+/** call callback on waiting_tcp, if not NULL */
+static void
+waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error,
+ struct comm_reply* reply_info)
+{
+ if(w && w->cb) {
+ fptr_ok(fptr_whitelist_pending_tcp(w->cb));
+ (void)(*w->cb)(c, w->cb_arg, error, reply_info);
+ }
+}
+
/** see if buffers can be used to service TCP queries */
static void
use_free_buffer(struct outside_network* outnet)
@@ -873,15 +964,10 @@ use_free_buffer(struct outside_network* outnet)
struct pending_tcp* pend_tcp = NULL;
#endif
struct reuse_tcp* reuse = NULL;
- w = outnet->tcp_wait_first;
- log_assert(w->on_tcp_waiting_list);
- outnet->tcp_wait_first = w->next_waiting;
- if(outnet->tcp_wait_last == w)
- outnet->tcp_wait_last = NULL;
+ w = outnet_waiting_tcp_list_pop(outnet);
log_assert(
(!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) ||
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
- w->on_tcp_waiting_list = 0;
reuse = reuse_tcp_find(outnet, &w->addr, w->addrlen,
w->ssl_upstream);
/* re-select an ID when moving to a new TCP buffer */
@@ -928,7 +1014,7 @@ use_free_buffer(struct outside_network* outnet)
#endif
} else {
/* no reuse and no free buffer, put back at the start */
- outnet_add_tcp_waiting_first(outnet, w, 0);
+ outnet_waiting_tcp_list_add_first(outnet, w, 0);
break;
}
#ifdef USE_DNSTAP
@@ -938,7 +1024,7 @@ use_free_buffer(struct outside_network* outnet)
sldns_buffer tmp;
sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len);
dt_msg_send_outside_query(outnet->dtenv, &w->sq->addr,
- &pend_tcp->pi->addr, comm_tcp, w->sq->zone,
+ &pend_tcp->pi->addr, comm_tcp, NULL, w->sq->zone,
w->sq->zonelen, &tmp);
}
#endif
@@ -983,7 +1069,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
if(verbosity >= VERB_CLIENT && pend->query->pkt_len > 12+2+2 &&
LDNS_QDCOUNT(pend->query->pkt) > 0 &&
dname_valid(pend->query->pkt+12, pend->query->pkt_len-12)) {
- char buf[LDNS_MAX_DOMAINLEN+1];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(pend->query->pkt+12, buf);
verbose(VERB_CLIENT, "reuse_move_writewait_away current %s %d bytes were written",
buf, (int)pend->c->tcp_write_byte_count);
@@ -1002,18 +1088,18 @@ reuse_move_writewait_away(struct outside_network* outnet,
* fail the query */
w->error_count ++;
reuse_tree_by_id_delete(&pend->reuse, w);
- outnet_add_tcp_waiting(outnet, w);
+ outnet_waiting_tcp_list_add(outnet, w, 1);
}
while((w = reuse_write_wait_pop(&pend->reuse)) != NULL) {
if(verbosity >= VERB_CLIENT && w->pkt_len > 12+2+2 &&
LDNS_QDCOUNT(w->pkt) > 0 &&
dname_valid(w->pkt+12, w->pkt_len-12)) {
- char buf[LDNS_MAX_DOMAINLEN+1];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(w->pkt+12, buf);
verbose(VERB_CLIENT, "reuse_move_writewait_away item %s", buf);
}
reuse_tree_by_id_delete(&pend->reuse, w);
- outnet_add_tcp_waiting(outnet, w);
+ outnet_waiting_tcp_list_add(outnet, w, 1);
}
}
@@ -1411,11 +1497,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
/* setup lookup key */
key.id = (unsigned)LDNS_ID_WIRE(sldns_buffer_begin(c->buffer));
- memcpy(&key.addr, &reply_info->addr, reply_info->addrlen);
- key.addrlen = reply_info->addrlen;
+ memcpy(&key.addr, &reply_info->remote_addr, reply_info->remote_addrlen);
+ key.addrlen = reply_info->remote_addrlen;
verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id);
log_addr(VERB_ALGO, "Incoming reply addr =",
- &reply_info->addr, reply_info->addrlen);
+ &reply_info->remote_addr, reply_info->remote_addrlen);
/* find it, see if this thing is a valid query response */
verbose(VERB_ALGO, "lookup size is %d entries", (int)outnet->pending->count);
@@ -1608,6 +1694,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
outnet->tcp_reuse_timeout= tcp_reuse_timeout;
outnet->tcp_auth_query_timeout = tcp_auth_query_timeout;
outnet->num_tcp_outgoing = 0;
+ outnet->num_udp_outgoing = 0;
outnet->infra = infra;
outnet->rnd = rnd;
outnet->sslctx = sslctx;
@@ -1683,7 +1770,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
return NULL;
}
pc->cp = comm_point_create_udp(outnet->base, -1,
- outnet->udp_buff, outnet_udp_cb, outnet, NULL);
+ outnet->udp_buff, 0, outnet_udp_cb, outnet, NULL);
if(!pc->cp) {
log_err("malloc failed");
free(pc);
@@ -1979,7 +2066,8 @@ select_id(struct outside_network* outnet, struct pending* pend,
}
/** return true is UDP connect error needs to be logged */
-static int udp_connect_needs_log(int err)
+static int udp_connect_needs_log(int err, struct sockaddr_storage* addr,
+ socklen_t addrlen)
{
switch(err) {
case ECONNREFUSED:
@@ -1995,11 +2083,23 @@ static int udp_connect_needs_log(int err)
# ifdef ENETDOWN
case ENETDOWN:
# endif
+# ifdef EADDRNOTAVAIL
+ case EADDRNOTAVAIL:
+# endif
case EPERM:
case EACCES:
if(verbosity >= VERB_ALGO)
return 1;
return 0;
+ case EINVAL:
+ /* Stop 'Invalid argument for fe80::/10' addresses appearing
+ * in the logs, at low verbosity. They cannot be sent to. */
+ if(addr_is_ip6linklocal(addr, addrlen)) {
+ if(verbosity >= VERB_ALGO)
+ return 1;
+ return 0;
+ }
+ break;
default:
break;
}
@@ -2066,7 +2166,8 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* connect() to the destination */
if(connect(fd, (struct sockaddr*)&pend->addr,
pend->addrlen) < 0) {
- if(udp_connect_needs_log(errno)) {
+ if(udp_connect_needs_log(errno,
+ &pend->addr, pend->addrlen)) {
log_err_addr("udp connect failed",
strerror(errno), &pend->addr,
pend->addrlen);
@@ -2139,6 +2240,7 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout)
portcomm_loweruse(outnet, pend->pc);
return 0;
}
+ outnet->num_udp_outgoing++;
/* system calls to set timeout after sending UDP to make roundtrip
smaller. */
@@ -2161,7 +2263,7 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout)
outnet->dtenv->log_forwarder_query_messages)) {
log_addr(VERB_ALGO, "from local addr", &pend->pc->pif->addr, pend->pc->pif->addrlen);
log_addr(VERB_ALGO, "request to upstream", &pend->addr, pend->addrlen);
- dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp,
+ dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp, NULL,
pend->sq->zone, pend->sq->zonelen, packet);
}
#endif
@@ -2226,7 +2328,7 @@ outnet_tcptimer(void* arg)
verbose(VERB_CLIENT, "outnet_tcptimer");
if(w->on_tcp_waiting_list) {
/* it is on the waiting list */
- waiting_list_remove(outnet, w);
+ outnet_waiting_tcp_list_remove(outnet, w);
waiting_tcp_callback(w, NULL, NETEVENT_TIMEOUT, NULL);
waiting_tcp_delete(w);
} else {
@@ -2294,7 +2396,7 @@ reuse_tcp_select_id(struct reuse_tcp* reuse, struct outside_network* outnet)
node = rbtree_first(&reuse->tree_by_id);
log_assert(node && node != RBTREE_NULL); /* tree not empty */
/* see if select is before first node */
- if(select < tree_by_id_get_id(node))
+ if(select < (unsigned)tree_by_id_get_id(node))
return select;
count += tree_by_id_get_id(node);
/* perhaps select is between nodes */
@@ -2441,7 +2543,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
sldns_buffer tmp;
sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len);
dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr,
- &pend->pi->addr, comm_tcp, sq->zone,
+ &pend->pi->addr, comm_tcp, NULL, sq->zone,
sq->zonelen, &tmp);
}
#endif
@@ -2453,7 +2555,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
#ifdef USE_DNSTAP
w->sq = sq;
#endif
- outnet_add_tcp_waiting(sq->outnet, w);
+ outnet_waiting_tcp_list_add(sq->outnet, w, 1);
}
return w;
}
@@ -2534,8 +2636,10 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
#ifdef UNBOUND_DEBUG
rbnode_type* ins;
#endif
- if(!sq)
+ if(!sq) {
+ alloc_reg_release(alloc, region);
return NULL;
+ }
sq->node.key = sq;
sq->alloc = alloc;
sq->region = region;
@@ -2599,30 +2703,6 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
return sq;
}
-/** remove waiting tcp from the outnet waiting list */
-static void
-waiting_list_remove(struct outside_network* outnet, struct waiting_tcp* w)
-{
- struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL;
- w->on_tcp_waiting_list = 0;
- while(p) {
- if(p == w) {
- /* remove w */
- if(prev)
- prev->next_waiting = w->next_waiting;
- else outnet->tcp_wait_first = w->next_waiting;
- if(outnet->tcp_wait_last == w)
- outnet->tcp_wait_last = prev;
- return;
- }
- prev = p;
- p = p->next_waiting;
- }
- /* waiting_list_remove is currently called only with items that are
- * already in the waiting list. */
- log_assert(0);
-}
-
/** reuse tcp stream, remove serviced query from stream,
* return true if the stream is kept, false if it is to be closed */
static int
@@ -2717,7 +2797,7 @@ serviced_delete(struct serviced_query* sq)
sq->pending = NULL;
} else {
verbose(VERB_CLIENT, "serviced_delete: tcpwait");
- waiting_list_remove(sq->outnet, w);
+ outnet_waiting_tcp_list_remove(sq->outnet, w);
if(!w->in_cb_and_decommission)
waiting_tcp_delete(w);
}
@@ -2747,7 +2827,7 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
random = ub_random(rnd);
bits = 30;
}
- if(random & 0x1) {
+ if((random & 0x1)) {
*d = (uint8_t)toupper((unsigned char)*d);
} else {
*d = (uint8_t)tolower((unsigned char)*d);
@@ -2760,12 +2840,31 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
lablen = *d++;
}
if(verbosity >= VERB_ALGO) {
- char buf[LDNS_MAX_DOMAINLEN+1];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(qbuf+10, buf);
verbose(VERB_ALGO, "qname perturbed to %s", buf);
}
}
+static uint16_t
+serviced_query_udp_size(struct serviced_query* sq, enum serviced_query_status status) {
+ uint16_t udp_size;
+ if(status == serviced_query_UDP_EDNS_FRAG) {
+ if(addr_is_ip6(&sq->addr, sq->addrlen)) {
+ if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
+ udp_size = EDNS_FRAG_SIZE_IP6;
+ else udp_size = EDNS_ADVERTISED_SIZE;
+ } else {
+ if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
+ udp_size = EDNS_FRAG_SIZE_IP4;
+ else udp_size = EDNS_ADVERTISED_SIZE;
+ }
+ } else {
+ udp_size = EDNS_ADVERTISED_SIZE;
+ }
+ return udp_size;
+}
+
/** put serviced query into a buffer */
static void
serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
@@ -2789,23 +2888,11 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
edns.opt_list_in = NULL;
edns.opt_list_out = sq->opt_list;
edns.opt_list_inplace_cb_out = NULL;
- if(sq->status == serviced_query_UDP_EDNS_FRAG) {
- if(addr_is_ip6(&sq->addr, sq->addrlen)) {
- if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
- edns.udp_size = EDNS_FRAG_SIZE_IP6;
- else edns.udp_size = EDNS_ADVERTISED_SIZE;
- } else {
- if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
- edns.udp_size = EDNS_FRAG_SIZE_IP4;
- else edns.udp_size = EDNS_ADVERTISED_SIZE;
- }
- } else {
- edns.udp_size = EDNS_ADVERTISED_SIZE;
- }
+ edns.udp_size = serviced_query_udp_size(sq, sq->status);
edns.bits = 0;
- if(sq->dnssec & EDNS_DO)
+ if((sq->dnssec & EDNS_DO))
edns.bits = EDNS_DO;
- if(sq->dnssec & BIT_CD)
+ if((sq->dnssec & BIT_CD))
LDNS_CD_SET(sldns_buffer_begin(buff));
if (sq->ssl_upstream && sq->padding_block_size) {
padding_option.opt_code = LDNS_EDNS_PADDING;
@@ -3029,7 +3116,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen);
log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen);
dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr,
- &pi->addr, c->type, sq->zone, sq->zonelen, sq->qbuf,
+ &pi->addr, c->type, c->ssl, sq->zone, sq->zonelen, sq->qbuf,
sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv,
c->buffer);
}
@@ -3090,8 +3177,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
rep = &r2;
r2.c = c;
}
- memcpy(&rep->addr, &sq->addr, sq->addrlen);
- rep->addrlen = sq->addrlen;
+ memcpy(&rep->remote_addr, &sq->addr, sq->addrlen);
+ rep->remote_addrlen = sq->addrlen;
serviced_callbacks(sq, error, c, rep);
return 0;
}
@@ -3198,7 +3285,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
sq->pending = NULL; /* removed after callback */
if(error == NETEVENT_TIMEOUT) {
- if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
+ if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000 &&
+ (serviced_query_udp_size(sq, serviced_query_UDP_EDNS_FRAG) < serviced_query_udp_size(sq, serviced_query_UDP_EDNS))) {
/* fallback to 1480/1280 */
sq->status = serviced_query_UDP_EDNS_FRAG;
log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
@@ -3242,7 +3330,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
log_addr(VERB_ALGO, "to local addr", &p->pc->pif->addr,
p->pc->pif->addrlen);
dt_msg_send_outside_response(outnet->dtenv, &sq->addr,
- &p->pc->pif->addr, c->type, sq->zone, sq->zonelen,
+ &p->pc->pif->addr, c->type, c->ssl, sq->zone, sq->zonelen,
sq->qbuf, sq->qbuflen, &sq->last_sent_time,
sq->outnet->now_tv, c->buffer);
}
@@ -3393,7 +3481,10 @@ outnet_serviced_query(struct outside_network* outnet,
timenow = *env->now;
if(!infra_ratelimit_inc(env->infra_cache, zone,
zonelen, timenow, env->cfg->ratelimit_backoff,
- &qstate->qinfo, qstate->reply)) {
+ &qstate->qinfo,
+ qstate->mesh_info->reply_list
+ ?&qstate->mesh_info->reply_list->query_reply
+ :NULL)) {
/* Can we pass through with slip factor? */
if(env->cfg->ratelimit_factor == 0 ||
ub_random_max(env->rnd,
@@ -3421,7 +3512,6 @@ outnet_serviced_query(struct outside_network* outnet,
infra_ratelimit_dec(env->infra_cache,
zone, zonelen, timenow);
}
- alloc_reg_release(env->alloc, region);
return NULL;
}
if(!(cb = (struct service_callback*)regional_alloc(
@@ -3570,7 +3660,7 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
if(fd == -1) {
return NULL;
}
- cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff,
+ cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff, 0,
cb, cb_arg, NULL);
if(!cp) {
log_err("malloc failure");
@@ -3643,7 +3733,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
+ outnet->ip_dscp, ssl);
if(fd == -1) {
return 0;
}
@@ -3658,8 +3749,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
close(fd);
return 0;
}
- cp->repinfo.addrlen = to_addrlen;
- memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+ cp->repinfo.remote_addrlen = to_addrlen;
+ memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
/* setup for SSL (if needed) */
if(ssl) {
@@ -3718,7 +3809,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
{
/* cp calls cb with err=NETEVENT_DONE when transfer is done */
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
+ outnet->ip_dscp, ssl);
if(fd == -1) {
return 0;
}
@@ -3734,8 +3826,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
close(fd);
return 0;
}
- cp->repinfo.addrlen = to_addrlen;
- memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+ cp->repinfo.remote_addrlen = to_addrlen;
+ memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
/* setup for SSL (if needed) */
if(ssl) {