BUG/MINOR: dns: fix missing lock protection on server.
To avoid inconsistencies server's attributes must be read or updated under lock.
This commit is contained in:
parent
5222d8eb25
commit
e9fd6b5916
10
src/dns.c
10
src/dns.c
@ -486,6 +486,7 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||||||
|
|
||||||
/* Remove any associated server */
|
/* Remove any associated server */
|
||||||
for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
|
for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
|
||||||
|
SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||||
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
|
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
|
||||||
item->data_len == srv->hostname_dn_len &&
|
item->data_len == srv->hostname_dn_len &&
|
||||||
!memcmp(srv->hostname_dn, item->target, item->data_len)) {
|
!memcmp(srv->hostname_dn, item->target, item->data_len)) {
|
||||||
@ -497,6 +498,7 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||||||
srv->hostname_dn_len = 0;
|
srv->hostname_dn_len = 0;
|
||||||
dns_unlink_resolution(srv->dns_requester);
|
dns_unlink_resolution(srv->dns_requester);
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,6 +518,7 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||||||
|
|
||||||
/* Check if a server already uses that hostname */
|
/* Check if a server already uses that hostname */
|
||||||
for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
|
for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
|
||||||
|
SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||||
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
|
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
|
||||||
item->data_len == srv->hostname_dn_len &&
|
item->data_len == srv->hostname_dn_len &&
|
||||||
!memcmp(srv->hostname_dn, item->target, item->data_len)) {
|
!memcmp(srv->hostname_dn, item->target, item->data_len)) {
|
||||||
@ -525,16 +528,20 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||||||
snprintf(weight, sizeof(weight), "%d", item->weight);
|
snprintf(weight, sizeof(weight), "%d", item->weight);
|
||||||
server_parse_weight_change_request(srv, weight);
|
server_parse_weight_change_request(srv, weight);
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
}
|
}
|
||||||
if (srv)
|
if (srv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If not, try to find a server with undefined hostname */
|
/* If not, try to find a server with undefined hostname */
|
||||||
for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
|
for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
|
||||||
|
SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||||
if (srv->srvrq == srvrq && !srv->hostname_dn)
|
if (srv->srvrq == srvrq && !srv->hostname_dn)
|
||||||
break;
|
break;
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
}
|
}
|
||||||
/* And update this server, if found */
|
/* And update this server, if found */
|
||||||
if (srv) {
|
if (srv) {
|
||||||
@ -556,6 +563,7 @@ static void dns_check_dns_response(struct dns_resolution *res)
|
|||||||
srv->check.port = item->port;
|
srv->check.port = item->port;
|
||||||
snprintf(weight, sizeof(weight), "%d", item->weight);
|
snprintf(weight, sizeof(weight), "%d", item->weight);
|
||||||
server_parse_weight_change_request(srv, weight);
|
server_parse_weight_change_request(srv, weight);
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1337,6 +1345,7 @@ int dns_link_resolution(void *requester, int requester_type)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (srv) {
|
if (srv) {
|
||||||
|
SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||||
if (srv->dns_requester == NULL) {
|
if (srv->dns_requester == NULL) {
|
||||||
if ((req = calloc(1, sizeof(*req))) == NULL)
|
if ((req = calloc(1, sizeof(*req))) == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
@ -1345,6 +1354,7 @@ int dns_link_resolution(void *requester, int requester_type)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
req = srv->dns_requester;
|
req = srv->dns_requester;
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
}
|
}
|
||||||
else if (srvrq) {
|
else if (srvrq) {
|
||||||
if (srvrq->dns_requester == NULL) {
|
if (srvrq->dns_requester == NULL) {
|
||||||
|
20
src/server.c
20
src/server.c
@ -3712,8 +3712,14 @@ struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char
|
|||||||
if (!srv)
|
if (!srv)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||||
|
|
||||||
be = srv->proxy;
|
be = srv->proxy;
|
||||||
for (tmpsrv = be->srv; tmpsrv; tmpsrv = tmpsrv->next) {
|
for (tmpsrv = be->srv; tmpsrv; tmpsrv = tmpsrv->next) {
|
||||||
|
/* we found the current server is the same, ignore it */
|
||||||
|
if (srv == tmpsrv)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* We want to compare the IP in the record with the IP of the servers in the
|
/* We want to compare the IP in the record with the IP of the servers in the
|
||||||
* same backend, only if:
|
* same backend, only if:
|
||||||
* * DNS resolution is enabled on the server
|
* * DNS resolution is enabled on the server
|
||||||
@ -3721,15 +3727,20 @@ struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char
|
|||||||
* one used for the server found in the backend
|
* one used for the server found in the backend
|
||||||
* * the server found in the backend is not our current server
|
* * the server found in the backend is not our current server
|
||||||
*/
|
*/
|
||||||
|
SPIN_LOCK(SERVER_LOCK, &tmpsrv->lock);
|
||||||
if ((tmpsrv->hostname_dn == NULL) ||
|
if ((tmpsrv->hostname_dn == NULL) ||
|
||||||
(srv->hostname_dn_len != tmpsrv->hostname_dn_len) ||
|
(srv->hostname_dn_len != tmpsrv->hostname_dn_len) ||
|
||||||
(strcmp(srv->hostname_dn, tmpsrv->hostname_dn) != 0) ||
|
(strcmp(srv->hostname_dn, tmpsrv->hostname_dn) != 0) ||
|
||||||
(srv->puid == tmpsrv->puid))
|
(srv->puid == tmpsrv->puid)) {
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* If the server has been taken down, don't consider it */
|
/* If the server has been taken down, don't consider it */
|
||||||
if (tmpsrv->next_admin & SRV_ADMF_RMAINT)
|
if (tmpsrv->next_admin & SRV_ADMF_RMAINT) {
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* At this point, we have 2 different servers using the same DNS hostname
|
/* At this point, we have 2 different servers using the same DNS hostname
|
||||||
* for their respective resolution.
|
* for their respective resolution.
|
||||||
@ -3739,10 +3750,15 @@ struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char
|
|||||||
memcmp(ip, &((struct sockaddr_in *)&tmpsrv->addr)->sin_addr, 4) == 0) ||
|
memcmp(ip, &((struct sockaddr_in *)&tmpsrv->addr)->sin_addr, 4) == 0) ||
|
||||||
(tmpsrv->addr.ss_family == AF_INET6 &&
|
(tmpsrv->addr.ss_family == AF_INET6 &&
|
||||||
memcmp(ip, &((struct sockaddr_in6 *)&tmpsrv->addr)->sin6_addr, 16) == 0))) {
|
memcmp(ip, &((struct sockaddr_in6 *)&tmpsrv->addr)->sin6_addr, 16) == 0))) {
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock);
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
return tmpsrv;
|
return tmpsrv;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user