MINOR: dns: Maximum DNS udp payload set to 8192

Following up DNS extension introduction, this patch aims at making the
computation of the maximum number of records in DNS response dynamic.
This computation is based on the announced payload size accepted by
HAProxy.
This commit is contained in:
Baptiste Assmann 2017-08-18 23:35:08 +02:00 committed by Willy Tarreau
parent 747359eeca
commit 9d8dbbc56b
5 changed files with 26 additions and 10 deletions

View File

@ -11716,9 +11716,11 @@ accepted_payload_size <nb>
<nb> is in bytes. If not set, HAProxy announces 512. (minimal value defined
by RFC 6891)
Note: to get biggers response but still be sure that responses won't be
Note: to get bigger responses but still be sure that responses won't be
dropped on the wire, one can choose a value between 1280 and 1410.
Note: the maximum allowed value is 8192.
nameserver <id> <ip>:<port>
DNS server description:
<id> : label of the server, should be unique

View File

@ -33,7 +33,7 @@ int dns_build_query(int query_id, int query_type, unsigned int accepted_payload_
struct task *dns_process_resolve(struct task *t);
int dns_init_resolvers(int close_socket);
uint16_t dns_rnd16(void);
int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct dns_resolution *resolution);
int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct dns_resolution *resolution, int max_answer_records);
int dns_get_ip_from_response(struct dns_response_packet *dns_p,
struct dns_options *dns_opts, void *currentip,
short currentip_sin_family,

View File

@ -30,7 +30,7 @@
*/
#define DNS_MAX_LABEL_SIZE 63
#define DNS_MAX_NAME_SIZE 255
#define DNS_MAX_UDP_MESSAGE 512
#define DNS_MAX_UDP_MESSAGE 8192
/* DNS minimun record size: 1 char + 1 NULL + type + class */
#define DNS_MIN_RECORD_SIZE ( 1 + 1 + 2 + 2 )

View File

@ -2294,13 +2294,24 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
}
else if (strcmp(args[0], "accepted_payload_size") == 0) {
int i = 0;
if (!*args[1]) {
Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
curr_resolvers->accepted_payload_size = atoi(args[1]);
i = atoi(args[1]);
if (i > DNS_MAX_UDP_MESSAGE) {
Alert("parsing [%s:%d] : '%s' size %d exceeds maximum allowed size %d.\n",
file, linenum, args[0], i, DNS_MAX_UDP_MESSAGE);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
curr_resolvers->accepted_payload_size = i;
}
else if (strcmp(args[0], "resolution_pool_size") == 0) {
if (!*args[1]) {

View File

@ -391,6 +391,7 @@ void dns_resolve_recv(struct dgram_conn *dgram)
unsigned char buf[DNS_MAX_UDP_MESSAGE + 1];
unsigned char *bufend;
int fd, buflen, dns_resp, need_resend = 0;
int max_answer_records = 0;
unsigned short query_id;
struct eb32_node *eb;
struct lru64 *lru = NULL;
@ -413,15 +414,15 @@ void dns_resolve_recv(struct dgram_conn *dgram)
while (1) {
int removed_reso = 0;
/* read message received */
memset(buf, '\0', DNS_MAX_UDP_MESSAGE + 1);
if ((buflen = recv(fd, (char*)buf , DNS_MAX_UDP_MESSAGE, 0)) < 0) {
memset(buf, '\0', resolvers->accepted_payload_size + 1);
if ((buflen = recv(fd, (char*)buf , resolvers->accepted_payload_size + 1, 0)) < 0) {
/* FIXME : for now we consider EAGAIN only */
fd_cant_recv(fd);
break;
}
/* message too big */
if (buflen > DNS_MAX_UDP_MESSAGE) {
if (buflen > resolvers->accepted_payload_size) {
nameserver->counters.too_big += 1;
continue;
}
@ -455,7 +456,9 @@ void dns_resolve_recv(struct dgram_conn *dgram)
/* number of responses received */
resolution->nb_responses += 1;
dns_resp = dns_validate_dns_response(buf, bufend, resolution);
max_answer_records = (resolvers->accepted_payload_size - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE;
dns_resp = dns_validate_dns_response(buf, bufend, resolution, max_answer_records);
switch (dns_resp) {
case DNS_RESP_VALID:
@ -1086,7 +1089,7 @@ int dns_read_name(unsigned char *buffer, unsigned char *bufend, unsigned char *n
* This function returns one of the DNS_RESP_* code to indicate the type of
* error found.
*/
int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct dns_resolution *resolution)
int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct dns_resolution *resolution, int max_answer_records)
{
unsigned char *reader;
char *previous_dname, tmpname[DNS_MAX_NAME_SIZE];
@ -1157,7 +1160,7 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct
if (dns_p->header.ancount == 0)
return DNS_RESP_ANCOUNT_ZERO;
/* check if too many records are announced */
if (dns_p->header.ancount > DNS_MAX_ANSWER_RECORDS)
if (dns_p->header.ancount > max_answer_records)
return DNS_RESP_INVALID;
reader += 2;