MINOR: dns: enabled edns0 extension and make accpeted payload size tunable
Edns extensions may be used to negotiate some settings between a DNS client and a server. For now we only use it to announce the maximum response payload size accpeted by HAProxy. This size can be set through a configuration parameter in the resolvers section. If not set, it defaults to 512 bytes.
This commit is contained in:
parent
572ab8b269
commit
2af08fe3de
|
@ -11710,6 +11710,15 @@ resolvers <resolvers id>
|
|||
|
||||
A resolvers section accept the following parameters:
|
||||
|
||||
accepted_payload_size <nb>
|
||||
Defines the maxium payload size accepted by HAProxy and announced to all the
|
||||
naeservers configured in this resolvers section.
|
||||
<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
|
||||
dropped on the wire, one can choose a value between 1280 and 1410.
|
||||
|
||||
nameserver <id> <ip>:<port>
|
||||
DNS server description:
|
||||
<id> : label of the server, should be unique
|
||||
|
|
|
@ -29,7 +29,7 @@ char *dns_str_to_dn_label(const char *string, char *dn, int dn_len);
|
|||
int dns_str_to_dn_label_len(const char *string);
|
||||
void dns_dn_label_to_str(char *dn, char *str, int dn_len);
|
||||
int dns_hostname_validation(const char *string, char **err);
|
||||
int dns_build_query(int query_id, int query_type, char *hostname_dn, int hostname_dn_len, char *buf, int bufsize);
|
||||
int dns_build_query(int query_id, int query_type, unsigned int accepted_payload_size, char *hostname_dn, int hostname_dn_len, char *buf, int bufsize);
|
||||
struct task *dns_process_resolve(struct task *t);
|
||||
int dns_init_resolvers(int close_socket);
|
||||
uint16_t dns_rnd16(void);
|
||||
|
|
|
@ -112,6 +112,20 @@ struct dns_query_item {
|
|||
unsigned short class; /* query class */
|
||||
};
|
||||
|
||||
/* NOTE: big endian structure */
|
||||
struct dns_additional_record {
|
||||
uint8_t name; /* domain name, must be 0 (RFC 6891) */
|
||||
uint16_t type; /* record type DNS_RTYPE_OPT (41) */
|
||||
uint16_t udp_payload_size; /* maximum size accepted for the response */
|
||||
uint32_t extension; /* extended rcode and flags, not used for now */
|
||||
uint16_t data_length; /* data length */
|
||||
/* as of today, we don't support yet edns options, that said I already put a placeholder here
|
||||
* for this purpose. We may need to define a dns_option_record structure which itself should
|
||||
* point to different type of data, based on the extension set (client subnet, tcp keepalive,
|
||||
* etc...)*/
|
||||
// struct list options; /* list of option records */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* NOTE: big endian structure */
|
||||
struct dns_answer_item {
|
||||
struct list list;
|
||||
|
@ -150,6 +164,7 @@ struct dns_resolvers {
|
|||
int line; /* line where the section appears */
|
||||
} conf; /* config information */
|
||||
struct list nameserver_list; /* dns server list */
|
||||
unsigned int accepted_payload_size; /* maximum payload size we accept for responses */
|
||||
int count_nameservers; /* total number of nameservers in a resolvers section */
|
||||
int resolve_retries; /* number of retries before giving up */
|
||||
struct { /* time to: */
|
||||
|
|
|
@ -2162,6 +2162,8 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
|
|||
curr_resolvers->conf.line = linenum;
|
||||
curr_resolvers->id = strdup(args[1]);
|
||||
curr_resolvers->query_ids = EB_ROOT;
|
||||
/* default maximum response size */
|
||||
curr_resolvers->accepted_payload_size = 512;
|
||||
/* default hold period for nx, other, refuse and timeout is 30s */
|
||||
curr_resolvers->hold.nx = 30000;
|
||||
curr_resolvers->hold.other = 30000;
|
||||
|
@ -2291,6 +2293,15 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
|
|||
}
|
||||
|
||||
}
|
||||
else if (strcmp(args[0], "accepted_payload_size") == 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]);
|
||||
}
|
||||
else if (strcmp(args[0], "resolution_pool_size") == 0) {
|
||||
if (!*args[1]) {
|
||||
Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
|
||||
|
|
22
src/dns.c
22
src/dns.c
|
@ -897,8 +897,8 @@ int dns_send_query(struct dns_resolution *resolution)
|
|||
if (!resolvers)
|
||||
return 0;
|
||||
|
||||
bufsize = dns_build_query(resolution->query_id, resolution->query_type, resolution->hostname_dn,
|
||||
resolution->hostname_dn_len, trash.str, trash.size);
|
||||
bufsize = dns_build_query(resolution->query_id, resolution->query_type, resolvers->accepted_payload_size,
|
||||
resolution->hostname_dn, resolution->hostname_dn_len, trash.str, trash.size);
|
||||
|
||||
if (bufsize == -1)
|
||||
return 0;
|
||||
|
@ -1820,10 +1820,11 @@ int dns_alloc_resolution_pool(struct dns_resolvers *resolvers)
|
|||
* returns:
|
||||
* -1 if <buf> is too short
|
||||
*/
|
||||
int dns_build_query(int query_id, int query_type, char *hostname_dn, int hostname_dn_len, char *buf, int bufsize)
|
||||
int dns_build_query(int query_id, int query_type, unsigned int accepted_payload_size, char *hostname_dn, int hostname_dn_len, char *buf, int bufsize)
|
||||
{
|
||||
struct dns_header *dns;
|
||||
struct dns_question qinfo;
|
||||
struct dns_additional_record edns;
|
||||
char *ptr, *bufend;
|
||||
|
||||
memset(buf, '\0', bufsize);
|
||||
|
@ -1841,7 +1842,7 @@ int dns_build_query(int query_id, int query_type, char *hostname_dn, int hostnam
|
|||
dns->qdcount = htons(1); /* 1 question */
|
||||
dns->ancount = 0;
|
||||
dns->nscount = 0;
|
||||
dns->arcount = 0;
|
||||
dns->arcount = htons(1);
|
||||
|
||||
/* move forward ptr */
|
||||
ptr += sizeof(struct dns_header);
|
||||
|
@ -1868,6 +1869,19 @@ int dns_build_query(int query_id, int query_type, char *hostname_dn, int hostnam
|
|||
|
||||
ptr += sizeof(struct dns_question);
|
||||
|
||||
/* check if there is enough room for additional records */
|
||||
if (ptr + sizeof(edns) >= bufend)
|
||||
return -1;
|
||||
|
||||
/* set the DNS extension */
|
||||
edns.name = 0;
|
||||
edns.type = htons(DNS_RTYPE_OPT);
|
||||
edns.udp_payload_size = htons(accepted_payload_size);
|
||||
edns.extension = 0;
|
||||
edns.data_length = 0;
|
||||
memcpy(ptr, &edns, sizeof(edns));
|
||||
ptr += sizeof(edns);
|
||||
|
||||
return ptr - buf;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue