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);
*/
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 */
/* 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 */
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 */
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;
cfgerr++;
} else {
if (newsrv->resolution)
- newsrv->resolution->resolvers = curr_resolvers;
+ newsrv->resolvers = curr_resolvers;
}
}
else {
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)) {
* 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);
}
}
*/
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
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;
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);
}
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);
*/
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);
* 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)
{
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:
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;
}
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)) {
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) {
*/
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)
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;
}
if (!found)
goto err;
- srv->resolution->resolvers = curr_resolvers;
+ srv->resolvers = curr_resolvers;
}
return 0;
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;
}
if (!srv->resolution)
return;
- free(srv->resolution->hostname_dn);
dns_free_resolution(srv->resolution);
srv->resolution = NULL;
}
if (ret)
return ret;
- if (srv->resolution)
- srv->resolution->opts = &srv->dns_opts;
-
srv->check.state |= state;
global.maxsock++;
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:
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);
/* 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)) {
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)) {
}
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;