diff --git a/.travis.yml b/.travis.yml index 33a6c780..98b98d95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,4 @@ addons: script: - mkdir tests - cd tests - - ../src/test/tpkg/run-parallel.sh + - ../src/test/tpkg/run-all.sh diff --git a/src/mdns.c b/src/mdns.c index 28de951f..56ce7013 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -1746,7 +1746,7 @@ mdns_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 ;) */ // TODO: check whether EDNS server cookies are required for MDNS @@ -1788,8 +1788,7 @@ mdns_udp_write_cb(void *userarg) netreq->debug_start_time = _getdns_get_time_as_uintt64(); netreq->debug_udp = 1; - netreq->query_id = (uint16_t) arc4random(); - GLDNS_ID_SET(netreq->query, netreq->query_id); + GLDNS_ID_SET(netreq->query, (uint16_t) arc4random()); /* do we need to handle options valid in the MDNS context? */ diff --git a/src/request-internal.c b/src/request-internal.c index d91563f4..15f97179 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -125,7 +125,6 @@ netreq_reset(getdns_network_req *net_req) _getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT); net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE; net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE; - net_req->query_id = 0; net_req->response_len = 0; /* Some fields to record info for return_call_reporting */ net_req->debug_start_time = 0; diff --git a/src/stub.c b/src/stub.c index 2fa121f1..f900d35c 100644 --- a/src/stub.c +++ b/src/stub.c @@ -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*/ diff --git a/src/test/check_getdns_transport.c b/src/test/check_getdns_transport.c index bf457257..300abc4d 100644 --- a/src/test/check_getdns_transport.c +++ b/src/test/check_getdns_transport.c @@ -529,7 +529,7 @@ getdns_transport_suite(void) { /* Note that the exact number of messages received depends on if a trust * anchor is configured so these tests just check that no messages are - * received on the wrong transport and at least one is recieved on the + * received on the wrong transport and at least one is received on the * expected transport */ /* Positive test cases */ diff --git a/src/types-internal.h b/src/types-internal.h index 22cf649a..7834fc32 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -226,7 +226,6 @@ typedef struct getdns_network_req size_t transport_current; getdns_tls_authentication_t tls_auth_min; getdns_eventloop_event event; - uint16_t query_id; int edns_maximum_udp_payload_size; uint16_t max_udp_payload_size;