|
|
|
@ -362,7 +362,7 @@ process_keepalive(
|
|
|
|
|
/* Use server sent value unless the client specified a shorter one.
|
|
|
|
|
Convert to ms first (wire value has units of 100ms) */
|
|
|
|
|
uint64_t server_keepalive = ((uint64_t)gldns_read_uint16(position))*100;
|
|
|
|
|
DEBUG_STUB("%s %-35s: FD: %d Server Keepalive recieved: %d ms\n",
|
|
|
|
|
DEBUG_STUB("%s %-35s: FD: %d Server Keepalive received: %d ms\n",
|
|
|
|
|
STUB_DEBUG_READ, __FUNC__, upstream->fd,
|
|
|
|
|
(int)server_keepalive);
|
|
|
|
|
if (netreq->owner->context->idle_timeout < server_keepalive)
|
|
|
|
@ -505,7 +505,6 @@ stub_cleanup(getdns_network_req *netreq)
|
|
|
|
|
getdns_dns_req *dnsreq = netreq->owner;
|
|
|
|
|
getdns_network_req *r, *prev_r;
|
|
|
|
|
getdns_upstream *upstream;
|
|
|
|
|
intptr_t query_id_intptr;
|
|
|
|
|
|
|
|
|
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
|
|
|
|
|
|
|
|
@ -514,9 +513,8 @@ stub_cleanup(getdns_network_req *netreq)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Delete from upstream->netreq_by_query_id (if present) */
|
|
|
|
|
query_id_intptr = (intptr_t)netreq->query_id;
|
|
|
|
|
(void) _getdns_rbtree_delete(
|
|
|
|
|
&upstream->netreq_by_query_id, (void *)query_id_intptr);
|
|
|
|
|
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
|
|
|
|
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
|
|
|
|
|
|
|
|
|
/* Delete from upstream->write_queue (if present) */
|
|
|
|
|
for (prev_r = NULL, r = upstream->write_queue; r;
|
|
|
|
@ -540,6 +538,8 @@ stub_cleanup(getdns_network_req *netreq)
|
|
|
|
|
static void
|
|
|
|
|
upstream_failed(getdns_upstream *upstream, int during_setup)
|
|
|
|
|
{
|
|
|
|
|
getdns_network_req *netreq;
|
|
|
|
|
|
|
|
|
|
DEBUG_STUB("%s %-35s: FD: %d Failure during connection setup = %d\n",
|
|
|
|
|
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd, during_setup);
|
|
|
|
|
/* Fallback code should take care of queue queries and then close conn
|
|
|
|
@ -565,16 +565,14 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
|
|
|
|
} else {
|
|
|
|
|
upstream->conn_shutdowns++;
|
|
|
|
|
/* [TLS1]TODO: Re-try these queries if possible.*/
|
|
|
|
|
getdns_network_req *netreq;
|
|
|
|
|
while (upstream->netreq_by_query_id.count) {
|
|
|
|
|
netreq = (getdns_network_req *)
|
|
|
|
|
_getdns_rbtree_first(&upstream->netreq_by_query_id);
|
|
|
|
|
stub_cleanup(netreq);
|
|
|
|
|
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
|
|
|
|
|
_getdns_check_dns_req_complete(netreq->owner);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (upstream->netreq_by_query_id.count) {
|
|
|
|
|
netreq = (getdns_network_req *)
|
|
|
|
|
_getdns_rbtree_first(&upstream->netreq_by_query_id);
|
|
|
|
|
stub_cleanup(netreq);
|
|
|
|
|
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
|
|
|
|
_getdns_check_dns_req_complete(netreq->owner);
|
|
|
|
|
}
|
|
|
|
|
upstream->conn_state = GETDNS_CONN_TEARDOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -779,6 +777,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|
|
|
|
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
|
|
|
|
|
|
|
|
|
GLDNS_ID_SET(netreq->query, query_id);
|
|
|
|
|
|
|
|
|
|
if (netreq->opt) {
|
|
|
|
|
_getdns_network_req_clear_upstream_options(netreq);
|
|
|
|
|
/* no limits on the max udp payload size with tcp */
|
|
|
|
@ -836,8 +835,13 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|
|
|
|
|
|
|
|
|
return STUB_TCP_WOULDBLOCK;
|
|
|
|
|
|
|
|
|
|
} else if (written == -1)
|
|
|
|
|
} else if (written == -1) {
|
|
|
|
|
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
|
|
|
|
|
" %s\n", STUB_DEBUG_WRITE, __FUNC__, (void*)netreq
|
|
|
|
|
, strerror(errno));
|
|
|
|
|
|
|
|
|
|
return STUB_TCP_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We were able to write everything! Start reading. */
|
|
|
|
|
return (int) query_id;
|
|
|
|
@ -856,8 +860,13 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|
|
|
|
if (written == -1) {
|
|
|
|
|
if (_getdns_EWOULDBLOCK)
|
|
|
|
|
return STUB_TCP_WOULDBLOCK;
|
|
|
|
|
else
|
|
|
|
|
else {
|
|
|
|
|
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
|
|
|
|
|
" %s\n", STUB_DEBUG_WRITE, __FUNC__, (void*)netreq
|
|
|
|
|
, strerror(errno));
|
|
|
|
|
|
|
|
|
|
return STUB_TCP_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tcp->written += written;
|
|
|
|
|
if (tcp->written < tcp->write_buf_len)
|
|
|
|
@ -1269,6 +1278,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|
|
|
|
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
|
|
|
|
|
|
|
|
|
GLDNS_ID_SET(netreq->query, query_id);
|
|
|
|
|
|
|
|
|
|
/* TODO: Review if more EDNS0 handling can be centralised.*/
|
|
|
|
|
if (netreq->opt) {
|
|
|
|
|
_getdns_network_req_clear_upstream_options(netreq);
|
|
|
|
@ -1416,7 +1426,7 @@ stub_udp_read_cb(void *userarg)
|
|
|
|
|
if (read < GLDNS_HEADER_SIZE)
|
|
|
|
|
return; /* Not DNS */
|
|
|
|
|
|
|
|
|
|
if (GLDNS_ID_WIRE(netreq->response) != netreq->query_id)
|
|
|
|
|
if (GLDNS_ID_WIRE(netreq->response) != GLDNS_ID_WIRE(netreq->query))
|
|
|
|
|
return; /* Cache poisoning attempt ;) */
|
|
|
|
|
|
|
|
|
|
if (netreq->owner->edns_cookies && match_and_process_server_cookie(
|
|
|
|
@ -1480,6 +1490,7 @@ stub_udp_write_cb(void *userarg)
|
|
|
|
|
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
|
|
|
|
getdns_dns_req *dnsreq = netreq->owner;
|
|
|
|
|
size_t pkt_len;
|
|
|
|
|
ssize_t written;
|
|
|
|
|
DEBUG_STUB("%s %-35s: MSG: %p \n", STUB_DEBUG_WRITE,
|
|
|
|
|
__FUNC__, (void *)netreq);
|
|
|
|
|
|
|
|
|
@ -1487,8 +1498,7 @@ stub_udp_write_cb(void *userarg)
|
|
|
|
|
|
|
|
|
|
netreq->debug_start_time = _getdns_get_time_as_uintt64();
|
|
|
|
|
netreq->debug_udp = 1;
|
|
|
|
|
netreq->query_id = arc4random();
|
|
|
|
|
GLDNS_ID_SET(netreq->query, netreq->query_id);
|
|
|
|
|
GLDNS_ID_SET(netreq->query, (uint16_t)arc4random());
|
|
|
|
|
if (netreq->opt) {
|
|
|
|
|
_getdns_network_req_clear_upstream_options(netreq);
|
|
|
|
|
if (netreq->edns_maximum_udp_payload_size == -1)
|
|
|
|
@ -1504,15 +1514,34 @@ stub_udp_write_cb(void *userarg)
|
|
|
|
|
return; /* too many upstream options */
|
|
|
|
|
}
|
|
|
|
|
pkt_len = _getdns_network_req_add_tsig(netreq);
|
|
|
|
|
if ((ssize_t)pkt_len != sendto(
|
|
|
|
|
if ((ssize_t)pkt_len != (written = sendto(
|
|
|
|
|
netreq->fd, (const void *)netreq->query, pkt_len, 0,
|
|
|
|
|
(struct sockaddr *)&netreq->upstream->addr,
|
|
|
|
|
netreq->upstream->addr_len)) {
|
|
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
|
closesocket(netreq->fd);
|
|
|
|
|
#else
|
|
|
|
|
close(netreq->fd);
|
|
|
|
|
netreq->upstream->addr_len))) {
|
|
|
|
|
|
|
|
|
|
#if defined(STUB_DEBUG) && STUB_DEBUG
|
|
|
|
|
if (written == -1)
|
|
|
|
|
DEBUG_STUB( "%s %-35s: MSG: %p error: %s\n"
|
|
|
|
|
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
|
|
|
|
|
, strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
DEBUG_STUB( "%s %-35s: MSG: %p returned: %d, expeced: %d\n"
|
|
|
|
|
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
|
|
|
|
|
, (int)written, (int)pkt_len);
|
|
|
|
|
#endif
|
|
|
|
|
stub_cleanup(netreq);
|
|
|
|
|
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
|
|
|
|
/* Handle upstream*/
|
|
|
|
|
if (netreq->fd >= 0) {
|
|
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
|
closesocket(netreq->fd);
|
|
|
|
|
#else
|
|
|
|
|
close(netreq->fd);
|
|
|
|
|
#endif
|
|
|
|
|
stub_next_upstream(netreq);
|
|
|
|
|
}
|
|
|
|
|
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
|
|
|
|
_getdns_check_dns_req_complete(netreq->owner);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
GETDNS_SCHEDULE_EVENT(dnsreq->loop, netreq->fd,
|
|
|
|
@ -1689,6 +1718,7 @@ upstream_write_cb(void *userarg)
|
|
|
|
|
*/
|
|
|
|
|
case STUB_TCP_WOULDBLOCK:
|
|
|
|
|
return;
|
|
|
|
|
case STUB_OUT_OF_OPTIONS:
|
|
|
|
|
case STUB_TCP_ERROR:
|
|
|
|
|
/* New problem with the TCP connection itself. Need to fallback.*/
|
|
|
|
|
/* Fall through */
|
|
|
|
@ -1696,6 +1726,8 @@ upstream_write_cb(void *userarg)
|
|
|
|
|
/* Could not complete the set up. Need to fallback.*/
|
|
|
|
|
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
|
|
|
|
|
__FUNC__, (void*)userarg, q);
|
|
|
|
|
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
|
|
|
|
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
|
|
|
|
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1));
|
|
|
|
|
/* Fall through */
|
|
|
|
|
case STUB_CONN_GONE:
|
|
|
|
@ -1709,7 +1741,7 @@ upstream_write_cb(void *userarg)
|
|
|
|
|
#endif
|
|
|
|
|
if (fallback_on_write(netreq) == STUB_TCP_ERROR) {
|
|
|
|
|
/* TODO: Need new state to report transport unavailable*/
|
|
|
|
|
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
|
|
|
|
|
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
|
|
|
|
_getdns_check_dns_req_complete(netreq->owner);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
@ -1726,7 +1758,7 @@ upstream_write_cb(void *userarg)
|
|
|
|
|
/* Need this because auth status is reset on connection close */
|
|
|
|
|
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
|
|
|
|
upstream->queries_sent++;
|
|
|
|
|
netreq->query_id = (uint16_t) q;
|
|
|
|
|
|
|
|
|
|
/* Unqueue the netreq from the write_queue */
|
|
|
|
|
if (!(upstream->write_queue = netreq->write_queue_tail)) {
|
|
|
|
|
upstream->write_queue_last = NULL;
|
|
|
|
@ -2056,6 +2088,8 @@ upstream_find_for_netreq(getdns_network_req *netreq)
|
|
|
|
|
netreq->transport_current = i;
|
|
|
|
|
netreq->upstream = upstream;
|
|
|
|
|
netreq->keepalive_sent = 0;
|
|
|
|
|
|
|
|
|
|
DEBUG_STUB("%s %-35s: MSG: %p found upstream %p with transport %d, fd: %d\n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq, (void *)upstream, (int)netreq->transports[i], fd);
|
|
|
|
|
return fd;
|
|
|
|
|
}
|
|
|
|
|
/* Handle better, will give generic error*/
|
|
|
|
|