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
;
135 str
= talloc_strdup(tmp_ctx
, name
);
140 list
= talloc_zero_array(tmp_ctx
, char *, 0);
145 ptr
= strtok(str
, ".");
146 while (ptr
!= NULL
) {
148 list
= talloc_realloc(tmp_ctx
, list
, char *, count
);
152 list
[count
-1] = talloc_strdup(tmp_ctx
, ptr
);
153 if (list
[count
-1] == NULL
) {
156 ptr
= strtok(NULL
, ".");
172 char *dns_split_node_name(TALLOC_CTX
*tmp_ctx
, const char *node_name
, const char *zone_name
)
174 char **nlist
, **zlist
;
176 int ncount
, zcount
, i
, match
;
179 * If node_name is "@", return the zone_name
180 * If node_name is ".", return NULL
181 * If there is no '.' in node_name, return the node_name as is.
183 * If node_name does not have zone_name in it, return the node_name as is.
185 * If node_name has additional components as compared to zone_name
186 * return only the additional components as a prefix.
189 if (strcmp(node_name
, "@") == 0) {
190 prefix
= talloc_strdup(tmp_ctx
, zone_name
);
191 } else if (strcmp(node_name
, ".") == 0) {
193 } else if (strchr(node_name
, '.') == NULL
) {
194 prefix
= talloc_strdup(tmp_ctx
, node_name
);
196 zcount
= dns_split_name_components(tmp_ctx
, zone_name
, &zlist
);
197 ncount
= dns_split_name_components(tmp_ctx
, node_name
, &nlist
);
198 if (zcount
< 0 || ncount
< 0) {
202 if (ncount
< zcount
) {
203 prefix
= talloc_strdup(tmp_ctx
, node_name
);
206 for (i
=1; i
<=zcount
; i
++) {
207 if (strcasecmp(nlist
[ncount
-i
], zlist
[zcount
-i
]) != 0) {
213 if (match
== ncount
) {
214 prefix
= talloc_strdup(tmp_ctx
, zone_name
);
216 prefix
= talloc_strdup(tmp_ctx
, nlist
[0]);
217 if (prefix
!= NULL
) {
218 for (i
=1; i
<ncount
-match
; i
++) {
219 prefix
= talloc_asprintf_append(prefix
, ".%s", nlist
[i
]);
220 if (prefix
== NULL
) {
236 void dnsp_to_dns_copy(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*dnsp
,
237 struct DNS_RPC_RECORD
*dns
)
243 dns
->wDataLength
= dnsp
->wDataLength
;
244 dns
->wType
= dnsp
->wType
;
245 dns
->dwFlags
= dnsp
->rank
;
246 dns
->dwSerial
= dnsp
->dwSerial
;
247 dns
->dwTtlSeconds
= dnsp
->dwTtlSeconds
;
248 dns
->dwTimeStamp
= dnsp
->dwTimeStamp
;
250 switch (dnsp
->wType
) {
252 case DNS_TYPE_TOMBSTONE
:
253 dns
->data
.timestamp
= dnsp
->data
.timestamp
;
257 dns
->data
.ipv4
= talloc_strdup(mem_ctx
, dnsp
->data
.ipv4
);
261 len
= strlen(dnsp
->data
.ns
);
262 if (dnsp
->data
.ns
[len
-1] == '.') {
263 dns
->data
.name
.len
= len
;
264 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.ns
);
266 dns
->data
.name
.len
= len
+1;
267 dns
->data
.name
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.ns
);
272 len
= strlen(dnsp
->data
.cname
);
273 if (dnsp
->data
.cname
[len
-1] == '.') {
274 dns
->data
.name
.len
= len
;
275 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.cname
);
277 dns
->data
.name
.len
= len
+1;
278 dns
->data
.name
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.cname
);
283 dns
->data
.soa
.dwSerialNo
= dnsp
->data
.soa
.serial
;
284 dns
->data
.soa
.dwRefresh
= dnsp
->data
.soa
.refresh
;
285 dns
->data
.soa
.dwRetry
= dnsp
->data
.soa
.retry
;
286 dns
->data
.soa
.dwExpire
= dnsp
->data
.soa
.expire
;
287 dns
->data
.soa
.dwMinimumTtl
= dnsp
->data
.soa
.minimum
;
289 len
= strlen(dnsp
->data
.soa
.mname
);
290 if (dnsp
->data
.soa
.mname
[len
-1] == '.') {
291 dns
->data
.soa
.NamePrimaryServer
.len
= len
;
292 dns
->data
.soa
.NamePrimaryServer
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.soa
.mname
);
294 dns
->data
.soa
.NamePrimaryServer
.len
= len
+1;
295 dns
->data
.soa
.NamePrimaryServer
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.soa
.mname
);
298 len
= strlen(dnsp
->data
.soa
.rname
);
299 if (dnsp
->data
.soa
.rname
[len
-1] == '.') {
300 dns
->data
.soa
.ZoneAdministratorEmail
.len
= len
;
301 dns
->data
.soa
.ZoneAdministratorEmail
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.soa
.rname
);
303 dns
->data
.soa
.ZoneAdministratorEmail
.len
= len
+1;
304 dns
->data
.soa
.ZoneAdministratorEmail
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.soa
.rname
);
309 dns
->data
.ptr
.len
= strlen(dnsp
->data
.ptr
);
310 dns
->data
.ptr
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.ptr
);
314 dns
->data
.mx
.wPreference
= dnsp
->data
.mx
.wPriority
;
315 len
= strlen(dnsp
->data
.mx
.nameTarget
);
316 if (dnsp
->data
.mx
.nameTarget
[len
-1] == '.') {
317 dns
->data
.mx
.nameExchange
.len
= len
;
318 dns
->data
.mx
.nameExchange
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.mx
.nameTarget
);
320 dns
->data
.mx
.nameExchange
.len
= len
+1;
321 dns
->data
.mx
.nameExchange
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.mx
.nameTarget
);
326 dns
->data
.txt
.count
= dnsp
->data
.txt
.count
;
327 dns
->data
.txt
.str
= talloc_array(mem_ctx
, struct DNS_RPC_NAME
, dnsp
->data
.txt
.count
);
328 for (i
=0; i
<dnsp
->data
.txt
.count
; i
++) {
329 dns
->data
.txt
.str
[i
].str
= talloc_strdup(mem_ctx
, dnsp
->data
.txt
.str
[i
]);
330 dns
->data
.txt
.str
[i
].len
= strlen(dnsp
->data
.txt
.str
[i
]);
335 dns
->data
.ipv6
= talloc_strdup(mem_ctx
, dnsp
->data
.ipv6
);
339 dns
->data
.srv
.wPriority
= dnsp
->data
.srv
.wPriority
;
340 dns
->data
.srv
.wWeight
= dnsp
->data
.srv
.wWeight
;
341 dns
->data
.srv
.wPort
= dnsp
->data
.srv
.wPort
;
342 len
= strlen(dnsp
->data
.srv
.nameTarget
);
343 if (dnsp
->data
.srv
.nameTarget
[len
-1] == '.') {
344 dns
->data
.srv
.nameTarget
.len
= len
;
345 dns
->data
.srv
.nameTarget
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.srv
.nameTarget
);
347 dns
->data
.srv
.nameTarget
.len
= len
+1;
348 dns
->data
.srv
.nameTarget
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.srv
.nameTarget
);
353 memcpy(&dns
->data
, &dnsp
->data
, sizeof(union DNS_RPC_DATA
));
354 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dnsp
->wType
));
360 struct dnsp_DnssrvRpcRecord
*dns_to_dnsp_copy(TALLOC_CTX
*mem_ctx
, struct DNS_RPC_RECORD
*dns
)
363 struct dnsp_DnssrvRpcRecord
*dnsp
;
365 dnsp
= talloc_zero(mem_ctx
, struct dnsp_DnssrvRpcRecord
);
370 dnsp
->wDataLength
= dns
->wDataLength
;
371 dnsp
->wType
= dns
->wType
;
373 dnsp
->rank
= dns
->dwFlags
& 0x000000FF;
374 dnsp
->dwSerial
= dns
->dwSerial
;
375 dnsp
->dwTtlSeconds
= dns
->dwTtlSeconds
;
376 dnsp
->dwTimeStamp
= dns
->dwTimeStamp
;
378 switch (dns
->wType
) {
380 case DNS_TYPE_TOMBSTONE
:
381 dnsp
->data
.timestamp
= dns
->data
.timestamp
;
385 dnsp
->data
.ipv4
= talloc_strdup(mem_ctx
, dns
->data
.ipv4
);
389 len
= dns
->data
.name
.len
;
390 if (dns
->data
.name
.str
[len
-1] == '.') {
391 dnsp
->data
.ns
= talloc_strndup(mem_ctx
, dns
->data
.name
.str
, len
-1);
393 dnsp
->data
.ns
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
398 len
= dns
->data
.name
.len
;
399 if (dns
->data
.name
.str
[len
-1] == '.') {
400 dnsp
->data
.cname
= talloc_strndup(mem_ctx
, dns
->data
.name
.str
, len
-1);
402 dnsp
->data
.cname
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
407 dnsp
->data
.soa
.serial
= dns
->data
.soa
.dwSerialNo
;
408 dnsp
->data
.soa
.refresh
= dns
->data
.soa
.dwRefresh
;
409 dnsp
->data
.soa
.retry
= dns
->data
.soa
.dwRetry
;
410 dnsp
->data
.soa
.expire
= dns
->data
.soa
.dwExpire
;
411 dnsp
->data
.soa
.minimum
= dns
->data
.soa
.dwMinimumTtl
;
413 len
= dns
->data
.soa
.NamePrimaryServer
.len
;
414 if (dns
->data
.soa
.NamePrimaryServer
.str
[len
-1] == '.') {
415 dnsp
->data
.soa
.mname
= talloc_strdup(mem_ctx
, dns
->data
.soa
.NamePrimaryServer
.str
);
417 dnsp
->data
.soa
.mname
= talloc_strndup(mem_ctx
, dns
->data
.soa
.NamePrimaryServer
.str
, len
-1);
420 len
= dns
->data
.soa
.ZoneAdministratorEmail
.len
;
421 if (dns
->data
.soa
.ZoneAdministratorEmail
.str
[len
-1] == '.') {
422 dnsp
->data
.soa
.rname
= talloc_strndup(mem_ctx
, dns
->data
.soa
.ZoneAdministratorEmail
.str
, len
-1);
424 dnsp
->data
.soa
.rname
= talloc_strdup(mem_ctx
, dns
->data
.soa
.ZoneAdministratorEmail
.str
);
429 dnsp
->data
.ptr
= talloc_strdup(mem_ctx
, dns
->data
.ptr
.str
);
433 dnsp
->data
.mx
.wPriority
= dns
->data
.mx
.wPreference
;
434 len
= dns
->data
.mx
.nameExchange
.len
;
435 if (dns
->data
.mx
.nameExchange
.str
[len
-1] == '.') {
436 dnsp
->data
.mx
.nameTarget
= talloc_strndup(mem_ctx
, dns
->data
.mx
.nameExchange
.str
, len
-1);
438 dnsp
->data
.mx
.nameTarget
= talloc_strdup(mem_ctx
, dns
->data
.mx
.nameExchange
.str
);
443 dnsp
->data
.txt
.count
= dns
->data
.txt
.count
;
444 dnsp
->data
.txt
.str
= talloc_array(mem_ctx
, const char *, dns
->data
.txt
.count
);
445 for (i
=0; i
<dns
->data
.txt
.count
; i
++) {
446 dnsp
->data
.txt
.str
[i
] = talloc_strdup(mem_ctx
, dns
->data
.txt
.str
[i
].str
);
451 dnsp
->data
.ipv6
= talloc_strdup(mem_ctx
, dns
->data
.ipv6
);
455 dnsp
->data
.srv
.wPriority
= dns
->data
.srv
.wPriority
;
456 dnsp
->data
.srv
.wWeight
= dns
->data
.srv
.wWeight
;
457 dnsp
->data
.srv
.wPort
= dns
->data
.srv
.wPort
;
459 len
= dns
->data
.srv
.nameTarget
.len
;
460 if (dns
->data
.srv
.nameTarget
.str
[len
-1] == '.') {
461 dnsp
->data
.srv
.nameTarget
= talloc_strndup(mem_ctx
, dns
->data
.srv
.nameTarget
.str
, len
-1);
463 dnsp
->data
.srv
.nameTarget
= talloc_strdup(mem_ctx
, dns
->data
.srv
.nameTarget
.str
);
468 memcpy(&dnsp
->data
, &dns
->data
, sizeof(union dnsRecordData
));
469 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dns
->wType
));
477 /* Intialize tree with given name as the root */
478 static struct dns_tree
*dns_tree_init(TALLOC_CTX
*mem_ctx
, const char *name
, void *data
)
480 struct dns_tree
*tree
;
482 tree
= talloc_zero(mem_ctx
, struct dns_tree
);
487 tree
->name
= talloc_strdup(tree
, name
);
488 if (tree
->name
== NULL
) {
499 /* Add a child one level below */
500 static struct dns_tree
*dns_tree_add(struct dns_tree
*tree
, const char *name
, void *data
)
502 struct dns_tree
*node
;
504 node
= talloc_zero(tree
, struct dns_tree
);
509 node
->name
= talloc_strdup(tree
, name
);
510 if (node
->name
== NULL
) {
514 node
->level
= tree
->level
+ 1;
515 node
->num_children
= 0;
516 node
->children
= NULL
;
519 if (tree
->num_children
== 0) {
520 tree
->children
= talloc_zero(tree
, struct dns_tree
*);
522 tree
->children
= talloc_realloc(tree
, tree
->children
, struct dns_tree
*,
523 tree
->num_children
+1);
525 if (tree
->children
== NULL
) {
529 tree
->children
[tree
->num_children
] = node
;
530 tree
->num_children
++;
535 /* Find a node that matches the name components */
536 static struct dns_tree
*dns_tree_find(struct dns_tree
*tree
, int ncount
, char **nlist
, int *match_count
)
538 struct dns_tree
*node
, *next
;
543 if (strcmp(tree
->name
, "@") == 0) {
546 if (strcasecmp(tree
->name
, nlist
[ncount
-1]) != 0) {
554 for (i
=start
; i
<ncount
; i
++) {
555 if (node
->num_children
== 0) {
559 for (j
=0; j
<node
->num_children
; j
++) {
560 if (strcasecmp(nlist
[(ncount
-1)-i
], node
->children
[j
]->name
) == 0) {
561 next
= node
->children
[j
];
576 /* Build a 2-level tree for resulting dns names */
577 struct dns_tree
*dns_build_tree(TALLOC_CTX
*mem_ctx
, const char *name
, struct ldb_result
*res
)
579 struct dns_tree
*root
, *base
, *tree
, *node
;
581 int rootcount
, ncount
;
583 int i
, level
, match_count
;
585 rootcount
= dns_split_name_components(mem_ctx
, name
, &nlist
);
586 if (rootcount
<= 0) {
590 root
= dns_tree_init(mem_ctx
, nlist
[rootcount
-1], NULL
);
596 for (i
=rootcount
-2; i
>=0; i
--) {
597 tree
= dns_tree_add(tree
, nlist
[i
], NULL
);
605 /* Add all names in the result in a tree */
606 for (i
=0; i
<res
->count
; i
++) {
607 ptr
= ldb_msg_find_attr_as_string(res
->msgs
[i
], "name", NULL
);
609 if (strcmp(ptr
, "@") == 0) {
610 base
->data
= res
->msgs
[i
];
612 } else if (strcasecmp(ptr
, name
) == 0) {
613 base
->data
= res
->msgs
[i
];
617 ncount
= dns_split_name_components(root
, ptr
, &nlist
);
622 /* Find matching node */
623 tree
= dns_tree_find(root
, ncount
, nlist
, &match_count
);
628 /* If the node is on leaf, then add record data */
629 if (match_count
+1 == ncount
) {
630 tree
->data
= res
->msgs
[i
];
633 /* Add missing name components */
634 for (level
=match_count
+1; level
<ncount
; level
++) {
635 if (tree
->level
== rootcount
+1) {
638 if (level
== ncount
-1) {
639 node
= dns_tree_add(tree
, nlist
[(ncount
-1)-level
], res
->msgs
[i
]);
641 node
= dns_tree_add(tree
, nlist
[(ncount
-1)-level
], NULL
);
652 /* Mark the base record, so it can be found easily */
663 static void _dns_add_name(TALLOC_CTX
*mem_ctx
, const char *name
, char ***add_names
, int *add_count
)
666 char **ptr
= *add_names
;
667 int count
= *add_count
;
669 for (i
=0; i
<count
; i
++) {
670 if (strcasecmp(ptr
[i
], name
) == 0) {
675 ptr
= talloc_realloc(mem_ctx
, ptr
, char *, count
+1);
680 ptr
[count
] = talloc_strdup(mem_ctx
, name
);
681 if (ptr
[count
] == NULL
) {
686 *add_count
= count
+1;
690 static void dns_find_additional_names(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*rec
, char ***add_names
, int *add_count
)
692 if (add_names
== NULL
) {
696 switch (rec
->wType
) {
699 _dns_add_name(mem_ctx
, rec
->data
.ns
, add_names
, add_count
);
703 _dns_add_name(mem_ctx
, rec
->data
.cname
, add_names
, add_count
);
707 _dns_add_name(mem_ctx
, rec
->data
.soa
.mname
, add_names
, add_count
);
711 _dns_add_name(mem_ctx
, rec
->data
.mx
.nameTarget
, add_names
, add_count
);
715 _dns_add_name(mem_ctx
, rec
->data
.srv
.nameTarget
, add_names
, add_count
);
724 WERROR
dns_fill_records_array(TALLOC_CTX
*mem_ctx
,
725 struct dnsserver_zone
*z
,
726 enum dns_record_type record_type
,
727 unsigned int select_flag
,
728 const char *branch_name
,
729 struct ldb_message
*msg
,
731 struct DNS_RPC_RECORDS_ARRAY
*recs
,
735 struct ldb_message_element
*el
;
740 if (recs
->count
== 0) {
741 recs
->rec
= talloc_zero(recs
, struct DNS_RPC_RECORDS
);
743 recs
->rec
= talloc_realloc(recs
, recs
->rec
, struct DNS_RPC_RECORDS
, recs
->count
+1);
745 if (recs
->rec
== NULL
) {
749 recs
->rec
[i
].wLength
= 0;
750 recs
->rec
[i
].wRecordCount
= 0;
751 recs
->rec
[i
].dwChildCount
= num_children
;
753 /* The base records returned with empty name */
754 /* Children records returned with names */
755 if (branch_name
== NULL
) {
756 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, "");
757 recs
->rec
[i
].dnsNodeName
.len
= 0;
759 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, branch_name
);
760 recs
->rec
[i
].dnsNodeName
.len
= strlen(branch_name
);
762 recs
->rec
[i
].records
= talloc_zero_array(recs
, struct DNS_RPC_RECORD
, 0);
765 /* Allow empty records */
770 /* Do not return RR records, if the node has children */
771 if (branch_name
!= NULL
&& num_children
> 0) {
775 ptr
= ldb_msg_find_attr_as_string(msg
, "name", NULL
);
776 el
= ldb_msg_find_element(msg
, "dnsRecord");
777 if (el
== NULL
|| el
->values
== 0) {
782 for (j
=0; j
<el
->num_values
; j
++) {
783 struct dnsp_DnssrvRpcRecord dnsp_rec
;
784 struct DNS_RPC_RECORD
*dns_rec
;
785 enum ndr_err_code ndr_err
;
787 ndr_err
= ndr_pull_struct_blob(&el
->values
[j
], mem_ctx
, &dnsp_rec
,
788 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
);
789 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
790 DEBUG(0, ("dnsserver: Unable to parse dns record (%s)", ldb_dn_get_linearized(msg
->dn
)));
791 return WERR_INTERNAL_DB_ERROR
;
794 /* Match the records based on search criteria */
795 if (record_type
== DNS_TYPE_ALL
|| dnsp_rec
.wType
== record_type
) {
798 if (select_flag
& DNS_RPC_VIEW_AUTHORITY_DATA
) {
799 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
803 if (select_flag
& DNS_RPC_VIEW_CACHE_DATA
) {
804 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
808 if (select_flag
& DNS_RPC_VIEW_GLUE_DATA
) {
809 if (dnsp_rec
.rank
== DNS_RANK_NS_GLUE
) {
813 if (select_flag
& DNS_RPC_VIEW_ROOT_HINT_DATA
) {
814 if (dnsp_rec
.rank
== DNS_RANK_ROOT_HINT
) {
820 recs
->rec
[i
].records
= talloc_realloc(recs
,
821 recs
->rec
[i
].records
,
822 struct DNS_RPC_RECORD
,
823 recs
->rec
[i
].wRecordCount
+1);
824 if (recs
->rec
[i
].records
== NULL
) {
828 dns_rec
= &recs
->rec
[i
].records
[recs
->rec
[i
].wRecordCount
];
829 dnsp_to_dns_copy(recs
, &dnsp_rec
, dns_rec
);
831 /* Fix record flags */
832 if (strcmp(ptr
, "@") == 0) {
833 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
835 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
836 dns_rec
->dwFlags
|= DNS_RPC_FLAG_AUTH_ZONE_ROOT
;
840 if (dns_rec
->dwFlags
== DNS_RANK_NS_GLUE
) {
841 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
844 recs
->rec
[i
].wRecordCount
++;
846 dns_find_additional_names(mem_ctx
, &dnsp_rec
, add_names
, add_count
);
855 int dns_name_compare(const struct ldb_message
**m1
, const struct ldb_message
**m2
,
858 const char *name1
, *name2
;
859 const char *ptr1
, *ptr2
;
861 name1
= ldb_msg_find_attr_as_string(*m1
, "name", NULL
);
862 name2
= ldb_msg_find_attr_as_string(*m2
, "name", NULL
);
863 if (name1
== NULL
|| name2
== NULL
) {
867 /* '@' record and the search_name record gets preference */
868 if (name1
[0] == '@') {
871 if (search_name
&& strcasecmp(name1
, search_name
) == 0) {
875 if (name2
[0] == '@') {
878 if (search_name
&& strcasecmp(name2
, search_name
) == 0) {
882 /* Compare the last components of names.
883 * If search_name is not NULL, compare the second last components of names */
884 ptr1
= strrchr(name1
, '.');
888 if (search_name
&& strcasecmp(ptr1
+1, search_name
) == 0) {
890 while (ptr1
!= name1
) {
902 ptr2
= strrchr(name2
, '.');
906 if (search_name
&& strcasecmp(ptr2
+1, search_name
) == 0) {
908 while (ptr2
!= name2
) {
920 return strcasecmp(ptr1
, ptr2
);
924 bool dns_name_equal(const char *name1
, const char *name2
)
926 size_t len1
= strlen(name1
);
927 size_t len2
= strlen(name2
);
929 if (name1
[len1
-1] == '.') len1
--;
930 if (name2
[len2
-1] == '.') len2
--;
934 return strncasecmp(name1
, name2
, len1
) == 0;
938 bool dns_record_match(struct dnsp_DnssrvRpcRecord
*rec1
, struct dnsp_DnssrvRpcRecord
*rec2
)
943 if (rec1
->wType
!= rec2
->wType
) {
947 switch(rec1
->wType
) {
948 case DNS_TYPE_TOMBSTONE
:
952 return strcmp(rec1
->data
.ipv4
, rec2
->data
.ipv4
) == 0;
955 return dns_name_equal(rec1
->data
.ns
, rec2
->data
.ns
);
958 return dns_name_equal(rec1
->data
.cname
, rec2
->data
.cname
);
961 return dns_name_equal(rec1
->data
.soa
.mname
, rec2
->data
.soa
.mname
) == 0 &&
962 dns_name_equal(rec1
->data
.soa
.rname
, rec2
->data
.soa
.rname
) == 0 &&
963 rec1
->data
.soa
.serial
== rec2
->data
.soa
.serial
&&
964 rec1
->data
.soa
.refresh
== rec2
->data
.soa
.refresh
&&
965 rec1
->data
.soa
.retry
== rec2
->data
.soa
.retry
&&
966 rec1
->data
.soa
.expire
== rec2
->data
.soa
.expire
&&
967 rec1
->data
.soa
.minimum
== rec2
->data
.soa
.minimum
;
970 return dns_name_equal(rec1
->data
.ptr
, rec2
->data
.ptr
);
973 return rec1
->data
.mx
.wPriority
== rec2
->data
.srv
.wPriority
&&
974 dns_name_equal(rec1
->data
.mx
.nameTarget
, rec2
->data
.srv
.nameTarget
);
977 if (rec1
->data
.txt
.count
!= rec2
->data
.txt
.count
) {
981 for (i
=0; i
<rec1
->data
.txt
.count
; i
++) {
982 status
= status
&& (strcmp(rec1
->data
.txt
.str
[i
],
983 rec2
->data
.txt
.str
[i
]) == 0);
988 return strcmp(rec1
->data
.ipv6
, rec2
->data
.ipv6
) == 0;
991 return rec1
->data
.srv
.wPriority
== rec2
->data
.srv
.wPriority
&&
992 rec1
->data
.srv
.wWeight
== rec2
->data
.srv
.wWeight
&&
993 rec1
->data
.srv
.wPort
== rec2
->data
.srv
.wPort
&&
994 dns_name_equal(rec1
->data
.srv
.nameTarget
, rec2
->data
.srv
.nameTarget
);
997 DEBUG(0, ("dnsserver: unhandled record type %u", rec1
->wType
));