void dns_purge_resolution_answer_records(struct dns_resolution *resolution);
int dns_link_resolution(void *requester, int requester_type, int requester_locked);
-void dns_unlink_resolution(struct dns_requester *requester);
+void dns_unlink_resolution(struct dns_requester *requester, int safe);
void dns_trigger_resolution(struct dns_requester *requester);
enum act_parse_ret dns_parse_do_resolve(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err);
int check_action_do_resolve(struct act_rule *rule, struct proxy *px, char **err);
if (srv->srvrq == srvrq && srv->svc_port == item->port &&
item->data_len == srv->hostname_dn_len &&
!dns_hostname_cmp(srv->hostname_dn, item->target, item->data_len)) {
- dns_unlink_resolution(srv->dns_requester);
+ dns_unlink_resolution(srv->dns_requester, 0);
srvrq_update_srv_status(srv, 1);
free(srv->hostname);
free(srv->hostname_dn);
/* Removes a requester from a DNS resoltion. It takes takes care of all the
* consequences. It also cleans up some parameters from the requester.
+ * if <safe> is set to 1, the corresponding resolution is not released.
*/
-void dns_unlink_resolution(struct dns_requester *requester)
+void dns_unlink_resolution(struct dns_requester *requester, int safe)
{
struct dns_resolution *res;
struct dns_requester *req;
if (!LIST_ISEMPTY(&res->requesters))
req = LIST_NEXT(&res->requesters, struct dns_requester *, list);
else {
+ if (safe) {
+ /* Don't release it yet. */
+ dns_reset_resolution(res);
+ res->hostname_dn = NULL;
+ res->hostname_dn_len = 0;
+ dns_purge_resolution_answer_records(res);
+ return;
+ }
+
dns_free_resolution(res);
return;
}
/* Handle all expired resolutions from the active list */
list_for_each_entry_safe(res, resback, &resolvers->resolutions.curr, list) {
+ if (LIST_ISEMPTY(&res->requesters)) {
+ dns_free_resolution(res);
+ continue;
+ }
+
/* When we find the first resolution in the future, then we can
* stop here */
exp = tick_add(res->last_query, resolvers->timeout.retry);
/* Handle all resolutions in the wait list */
list_for_each_entry_safe(res, resback, &resolvers->resolutions.wait, list) {
+ if (LIST_ISEMPTY(&res->requesters)) {
+ dns_free_resolution(res);
+ continue;
+ }
+
exp = tick_add(res->last_resolution, dns_resolution_timeout(res));
if (tick_isset(res->last_resolution) && !tick_is_expired(exp, now_ms))
continue;
s->dns_ctx.hostname_dn = NULL;
s->dns_ctx.hostname_dn_len = 0;
if (s->dns_ctx.dns_requester) {
- dns_unlink_resolution(s->dns_ctx.dns_requester);
+ dns_unlink_resolution(s->dns_ctx.dns_requester, 0);
pool_free(dns_requester_pool, s->dns_ctx.dns_requester);
s->dns_ctx.dns_requester = NULL;
}
for (s = srvrq->proxy->srv; s != NULL; s = s->next) {
HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
if (s->srvrq == srvrq) {
- dns_unlink_resolution(s->dns_requester);
+ dns_unlink_resolution(s->dns_requester, 1);
srvrq_update_srv_status(s, 1);
free(s->hostname);
free(s->hostname_dn);
strcasecmp(resolution->hostname_dn, hostname_dn) == 0)
goto end;
- dns_unlink_resolution(srv->dns_requester);
+ dns_unlink_resolution(srv->dns_requester, 0);
free(srv->hostname);
free(srv->hostname_dn);
HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
free(s->dns_ctx.hostname_dn); s->dns_ctx.hostname_dn = NULL;
s->dns_ctx.hostname_dn_len = 0;
- dns_unlink_resolution(s->dns_ctx.dns_requester);
+ dns_unlink_resolution(s->dns_ctx.dns_requester, 0);
HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
pool_free(dns_requester_pool, s->dns_ctx.dns_requester);