REORG: dns: dns_option structure, storage of hostname_dn
This patch introduces a some re-organisation around the DNS code in HAProxy. 1. make the dns_* functions less dependent on 'struct server' and 'struct resolution'. With this in mind, the following changes were performed: - 'struct dns_options' has been removed from 'struct resolution' (well, we might need it back at some point later, we'll see) ==> we'll use the 'struct dns_options' from the owner of the resolution - dns_get_ip_from_response(): takes a 'struct dns_options' instead of 'struct resolution' ==> so the caller can pass its own dns options to get the most appropriate IP from the response - dns_process_resolve(): struct dns_option is deduced from new resolution->requester_type parameter 2. add hostname_dn and hostname_dn_len into struct server In order to avoid recomputing a server's hostname into its domain name format (and use a trash buffer to store the result), it is safer to compute it once at configuration parsing and to store it into the struct server. In the mean time, the struct resolution linked to the server doesn't need anymore to store the hostname in domain name format. A simple pointer to the server one will make the trick. The function srv_alloc_dns_resolution() properly manages everything for us: memory allocation, pointer updates, etc... 3. move resolvers pointer into struct server This patch makes the pointer to struct dns_resolvers from struct dns_resolution obsolete. Purpose is to make the resolution as "neutral" as possible and since the requester is already linked to the resolvers, then we don't need this information anymore in the resolution itself.
This commit is contained in:
parent
4f91f7ea59
commit
42746373eb
@ -33,8 +33,8 @@ 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_response_packet *dns_p);
|
||||
int dns_get_ip_from_response(struct dns_response_packet *dns_p,
|
||||
struct dns_resolution *resol, void *currentip,
|
||||
int dns_get_ip_from_response(struct dns_response_packet *dns_p, struct dns_resolution *resol,
|
||||
struct dns_options *dns_opts, void *currentip,
|
||||
short currentip_sin_family,
|
||||
void **newip, short *newip_sin_family);
|
||||
void dns_resolve_send(struct dgram_conn *dgram);
|
||||
|
@ -218,7 +218,6 @@ struct dns_options {
|
||||
*/
|
||||
struct dns_resolution {
|
||||
struct list list; /* resolution list */
|
||||
struct dns_resolvers *resolvers; /* resolvers section associated to this resolution */
|
||||
void *requester; /* owner of this name resolution */
|
||||
int (*requester_cb)(struct dns_resolution *, struct dns_nameserver *, struct dns_response_packet *);
|
||||
/* requester callback for valid response */
|
||||
@ -226,7 +225,6 @@ struct dns_resolution {
|
||||
/* requester callback, for error management */
|
||||
char *hostname_dn; /* server hostname in domain name label format */
|
||||
int hostname_dn_len; /* server domain name label len */
|
||||
struct dns_options *opts; /* IP selection options inherited from the configuration file. */
|
||||
unsigned int last_resolution; /* time of the lastest valid resolution */
|
||||
unsigned int last_sent_packet; /* time of the latest DNS packet sent */
|
||||
unsigned int last_status_change; /* time of the latest DNS resolution status change */
|
||||
@ -273,6 +271,7 @@ enum {
|
||||
DNS_RESP_TRUNCATED, /* DNS response is truncated */
|
||||
DNS_RESP_NO_EXPECTED_RECORD, /* No expected records were found in the response */
|
||||
DNS_RESP_QUERY_COUNT_ERROR, /* we did not get the expected number of queries in the response */
|
||||
DNS_RESP_INTERNAL, /* internal resolver error */
|
||||
};
|
||||
|
||||
/* return codes after searching an IP in a DNS response buffer, using a family preference */
|
||||
|
@ -255,7 +255,10 @@ struct server {
|
||||
struct check agent; /* agent specific configuration */
|
||||
|
||||
char *resolvers_id; /* resolvers section used by this server */
|
||||
struct dns_resolvers *resolvers; /* pointer to the resolvers structure used by this server */
|
||||
char *hostname; /* server hostname */
|
||||
char *hostname_dn; /* server hostname in Domain Name format */
|
||||
int hostname_dn_len; /* sting lenght of the server hostname in Domain Name format */
|
||||
char *lastaddr; /* the address string provided by the server-state file */
|
||||
struct dns_resolution *resolution; /* server name resolution */
|
||||
struct dns_options dns_opts;
|
||||
|
@ -8515,7 +8515,7 @@ out_uri_auth_compat:
|
||||
cfgerr++;
|
||||
} else {
|
||||
if (newsrv->resolution)
|
||||
newsrv->resolution->resolvers = curr_resolvers;
|
||||
newsrv->resolvers = curr_resolvers;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
12
src/checks.c
12
src/checks.c
@ -2209,6 +2209,7 @@ static struct task *process_chk(struct task *t)
|
||||
struct check *check = t->context;
|
||||
struct server *s = check->server;
|
||||
struct dns_resolution *resolution = s->resolution;
|
||||
struct dns_resolvers *resolvers = s->resolvers;
|
||||
|
||||
/* trigger name resolution */
|
||||
if ((s->check.state & CHK_ST_ENABLED) && (resolution)) {
|
||||
@ -2218,7 +2219,7 @@ static struct task *process_chk(struct task *t)
|
||||
* if there has not been any name resolution for a longer period than
|
||||
* hold.valid, let's trigger a new one.
|
||||
*/
|
||||
if (!resolution->last_resolution || tick_is_expired(tick_add(resolution->last_resolution, resolution->resolvers->hold.valid), now_ms)) {
|
||||
if (!resolution->last_resolution || tick_is_expired(tick_add(resolution->last_resolution, resolvers->hold.valid), now_ms)) {
|
||||
trigger_resolution(s);
|
||||
}
|
||||
}
|
||||
@ -2242,13 +2243,13 @@ static struct task *process_chk(struct task *t)
|
||||
*/
|
||||
int trigger_resolution(struct server *s)
|
||||
{
|
||||
struct dns_resolution *resolution;
|
||||
struct dns_resolvers *resolvers;
|
||||
struct dns_resolution *resolution = NULL;
|
||||
struct dns_resolvers *resolvers = NULL;
|
||||
int query_id;
|
||||
int i;
|
||||
|
||||
resolution = s->resolution;
|
||||
resolvers = resolution->resolvers;
|
||||
resolvers = s->resolvers;
|
||||
|
||||
/*
|
||||
* check if a resolution has already been started for this server
|
||||
@ -2277,8 +2278,7 @@ int trigger_resolution(struct server *s)
|
||||
resolution->query_id = query_id;
|
||||
resolution->qid.key = query_id;
|
||||
resolution->step = RSLV_STEP_RUNNING;
|
||||
resolution->opts = &s->dns_opts;
|
||||
if (resolution->opts->family_prio == AF_INET) {
|
||||
if (s->dns_opts.family_prio == AF_INET) {
|
||||
resolution->query_type = DNS_RTYPE_A;
|
||||
} else {
|
||||
resolution->query_type = DNS_RTYPE_AAAA;
|
||||
|
43
src/dns.c
43
src/dns.c
@ -118,13 +118,6 @@ void dns_reset_resolution(struct dns_resolution *resolution)
|
||||
resolution->query_id = 0;
|
||||
resolution->qid.key = 0;
|
||||
|
||||
/* default values */
|
||||
if (resolution->opts->family_prio == AF_INET) {
|
||||
resolution->query_type = DNS_RTYPE_A;
|
||||
} else {
|
||||
resolution->query_type = DNS_RTYPE_AAAA;
|
||||
}
|
||||
|
||||
/* the second resolution in the queue becomes the first one */
|
||||
LIST_DEL(&resolution->list);
|
||||
}
|
||||
@ -217,6 +210,7 @@ void dns_resolve_recv(struct dgram_conn *dgram)
|
||||
resolution->requester_error_cb(resolution, DNS_RESP_INVALID);
|
||||
continue;
|
||||
|
||||
case DNS_RESP_INTERNAL:
|
||||
case DNS_RESP_ERROR:
|
||||
nameserver->counters.other += 1;
|
||||
resolution->requester_error_cb(resolution, DNS_RESP_ERROR);
|
||||
@ -308,11 +302,14 @@ void dns_resolve_send(struct dgram_conn *dgram)
|
||||
*/
|
||||
int dns_send_query(struct dns_resolution *resolution)
|
||||
{
|
||||
struct dns_resolvers *resolvers;
|
||||
struct dns_resolvers *resolvers = NULL;
|
||||
struct dns_nameserver *nameserver;
|
||||
int ret, bufsize, fd;
|
||||
|
||||
resolvers = resolution->resolvers;
|
||||
resolvers = ((struct server *)resolution->requester)->resolvers;
|
||||
|
||||
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);
|
||||
@ -722,8 +719,8 @@ int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct
|
||||
* returns one of the DNS_UPD_* code
|
||||
*/
|
||||
#define DNS_MAX_IP_REC 20
|
||||
int dns_get_ip_from_response(struct dns_response_packet *dns_p,
|
||||
struct dns_resolution *resol, void *currentip,
|
||||
int dns_get_ip_from_response(struct dns_response_packet *dns_p, struct dns_resolution *resol,
|
||||
struct dns_options *dns_opts, void *currentip,
|
||||
short currentip_sin_family,
|
||||
void **newip, short *newip_sin_family)
|
||||
{
|
||||
@ -739,14 +736,15 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p,
|
||||
int j;
|
||||
int rec_nb = 0;
|
||||
int score, max_score;
|
||||
struct dns_response_packet *dns_response = dns_p;
|
||||
|
||||
family_priority = resol->opts->family_prio;
|
||||
family_priority = dns_opts->family_prio;
|
||||
*newip = newip4 = newip6 = NULL;
|
||||
currentip_found = 0;
|
||||
*newip_sin_family = AF_UNSPEC;
|
||||
|
||||
/* now parsing response records */
|
||||
list_for_each_entry(record, &dns_response.answer_list, list) {
|
||||
list_for_each_entry(record, &dns_response->answer_list, list) {
|
||||
/* analyzing record content */
|
||||
switch (record->type) {
|
||||
case DNS_RTYPE_A:
|
||||
@ -801,20 +799,20 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p,
|
||||
score += 8;
|
||||
|
||||
/* Check for prefered network. */
|
||||
for (j = 0; j < resol->opts->pref_net_nb; j++) {
|
||||
for (j = 0; j < dns_opts->pref_net_nb; j++) {
|
||||
|
||||
/* Compare only the same adresses class. */
|
||||
if (resol->opts->pref_net[j].family != rec[i].type)
|
||||
if (dns_opts->pref_net[j].family != rec[i].type)
|
||||
continue;
|
||||
|
||||
if ((rec[i].type == AF_INET &&
|
||||
in_net_ipv4(rec[i].ip,
|
||||
&resol->opts->pref_net[j].mask.in4,
|
||||
&resol->opts->pref_net[j].addr.in4)) ||
|
||||
&dns_opts->pref_net[j].mask.in4,
|
||||
&dns_opts->pref_net[j].addr.in4)) ||
|
||||
(rec[i].type == AF_INET6 &&
|
||||
in_net_ipv6(rec[i].ip,
|
||||
&resol->opts->pref_net[j].mask.in6,
|
||||
&resol->opts->pref_net[j].addr.in6))) {
|
||||
&dns_opts->pref_net[j].mask.in6,
|
||||
&dns_opts->pref_net[j].addr.in6))) {
|
||||
score += 4;
|
||||
break;
|
||||
}
|
||||
@ -1261,6 +1259,7 @@ struct task *dns_process_resolve(struct task *t)
|
||||
struct dns_resolvers *resolvers = t->context;
|
||||
struct dns_resolution *resolution, *res_back;
|
||||
int res_preferred_afinet, res_preferred_afinet6;
|
||||
struct dns_options *dns_opts = NULL;
|
||||
|
||||
/* timeout occurs inevitably for the first element of the FIFO queue */
|
||||
if (LIST_ISEMPTY(&resolvers->curr_resolution)) {
|
||||
@ -1290,8 +1289,10 @@ struct task *dns_process_resolve(struct task *t)
|
||||
|
||||
resolution->try -= 1;
|
||||
|
||||
res_preferred_afinet = resolution->opts->family_prio == AF_INET && resolution->query_type == DNS_RTYPE_A;
|
||||
res_preferred_afinet6 = resolution->opts->family_prio == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA;
|
||||
dns_opts = &((struct server *)resolution->requester)->dns_opts;
|
||||
|
||||
res_preferred_afinet = dns_opts->family_prio == AF_INET && resolution->query_type == DNS_RTYPE_A;
|
||||
res_preferred_afinet6 = dns_opts->family_prio == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA;
|
||||
|
||||
/* let's change the query type if needed */
|
||||
if (res_preferred_afinet6) {
|
||||
|
39
src/server.c
39
src/server.c
@ -1658,8 +1658,6 @@ static void srv_ssl_settings_cpy(struct server *srv, struct server *src)
|
||||
*/
|
||||
static int srv_alloc_dns_resolution(struct server *srv, const char *hostname)
|
||||
{
|
||||
char *hostname_dn;
|
||||
int hostname_dn_len;
|
||||
struct dns_resolution *dst_dns_rslt;
|
||||
|
||||
if (!hostname)
|
||||
@ -1669,21 +1667,21 @@ static int srv_alloc_dns_resolution(struct server *srv, const char *hostname)
|
||||
srv->hostname = strdup(hostname);
|
||||
dst_dns_rslt = dns_alloc_resolution();
|
||||
|
||||
hostname_dn_len = dns_str_to_dn_label_len(hostname);
|
||||
hostname_dn = calloc(hostname_dn_len + 1, sizeof(char));
|
||||
srv->hostname_dn_len = dns_str_to_dn_label_len(hostname);
|
||||
srv->hostname_dn = calloc(srv->hostname_dn_len + 1, sizeof(char));
|
||||
|
||||
if (!srv->hostname || !dst_dns_rslt || !hostname_dn)
|
||||
if (!srv->hostname || !dst_dns_rslt || !srv->hostname_dn)
|
||||
goto err;
|
||||
|
||||
srv->resolution = dst_dns_rslt;
|
||||
srv->resolution->hostname_dn = hostname_dn;
|
||||
srv->resolution->hostname_dn_len = hostname_dn_len;
|
||||
|
||||
if (!dns_str_to_dn_label(srv->hostname,
|
||||
srv->resolution->hostname_dn,
|
||||
srv->resolution->hostname_dn_len + 1))
|
||||
srv->hostname_dn,
|
||||
srv->hostname_dn_len + 1))
|
||||
goto err;
|
||||
|
||||
srv->resolution->hostname_dn = srv->hostname_dn;
|
||||
srv->resolution->hostname_dn_len = srv->hostname_dn_len;
|
||||
srv->resolution->requester = srv;
|
||||
srv->resolution->requester_cb = snr_resolution_cb;
|
||||
srv->resolution->requester_error_cb = snr_resolution_error_cb;
|
||||
@ -1704,7 +1702,7 @@ static int srv_alloc_dns_resolution(struct server *srv, const char *hostname)
|
||||
}
|
||||
if (!found)
|
||||
goto err;
|
||||
srv->resolution->resolvers = curr_resolvers;
|
||||
srv->resolvers = curr_resolvers;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1712,7 +1710,8 @@ static int srv_alloc_dns_resolution(struct server *srv, const char *hostname)
|
||||
err:
|
||||
free(srv->hostname);
|
||||
srv->hostname = NULL;
|
||||
free(hostname_dn);
|
||||
free(srv->hostname_dn);
|
||||
srv->hostname_dn = NULL;
|
||||
dns_free_resolution(dst_dns_rslt);
|
||||
return -1;
|
||||
}
|
||||
@ -1722,7 +1721,6 @@ static void srv_free_dns_resolution(struct server *srv)
|
||||
if (!srv->resolution)
|
||||
return;
|
||||
|
||||
free(srv->resolution->hostname_dn);
|
||||
dns_free_resolution(srv->resolution);
|
||||
srv->resolution = NULL;
|
||||
}
|
||||
@ -1926,9 +1924,6 @@ static const char *do_health_check_init(struct server *srv, int check_type, int
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (srv->resolution)
|
||||
srv->resolution->opts = &srv->dns_opts;
|
||||
|
||||
srv->check.state |= state;
|
||||
global.maxsock++;
|
||||
|
||||
@ -3749,9 +3744,7 @@ out:
|
||||
int snr_update_srv_status(struct server *s)
|
||||
{
|
||||
struct dns_resolution *resolution = s->resolution;
|
||||
struct dns_resolvers *resolvers;
|
||||
|
||||
resolvers = resolution->resolvers;
|
||||
struct dns_resolvers *resolvers = s->resolvers;
|
||||
|
||||
switch (resolution->status) {
|
||||
case RSLV_STATUS_NONE:
|
||||
@ -3866,7 +3859,7 @@ int snr_resolution_cb(struct dns_resolution *resolution, struct dns_nameserver *
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
ret = dns_get_ip_from_response(dns_p, resolution,
|
||||
ret = dns_get_ip_from_response(dns_p, resolution, &s->dns_opts,
|
||||
serverip, server_sin_family, &firstip,
|
||||
&firstip_sin_family);
|
||||
|
||||
@ -3958,7 +3951,7 @@ int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code)
|
||||
|
||||
/* shortcut to the server whose name is being resolved */
|
||||
s = resolution->requester;
|
||||
resolvers = resolution->resolvers;
|
||||
resolvers = s->resolvers;
|
||||
|
||||
/* can be ignored if this is not the last response */
|
||||
if ((error_code != DNS_RESP_TIMEOUT) && (resolution->nb_responses < resolvers->count_nameservers)) {
|
||||
@ -3979,8 +3972,8 @@ int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code)
|
||||
case DNS_RESP_ERROR:
|
||||
case DNS_RESP_NO_EXPECTED_RECORD:
|
||||
case DNS_RESP_CNAME_ERROR:
|
||||
res_preferred_afinet = resolution->opts->family_prio == AF_INET && resolution->query_type == DNS_RTYPE_A;
|
||||
res_preferred_afinet6 = resolution->opts->family_prio == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA;
|
||||
res_preferred_afinet = s->dns_opts.family_prio == AF_INET && resolution->query_type == DNS_RTYPE_A;
|
||||
res_preferred_afinet6 = s->dns_opts.family_prio == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA;
|
||||
|
||||
if ((res_preferred_afinet || res_preferred_afinet6)
|
||||
|| (resolution->try > 0)) {
|
||||
@ -3995,7 +3988,7 @@ int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code)
|
||||
}
|
||||
else {
|
||||
resolution->try -= 1;
|
||||
if (resolution->opts->family_prio == AF_INET) {
|
||||
if (s->dns_opts.family_prio == AF_INET) {
|
||||
resolution->query_type = DNS_RTYPE_A;
|
||||
} else {
|
||||
resolution->query_type = DNS_RTYPE_AAAA;
|
||||
|
Loading…
Reference in New Issue
Block a user