]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
dns: merge dlz/internal dns_records_match()
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Mon, 12 Apr 2021 19:00:41 +0000 (07:00 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 11 Jun 2021 08:38:34 +0000 (08:38 +0000)
We have had three nearly identical functions called
dns_record[s]_match. This patch merges two of them, attempting to keep
the good bits and not the bugs.

That means:

1. We use the AAAA match from dlz, which is agnostic to all the
billions of ways you can write the same IPv6 address (case sensitivity
is just the beginning).

2. We lean more on the TXT match from dns_utils, because the dlz used
a weird bitwise &= operator, but we adjust to exit early.

3. Keep HINFO from dlz (for now).

4. Use the dns_name_equal() that was already in dns_common, which was
used by dlz. dns_utils had a strange one that probably did the same
thing.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/dns_server/dlz_bind9.c
source4/dns_server/dns_server.h
source4/dns_server/dns_utils.c
source4/dns_server/dnsserver_common.c
source4/dns_server/dnsserver_common.h

index eba4bebb8f5626c5dbc20372c235a1011bcfed48..904badc1de5cd412c0630a9e6db020b36f33ad63 100644 (file)
@@ -1760,11 +1760,6 @@ exit:
 static bool b9_record_match(struct dnsp_DnssrvRpcRecord *rec1,
                            struct dnsp_DnssrvRpcRecord *rec2)
 {
-       bool status;
-       int i;
-       struct in6_addr rec1_in_addr6;
-       struct in6_addr rec2_in_addr6;
-
        if (rec1->wType != rec2->wType) {
                return false;
        }
@@ -1773,65 +1768,7 @@ static bool b9_record_match(struct dnsp_DnssrvRpcRecord *rec1,
                return true;
        }
 
-       /* see if the data matches */
-       switch (rec1->wType) {
-       case DNS_TYPE_A:
-               return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0;
-       case DNS_TYPE_AAAA: {
-               int ret;
-
-               ret = inet_pton(AF_INET6, rec1->data.ipv6, &rec1_in_addr6);
-               if (ret != 1) {
-                       return false;
-               }
-               ret = inet_pton(AF_INET6, rec2->data.ipv6, &rec2_in_addr6);
-               if (ret != 1) {
-                       return false;
-               }
-
-               return memcmp(&rec1_in_addr6, &rec2_in_addr6, sizeof(rec1_in_addr6)) == 0;
-       }
-       case DNS_TYPE_CNAME:
-               return dns_name_equal(rec1->data.cname, rec2->data.cname);
-       case DNS_TYPE_TXT:
-               status = (rec1->data.txt.count == rec2->data.txt.count);
-               if (!status) return status;
-               for (i=0; i<rec1->data.txt.count; i++) {
-                       status &= (strcmp(rec1->data.txt.str[i], rec2->data.txt.str[i]) == 0);
-               }
-               return status;
-       case DNS_TYPE_PTR:
-               return dns_name_equal(rec1->data.ptr, rec2->data.ptr);
-       case DNS_TYPE_NS:
-               return dns_name_equal(rec1->data.ns, rec2->data.ns);
-
-       case DNS_TYPE_SRV:
-               return rec1->data.srv.wPriority == rec2->data.srv.wPriority &&
-                       rec1->data.srv.wWeight  == rec2->data.srv.wWeight &&
-                       rec1->data.srv.wPort    == rec2->data.srv.wPort &&
-                       dns_name_equal(rec1->data.srv.nameTarget, rec2->data.srv.nameTarget);
-
-       case DNS_TYPE_MX:
-               return rec1->data.mx.wPriority == rec2->data.mx.wPriority &&
-                       dns_name_equal(rec1->data.mx.nameTarget, rec2->data.mx.nameTarget);
-
-       case DNS_TYPE_HINFO:
-               return strcmp(rec1->data.hinfo.cpu, rec2->data.hinfo.cpu) == 0 &&
-                       strcmp(rec1->data.hinfo.os, rec2->data.hinfo.os) == 0;
-
-       case DNS_TYPE_SOA:
-               return dns_name_equal(rec1->data.soa.mname, rec2->data.soa.mname) &&
-                       dns_name_equal(rec1->data.soa.rname, rec2->data.soa.rname) &&
-                       rec1->data.soa.serial == rec2->data.soa.serial &&
-                       rec1->data.soa.refresh == rec2->data.soa.refresh &&
-                       rec1->data.soa.retry == rec2->data.soa.retry &&
-                       rec1->data.soa.expire == rec2->data.soa.expire &&
-                       rec1->data.soa.minimum == rec2->data.soa.minimum;
-       default:
-               break;
-       }
-
-       return false;
+       return dns_records_match(rec1, rec2);
 }
 
 /*
index 48dd5ff81859b57fa621a4d277367b65ae520760..f4e5a61c43f78e519d60507e514c1f96eb6e50df 100644 (file)
@@ -82,8 +82,6 @@ WERROR dns_server_process_update(struct dns_server *dns,
                                 struct dns_res_rec **updates,    uint16_t *update_count,
                                 struct dns_res_rec **additional, uint16_t *arcount);
 
-bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1,
-                      struct dnsp_DnssrvRpcRecord *rec2);
 bool dns_authoritative_for_zone(struct dns_server *dns,
                                const char *name);
 const char *dns_get_authoritative_zone(struct dns_server *dns,
index 081ee33caee6cb58c669686c3a62104ba435f2c5..d0661f35f6f69c0f7961bc94f67873996d868a01 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_DNS
 
-/* Names are equal if they match and there's nothing left over */
-bool dns_name_equal(const char *name1, const char *name2)
-{
-       size_t host_part_len;
-       bool ret = dns_name_match(name1, name2, &host_part_len);
-
-       return ret && (host_part_len == 0);
-}
-
-/*
-  see if two dns records match
- */
-bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1,
-                      struct dnsp_DnssrvRpcRecord *rec2)
-{
-       bool status;
-       int i;
-
-       if (rec1->wType != rec2->wType) {
-               return false;
-       }
-
-       /* see if the data matches */
-       switch (rec1->wType) {
-       case DNS_TYPE_A:
-               return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0;
-       case DNS_TYPE_AAAA:
-               return strcmp(rec1->data.ipv6, rec2->data.ipv6) == 0;
-       case DNS_TYPE_CNAME:
-               return dns_name_equal(rec1->data.cname, rec2->data.cname);
-       case DNS_TYPE_TXT:
-               if (rec1->data.txt.count != rec2->data.txt.count) {
-                       return false;
-               }
-               status = true;
-               for (i=0; i<rec1->data.txt.count; i++) {
-                       status = status && (strcmp(rec1->data.txt.str[i],
-                                               rec2->data.txt.str[i]) == 0);
-               }
-               return status;
-       case DNS_TYPE_PTR:
-               return strcmp(rec1->data.ptr, rec2->data.ptr) == 0;
-       case DNS_TYPE_NS:
-               return dns_name_equal(rec1->data.ns, rec2->data.ns);
-
-       case DNS_TYPE_SRV:
-               return rec1->data.srv.wPriority == rec2->data.srv.wPriority &&
-                       rec1->data.srv.wWeight  == rec2->data.srv.wWeight &&
-                       rec1->data.srv.wPort    == rec2->data.srv.wPort &&
-                       dns_name_equal(rec1->data.srv.nameTarget, rec2->data.srv.nameTarget);
-
-       case DNS_TYPE_MX:
-               return rec1->data.mx.wPriority == rec2->data.mx.wPriority &&
-                       dns_name_equal(rec1->data.mx.nameTarget, rec2->data.mx.nameTarget);
-
-       case DNS_TYPE_HINFO:
-               return strcmp(rec1->data.hinfo.cpu, rec2->data.hinfo.cpu) == 0 &&
-                       strcmp(rec1->data.hinfo.os, rec2->data.hinfo.os) == 0;
-
-       case DNS_TYPE_SOA:
-               return dns_name_equal(rec1->data.soa.mname, rec2->data.soa.mname) &&
-                       dns_name_equal(rec1->data.soa.rname, rec2->data.soa.rname) &&
-                       rec1->data.soa.serial == rec2->data.soa.serial &&
-                       rec1->data.soa.refresh == rec2->data.soa.refresh &&
-                       rec1->data.soa.retry == rec2->data.soa.retry &&
-                       rec1->data.soa.expire == rec2->data.soa.expire &&
-                       rec1->data.soa.minimum == rec2->data.soa.minimum;
-       default:
-               break;
-       }
-
-       return false;
-}
 
 /*
  * Lookup a DNS record, performing an exact match.
index 7bd6e4f64bde9c2bd4536ac99754a131e18557d5..bf0ce7d3e892f5e8bea5e922a85eacbeb00235c0 100644 (file)
@@ -33,6 +33,7 @@
 #include "dns_server/dnsserver_common.h"
 #include "rpc_server/dnsserver/dnsserver.h"
 #include "lib/util/dlinklist.h"
+#include "system/network.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_DNS
@@ -1266,6 +1267,88 @@ WERROR dns_common_name2dn(struct ldb_context *samdb,
        return WERR_OK;
 }
 
+
+/*
+  see if two dns records match
+ */
+
+
+bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1,
+                      struct dnsp_DnssrvRpcRecord *rec2)
+{
+       int i;
+       struct in6_addr rec1_in_addr6;
+       struct in6_addr rec2_in_addr6;
+
+       if (rec1->wType != rec2->wType) {
+               return false;
+       }
+
+       /* see if the data matches */
+       switch (rec1->wType) {
+       case DNS_TYPE_A:
+               return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0;
+       case DNS_TYPE_AAAA: {
+               int ret;
+
+               ret = inet_pton(AF_INET6, rec1->data.ipv6, &rec1_in_addr6);
+               if (ret != 1) {
+                       return false;
+               }
+               ret = inet_pton(AF_INET6, rec2->data.ipv6, &rec2_in_addr6);
+               if (ret != 1) {
+                       return false;
+               }
+
+               return memcmp(&rec1_in_addr6, &rec2_in_addr6, sizeof(rec1_in_addr6)) == 0;
+       }
+       case DNS_TYPE_CNAME:
+               return dns_name_equal(rec1->data.cname, rec2->data.cname);
+       case DNS_TYPE_TXT:
+               if (rec1->data.txt.count != rec2->data.txt.count) {
+                       return false;
+               }
+               for (i = 0; i < rec1->data.txt.count; i++) {
+                       if (strcmp(rec1->data.txt.str[i], rec2->data.txt.str[i]) != 0) {
+                               return false;
+                       }
+               }
+               return true;
+       case DNS_TYPE_PTR:
+               return dns_name_equal(rec1->data.ptr, rec2->data.ptr);
+       case DNS_TYPE_NS:
+               return dns_name_equal(rec1->data.ns, rec2->data.ns);
+
+       case DNS_TYPE_SRV:
+               return rec1->data.srv.wPriority == rec2->data.srv.wPriority &&
+                       rec1->data.srv.wWeight  == rec2->data.srv.wWeight &&
+                       rec1->data.srv.wPort    == rec2->data.srv.wPort &&
+                       dns_name_equal(rec1->data.srv.nameTarget, rec2->data.srv.nameTarget);
+
+       case DNS_TYPE_MX:
+               return rec1->data.mx.wPriority == rec2->data.mx.wPriority &&
+                       dns_name_equal(rec1->data.mx.nameTarget, rec2->data.mx.nameTarget);
+
+       case DNS_TYPE_HINFO:
+               return strcmp(rec1->data.hinfo.cpu, rec2->data.hinfo.cpu) == 0 &&
+                       strcmp(rec1->data.hinfo.os, rec2->data.hinfo.os) == 0;
+
+       case DNS_TYPE_SOA:
+               return dns_name_equal(rec1->data.soa.mname, rec2->data.soa.mname) &&
+                       dns_name_equal(rec1->data.soa.rname, rec2->data.soa.rname) &&
+                       rec1->data.soa.serial == rec2->data.soa.serial &&
+                       rec1->data.soa.refresh == rec2->data.soa.refresh &&
+                       rec1->data.soa.retry == rec2->data.soa.retry &&
+                       rec1->data.soa.expire == rec2->data.soa.expire &&
+                       rec1->data.soa.minimum == rec2->data.soa.minimum;
+       default:
+               break;
+       }
+
+       return false;
+}
+
+
 static int dns_common_sort_zones(struct ldb_message **m1, struct ldb_message **m2)
 {
        const char *n1, *n2;
index 98af0a9a274f51edbdf88571078aa36c4a9c8063..4f451725508522ab08be76298cd9d9f50fd20d56 100644 (file)
@@ -78,6 +78,9 @@ WERROR dns_common_name2dn(struct ldb_context *samdb,
                          struct ldb_dn **_dn);
 bool dns_name_equal(const char *name1, const char *name2);
 
+bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1,
+                      struct dnsp_DnssrvRpcRecord *rec2);
+
 /*
  * For this routine, base_dn is generally NULL.  The exception comes
  * from the python bindings to support setting ACLs on DNS objects