mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-03 10:01:27 +00:00
MINOR: dns: new snr_check_ip_callback function
In the process of breaking links between dns_* functions and other structures (mainly server and a bit of resolution), the function dns_get_ip_from_response needs to be reworked: it now can call "callback" functions based on resolution's owner type to allow modifying the way the response is processed. For now, main purpose of the callback function is to check that an IP address is not already affected to an element of the same type. For now, only server type has a callback.
This commit is contained in:
parent
42746373eb
commit
fb7091e213
@ -33,10 +33,11 @@ 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,
|
||||
int dns_get_ip_from_response(struct dns_response_packet *dns_p,
|
||||
struct dns_options *dns_opts, void *currentip,
|
||||
short currentip_sin_family,
|
||||
void **newip, short *newip_sin_family);
|
||||
void **newip, short *newip_sin_family,
|
||||
void *owner);
|
||||
void dns_resolve_send(struct dgram_conn *dgram);
|
||||
void dns_resolve_recv(struct dgram_conn *dgram);
|
||||
int dns_send_query(struct dns_resolution *resolution);
|
||||
|
@ -55,6 +55,7 @@ struct server *cli_find_server(struct appctx *appctx, char *arg);
|
||||
int snr_update_srv_status(struct server *s);
|
||||
int snr_resolution_cb(struct dns_resolution *resolution, struct dns_nameserver *nameserver, struct dns_response_packet *dns_p);
|
||||
int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code);
|
||||
struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char *ip_family);
|
||||
|
||||
/* increase the number of cumulated connections on the designated server */
|
||||
static void inline srv_inc_sess_ctr(struct server *s)
|
||||
|
41
src/dns.c
41
src/dns.c
@ -719,10 +719,11 @@ 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,
|
||||
int dns_get_ip_from_response(struct dns_response_packet *dns_p,
|
||||
struct dns_options *dns_opts, void *currentip,
|
||||
short currentip_sin_family,
|
||||
void **newip, short *newip_sin_family)
|
||||
void **newip, short *newip_sin_family,
|
||||
void *owner)
|
||||
{
|
||||
struct dns_answer_item *record;
|
||||
int family_priority;
|
||||
@ -788,8 +789,6 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p, struct dns_resol
|
||||
*/
|
||||
max_score = -1;
|
||||
for (i = 0; i < rec_nb; i++) {
|
||||
struct server *srv, *tmpsrv;
|
||||
struct proxy *be;
|
||||
int record_ip_already_affected = 0;
|
||||
|
||||
score = 0;
|
||||
@ -818,36 +817,14 @@ int dns_get_ip_from_response(struct dns_response_packet *dns_p, struct dns_resol
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the IP found in the record is already affected to an other server. */
|
||||
srv = resol->requester;
|
||||
be = srv->proxy;
|
||||
for (tmpsrv = be->srv; tmpsrv; tmpsrv = tmpsrv->next) {
|
||||
/* We want to compare the IP in the record with the IP of the servers in the
|
||||
* same backend, only if:
|
||||
* * DNS resolution is enabled on the server
|
||||
* * the hostname used for the resolution by our server is the same than the
|
||||
* one used for the server found in the backend
|
||||
* * the server found in the backend is not our current server
|
||||
*/
|
||||
if ((tmpsrv->resolution == NULL) ||
|
||||
(srv->resolution->hostname_dn_len != tmpsrv->resolution->hostname_dn_len) ||
|
||||
(strcmp(srv->resolution->hostname_dn, tmpsrv->resolution->hostname_dn) != 0) ||
|
||||
(srv->puid == tmpsrv->puid))
|
||||
continue;
|
||||
|
||||
/* At this point, we have 2 different servers using the same DNS hostname
|
||||
* for their respective resolution.
|
||||
*/
|
||||
if (rec[i].type == tmpsrv->addr.ss_family &&
|
||||
((tmpsrv->addr.ss_family == AF_INET &&
|
||||
memcmp(rec[i].ip, &((struct sockaddr_in *)&tmpsrv->addr)->sin_addr, 4) == 0) ||
|
||||
(tmpsrv->addr.ss_family == AF_INET6 &&
|
||||
memcmp(rec[i].ip, &((struct sockaddr_in6 *)&tmpsrv->addr)->sin6_addr, 16) == 0))) {
|
||||
/* Check if the IP found in the record is already affected to a member of a group.
|
||||
* If yes, the score should be incremented by 2.
|
||||
*/
|
||||
if (owner) {
|
||||
if (snr_check_ip_callback(owner, rec[i].ip, &rec[i].type))
|
||||
record_ip_already_affected = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!record_ip_already_affected)
|
||||
if (record_ip_already_affected == 0)
|
||||
score += 2;
|
||||
|
||||
/* Check for current ip matching. */
|
||||
|
49
src/server.c
49
src/server.c
@ -3859,9 +3859,9 @@ int snr_resolution_cb(struct dns_resolution *resolution, struct dns_nameserver *
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
ret = dns_get_ip_from_response(dns_p, resolution, &s->dns_opts,
|
||||
ret = dns_get_ip_from_response(dns_p, &s->dns_opts,
|
||||
serverip, server_sin_family, &firstip,
|
||||
&firstip_sin_family);
|
||||
&firstip_sin_family, s);
|
||||
|
||||
switch (ret) {
|
||||
case DNS_UPD_NO:
|
||||
@ -4055,6 +4055,51 @@ int snr_resolution_error_cb(struct dns_resolution *resolution, int error_code)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to check if <ip> is already affected to a server in the backend
|
||||
* which owns <srv>.
|
||||
* It returns a pointer to the first server found or NULL if <ip> is not yet
|
||||
* assigned.
|
||||
* NOTE: <ip> and <ip_family> are provided by a 'struct rec' available in dns.c.
|
||||
*/
|
||||
struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char *ip_family)
|
||||
{
|
||||
struct server *tmpsrv;
|
||||
struct proxy *be;
|
||||
|
||||
if (!srv)
|
||||
return NULL;
|
||||
|
||||
be = srv->proxy;
|
||||
for (tmpsrv = be->srv; tmpsrv; tmpsrv = tmpsrv->next) {
|
||||
/* We want to compare the IP in the record with the IP of the servers in the
|
||||
* same backend, only if:
|
||||
* * DNS resolution is enabled on the server
|
||||
* * the hostname used for the resolution by our server is the same than the
|
||||
* one used for the server found in the backend
|
||||
* * the server found in the backend is not our current server
|
||||
*/
|
||||
if ((tmpsrv->resolution == NULL) ||
|
||||
(srv->resolution->hostname_dn_len != tmpsrv->resolution->hostname_dn_len) ||
|
||||
(strcmp(srv->resolution->hostname_dn, tmpsrv->resolution->hostname_dn) != 0) ||
|
||||
(srv->puid == tmpsrv->puid))
|
||||
continue;
|
||||
|
||||
/* At this point, we have 2 different servers using the same DNS hostname
|
||||
* for their respective resolution.
|
||||
*/
|
||||
if (*ip_family == tmpsrv->addr.ss_family &&
|
||||
((tmpsrv->addr.ss_family == AF_INET &&
|
||||
memcmp(ip, &((struct sockaddr_in *)&tmpsrv->addr)->sin_addr, 4) == 0) ||
|
||||
(tmpsrv->addr.ss_family == AF_INET6 &&
|
||||
memcmp(ip, &((struct sockaddr_in6 *)&tmpsrv->addr)->sin6_addr, 16) == 0))) {
|
||||
return tmpsrv;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sets the server's address (srv->addr) from srv->hostname using the libc's
|
||||
* resolver. This is suited for initial address configuration. Returns 0 on
|
||||
* success otherwise a non-zero error code. In case of error, *err_code, if
|
||||
|
Loading…
Reference in New Issue
Block a user