From 77f860699c17426ee6e727fa07a287b32276f1dd Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Wed, 10 Mar 2021 15:19:57 +0100 Subject: [PATCH] BUG/MEDIUM: resolvers: Fix the loop looking for an existing ADD item For each ADD item found in a SRV response, we try to find a corresponding ADD item already attached to an existing SRV item. If found, the ADD last_seen time is updated, otherwise we try to find a SRV item with no ADD to attached the new one. However, the loop is buggy. Instead of comparing 2 ADD items, it compares the new ADD item with the SRV item. Because of this bug, we are unable to renew last_seen time of existing ADD. This patch must be backported as far as 2.2. --- src/resolvers.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/resolvers.c b/src/resolvers.c index 859189d..4d960b7 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -1187,27 +1187,33 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe /* Move forward answer_record->data_len for analyzing next * record in the response */ - reader += ((answer_record->type == DNS_RTYPE_SRV) - ? offset - : answer_record->data_len); + reader += answer_record->data_len; /* Lookup to see if we already had this entry */ found = 0; list_for_each_entry(tmp_record, &r_res->answer_list, list) { - if (tmp_record->type != answer_record->type) + struct resolv_answer_item *ar_item; + + if (tmp_record->type != DNS_RTYPE_SRV || !tmp_record->ar_item) continue; - switch(tmp_record->type) { + ar_item = tmp_record->ar_item; + if (ar_item->type != answer_record->type || + len != tmp_record->data_len || + resolv_hostname_cmp(answer_record->name, tmp_record->target, tmp_record->data_len)) + continue; + + switch(ar_item->type) { case DNS_RTYPE_A: if (!memcmp(&((struct sockaddr_in *)&answer_record->address)->sin_addr, - &((struct sockaddr_in *)&tmp_record->address)->sin_addr, + &((struct sockaddr_in *)&ar_item->address)->sin_addr, sizeof(in_addr_t))) found = 1; break; case DNS_RTYPE_AAAA: if (!memcmp(&((struct sockaddr_in6 *)&answer_record->address)->sin6_addr, - &((struct sockaddr_in6 *)&tmp_record->address)->sin6_addr, + &((struct sockaddr_in6 *)&ar_item->address)->sin6_addr, sizeof(struct in6_addr))) found = 1; break; @@ -1221,7 +1227,7 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe } if (found == 1) { - tmp_record->last_seen = now.tv_sec; + tmp_record->ar_item->last_seen = now.tv_sec; pool_free(resolv_answer_item_pool, answer_record); answer_record = NULL; } -- 1.7.10.4