2 Unix SMB/CIFS implementation.
6 Copyright (C) Amitay Isaacs 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "dnsserver.h"
24 #include "lib/replace/system/network.h"
25 #include "librpc/gen_ndr/ndr_dnsp.h"
26 #include "librpc/gen_ndr/ndr_dnsserver.h"
29 struct IP4_ARRAY
*ip4_array_copy(TALLOC_CTX
*mem_ctx
, struct IP4_ARRAY
*ip4
)
31 struct IP4_ARRAY
*ret
;
37 ret
= talloc_zero(mem_ctx
, struct IP4_ARRAY
);
42 ret
->AddrCount
= ip4
->AddrCount
;
43 if (ip4
->AddrCount
> 0) {
44 ret
->AddrArray
= talloc_zero_array(mem_ctx
, unsigned int, ip4
->AddrCount
);
46 memcpy(ret
->AddrArray
, ip4
->AddrArray
,
47 sizeof(unsigned int) * ip4
->AddrCount
);
57 struct DNS_ADDR_ARRAY
*ip4_array_to_dns_addr_array(TALLOC_CTX
*mem_ctx
,
58 struct IP4_ARRAY
*ip4
)
60 struct DNS_ADDR_ARRAY
*ret
;
67 ret
= talloc_zero(mem_ctx
, struct DNS_ADDR_ARRAY
);
72 ret
->MaxCount
= ip4
->AddrCount
;
73 ret
->AddrCount
= ip4
->AddrCount
;
74 ret
->Family
= AF_INET
;
75 if (ip4
->AddrCount
> 0) {
76 ret
->AddrArray
= talloc_zero_array(mem_ctx
, struct DNS_ADDR
, ip4
->AddrCount
);
78 for (i
=0; i
<ip4
->AddrCount
; i
++) {
79 ret
->AddrArray
[i
].MaxSa
[0] = 0x02;
80 ret
->AddrArray
[i
].MaxSa
[3] = 53;
81 memcpy(&ret
->AddrArray
[i
].MaxSa
[4], ip4
->AddrArray
,
82 sizeof(unsigned int));
83 ret
->AddrArray
[i
].DnsAddrUserDword
[0] = 6;
95 struct DNS_ADDR_ARRAY
*dns_addr_array_copy(TALLOC_CTX
*mem_ctx
,
96 struct DNS_ADDR_ARRAY
*addr
)
98 struct DNS_ADDR_ARRAY
*ret
;
104 ret
= talloc_zero(mem_ctx
, struct DNS_ADDR_ARRAY
);
109 ret
->MaxCount
= addr
->MaxCount
;
110 ret
->AddrCount
= addr
->AddrCount
;
111 ret
->Family
= addr
->Family
;
112 if (addr
->AddrCount
> 0) {
113 ret
->AddrArray
= talloc_zero_array(mem_ctx
, struct DNS_ADDR
, addr
->AddrCount
);
114 if (ret
->AddrArray
) {
115 memcpy(ret
->AddrArray
, addr
->AddrArray
,
116 sizeof(struct DNS_ADDR
) * addr
->AddrCount
);
126 int dns_split_name_components(TALLOC_CTX
*tmp_ctx
, const char *name
, char ***components
)
128 char *str
= NULL
, *ptr
, **list
;
131 str
= talloc_strdup(tmp_ctx
, name
);
136 list
= talloc_zero_array(tmp_ctx
, char *, 0);
141 ptr
= strtok(str
, ".");
142 while (ptr
!= NULL
) {
144 list
= talloc_realloc(tmp_ctx
, list
, char *, count
);
148 list
[count
-1] = talloc_strdup(tmp_ctx
, ptr
);
149 if (list
[count
-1] == NULL
) {
152 ptr
= strtok(NULL
, ".");
168 char *dns_split_node_name(TALLOC_CTX
*tmp_ctx
, const char *node_name
, const char *zone_name
)
170 char **nlist
, **zlist
;
172 int ncount
, zcount
, i
, match
;
175 * If node_name is "@", return the zone_name
176 * If node_name is ".", return NULL
177 * If there is no '.' in node_name, return the node_name as is.
179 * If node_name does not have zone_name in it, return the node_name as is.
181 * If node_name has additional components as compared to zone_name
182 * return only the additional components as a prefix.
185 if (strcmp(node_name
, "@") == 0) {
186 prefix
= talloc_strdup(tmp_ctx
, zone_name
);
187 } else if (strcmp(node_name
, ".") == 0) {
189 } else if (strchr(node_name
, '.') == NULL
) {
190 prefix
= talloc_strdup(tmp_ctx
, node_name
);
192 zcount
= dns_split_name_components(tmp_ctx
, zone_name
, &zlist
);
193 ncount
= dns_split_name_components(tmp_ctx
, node_name
, &nlist
);
194 if (zcount
< 0 || ncount
< 0) {
198 if (ncount
< zcount
) {
199 prefix
= talloc_strdup(tmp_ctx
, node_name
);
202 for (i
=1; i
<=zcount
; i
++) {
203 if (strcmp(nlist
[ncount
-i
], zlist
[zcount
-i
]) != 0) {
209 if (match
== ncount
) {
210 prefix
= talloc_strdup(tmp_ctx
, zone_name
);
212 prefix
= talloc_strdup(tmp_ctx
, nlist
[0]);
213 if (prefix
!= NULL
) {
214 for (i
=1; i
<ncount
-match
; i
++) {
215 prefix
= talloc_asprintf_append(prefix
, ".%s", nlist
[i
]);
216 if (prefix
== NULL
) {
232 void dnsp_to_dns_copy(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*dnsp
,
233 struct DNS_RPC_RECORD
*dns
)
239 dns
->wDataLength
= dnsp
->wDataLength
;
240 dns
->wType
= dnsp
->wType
;
241 dns
->dwFlags
= dnsp
->rank
;
242 dns
->dwSerial
= dnsp
->dwSerial
;
243 dns
->dwTtlSeconds
= dnsp
->dwTtlSeconds
;
244 dns
->dwTimeStamp
= dnsp
->dwTimeStamp
;
246 switch (dnsp
->wType
) {
248 case DNS_TYPE_TOMBSTONE
:
249 dns
->data
.timestamp
= dnsp
->data
.timestamp
;
253 dns
->data
.ipv4
= talloc_strdup(mem_ctx
, dnsp
->data
.ipv4
);
257 len
= strlen(dnsp
->data
.ns
);
258 if (dnsp
->data
.ns
[len
-1] == '.') {
259 dns
->data
.name
.len
= len
;
260 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.ns
);
262 dns
->data
.name
.len
= len
+1;
263 dns
->data
.name
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.ns
);
268 len
= strlen(dnsp
->data
.cname
);
269 if (dnsp
->data
.cname
[len
-1] == '.') {
270 dns
->data
.name
.len
= len
;
271 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.cname
);
273 dns
->data
.name
.len
= len
+1;
274 dns
->data
.name
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.cname
);
279 dns
->data
.soa
.dwSerialNo
= dnsp
->data
.soa
.serial
;
280 dns
->data
.soa
.dwRefresh
= dnsp
->data
.soa
.refresh
;
281 dns
->data
.soa
.dwRetry
= dnsp
->data
.soa
.retry
;
282 dns
->data
.soa
.dwExpire
= dnsp
->data
.soa
.expire
;
283 dns
->data
.soa
.dwMinimumTtl
= dnsp
->data
.soa
.minimum
;
285 len
= strlen(dnsp
->data
.soa
.mname
);
286 if (dnsp
->data
.soa
.mname
[len
-1] == '.') {
287 dns
->data
.soa
.NamePrimaryServer
.len
= len
;
288 dns
->data
.soa
.NamePrimaryServer
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.soa
.mname
);
290 dns
->data
.soa
.NamePrimaryServer
.len
= len
+1;
291 dns
->data
.soa
.NamePrimaryServer
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.soa
.mname
);
294 len
= strlen(dnsp
->data
.soa
.rname
);
295 if (dnsp
->data
.soa
.rname
[len
-1] == '.') {
296 dns
->data
.soa
.ZoneAdministratorEmail
.len
= len
;
297 dns
->data
.soa
.ZoneAdministratorEmail
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.soa
.rname
);
299 dns
->data
.soa
.ZoneAdministratorEmail
.len
= len
+1;
300 dns
->data
.soa
.ZoneAdministratorEmail
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.soa
.rname
);
305 dns
->data
.ptr
.len
= strlen(dnsp
->data
.ptr
);
306 dns
->data
.ptr
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.ptr
);
310 dns
->data
.mx
.wPreference
= dnsp
->data
.mx
.wPriority
;
311 len
= strlen(dnsp
->data
.mx
.nameTarget
);
312 if (dnsp
->data
.mx
.nameTarget
[len
-1] == '.') {
313 dns
->data
.mx
.nameExchange
.len
= len
;
314 dns
->data
.mx
.nameExchange
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.mx
.nameTarget
);
316 dns
->data
.mx
.nameExchange
.len
= len
+1;
317 dns
->data
.mx
.nameExchange
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.mx
.nameTarget
);
322 dns
->data
.name
.len
= strlen(dnsp
->data
.txt
);
323 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.txt
);
327 dns
->data
.ipv6
= talloc_strdup(mem_ctx
, dnsp
->data
.ipv6
);
331 dns
->data
.srv
.wPriority
= dnsp
->data
.srv
.wPriority
;
332 dns
->data
.srv
.wWeight
= dnsp
->data
.srv
.wWeight
;
333 dns
->data
.srv
.wPort
= dnsp
->data
.srv
.wPort
;
334 len
= strlen(dnsp
->data
.srv
.nameTarget
);
335 if (dnsp
->data
.srv
.nameTarget
[len
-1] == '.') {
336 dns
->data
.srv
.nameTarget
.len
= len
;
337 dns
->data
.srv
.nameTarget
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.srv
.nameTarget
);
339 dns
->data
.srv
.nameTarget
.len
= len
+1;
340 dns
->data
.srv
.nameTarget
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.srv
.nameTarget
);
345 memcpy(&dns
->data
, &dnsp
->data
, sizeof(union DNS_RPC_DATA
));
346 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dnsp
->wType
));
352 struct dnsp_DnssrvRpcRecord
*dns_to_dnsp_copy(TALLOC_CTX
*mem_ctx
, struct DNS_RPC_RECORD
*dns
)
355 struct dnsp_DnssrvRpcRecord
*dnsp
;
357 dnsp
= talloc_zero(mem_ctx
, struct dnsp_DnssrvRpcRecord
);
362 dnsp
->wDataLength
= dns
->wDataLength
;
363 dnsp
->wType
= dns
->wType
;
365 dnsp
->rank
= dns
->dwFlags
& 0x000000FF;
366 dnsp
->dwSerial
= dns
->dwSerial
;
367 dnsp
->dwTtlSeconds
= dns
->dwTtlSeconds
;
368 dnsp
->dwTimeStamp
= dns
->dwTimeStamp
;
370 switch (dns
->wType
) {
372 case DNS_TYPE_TOMBSTONE
:
373 dnsp
->data
.timestamp
= dns
->data
.timestamp
;
377 dnsp
->data
.ipv4
= talloc_strdup(mem_ctx
, dns
->data
.ipv4
);
381 len
= dns
->data
.name
.len
;
382 if (dns
->data
.name
.str
[len
-1] == '.') {
383 dnsp
->data
.ns
= talloc_strndup(mem_ctx
, dns
->data
.name
.str
, len
-1);
385 dnsp
->data
.ns
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
390 len
= dns
->data
.name
.len
;
391 if (dns
->data
.name
.str
[len
-1] == '.') {
392 dnsp
->data
.cname
= talloc_strndup(mem_ctx
, dns
->data
.name
.str
, len
-1);
394 dnsp
->data
.cname
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
399 dnsp
->data
.soa
.serial
= dns
->data
.soa
.dwSerialNo
;
400 dnsp
->data
.soa
.refresh
= dns
->data
.soa
.dwRefresh
;
401 dnsp
->data
.soa
.retry
= dns
->data
.soa
.dwRetry
;
402 dnsp
->data
.soa
.expire
= dns
->data
.soa
.dwExpire
;
403 dnsp
->data
.soa
.minimum
= dns
->data
.soa
.dwMinimumTtl
;
405 len
= dns
->data
.soa
.NamePrimaryServer
.len
;
406 if (dns
->data
.soa
.NamePrimaryServer
.str
[len
-1] == '.') {
407 dnsp
->data
.soa
.mname
= talloc_strdup(mem_ctx
, dns
->data
.soa
.NamePrimaryServer
.str
);
409 dnsp
->data
.soa
.mname
= talloc_strndup(mem_ctx
, dns
->data
.soa
.NamePrimaryServer
.str
, len
-1);
412 len
= dns
->data
.soa
.ZoneAdministratorEmail
.len
;
413 if (dns
->data
.soa
.ZoneAdministratorEmail
.str
[len
-1] == '.') {
414 dnsp
->data
.soa
.rname
= talloc_strndup(mem_ctx
, dns
->data
.soa
.ZoneAdministratorEmail
.str
, len
-1);
416 dnsp
->data
.soa
.rname
= talloc_strdup(mem_ctx
, dns
->data
.soa
.ZoneAdministratorEmail
.str
);
421 dnsp
->data
.ptr
= talloc_strdup(mem_ctx
, dns
->data
.ptr
.str
);
425 dnsp
->data
.mx
.wPriority
= dns
->data
.mx
.wPreference
;
426 len
= dns
->data
.mx
.nameExchange
.len
;
427 if (dns
->data
.mx
.nameExchange
.str
[len
-1] == '.') {
428 dnsp
->data
.mx
.nameTarget
= talloc_strndup(mem_ctx
, dns
->data
.mx
.nameExchange
.str
, len
-1);
430 dnsp
->data
.mx
.nameTarget
= talloc_strdup(mem_ctx
, dns
->data
.mx
.nameExchange
.str
);
435 dnsp
->data
.txt
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
439 dnsp
->data
.ipv6
= talloc_strdup(mem_ctx
, dns
->data
.ipv6
);
443 dnsp
->data
.srv
.wPriority
= dns
->data
.srv
.wPriority
;
444 dnsp
->data
.srv
.wWeight
= dns
->data
.srv
.wWeight
;
445 dnsp
->data
.srv
.wPort
= dns
->data
.srv
.wPort
;
447 len
= dns
->data
.srv
.nameTarget
.len
;
448 if (dns
->data
.srv
.nameTarget
.str
[len
-1] == '.') {
449 dnsp
->data
.srv
.nameTarget
= talloc_strndup(mem_ctx
, dns
->data
.srv
.nameTarget
.str
, len
-1);
451 dnsp
->data
.srv
.nameTarget
= talloc_strdup(mem_ctx
, dns
->data
.srv
.nameTarget
.str
);
456 memcpy(&dnsp
->data
, &dns
->data
, sizeof(union dnsRecordData
));
457 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dns
->wType
));
465 static void _dns_add_name(TALLOC_CTX
*mem_ctx
, const char *name
, char ***add_names
, int *add_count
)
468 char **ptr
= *add_names
;
469 int count
= *add_count
;
471 for (i
=0; i
<count
; i
++) {
472 if (strcmp(ptr
[i
], name
) == 0) {
477 ptr
= talloc_realloc(mem_ctx
, ptr
, char *, count
+1);
482 ptr
[count
] = talloc_strdup(mem_ctx
, name
);
483 if (ptr
[count
] == NULL
) {
488 *add_count
= count
+1;
492 static void dns_find_additional_names(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*rec
, char ***add_names
, int *add_count
)
494 if (add_names
== NULL
) {
498 switch (rec
->wType
) {
501 _dns_add_name(mem_ctx
, rec
->data
.ns
, add_names
, add_count
);
505 _dns_add_name(mem_ctx
, rec
->data
.cname
, add_names
, add_count
);
509 _dns_add_name(mem_ctx
, rec
->data
.soa
.mname
, add_names
, add_count
);
513 _dns_add_name(mem_ctx
, rec
->data
.mx
.nameTarget
, add_names
, add_count
);
517 _dns_add_name(mem_ctx
, rec
->data
.srv
.nameTarget
, add_names
, add_count
);
526 WERROR
dns_fill_records_array(TALLOC_CTX
*mem_ctx
,
527 struct dnsserver_zone
*z
,
528 enum dns_record_type record_type
,
529 unsigned int select_flag
,
530 const char *branch_name
,
531 struct ldb_message
*msg
,
532 struct DNS_RPC_RECORDS_ARRAY
*recs
,
536 const char *nodename
;
537 struct ldb_message_element
*el
;
539 bool found
, node_is_rootzone
;
541 /* Check if we already have created record for the branch */
543 if (branch_name
== NULL
) {
545 if (recs
->count
> 0) {
549 for (i
=0; i
<recs
->count
; i
++) {
550 if (strcmp(branch_name
, recs
->rec
[i
].dnsNodeName
.str
) == 0) {
557 /* If not, add empty record */
559 if (recs
->count
== 0) {
560 recs
->rec
= talloc_zero(recs
, struct DNS_RPC_RECORDS
);
562 recs
->rec
= talloc_realloc(recs
, recs
->rec
, struct DNS_RPC_RECORDS
, recs
->count
+1);
564 if (recs
->rec
== NULL
) {
568 recs
->rec
[i
].wLength
= 0;
569 recs
->rec
[i
].wRecordCount
= 0;
570 recs
->rec
[i
].dwChildCount
= 0;
572 /* The base records returned with empty name */
573 /* Children records returned with names */
574 if (branch_name
== NULL
) {
575 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, "");
576 recs
->rec
[i
].dnsNodeName
.len
= 0;
578 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, branch_name
);
579 recs
->rec
[i
].dnsNodeName
.len
= strlen(branch_name
);
581 recs
->rec
[i
].records
= talloc_zero_array(recs
, struct DNS_RPC_RECORD
, 0);
585 /* Allow empty records */
590 nodename
= ldb_msg_find_attr_as_string(msg
, "name", NULL
);
592 if (strcmp(nodename
, "@") == 0) {
593 node_is_rootzone
= true;
595 node_is_rootzone
= false;
598 if (branch_name
!= NULL
) {
599 if (branch_name
[strlen(branch_name
)-1] != '.'
600 && strcmp(nodename
, branch_name
) != 0) {
601 recs
->rec
[i
].dwChildCount
++;
607 el
= ldb_msg_find_element(msg
, "dnsRecord");
608 if (el
== NULL
|| el
->values
== 0) {
609 DEBUG(0, ("dnsserver: Missing dnsRecord for %s\n", ldb_dn_get_linearized(msg
->dn
)));
613 /* branch level record */
614 for (j
=0; j
<el
->num_values
; j
++) {
615 struct dnsp_DnssrvRpcRecord dnsp_rec
;
616 struct DNS_RPC_RECORD
*dns_rec
;
617 enum ndr_err_code ndr_err
;
619 ndr_err
= ndr_pull_struct_blob(&el
->values
[j
], mem_ctx
, &dnsp_rec
,
620 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
);
621 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
622 DEBUG(0, ("dnsserver: Unable to parse dns record (%s)", ldb_dn_get_linearized(msg
->dn
)));
623 return WERR_INTERNAL_DB_ERROR
;
626 /* Match the records based on search criteria */
627 if (record_type
== DNS_TYPE_ALL
|| dnsp_rec
.wType
== record_type
) {
630 if (select_flag
& DNS_RPC_VIEW_AUTHORITY_DATA
) {
631 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
635 if (select_flag
& DNS_RPC_VIEW_CACHE_DATA
) {
636 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
640 if (select_flag
& DNS_RPC_VIEW_GLUE_DATA
) {
641 if (dnsp_rec
.rank
== DNS_RANK_NS_GLUE
) {
645 if (select_flag
& DNS_RPC_VIEW_ROOT_HINT_DATA
) {
646 if (dnsp_rec
.rank
== DNS_RANK_ROOT_HINT
) {
652 recs
->rec
[i
].records
= talloc_realloc(recs
,
653 recs
->rec
[i
].records
,
654 struct DNS_RPC_RECORD
,
655 recs
->rec
[i
].wRecordCount
+1);
656 if (recs
->rec
[i
].records
== NULL
) {
660 dns_rec
= &recs
->rec
[i
].records
[recs
->rec
[i
].wRecordCount
];
661 dnsp_to_dns_copy(recs
, &dnsp_rec
, dns_rec
);
663 /* Fix record flags */
664 if (node_is_rootzone
) {
665 dns_rec
->dwFlags
|= (DNS_RPC_FLAG_ZONE_ROOT
| DNS_RPC_FLAG_AUTH_ZONE_ROOT
);
668 if (dns_rec
->dwFlags
== DNS_RANK_NS_GLUE
) {
669 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
672 recs
->rec
[i
].wRecordCount
++;
674 dns_find_additional_names(mem_ctx
, &dnsp_rec
, add_names
, add_count
);
683 int dns_name_compare(const struct ldb_message
**m1
, const struct ldb_message
**m2
,
686 const char *name1
, *name2
;
687 const char *ptr1
, *ptr2
;
689 name1
= ldb_msg_find_attr_as_string(*m1
, "name", NULL
);
690 name2
= ldb_msg_find_attr_as_string(*m2
, "name", NULL
);
691 if (name1
== NULL
|| name2
== NULL
) {
695 /* '@' record and the search_name record gets preference */
696 if (name1
[0] == '@') {
699 if (search_name
&& strcmp(name1
, search_name
) == 0) {
703 if (name2
[0] == '@') {
706 if (search_name
&& strcmp(name2
, search_name
) == 0) {
710 ptr1
= strrchr(name1
, '.');
717 ptr2
= strrchr(name2
, '.');
724 return strcasecmp(ptr1
, ptr2
);
728 bool dns_name_equal(const char *name1
, const char *name2
)
730 size_t len1
= strlen(name1
);
731 size_t len2
= strlen(name2
);
733 if (name1
[len1
-1] == '.') len1
--;
734 if (name2
[len2
-1] == '.') len2
--;
738 return strncasecmp(name1
, name2
, len1
) == 0;
742 bool dns_record_match(struct dnsp_DnssrvRpcRecord
*rec1
, struct dnsp_DnssrvRpcRecord
*rec2
)
744 if (rec1
->wType
!= rec2
->wType
) {
748 switch(rec1
->wType
) {
749 case DNS_TYPE_TOMBSTONE
:
753 return strcmp(rec1
->data
.ipv4
, rec2
->data
.ipv4
) == 0;
756 return dns_name_equal(rec1
->data
.ns
, rec1
->data
.ns
);
759 return dns_name_equal(rec1
->data
.cname
, rec1
->data
.cname
);
762 return dns_name_equal(rec1
->data
.soa
.mname
, rec2
->data
.soa
.mname
) == 0 &&
763 dns_name_equal(rec1
->data
.soa
.rname
, rec2
->data
.soa
.rname
) == 0 &&
764 rec1
->data
.soa
.serial
== rec2
->data
.soa
.serial
&&
765 rec1
->data
.soa
.refresh
== rec2
->data
.soa
.refresh
&&
766 rec1
->data
.soa
.retry
== rec2
->data
.soa
.retry
&&
767 rec1
->data
.soa
.expire
== rec2
->data
.soa
.expire
&&
768 rec1
->data
.soa
.minimum
== rec2
->data
.soa
.minimum
;
771 return strcmp(rec1
->data
.ptr
, rec2
->data
.ptr
) == 0;
774 return rec1
->data
.mx
.wPriority
== rec2
->data
.srv
.wPriority
&&
775 dns_name_equal(rec1
->data
.mx
.nameTarget
, rec2
->data
.srv
.nameTarget
);
778 return strcmp(rec1
->data
.txt
, rec2
->data
.txt
) == 0;
781 return strcmp(rec1
->data
.ipv6
, rec2
->data
.ipv6
) == 0;
784 return rec1
->data
.srv
.wPriority
== rec2
->data
.srv
.wPriority
&&
785 rec1
->data
.srv
.wWeight
== rec2
->data
.srv
.wWeight
&&
786 rec1
->data
.srv
.wPort
== rec2
->data
.srv
.wPort
&&
787 dns_name_equal(rec1
->data
.srv
.nameTarget
, rec2
->data
.srv
.nameTarget
);
790 DEBUG(0, ("dnsserver: unhandled record type %u", rec1
->wType
));