]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
detect dup EDE with bitmap and store next pos
authorColin Vidal <colin@isc.org>
Wed, 29 Jan 2025 22:27:34 +0000 (23:27 +0100)
committerColin Vidal <colin@isc.org>
Thu, 30 Jan 2025 10:52:53 +0000 (11:52 +0100)
In order to avoid to loop to find the next position to store an EDE in
a dns_edectx_t, add a "nextede" state which holds the next available
position.

Also, in order ot avoid to loop to find if an EDE is already existing in
a dns_edectx_t, and avoid a duplicate, use a bitmap to immediately know
if the EDE is there or not.

Those both changes applies for adding or copying EDE.

Also make the direction of dns_ede_copy more explicit/avoid errors by
making "edectx_from" a const pointer.

lib/dns/ede.c
lib/dns/include/dns/ede.h

index 7dcb05f281c4453f60ef48edf33a3bbdc022d271..7fbbd8390501ab45607b3fc0627360441f1d4d37 100644 (file)
 #define DNS_EDE_MAGIC   ISC_MAGIC('E', 'D', 'E', '!')
 #define DNS_EDE_VALID(v) ISC_MAGIC_VALID(v, DNS_EDE_MAGIC)
 
+static bool
+dns__ede_checkandupdateedeused(dns_edectx_t *edectx, uint16_t code) {
+       if (edectx->edeused & (1 << code)) {
+               return true;
+       }
+
+       edectx->edeused |= 1 << code;
+       return false;
+}
+
 void
 dns_ede_add(dns_edectx_t *edectx, uint16_t code, const char *text) {
        REQUIRE(DNS_EDE_VALID(edectx));
        REQUIRE(code <= DNS_EDE_MAX_CODE);
 
-       size_t pos = 0;
        uint16_t becode = htobe16(code);
        dns_ednsopt_t *edns = NULL;
        size_t textlen = 0;
 
-       for (pos = 0; pos < DNS_EDE_MAX_ERRORS; pos++) {
-               edns = edectx->ede[pos];
-
-               if (edns == NULL) {
-                       break;
-               }
-
-               if (memcmp(&becode, edns->value, sizeof(becode)) == 0) {
-                       isc_log_write(DNS_LOGCATEGORY_RESOLVER,
-                                     DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(1),
-                                     "ignoring duplicate ede %u %s", code,
-                                     text == NULL ? "(null)" : text);
-                       return;
-               }
+       if (dns__ede_checkandupdateedeused(edectx, code)) {
+               isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
+                             ISC_LOG_DEBUG(1), "ignoring duplicate ede %u %s",
+                             code, text == NULL ? "(null)" : text);
+               return;
        }
 
-       if (pos >= DNS_EDE_MAX_ERRORS) {
+       if (edectx->nextede >= DNS_EDE_MAX_ERRORS) {
                isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
                              ISC_LOG_DEBUG(1), "too many ede, ignoring %u %s",
                              code, text == NULL ? "(null)" : text);
                return;
        }
+       INSIST(edectx->ede[edectx->nextede] == NULL);
 
        isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
                      ISC_LOG_DEBUG(1), "set ede: info-code %u extra-text %s",
@@ -83,7 +84,8 @@ dns_ede_add(dns_edectx_t *edectx, uint16_t code, const char *text) {
                memmove(edns->value + sizeof(becode), text, textlen);
        }
 
-       edectx->ede[pos] = edns;
+       edectx->ede[edectx->nextede] = edns;
+       edectx->nextede++;
 }
 
 void
@@ -113,6 +115,8 @@ dns_ede_reset(dns_edectx_t *edectx) {
                isc_mem_put(edectx->mctx, edns, sizeof(*edns) + edns->length);
                edectx->ede[i] = NULL;
        }
+
+       dns_ede_init(edectx->mctx, edectx);
 }
 
 void
@@ -126,31 +130,30 @@ dns_ede_invalidate(dns_edectx_t *edectx) {
 }
 
 void
-dns_ede_copy(dns_edectx_t *edectx_to, dns_edectx_t *edectx_from) {
+dns_ede_copy(dns_edectx_t *edectx_to, const dns_edectx_t *edectx_from) {
        REQUIRE(DNS_EDE_VALID(edectx_to));
        REQUIRE(DNS_EDE_VALID(edectx_from));
 
-       size_t nextede = 0;
+       for (size_t pos = 0; pos < DNS_EDE_MAX_ERRORS; pos++) {
+               uint16_t fromcode;
 
-       for (nextede = 0; nextede < DNS_EDE_MAX_ERRORS; nextede++) {
-               if (edectx_to->ede[nextede] == NULL) {
+               if (edectx_from->ede[pos] == NULL) {
                        break;
                }
-       }
 
-       for (size_t pos = 0; pos < DNS_EDE_MAX_ERRORS; pos++) {
-               if (edectx_from->ede[pos] == NULL) {
-                       break;
+               fromcode = ISC_U8TO16_BE(edectx_from->ede[pos]->value);
+               if (dns__ede_checkandupdateedeused(edectx_to, fromcode)) {
+                       continue;
                }
 
-               if (nextede >= DNS_EDE_MAX_ERRORS) {
+               if (edectx_to->nextede >= DNS_EDE_MAX_ERRORS) {
                        isc_log_write(DNS_LOGCATEGORY_RESOLVER,
                                      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(1),
                                      "too many ede from subfetch");
                        break;
                }
 
-               INSIST(edectx_to->ede[nextede] == NULL);
+               INSIST(edectx_to->ede[edectx_to->nextede] == NULL);
 
                dns_ednsopt_t *edns = isc_mem_get(
                        edectx_to->mctx,
@@ -163,7 +166,7 @@ dns_ede_copy(dns_edectx_t *edectx_to, dns_edectx_t *edectx_from) {
                memmove(edns->value, edectx_from->ede[pos]->value,
                        edectx_from->ede[pos]->length);
 
-               edectx_to->ede[nextede] = edns;
-               nextede++;
+               edectx_to->ede[edectx_to->nextede] = edns;
+               edectx_to->nextede++;
        }
 }
index 8f6cf3bf9a4962786175e29a2f2f3a609dbfa860..37194dd5ef08fdb58c40d00734f4b19ef687515b 100644 (file)
@@ -63,6 +63,8 @@ struct dns_edectx {
        int            magic;
        isc_mem_t     *mctx;
        dns_ednsopt_t *ede[DNS_EDE_MAX_ERRORS];
+       uint32_t       edeused;
+       size_t         nextede;
 };
 /*%<
  * Multiple extended DNS errors (EDE) (defined in RFC 8914) can be raised during
@@ -132,7 +134,7 @@ dns_ede_add(dns_edectx_t *edectx, uint16_t code, const char *text);
  */
 
 void
-dns_ede_copy(dns_edectx_t *edectx_to, dns_edectx_t *edectx_from);
+dns_ede_copy(dns_edectx_t *edectx_to, const dns_edectx_t *edectx_from);
 /*%<
  * Copy all EDE from "edectx_from" into "edectx_to". If "edectx_to" reaches the
  * maximum number of EDE (see DNS_EDE_MAX_ERRORS), the copy stops and