Improve DNS handling for compatibility with actual resolvers

- included unbound config
This commit is contained in:
Jop Zitman 2024-12-19 19:18:18 +08:00
parent eb6c7b538f
commit 16c45883b8
7 changed files with 213 additions and 89 deletions

View file

@ -10,7 +10,6 @@ set(ENABLE_ASAN OFF)
set(ENABLE_UBSAN OFF)
set(BUILD_DEMO OFF)
set(BUILD_HTTP OFF)
set(BUILD_LOGLIB ON)
set(BUILD_LOGREADER OFF)
set(BUILD_TESTING OFF)
@ -23,13 +22,12 @@ endif()
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
list(APPEND PICOQUIC_ADDITIONAL_C_FLAGS -Og)
list(APPEND PICOQUIC_ADDITIONAL_CXX_FLAGS -Og)
list(APPEND PICOQUIC_COMPILE_DEFINITIONS BUILD_LOGLIB)
set(BUILD_LOGLIB ON)
else()
list(APPEND PICOQUIC_ADDITIONAL_C_FLAGS -O3)
list(APPEND PICOQUIC_ADDITIONAL_CXX_FLAGS -O3)
endif()
if(BUILD_LOGLIB)
list(APPEND PICOQUIC_COMPILE_DEFINITIONS BUILD_LOGLIB)
set(BUILD_LOGLIB OFF)
endif()
if(POLICY CMP0048)

2
extern/picoquic vendored

@ -1 +1 @@
Subproject commit 7ac027d6e16ef344a19f8e32d49c93a6caef15da
Subproject commit afb1a46057b1e506d48d8126b4f958fbc1e9d869

View file

