|
40 | 40 | #define DNS_BUFFER_MAXSIZE 4096 |
41 | 41 | #define DNS_HEADER_MIN 12 |
42 | 42 | #define TLS_IO_TIMEOUT_SEC 5 |
| 43 | +#define DOH_EXCHANGE_TIMEOUT_SEC 20 |
43 | 44 | #define DEFAULT_CA_BUNDLE "/etc/ssl/certs/ca-certificates.crt" |
44 | 45 | #define DEFAULT_BOOTSTRAP_DNS_IP "1.1.1.1" |
45 | 46 | #define DEFAULT_BOOTSTRAP_DNS_PORT 53 |
@@ -344,6 +345,17 @@ static int make_servfail(const uint8_t *in, size_t inlen, uint8_t *out, size_t * |
344 | 345 | return 0; |
345 | 346 | } |
346 | 347 |
|
| 348 | +static unsigned long long monotonic_ms(void) |
| 349 | +{ |
| 350 | + struct timespec ts; |
| 351 | + |
| 352 | + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) |
| 353 | + return 0; |
| 354 | + |
| 355 | + return ((unsigned long long)ts.tv_sec * 1000ULL) + |
| 356 | + ((unsigned long long)ts.tv_nsec / 1000000ULL); |
| 357 | +} |
| 358 | + |
347 | 359 | static uint16_t rd_u16(const uint8_t *p) |
348 | 360 | { |
349 | 361 | return (uint16_t)((p[0] << 8) | p[1]); |
@@ -428,8 +440,11 @@ static int resolve_host_bootstrap_type(const char *host, uint16_t qtype, |
428 | 440 |
|
429 | 441 | tv.tv_sec = DNS_TIMEOUT_SEC; |
430 | 442 | tv.tv_usec = 0; |
431 | | - setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); |
432 | | - setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); |
| 443 | + if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 || |
| 444 | + setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { |
| 445 | + close(sd); |
| 446 | + return -1; |
| 447 | + } |
433 | 448 |
|
434 | 449 | id = (uint16_t)(((unsigned)getpid() ^ (unsigned)time(NULL)) & 0xFFFF); |
435 | 450 | qbuf[0] = (uint8_t)(id >> 8); |
@@ -582,8 +597,11 @@ static int tcp_connect_timeout(const struct doh_upstream *up) |
582 | 597 | if (fd < 0) |
583 | 598 | return -1; |
584 | 599 |
|
585 | | - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); |
586 | | - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); |
| 600 | + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 || |
| 601 | + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { |
| 602 | + close(fd); |
| 603 | + return -1; |
| 604 | + } |
587 | 605 |
|
588 | 606 | if (connect(fd, (struct sockaddr *)&resolved, resolved_len) != 0) { |
589 | 607 | close(fd); |
@@ -758,8 +776,10 @@ static int doh_query_roundtrip(WOLFSSL_CTX *wctx, |
758 | 776 | uint8_t tlsbuf[DNS_BUFFER_MAXSIZE]; |
759 | 777 | char clength[32]; |
760 | 778 | char errbuf[160]; |
| 779 | + unsigned long long deadline_ms; |
761 | 780 |
|
762 | 781 | *reply_len = 0; |
| 782 | + deadline_ms = monotonic_ms() + (DOH_EXCHANGE_TIMEOUT_SEC * 1000ULL); |
763 | 783 |
|
764 | 784 | fd = tcp_connect_timeout(up); |
765 | 785 | if (fd < 0) { |
@@ -849,6 +869,13 @@ static int doh_query_roundtrip(WOLFSSL_CTX *wctx, |
849 | 869 | } |
850 | 870 |
|
851 | 871 | while (!x.stream_closed && !x.failed) { |
| 872 | + unsigned long long now_ms = monotonic_ms(); |
| 873 | + if (now_ms > 0 && now_ms >= deadline_ms) { |
| 874 | + dohprint(DOH_DEBUG, "DoH exchange timed out"); |
| 875 | + x.failed = 1; |
| 876 | + break; |
| 877 | + } |
| 878 | + |
852 | 879 | ret = nghttp2_session_send(session); |
853 | 880 | if (ret != 0) { |
854 | 881 | dohprint(DOH_DEBUG, "nghttp2_session_send failed (%s)", nghttp2_strerror(ret)); |
@@ -1024,14 +1051,24 @@ int main(int argc, char *argv[]) |
1024 | 1051 | int pid = fork(); |
1025 | 1052 | if (pid < 0) |
1026 | 1053 | return 1; |
1027 | | - if (pid > 0) |
| 1054 | + if (pid > 0) { |
| 1055 | + free(user); |
| 1056 | + free(resolver_ip); |
| 1057 | + free(cafile); |
| 1058 | + free(url); |
1028 | 1059 | return 0; |
| 1060 | + } |
1029 | 1061 |
|
1030 | 1062 | pid = fork(); |
1031 | 1063 | if (pid < 0) |
1032 | 1064 | return 1; |
1033 | | - if (pid > 0) |
| 1065 | + if (pid > 0) { |
| 1066 | + free(user); |
| 1067 | + free(resolver_ip); |
| 1068 | + free(cafile); |
| 1069 | + free(url); |
1034 | 1070 | return 0; |
| 1071 | + } |
1035 | 1072 |
|
1036 | 1073 | setsid(); |
1037 | 1074 | close(STDIN_FILENO); |
|
0 commit comments