fix: stub udp max_udp_size > 4096 support

This commit is contained in:
Willem Toorop 2014-10-23 15:17:54 +02:00
parent 6f6b8e65a2
commit d03a22ba62
3 changed files with 30 additions and 17 deletions

View File

@ -76,6 +76,8 @@ network_req_new(getdns_dns_req * owner,
net_req->fd = -1; net_req->fd = -1;
memset(&net_req->event, 0, sizeof(net_req->event)); memset(&net_req->event, 0, sizeof(net_req->event));
memset(&net_req->tcp, 0, sizeof(net_req->tcp)); memset(&net_req->tcp, 0, sizeof(net_req->tcp));
net_req->query_id = 0;
net_req->max_udp_payload_size = 0;
net_req->write_queue_tail = NULL; net_req->write_queue_tail = NULL;
return net_req; return net_req;
} }

View File

@ -44,8 +44,8 @@
#include "general.h" #include "general.h"
static int static int
getdns_make_query_pkt_buf( getdns_make_query_pkt_buf(const getdns_network_req *netreq, uint8_t *buf,
getdns_network_req *netreq, uint8_t *buf, size_t *olen) size_t *olen, uint16_t *omax_udp_payload_size)
{ {
size_t len; size_t len;
@ -163,6 +163,7 @@ getdns_make_query_pkt_buf(
if (len < 11) if (len < 11)
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
*omax_udp_payload_size = edns_maximum_udp_payload_size;
buf[0] = 0; /* dname for . */ buf[0] = 0; /* dname for . */
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT); gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
gldns_write_uint16(buf + 3, gldns_write_uint16(buf + 3,
@ -402,15 +403,21 @@ stub_udp_read_cb(void *userarg)
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
if (netreq->max_udp_payload_size > pkt_buf_len) {
pkt_len = netreq->max_udp_payload_size;
if (!(pkt = GETDNS_XMALLOC(
dnsreq->context->mf, uint8_t, pkt_len)))
goto done;
}
read = recvfrom(netreq->fd, pkt, pkt_len, 0, NULL, NULL); read = recvfrom(netreq->fd, pkt, pkt_len, 0, NULL, NULL);
if (read == -1 && (errno = EAGAIN || errno == EWOULDBLOCK)) if (read == -1 && (errno = EAGAIN || errno == EWOULDBLOCK))
return; goto exit;
if (read < GLDNS_HEADER_SIZE) if (read < GLDNS_HEADER_SIZE)
return; /* Not DNS */ goto exit; /* Not DNS */
if (GLDNS_ID_WIRE(pkt) != netreq->query_id) if (GLDNS_ID_WIRE(pkt) != netreq->query_id)
return; /* Cache poisoning attempt ;) */ goto exit; /* Cache poisoning attempt ;) */
close(netreq->fd); close(netreq->fd);
if (GLDNS_TC_WIRE(pkt) && if (GLDNS_TC_WIRE(pkt) &&
@ -433,7 +440,7 @@ stub_udp_read_cb(void *userarg)
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
NULL, stub_tcp_write_cb, stub_timeout_cb)); NULL, stub_tcp_write_cb, stub_timeout_cb));
return; goto exit;
} }
ldns_wire2pkt(&(netreq->result), pkt, read); ldns_wire2pkt(&(netreq->result), pkt, read);
dnsreq->upstreams->current = 0; dnsreq->upstreams->current = 0;
@ -441,10 +448,13 @@ stub_udp_read_cb(void *userarg)
/* TODO: DNSSEC */ /* TODO: DNSSEC */
netreq->secure = 0; netreq->secure = 0;
netreq->bogus = 0; netreq->bogus = 0;
done: done:
netreq->state = NET_REQ_FINISHED; netreq->state = NET_REQ_FINISHED;
priv_getdns_check_dns_req_complete(dnsreq); exit:
if (pkt && pkt != pkt_buf)
GETDNS_FREE(dnsreq->context->mf, pkt);
if (netreq->state == NET_REQ_FINISHED)
priv_getdns_check_dns_req_complete(dnsreq);
} }
static void static void
@ -471,8 +481,9 @@ stub_udp_write_cb(void *userarg)
} else } else
pkt_len = pkt_buf_len; pkt_len = pkt_buf_len;
if (getdns_make_query_pkt_buf(netreq, pkt_buf, &pkt_len)) if (getdns_make_query_pkt_buf(netreq, pkt_buf, &pkt_len,
goto done; &netreq->max_udp_payload_size))
goto exit;
netreq->query_id = ldns_get_random(); netreq->query_id = ldns_get_random();
GLDNS_ID_SET(pkt, netreq->query_id); GLDNS_ID_SET(pkt, netreq->query_id);
@ -481,18 +492,15 @@ stub_udp_write_cb(void *userarg)
(struct sockaddr *)&netreq->upstream->addr, (struct sockaddr *)&netreq->upstream->addr,
netreq->upstream->addr_len)) { netreq->upstream->addr_len)) {
close(netreq->fd); close(netreq->fd);
goto done; goto exit;
} }
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(
dnsreq->loop, netreq->fd, dnsreq->context->timeout, dnsreq->loop, netreq->fd, dnsreq->context->timeout,
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
stub_udp_read_cb, NULL, stub_timeout_cb)); stub_udp_read_cb, NULL, stub_timeout_cb));
exit:
done: if (pkt && pkt != pkt_buf)
if (pkt_size_needed > pkt_buf_len)
GETDNS_FREE(dnsreq->context->mf, pkt); GETDNS_FREE(dnsreq->context->mf, pkt);
return;
} }
static getdns_upstream * static getdns_upstream *
@ -754,7 +762,8 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
pkt_len = pkt_buf_len - 2; pkt_len = pkt_buf_len - 2;
/* Construct query packet */ /* Construct query packet */
if (getdns_make_query_pkt_buf(netreq, pkt + 2, &pkt_len)) if (getdns_make_query_pkt_buf(netreq, pkt + 2, &pkt_len,
&netreq->max_udp_payload_size))
return STUB_TCP_ERROR; return STUB_TCP_ERROR;
/* Prepend length short */ /* Prepend length short */

View File

@ -202,6 +202,8 @@ typedef struct getdns_network_req
getdns_tcp_state tcp; getdns_tcp_state tcp;
uint16_t query_id; uint16_t query_id;
uint16_t max_udp_payload_size;
/* Network requests scheduled to write after me */ /* Network requests scheduled to write after me */
struct getdns_network_req *write_queue_tail; struct getdns_network_req *write_queue_tail;