@ -2,21 +2,24 @@
#define SLIPSTREAM_DNS_REQUEST_BUFFER
#include <stdbool.h>
#include <picohash.h>
#include "SPCDNS/src/dns.h"
#define GLOBAL_BUFFER_SIZE 4096
#define GLOBAL_BUFFER_SIZE 32
typedef struct st_slipstream_cnxid_dns_request_buffer_t slipstream_cnxid_dns_request_buffer_t;
typedef struct st_element_t {
dns_decoded_t dns_decoded[DNS_DECODEBUF_4K];
struct sockaddr_storage peer_addr;
struct sockaddr_storage local_addr;
struct st_element_t* buffer_prev;
struct st_element_t* buffer_next;
struct st_element_t* cnxid_buffer_prev;
struct st_element_t* cnxid_buffer_next;
slipstream_cnxid_dns_request_buffer_t* cnxid_buffer;
uint64_t created_time;
int query_id;
} slot_t;
typedef struct st_slipstream_cnxid_dns_request_buffer_t {
@ -25,11 +28,13 @@ typedef struct st_slipstream_cnxid_dns_request_buffer_t {
} slipstream_cnxid_dns_request_buffer_t;
typedef struct {
slot_t elements[GLOBAL_BUFFER_SIZE];
slot_t slots[GLOBAL_BUFFER_SIZE];
slot_t* head;
slot_t* tail;
slot_t* free;
picohash_table* cnxid_to_cnxid_buffer;
slipstream_cnxid_dns_request_buffer_t** cnxid_buffers;
size_t cnxid_buffers_len;
} slipstream_dns_request_buffer_t;
typedef struct st_cnxid_to_cnxid_buffer_t {
@ -43,6 +48,8 @@ void slipstream_dns_request_buffer_init(slipstream_dns_request_buffer_t* buffer)
slipstream_cnxid_dns_request_buffer_t* slipstream_dns_request_buffer_get_cnxid_buffer(
slipstream_dns_request_buffer_t* buffer, picoquic_connection_id_t* initial_cnxid, bool create);
void slipstream_dns_request_buffer_free_slot(slipstream_dns_request_buffer_t* buffer, slot_t* slot);
slot_t* slipstream_dns_request_buffer_get_write_slot(slipstream_dns_request_buffer_t* buffer);
void slipstream_dns_request_buffer_commit_slot_to_cnxid_buffer(slipstream_dns_request_buffer_t* buffer,

View file

@ -47,7 +47,7 @@ ssize_t client_encode_segment(picoquic_quic_t* quic, dns_packet_t* packet, size_
edns.opt.type = RR_OPT;
edns.opt.class = CLASS_UNKNOWN;
edns.opt.ttl = 0;
edns.opt.udp_payload = 4096;
edns.opt.udp_payload = 1232;
dns_query_t query = {0};
query.id = rand() % UINT16_MAX;
@ -62,14 +62,14 @@ ssize_t client_encode_segment(picoquic_quic_t* quic, dns_packet_t* packet, size_
const dns_rcode_t rc = dns_encode(packet, packet_len, &query);
if (rc != RCODE_OKAY) {
fprintf(stderr, "dns_encode() = (%d) %s\n", rc, dns_rcode_text(rc));
DBG_PRINTF( "dns_encode() = (%d) %s\n", rc, dns_rcode_text(rc));
return -1;
}
return 0;
}
ssize_t client_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, unsigned char** dest_buf, const unsigned char* src_buf, size_t src_buf_len, size_t* segment_len, struct sockaddr_storage* peer_addr) {
ssize_t client_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, picoquic_socket_ctx_t* s_ctx, size_t s_ctx_len, unsigned char** dest_buf, const unsigned char* src_buf, size_t src_buf_len, size_t* segment_len, struct sockaddr_storage* peer_addr, struct sockaddr_storage* local_addr) {
// optimize path for single segment
if (src_buf_len <= *segment_len) {
size_t packet_len = MAX_DNS_QUERY_SIZE;
@ -124,34 +124,34 @@ ssize_t client_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
*dest_buf = NULL;
size_t bufsize = DNS_DECODEBUF_4K * sizeof(dns_decoded_t);
dns_decoded_t decoded[DNS_DECODEBUF_4K];
dns_decoded_t decoded[DNS_DECODEBUF_4K] = {0};
const dns_rcode_t rc = dns_decode(decoded, &bufsize, (const dns_packet_t*) src_buf, src_buf_len);
if (rc != RCODE_OKAY) {
fprintf(stderr, "dns_decode() = (%d) %s\n", rc, dns_rcode_text(rc));
DBG_PRINTF("dns_decode() = (%d) %s", rc, dns_rcode_text(rc));
return -1;
}
const dns_query_t *query = (dns_query_t *)decoded;
if (query->query == 1) {
fprintf(stderr, "dns record is not a response\n");
return -1;
DBG_PRINTF("[%d] dns record is not a response", query->id, NULL);
return 0;
}
if (query->rcode != RCODE_OKAY) {
fprintf(stderr, "dns record rcode not okay: %d\n", query->rcode);
return -1;
DBG_PRINTF("[%d] dns record rcode not okay: %d", query->id, query->rcode);
return 0;
}
if (query->ancount != 1) {
fprintf(stderr, "dns record should contain exactly one answer\n");
return -1;
DBG_PRINTF("[%d] dns record should contain exactly one answer", query->id);
return 0;
}
dns_txt_t *answer_txt = (dns_txt_t*) &query->answers[0];
if (answer_txt->type != RR_TXT) {
fprintf(stderr, "answer type is not TXT\n");
return -1;
DBG_PRINTF("[%d] answer type is not TXT", query->id, NULL);
return 0;
}
*dest_buf = malloc(answer_txt->len);
@ -164,13 +164,13 @@ ssize_t client_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
int ret = slipstream_packet_parse(*dest_buf, answer_txt->len, PICOQUIC_SHORT_HEADER_CONNECTION_ID_SIZE,
&incoming_src_connection_id, &incoming_dest_connection_id, &is_poll_packet);
if (ret != 0 || is_poll_packet) {
fprintf(stderr, "error parsing slipstream packet: %d\n", ret);
DBG_PRINTF("[%d] error parsing slipstream packet: %d", query->id, ret);
return answer_txt->len;
}
const SOCKET_TYPE send_socket = picoquic_socket_get_send_socket(s_ctx, s_ctx_len, peer_addr, local_addr);
if (send_socket == INVALID_SOCKET) {
fprintf(stderr, "no valid socket found for poll packet\n");
DBG_PRINTF("[%d] no valid socket found for poll packet", query->id);
return answer_txt->len;
}
@ -188,15 +188,15 @@ ssize_t client_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
size_t poll_packet_len;
ret = slipstream_packet_create_poll(&poll_packet_buf, &poll_packet_len, outgoing_dest_connection_id);
if (ret < 0) {
fprintf(stderr, "error creating poll packet\n");
DBG_PRINTF("error creating poll packet", NULL);
return answer_txt->len;
}
unsigned char* encoded;
ssize_t encoded_len = client_encode(quic, cnx, &encoded, poll_packet_buf, poll_packet_len, &poll_packet_len,
peer_addr);
ssize_t encoded_len = client_encode(quic, cnx, s_ctx, s_ctx_len, &encoded, poll_packet_buf, poll_packet_len,
&poll_packet_len, peer_addr, local_addr);
if (encoded_len <= 0) {
fprintf(stderr, "error encoding poll packet\n");
DBG_PRINTF("error encoding poll packet", NULL);
free(poll_packet_buf);
return answer_txt->len;
}
@ -206,7 +206,7 @@ ssize_t client_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
(struct sockaddr*)peer_addr, (struct sockaddr*)local_addr, 0,
(const char*)encoded, encoded_len, 0, &sock_err);
if (ret < 0) {
fprintf(stderr, "Error sending poll packet, ret=%d, sock_err=%d %s\n", ret, sock_err, strerror(sock_err));
DBG_PRINTF("Error sending poll packet, ret=%d, sock_err=%d %s", ret, sock_err, strerror(sock_err));
free(poll_packet_buf);
free(encoded);
return answer_txt->len;
@ -577,6 +577,14 @@ int slipstream_client_callback(picoquic_cnx_t* cnx,
for (size_t i = 1; i < client_ctx->server_address_count; i++) {
struct sockaddr* server_address = (struct sockaddr*)&client_ctx->server_addresses[i];
uint64_t current_time = picoquic_current_time();
// convert server address to string
char host[NI_MAXHOST];
socklen_t addrlen = sizeof(*server_address);
ret = getnameinfo(server_address, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
if (ret == 0) {
printf("Probing path: %s", host);
}
ret = picoquic_probe_new_path(cnx, server_address, NULL, current_time);
if (ret != 0) {
fprintf(stderr, "Could not create probe new path\n");
@ -630,6 +638,9 @@ static int slipstream_connect(struct sockaddr_storage* server_address,
return -1;
}
// 400ms
picoquic_enable_keep_alive(*cnx, 400000);
/* Document connection in client's context */
client_ctx->cnx = *cnx;
/* Set the client callback context */
@ -704,6 +715,7 @@ int picoquic_slipstream_client(int listen_port, char const* resolver_addresses_f
debug_printf_push_stream(stderr);
#endif
picoquic_set_key_log_file_from_env(quic);
// TODO: idle timeout?
/* Read the server address list from the file */
client_ctx->server_addresses = read_resolver_addresses(resolver_addresses_filename, &client_ctx->server_address_count);

View file

@ -28,7 +28,7 @@ void slipstream_dns_request_buffer_init(slipstream_dns_request_buffer_t* buffer)
buffer->tail = NULL;
for (int i = 0; i < GLOBAL_BUFFER_SIZE; i++) {
slot_t* element = &buffer->elements[i];
slot_t* element = &buffer->slots[i];
element->buffer_next = buffer->free;
element->buffer_prev = NULL;
buffer->free = element;
@ -70,31 +70,42 @@ slipstream_cnxid_dns_request_buffer_t* slipstream_dns_request_buffer_get_cnxid_b
fprintf(stderr, "error adding a cnx buffer for a new cnx id\n");
return NULL;
}
buffer->cnxid_buffers_len++;
slipstream_cnxid_dns_request_buffer_t** cnxid_buffers = realloc(buffer->cnxid_buffers,
buffer->cnxid_buffers_len * sizeof(slipstream_cnxid_dns_request_buffer_t*));
if (cnxid_buffers == NULL) {
return NULL;
}
buffer->cnxid_buffers = cnxid_buffers;
buffer->cnxid_buffers[buffer->cnxid_buffers_len - 1] = new_key->cnxid_buffer;
return new_key->cnxid_buffer;
}
void slipstream_cnxid_dns_request_buffer_free_slot(slipstream_cnxid_dns_request_buffer_t* cnxid_buffer, slot_t* slot) {
if (slot->cnxid_buffer_prev != NULL) {
slot->cnxid_buffer_prev->cnxid_buffer_next = slot->cnxid_buffer_next;
}
if (slot->cnxid_buffer_next != NULL) {
slot->cnxid_buffer_next->cnxid_buffer_prev = slot->cnxid_buffer_prev;
}
if (cnxid_buffer->head == slot) {
cnxid_buffer->head = slot->cnxid_buffer_next;
}
if (cnxid_buffer->tail == slot) {
cnxid_buffer->tail = slot->cnxid_buffer_prev;
}
slot->cnxid_buffer = NULL;
}
void slipstream_dns_request_buffer_free_slot(slipstream_dns_request_buffer_t* buffer, slot_t* slot) {
slipstream_cnxid_dns_request_buffer_t* cnxid_buffer = slot->cnxid_buffer;
if (cnxid_buffer != NULL) {
if (slot->cnxid_buffer_prev != NULL) {
slot->cnxid_buffer_prev->cnxid_buffer_next = slot->cnxid_buffer_next;
}
if (slot->cnxid_buffer_next != NULL) {
slot->cnxid_buffer_next->cnxid_buffer_prev = slot->cnxid_buffer_prev;
}
if (cnxid_buffer->head == slot) {
cnxid_buffer->head = slot->cnxid_buffer_next;
}
if (cnxid_buffer->tail == slot) {
cnxid_buffer->tail = slot->cnxid_buffer_prev;
}
slot->cnxid_buffer = NULL;
}
if (slot->buffer_prev != NULL) {
slot->buffer_prev->buffer_next = slot->buffer_next;
}
@ -116,14 +127,12 @@ void slipstream_dns_request_buffer_free_slot(slipstream_dns_request_buffer_t* bu
}
slot->buffer_next = buffer->free;
buffer->free = slot;
slot->query_id = 0;
}
slot_t* slipstream_dns_request_buffer_get_write_slot(slipstream_dns_request_buffer_t* buffer) {
if (!buffer->free) {
slot_t* tail = buffer->tail;
assert(tail != NULL);
slipstream_cnxid_dns_request_buffer_free_slot(tail->cnxid_buffer, tail);
slipstream_dns_request_buffer_free_slot(buffer, tail);
return NULL;
}
// Get the first free element
@ -167,16 +176,13 @@ void slipstream_dns_request_buffer_commit_slot_to_cnxid_buffer(slipstream_dns_re
}
slot_t* slipstream_dns_request_buffer_get_read_slot(slipstream_dns_request_buffer_t* buffer,
slipstream_cnxid_dns_request_buffer_t* cnxid_buffer) {
slipstream_cnxid_dns_request_buffer_t* cnxid_buffer) {
// Get the last element from the cnxid buffer
slot_t* slot = cnxid_buffer->tail;
if (!slot) {
return NULL;
}
slipstream_cnxid_dns_request_buffer_free_slot(slot->cnxid_buffer, slot);
slipstream_dns_request_buffer_free_slot(buffer, slot);
return slot;
}

View file

@ -6,7 +6,6 @@
#ifdef BUILD_LOGLIB
#include <autoqlog.h>
#endif
#include <picohash.h>
#include <pthread.h>
#include <stdbool.h>
#include <arpa/nameser.h>
@ -30,7 +29,53 @@ size_t server_domain_name_len = 0;
slipstream_dns_request_buffer_t slipstream_server_dns_request_buffer;
ssize_t server_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, unsigned char** dest_buf, const unsigned char* src_buf, size_t src_buf_len, size_t* segment_size, struct sockaddr_storage *peer_addr) {
ssize_t respond_and_free_slot(slot_t* slot, const picoquic_socket_ctx_t* s_ctx, const size_t s_ctx_len, dns_rcode_t rcode) {
const dns_query_t *query = (dns_query_t *) slot->dns_decoded;
dns_query_t response = {0};
response.id = query->id;
response.query = false;
response.opcode = query->opcode;
response.aa = true;
response.rd = query->rd;
response.cd = query->cd;
response.rcode = rcode;
response.qdcount = query->qdcount;
response.questions = query->questions;
dns_packet_t packet[DNS_BUFFER_UDP_MAX];
size_t packet_len = MAX_UDP_PACKET_SIZE;
dns_rcode_t rc = dns_encode(packet, &packet_len, &response);
// slot not used anymore, free it
slipstream_dns_request_buffer_free_slot(&slipstream_server_dns_request_buffer, slot);
if (rc != RCODE_OKAY) {
DBG_PRINTF("dns_encode() = (%d) %s", rc, dns_rcode_text(rc));
return -1;
}
const struct sockaddr_storage *peer_addr = &slot->peer_addr;
const struct sockaddr_storage *local_addr = &slot->local_addr;
const SOCKET_TYPE send_socket = picoquic_socket_get_send_socket(s_ctx, s_ctx_len, peer_addr, local_addr);
if (send_socket == INVALID_SOCKET) {
DBG_PRINTF("no valid socket found for poll packet", NULL);
return -1;
}
int sock_err = 0;
int ret = picoquic_sendmsg(send_socket,
(struct sockaddr*)peer_addr, (struct sockaddr*)local_addr, 0,
(const char*)packet, packet_len, 0, &sock_err);
if (ret < 0) {
DBG_PRINTF("Error sending poll packet, ret=%d, sock_err=%d %s", ret, sock_err, strerror(sock_err));
return -1;
}
return 0;
}
ssize_t server_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, picoquic_socket_ctx_t* s_ctx, size_t s_ctx_len,
unsigned char** dest_buf, const unsigned char* src_buf, size_t src_buf_len, size_t* segment_size,
struct sockaddr_storage* peer_addr, struct sockaddr_storage* local_addr) {
// we don't support segmentation in the server
assert(segment_size == NULL || *segment_size == 0 || *segment_size == src_buf_len);
@ -39,22 +84,16 @@ ssize_t server_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, unsigned char*
slipstream_cnxid_dns_request_buffer_t* cnxid_buffer = slipstream_dns_request_buffer_get_cnxid_buffer(
&slipstream_server_dns_request_buffer, &initial_cnxid, false);
if (cnxid_buffer == NULL) {
fprintf(stderr, "error getting cnxid buffer\n");
DBG_PRINTF("error getting cnxid buffer", NULL);
return -1;
}
slot_t *slot = slipstream_dns_request_buffer_get_read_slot(&slipstream_server_dns_request_buffer, cnxid_buffer);
if (slot == NULL) {
fprintf(stderr, "no available DNS request to respond to\n");
DBG_PRINTF("no available DNS request to respond to", NULL);
return -1;
}
dns_query_t *query = (dns_query_t *) slot->dns_decoded;
if (query->questions == NULL) {
fprintf(stderr, "no questions in DNS request\n");
return -1;
}
const dns_question_t *question = &query->questions[0]; // assuming server_decode ensures there is exactly one question
dns_txt_t answer_txt;
answer_txt.name = question->name;
@ -69,13 +108,15 @@ ssize_t server_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, unsigned char*
edns.opt.type = RR_OPT;
edns.opt.class = CLASS_UNKNOWN;
edns.opt.ttl = 0;
edns.opt.udp_payload = 4096;
edns.opt.udp_payload = 1232;
dns_query_t response = {0};
response.id = query->id;
response.query = false;
response.opcode = OP_QUERY;
response.rd = true;
response.aa = true;
response.rd = query->rd;
response.cd = query->cd;
response.rcode = RCODE_OKAY;
response.qdcount = 1;
response.questions = query->questions;
@ -87,9 +128,10 @@ ssize_t server_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, unsigned char*
dns_packet_t* packet = malloc(MAX_UDP_PACKET_SIZE);
size_t packet_len = MAX_UDP_PACKET_SIZE;
dns_rcode_t rc = dns_encode(packet, &packet_len, &response);
slipstream_dns_request_buffer_free_slot(&slipstream_server_dns_request_buffer, slot);
if (rc != RCODE_OKAY) {
free(packet);
fprintf(stderr, "dns_encode() = (%d) %s\n", rc, dns_rcode_text(rc));
DBG_PRINTF("dns_encode() = (%d) %s", rc, dns_rcode_text(rc));
return EXIT_FAILURE;
}
*dest_buf = (unsigned char*)packet;
@ -102,46 +144,60 @@ ssize_t server_encode(picoquic_quic_t* quic, picoquic_cnx_t* cnx, unsigned char*
ssize_t server_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_t s_ctx_len, unsigned char** dest_buf, const unsigned char* src_buf, size_t src_buf_len, struct sockaddr_storage *peer_addr, struct sockaddr_storage *local_addr) {
*dest_buf = NULL;
slot_t* slot = slipstream_dns_request_buffer_get_write_slot(&slipstream_server_dns_request_buffer);
slot_t* slot;
if (!slipstream_server_dns_request_buffer.free) {
slot = slipstream_server_dns_request_buffer.tail;
assert(slot != NULL);
assert(slot->cnxid_buffer != NULL);
respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_NAME_ERROR);
}
slot = slipstream_dns_request_buffer_get_write_slot(&slipstream_server_dns_request_buffer);
if (slot == NULL) {
fprintf(stderr, "error getting write slot\n");
DBG_PRINTF("error getting write slot", NULL);
sockaddr_dummy(peer_addr);
return -1;
}
slot->created_time = picoquic_current_time();
// DNS packets arrive from random source ports, so:
// * save the original address in the dns query slot
// * set the source address to a dummy address (to prevent QUIC from using it)
memcpy(&slot->peer_addr, peer_addr, sizeof(struct sockaddr_storage));
sockaddr_dummy(peer_addr);
// Save local address for right response local addr
memcpy(&slot->local_addr, local_addr, sizeof(struct sockaddr_storage));
size_t packet_len = DNS_DECODEBUF_4K * sizeof(dns_decoded_t);
dns_decoded_t* packet = slot->dns_decoded;
const dns_rcode_t rc = dns_decode(packet, &packet_len, (const dns_packet_t*) src_buf, src_buf_len);
if (rc != RCODE_OKAY) {
fprintf(stderr, "dns_decode() = (%d) %s\n", rc, dns_rcode_text(rc));
return -1;
DBG_PRINTF("dns_decode() = (%d) %s", rc, dns_rcode_text(rc));
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_SERVER_FAILURE);
}
const dns_query_t *query = (dns_query_t*) packet;
if (!query->query) {
fprintf(stderr, "dns record is not a query\n");
return -1;
DBG_PRINTF("dns record is not a query", NULL);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_REFUSED);
}
if (query->qdcount != 1) {
fprintf(stderr, "dns record should contain exactly one query\n");
return -1;
DBG_PRINTF("dns record should contain exactly one query", NULL);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_REFUSED);
}
const dns_question_t *question = &query->questions[0];
if (question->type != RR_TXT) {
fprintf(stderr, "query type is not TXT\n");
return -1;
DBG_PRINTF("query type is not TXT", NULL);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_REFUSED);
}
const size_t data_len = strlen(question->name) - server_domain_name_len - 1 - 1;
const ssize_t data_len = strlen(question->name) - server_domain_name_len - 1 - 1;
if (data_len <= 0) {
DBG_PRINTF("subdomain is empty", NULL);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_REFUSED);
}
// copy the subdomain from name to a new buffer
char data_buf[data_len];
@ -153,8 +209,8 @@ ssize_t server_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
const size_t decoded_len = b32_decode(decoded_buf, data_buf, encoded_len, false);
if (decoded_len == (size_t) -1) {
free(decoded_buf);
fprintf(stderr, "error decoding base32: %lu\n", decoded_len);
return -1;
DBG_PRINTF("error decoding base32: %lu", decoded_len);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_SERVER_FAILURE);
}
picoquic_connection_id_t incoming_src_connection_id = {0};
@ -165,8 +221,8 @@ ssize_t server_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
&incoming_src_connection_id, &incoming_dest_connection_id, &is_poll_packet);
if (ret != 0) {
free(decoded_buf);
fprintf(stderr, "error parsing slipstream packet: %d\n", ret);
return -1;
DBG_PRINTF("error parsing slipstream packet: %d", ret);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_SERVER_FAILURE);
}
picoquic_cnx_t *cnx = picoquic_cnx_by_id_(quic, incoming_dest_connection_id);
@ -181,10 +237,11 @@ ssize_t server_decode(picoquic_quic_t* quic, picoquic_socket_ctx_t* s_ctx, size_
&slipstream_server_dns_request_buffer, &initial_cnxid, true);
if (cnxid_buffer == NULL) {
free(decoded_buf);
fprintf(stderr, "error getting or creating cnxid buffer\n");
return -1;
DBG_PRINTF("error getting or creating cnxid buffer", NULL);
return respond_and_free_slot(slot, s_ctx, s_ctx_len, RCODE_SERVER_FAILURE);
}
slot->query_id = query->id;
slipstream_dns_request_buffer_commit_slot_to_cnxid_buffer(&slipstream_server_dns_request_buffer, cnxid_buffer, slot);
if (is_poll_packet) {
@ -295,6 +352,28 @@ int slipstream_server_sockloop_callback(picoquic_quic_t* quic, picoquic_packet_l
slipstream_server_ctx_t* server_ctx = callback_ctx;
switch (cb_mode) {
case picoquic_packet_loop_after_select:
const picoquic_socket_ctxs_t* s_ctxs = (picoquic_socket_ctxs_t*)callback_arg;
uint64_t current_time = picoquic_current_time();
for (int i = 0; i < slipstream_server_dns_request_buffer.cnxid_buffers_len; ++i) {
const slipstream_cnxid_dns_request_buffer_t* cnxid_buffer = slipstream_server_dns_request_buffer.cnxid_buffers[i];
assert(cnxid_buffer != NULL);
slot_t* slot = cnxid_buffer->tail;
while (slot != NULL) {
const uint64_t age = current_time - slot->created_time;
if (age < 10000) {
DBG_PRINTF("[%d][age:%d] found young slot", slot->query_id, age);
break;
}
// attempt to reply before resolver retries
DBG_PRINTF("[%d][age:%d] freeing old slot", slot->query_id, age);
respond_and_free_slot(slot, s_ctxs->s_ctx, s_ctxs->len, RCODE_NAME_ERROR);
slot = slot->cnxid_buffer_prev;
}
}
break;
case picoquic_packet_loop_wake_up:
if (callback_ctx == NULL) {
return 0;

22
unbound.conf Executable file
View file

@ -0,0 +1,22 @@
server:
interface: 0.0.0.0
access-control: 0.0.0.0/0 allow
do-not-query-localhost: no
verbosity: 1
do-tcp: no
log-queries: yes
log-replies: yes
remote-control:
control-enable: yes
control-interface: 0.0.0.0
control-port: 8953
control-use-cert: no
stub-zone:
name: "test.com"
stub-addr: 127.0.0.3@8853
forward-zone:
name: "."
forward-addr: 10.64.0.1