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;
94 struct IP4_ARRAY
*dns_addr_array_to_ip4_array(TALLOC_CTX
*mem_ctx
,
95 struct DNS_ADDR_ARRAY
*ip
)
97 struct IP4_ARRAY
*ret
;
103 /* We must only return IPv4 addresses.
104 The passed DNS_ADDR_ARRAY may contain:
105 - only ipv4 addresses
106 - only ipv6 addresses
110 ret
= talloc_zero(mem_ctx
, struct IP4_ARRAY
);
114 if (ip
->AddrCount
== 0 || ip
->Family
== AF_INET6
) {
118 /* Now only ipv4 addresses or a mixture are left */
120 for (i
= 0; i
< ip
->AddrCount
; i
++) {
121 if (ip
->AddrArray
[i
].MaxSa
[0] == 0x02) {
127 /* should not happen */
131 ret
->AddrArray
= talloc_zero_array(mem_ctx
, uint32_t, count
);
132 if (ret
->AddrArray
) {
134 for (i
= 0; i
< ip
->AddrCount
; i
++) {
135 if (ip
->AddrArray
[i
].MaxSa
[0] == 0x02) {
137 memcpy(&ret
->AddrArray
[curr
],
138 &ip
->AddrArray
[i
].MaxSa
[4],
147 ret
->AddrCount
= curr
;
151 struct DNS_ADDR_ARRAY
*dns_addr_array_copy(TALLOC_CTX
*mem_ctx
,
152 struct DNS_ADDR_ARRAY
*addr
)
154 struct DNS_ADDR_ARRAY
*ret
;
160 ret
= talloc_zero(mem_ctx
, struct DNS_ADDR_ARRAY
);
165 ret
->MaxCount
= addr
->MaxCount
;
166 ret
->AddrCount
= addr
->AddrCount
;
167 ret
->Family
= addr
->Family
;
168 if (addr
->AddrCount
> 0) {
169 ret
->AddrArray
= talloc_zero_array(mem_ctx
, struct DNS_ADDR
, addr
->AddrCount
);
170 if (ret
->AddrArray
) {
171 memcpy(ret
->AddrArray
, addr
->AddrArray
,
172 sizeof(struct DNS_ADDR
) * addr
->AddrCount
);
182 int dns_split_name_components(TALLOC_CTX
*tmp_ctx
, const char *name
, char ***components
)
184 char *str
= NULL
, *ptr
, **list
;
191 str
= talloc_strdup(tmp_ctx
, name
);
196 list
= talloc_zero_array(tmp_ctx
, char *, 0);
201 ptr
= strtok(str
, ".");
202 while (ptr
!= NULL
) {
204 list
= talloc_realloc(tmp_ctx
, list
, char *, count
);
208 list
[count
-1] = talloc_strdup(tmp_ctx
, ptr
);
209 if (list
[count
-1] == NULL
) {
212 ptr
= strtok(NULL
, ".");
228 char *dns_split_node_name(TALLOC_CTX
*tmp_ctx
, const char *node_name
, const char *zone_name
)
230 char **nlist
, **zlist
;
232 int ncount
, zcount
, i
, match
;
235 * If node_name is "@", return the zone_name
236 * If node_name is ".", return NULL
237 * If there is no '.' in node_name, return the node_name as is.
239 * If node_name does not have zone_name in it, return the node_name as is.
241 * If node_name has additional components as compared to zone_name
242 * return only the additional components as a prefix.
245 if (strcmp(node_name
, "@") == 0) {
246 prefix
= talloc_strdup(tmp_ctx
, zone_name
);
247 } else if (strcmp(node_name
, ".") == 0) {
249 } else if (strchr(node_name
, '.') == NULL
) {
250 prefix
= talloc_strdup(tmp_ctx
, node_name
);
252 zcount
= dns_split_name_components(tmp_ctx
, zone_name
, &zlist
);
253 ncount
= dns_split_name_components(tmp_ctx
, node_name
, &nlist
);
254 if (zcount
< 0 || ncount
< 0) {
258 if (ncount
< zcount
) {
259 prefix
= talloc_strdup(tmp_ctx
, node_name
);
262 for (i
=1; i
<=zcount
; i
++) {
263 if (strcasecmp(nlist
[ncount
-i
], zlist
[zcount
-i
]) != 0) {
269 if (match
== ncount
) {
270 prefix
= talloc_strdup(tmp_ctx
, zone_name
);
272 prefix
= talloc_strdup(tmp_ctx
, nlist
[0]);
273 if (prefix
!= NULL
) {
274 for (i
=1; i
<ncount
-match
; i
++) {
275 prefix
= talloc_asprintf_append(prefix
, ".%s", nlist
[i
]);
276 if (prefix
== NULL
) {
292 void dnsp_to_dns_copy(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*dnsp
,
293 struct DNS_RPC_RECORD
*dns
)
299 dns
->wDataLength
= dnsp
->wDataLength
;
300 dns
->wType
= dnsp
->wType
;
301 dns
->dwFlags
= dnsp
->rank
;
302 dns
->dwSerial
= dnsp
->dwSerial
;
303 dns
->dwTtlSeconds
= dnsp
->dwTtlSeconds
;
304 dns
->dwTimeStamp
= dnsp
->dwTimeStamp
;
306 switch (dnsp
->wType
) {
308 case DNS_TYPE_TOMBSTONE
:
309 dns
->data
.timestamp
= dnsp
->data
.timestamp
;
313 dns
->data
.ipv4
= talloc_strdup(mem_ctx
, dnsp
->data
.ipv4
);
317 len
= strlen(dnsp
->data
.ns
);
318 if (dnsp
->data
.ns
[len
-1] == '.') {
319 dns
->data
.name
.len
= len
;
320 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.ns
);
322 dns
->data
.name
.len
= len
+1;
323 dns
->data
.name
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.ns
);
328 len
= strlen(dnsp
->data
.cname
);
329 if (dnsp
->data
.cname
[len
-1] == '.') {
330 dns
->data
.name
.len
= len
;
331 dns
->data
.name
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.cname
);
333 dns
->data
.name
.len
= len
+1;
334 dns
->data
.name
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.cname
);
339 dns
->data
.soa
.dwSerialNo
= dnsp
->data
.soa
.serial
;
340 dns
->data
.soa
.dwRefresh
= dnsp
->data
.soa
.refresh
;
341 dns
->data
.soa
.dwRetry
= dnsp
->data
.soa
.retry
;
342 dns
->data
.soa
.dwExpire
= dnsp
->data
.soa
.expire
;
343 dns
->data
.soa
.dwMinimumTtl
= dnsp
->data
.soa
.minimum
;
345 len
= strlen(dnsp
->data
.soa
.mname
);
346 if (dnsp
->data
.soa
.mname
[len
-1] == '.') {
347 dns
->data
.soa
.NamePrimaryServer
.len
= len
;
348 dns
->data
.soa
.NamePrimaryServer
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.soa
.mname
);
350 dns
->data
.soa
.NamePrimaryServer
.len
= len
+1;
351 dns
->data
.soa
.NamePrimaryServer
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.soa
.mname
);
354 len
= strlen(dnsp
->data
.soa
.rname
);
355 if (dnsp
->data
.soa
.rname
[len
-1] == '.') {
356 dns
->data
.soa
.ZoneAdministratorEmail
.len
= len
;
357 dns
->data
.soa
.ZoneAdministratorEmail
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.soa
.rname
);
359 dns
->data
.soa
.ZoneAdministratorEmail
.len
= len
+1;
360 dns
->data
.soa
.ZoneAdministratorEmail
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.soa
.rname
);
365 dns
->data
.ptr
.len
= strlen(dnsp
->data
.ptr
);
366 dns
->data
.ptr
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.ptr
);
370 dns
->data
.mx
.wPreference
= dnsp
->data
.mx
.wPriority
;
371 len
= strlen(dnsp
->data
.mx
.nameTarget
);
372 if (dnsp
->data
.mx
.nameTarget
[len
-1] == '.') {
373 dns
->data
.mx
.nameExchange
.len
= len
;
374 dns
->data
.mx
.nameExchange
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.mx
.nameTarget
);
376 dns
->data
.mx
.nameExchange
.len
= len
+1;
377 dns
->data
.mx
.nameExchange
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.mx
.nameTarget
);
382 dns
->data
.txt
.count
= dnsp
->data
.txt
.count
;
383 dns
->data
.txt
.str
= talloc_array(mem_ctx
, struct DNS_RPC_NAME
, dnsp
->data
.txt
.count
);
384 for (i
=0; i
<dnsp
->data
.txt
.count
; i
++) {
385 dns
->data
.txt
.str
[i
].str
= talloc_strdup(mem_ctx
, dnsp
->data
.txt
.str
[i
]);
386 dns
->data
.txt
.str
[i
].len
= strlen(dnsp
->data
.txt
.str
[i
]);
391 dns
->data
.ipv6
= talloc_strdup(mem_ctx
, dnsp
->data
.ipv6
);
395 dns
->data
.srv
.wPriority
= dnsp
->data
.srv
.wPriority
;
396 dns
->data
.srv
.wWeight
= dnsp
->data
.srv
.wWeight
;
397 dns
->data
.srv
.wPort
= dnsp
->data
.srv
.wPort
;
398 len
= strlen(dnsp
->data
.srv
.nameTarget
);
399 if (dnsp
->data
.srv
.nameTarget
[len
-1] == '.') {
400 dns
->data
.srv
.nameTarget
.len
= len
;
401 dns
->data
.srv
.nameTarget
.str
= talloc_strdup(mem_ctx
, dnsp
->data
.srv
.nameTarget
);
403 dns
->data
.srv
.nameTarget
.len
= len
+1;
404 dns
->data
.srv
.nameTarget
.str
= talloc_asprintf(mem_ctx
, "%s.", dnsp
->data
.srv
.nameTarget
);
409 memcpy(&dns
->data
, &dnsp
->data
, sizeof(union DNS_RPC_DATA
));
410 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dnsp
->wType
));
416 struct dnsp_DnssrvRpcRecord
*dns_to_dnsp_copy(TALLOC_CTX
*mem_ctx
, struct DNS_RPC_RECORD
*dns
)
419 struct dnsp_DnssrvRpcRecord
*dnsp
;
421 dnsp
= talloc_zero(mem_ctx
, struct dnsp_DnssrvRpcRecord
);
426 dnsp
->wDataLength
= dns
->wDataLength
;
427 dnsp
->wType
= dns
->wType
;
429 dnsp
->rank
= dns
->dwFlags
& 0x000000FF;
430 dnsp
->dwSerial
= dns
->dwSerial
;
431 dnsp
->dwTtlSeconds
= dns
->dwTtlSeconds
;
432 dnsp
->dwTimeStamp
= dns
->dwTimeStamp
;
434 switch (dns
->wType
) {
436 case DNS_TYPE_TOMBSTONE
:
437 dnsp
->data
.timestamp
= dns
->data
.timestamp
;
441 dnsp
->data
.ipv4
= talloc_strdup(mem_ctx
, dns
->data
.ipv4
);
445 len
= dns
->data
.name
.len
;
446 if (dns
->data
.name
.str
[len
-1] == '.') {
447 dnsp
->data
.ns
= talloc_strndup(mem_ctx
, dns
->data
.name
.str
, len
-1);
449 dnsp
->data
.ns
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
454 len
= dns
->data
.name
.len
;
455 if (dns
->data
.name
.str
[len
-1] == '.') {
456 dnsp
->data
.cname
= talloc_strndup(mem_ctx
, dns
->data
.name
.str
, len
-1);
458 dnsp
->data
.cname
= talloc_strdup(mem_ctx
, dns
->data
.name
.str
);
463 dnsp
->data
.soa
.serial
= dns
->data
.soa
.dwSerialNo
;
464 dnsp
->data
.soa
.refresh
= dns
->data
.soa
.dwRefresh
;
465 dnsp
->data
.soa
.retry
= dns
->data
.soa
.dwRetry
;
466 dnsp
->data
.soa
.expire
= dns
->data
.soa
.dwExpire
;
467 dnsp
->data
.soa
.minimum
= dns
->data
.soa
.dwMinimumTtl
;
469 len
= dns
->data
.soa
.NamePrimaryServer
.len
;
470 if (dns
->data
.soa
.NamePrimaryServer
.str
[len
-1] == '.') {
471 dnsp
->data
.soa
.mname
= talloc_strndup(mem_ctx
, dns
->data
.soa
.NamePrimaryServer
.str
, len
-1);
473 dnsp
->data
.soa
.mname
= talloc_strdup(mem_ctx
, dns
->data
.soa
.NamePrimaryServer
.str
);
476 len
= dns
->data
.soa
.ZoneAdministratorEmail
.len
;
477 if (dns
->data
.soa
.ZoneAdministratorEmail
.str
[len
-1] == '.') {
478 dnsp
->data
.soa
.rname
= talloc_strndup(mem_ctx
, dns
->data
.soa
.ZoneAdministratorEmail
.str
, len
-1);
480 dnsp
->data
.soa
.rname
= talloc_strdup(mem_ctx
, dns
->data
.soa
.ZoneAdministratorEmail
.str
);
485 dnsp
->data
.ptr
= talloc_strdup(mem_ctx
, dns
->data
.ptr
.str
);
489 dnsp
->data
.mx
.wPriority
= dns
->data
.mx
.wPreference
;
490 len
= dns
->data
.mx
.nameExchange
.len
;
491 if (dns
->data
.mx
.nameExchange
.str
[len
-1] == '.') {
492 dnsp
->data
.mx
.nameTarget
= talloc_strndup(mem_ctx
, dns
->data
.mx
.nameExchange
.str
, len
-1);
494 dnsp
->data
.mx
.nameTarget
= talloc_strdup(mem_ctx
, dns
->data
.mx
.nameExchange
.str
);
499 dnsp
->data
.txt
.count
= dns
->data
.txt
.count
;
500 dnsp
->data
.txt
.str
= talloc_array(mem_ctx
, const char *, dns
->data
.txt
.count
);
501 for (i
=0; i
<dns
->data
.txt
.count
; i
++) {
502 dnsp
->data
.txt
.str
[i
] = talloc_strdup(mem_ctx
, dns
->data
.txt
.str
[i
].str
);
507 dnsp
->data
.ipv6
= talloc_strdup(mem_ctx
, dns
->data
.ipv6
);
511 dnsp
->data
.srv
.wPriority
= dns
->data
.srv
.wPriority
;
512 dnsp
->data
.srv
.wWeight
= dns
->data
.srv
.wWeight
;
513 dnsp
->data
.srv
.wPort
= dns
->data
.srv
.wPort
;
515 len
= dns
->data
.srv
.nameTarget
.len
;
516 if (dns
->data
.srv
.nameTarget
.str
[len
-1] == '.') {
517 dnsp
->data
.srv
.nameTarget
= talloc_strndup(mem_ctx
, dns
->data
.srv
.nameTarget
.str
, len
-1);
519 dnsp
->data
.srv
.nameTarget
= talloc_strdup(mem_ctx
, dns
->data
.srv
.nameTarget
.str
);
524 memcpy(&dnsp
->data
, &dns
->data
, sizeof(union dnsRecordData
));
525 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dns
->wType
));
533 /* Intialize tree with given name as the root */
534 static struct dns_tree
*dns_tree_init(TALLOC_CTX
*mem_ctx
, const char *name
, void *data
)
536 struct dns_tree
*tree
;
538 tree
= talloc_zero(mem_ctx
, struct dns_tree
);
543 tree
->name
= talloc_strdup(tree
, name
);
544 if (tree
->name
== NULL
) {
555 /* Add a child one level below */
556 static struct dns_tree
*dns_tree_add(struct dns_tree
*tree
, const char *name
, void *data
)
558 struct dns_tree
*node
;
560 node
= talloc_zero(tree
, struct dns_tree
);
565 node
->name
= talloc_strdup(tree
, name
);
566 if (node
->name
== NULL
) {
570 node
->level
= tree
->level
+ 1;
571 node
->num_children
= 0;
572 node
->children
= NULL
;
575 if (tree
->num_children
== 0) {
576 tree
->children
= talloc_zero(tree
, struct dns_tree
*);
578 tree
->children
= talloc_realloc(tree
, tree
->children
, struct dns_tree
*,
579 tree
->num_children
+1);
581 if (tree
->children
== NULL
) {
585 tree
->children
[tree
->num_children
] = node
;
586 tree
->num_children
++;
591 /* Find a node that matches the name components */
592 static struct dns_tree
*dns_tree_find(struct dns_tree
*tree
, int ncount
, char **nlist
, int *match_count
)
594 struct dns_tree
*node
, *next
;
599 if (strcmp(tree
->name
, "@") == 0) {
602 if (strcasecmp(tree
->name
, nlist
[ncount
-1]) != 0) {
610 for (i
=start
; i
<ncount
; i
++) {
611 if (node
->num_children
== 0) {
615 for (j
=0; j
<node
->num_children
; j
++) {
616 if (strcasecmp(nlist
[(ncount
-1)-i
], node
->children
[j
]->name
) == 0) {
617 next
= node
->children
[j
];
632 /* Build a 2-level tree for resulting dns names */
633 struct dns_tree
*dns_build_tree(TALLOC_CTX
*mem_ctx
, const char *name
, struct ldb_result
*res
)
635 struct dns_tree
*root
, *base
, *tree
, *node
;
637 int rootcount
, ncount
;
639 int i
, level
, match_count
;
641 rootcount
= dns_split_name_components(mem_ctx
, name
, &nlist
);
642 if (rootcount
<= 0) {
646 root
= dns_tree_init(mem_ctx
, nlist
[rootcount
-1], NULL
);
652 for (i
=rootcount
-2; i
>=0; i
--) {
653 tree
= dns_tree_add(tree
, nlist
[i
], NULL
);
661 /* Add all names in the result in a tree */
662 for (i
=0; i
<res
->count
; i
++) {
663 ptr
= ldb_msg_find_attr_as_string(res
->msgs
[i
], "name", NULL
);
665 if (strcmp(ptr
, "@") == 0) {
666 base
->data
= res
->msgs
[i
];
668 } else if (strcasecmp(ptr
, name
) == 0) {
669 base
->data
= res
->msgs
[i
];
673 ncount
= dns_split_name_components(root
, ptr
, &nlist
);
678 /* Find matching node */
679 tree
= dns_tree_find(root
, ncount
, nlist
, &match_count
);
684 /* If the node is on leaf, then add record data */
685 if (match_count
+1 == ncount
) {
686 tree
->data
= res
->msgs
[i
];
689 /* Add missing name components */
690 for (level
=match_count
+1; level
<ncount
; level
++) {
691 if (tree
->level
== rootcount
+1) {
694 if (level
== ncount
-1) {
695 node
= dns_tree_add(tree
, nlist
[(ncount
-1)-level
], res
->msgs
[i
]);
697 node
= dns_tree_add(tree
, nlist
[(ncount
-1)-level
], NULL
);
708 /* Mark the base record, so it can be found easily */
719 static void _dns_add_name(TALLOC_CTX
*mem_ctx
, const char *name
, char ***add_names
, int *add_count
)
722 char **ptr
= *add_names
;
723 int count
= *add_count
;
725 for (i
=0; i
<count
; i
++) {
726 if (strcasecmp(ptr
[i
], name
) == 0) {
731 ptr
= talloc_realloc(mem_ctx
, ptr
, char *, count
+1);
736 ptr
[count
] = talloc_strdup(mem_ctx
, name
);
737 if (ptr
[count
] == NULL
) {
742 *add_count
= count
+1;
746 static void dns_find_additional_names(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*rec
, char ***add_names
, int *add_count
)
748 if (add_names
== NULL
) {
752 switch (rec
->wType
) {
755 _dns_add_name(mem_ctx
, rec
->data
.ns
, add_names
, add_count
);
759 _dns_add_name(mem_ctx
, rec
->data
.cname
, add_names
, add_count
);
763 _dns_add_name(mem_ctx
, rec
->data
.soa
.mname
, add_names
, add_count
);
767 _dns_add_name(mem_ctx
, rec
->data
.mx
.nameTarget
, add_names
, add_count
);
771 _dns_add_name(mem_ctx
, rec
->data
.srv
.nameTarget
, add_names
, add_count
);
780 WERROR
dns_fill_records_array(TALLOC_CTX
*mem_ctx
,
781 struct dnsserver_zone
*z
,
782 enum dns_record_type record_type
,
783 unsigned int select_flag
,
784 const char *branch_name
,
785 struct ldb_message
*msg
,
787 struct DNS_RPC_RECORDS_ARRAY
*recs
,
791 struct ldb_message_element
*el
;
796 if (recs
->count
== 0) {
797 recs
->rec
= talloc_zero(recs
, struct DNS_RPC_RECORDS
);
799 recs
->rec
= talloc_realloc(recs
, recs
->rec
, struct DNS_RPC_RECORDS
, recs
->count
+1);
801 if (recs
->rec
== NULL
) {
805 recs
->rec
[i
].wLength
= 0;
806 recs
->rec
[i
].wRecordCount
= 0;
807 recs
->rec
[i
].dwChildCount
= num_children
;
808 recs
->rec
[i
].dwFlags
= 0;
810 /* The base records returned with empty name */
811 /* Children records returned with names */
812 if (branch_name
== NULL
) {
813 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, "");
814 recs
->rec
[i
].dnsNodeName
.len
= 0;
816 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, branch_name
);
817 recs
->rec
[i
].dnsNodeName
.len
= strlen(branch_name
);
819 recs
->rec
[i
].records
= talloc_zero_array(recs
, struct DNS_RPC_RECORD
, 0);
822 /* Allow empty records */
827 /* Do not return RR records, if the node has children */
828 if (branch_name
!= NULL
&& num_children
> 0) {
832 ptr
= ldb_msg_find_attr_as_string(msg
, "name", NULL
);
833 el
= ldb_msg_find_element(msg
, "dnsRecord");
834 if (el
== NULL
|| el
->values
== 0) {
839 for (j
=0; j
<el
->num_values
; j
++) {
840 struct dnsp_DnssrvRpcRecord dnsp_rec
;
841 struct DNS_RPC_RECORD
*dns_rec
;
842 enum ndr_err_code ndr_err
;
844 ndr_err
= ndr_pull_struct_blob(&el
->values
[j
], mem_ctx
, &dnsp_rec
,
845 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
);
846 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
847 DEBUG(0, ("dnsserver: Unable to parse dns record (%s)", ldb_dn_get_linearized(msg
->dn
)));
848 return WERR_INTERNAL_DB_ERROR
;
851 /* Match the records based on search criteria */
852 if (record_type
== DNS_TYPE_ALL
|| dnsp_rec
.wType
== record_type
) {
855 if (select_flag
& DNS_RPC_VIEW_AUTHORITY_DATA
) {
856 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
858 } else if (dnsp_rec
.rank
== DNS_RANK_NS_GLUE
) {
860 * If branch_name is NULL, we're
861 * explicitly asked to also return
862 * DNS_RANK_NS_GLUE records
864 if (branch_name
== NULL
) {
869 if (select_flag
& DNS_RPC_VIEW_CACHE_DATA
) {
870 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
874 if (select_flag
& DNS_RPC_VIEW_GLUE_DATA
) {
875 if (dnsp_rec
.rank
== DNS_RANK_GLUE
) {
879 if (select_flag
& DNS_RPC_VIEW_ROOT_HINT_DATA
) {
880 if (dnsp_rec
.rank
== DNS_RANK_ROOT_HINT
) {
886 recs
->rec
[i
].records
= talloc_realloc(recs
,
887 recs
->rec
[i
].records
,
888 struct DNS_RPC_RECORD
,
889 recs
->rec
[i
].wRecordCount
+1);
890 if (recs
->rec
[i
].records
== NULL
) {
894 dns_rec
= &recs
->rec
[i
].records
[recs
->rec
[i
].wRecordCount
];
895 dnsp_to_dns_copy(recs
, &dnsp_rec
, dns_rec
);
897 /* Fix record flags */
898 if (strcmp(ptr
, "@") == 0) {
899 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
901 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
902 dns_rec
->dwFlags
|= DNS_RPC_FLAG_AUTH_ZONE_ROOT
;
906 if (dns_rec
->dwFlags
== DNS_RANK_NS_GLUE
) {
907 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
910 recs
->rec
[i
].wRecordCount
++;
912 dns_find_additional_names(mem_ctx
, &dnsp_rec
, add_names
, add_count
);
921 int dns_name_compare(const struct ldb_message
**m1
, const struct ldb_message
**m2
,
924 const char *name1
, *name2
;
925 const char *ptr1
, *ptr2
;
927 name1
= ldb_msg_find_attr_as_string(*m1
, "name", NULL
);
928 name2
= ldb_msg_find_attr_as_string(*m2
, "name", NULL
);
929 if (name1
== NULL
|| name2
== NULL
) {
933 /* '@' record and the search_name record gets preference */
934 if (name1
[0] == '@') {
937 if (search_name
&& strcasecmp(name1
, search_name
) == 0) {
941 if (name2
[0] == '@') {
944 if (search_name
&& strcasecmp(name2
, search_name
) == 0) {
948 /* Compare the last components of names.
949 * If search_name is not NULL, compare the second last components of names */
950 ptr1
= strrchr(name1
, '.');
954 if (search_name
&& strcasecmp(ptr1
+1, search_name
) == 0) {
956 while (ptr1
!= name1
) {
968 ptr2
= strrchr(name2
, '.');
972 if (search_name
&& strcasecmp(ptr2
+1, search_name
) == 0) {
974 while (ptr2
!= name2
) {
986 return strcasecmp(ptr1
, ptr2
);
990 bool dns_name_equal(const char *name1
, const char *name2
)
992 size_t len1
= strlen(name1
);
993 size_t len2
= strlen(name2
);
995 if (name1
[len1
-1] == '.') len1
--;
996 if (name2
[len2
-1] == '.') len2
--;
1000 return strncasecmp(name1
, name2
, len1
) == 0;
1004 bool dns_record_match(struct dnsp_DnssrvRpcRecord
*rec1
, struct dnsp_DnssrvRpcRecord
*rec2
)
1009 if (rec1
->wType
!= rec2
->wType
) {
1013 switch(rec1
->wType
) {
1014 case DNS_TYPE_TOMBSTONE
:
1018 return strcmp(rec1
->data
.ipv4
, rec2
->data
.ipv4
) == 0;
1021 return dns_name_equal(rec1
->data
.ns
, rec2
->data
.ns
);
1023 case DNS_TYPE_CNAME
:
1024 return dns_name_equal(rec1
->data
.cname
, rec2
->data
.cname
);
1027 return dns_name_equal(rec1
->data
.soa
.mname
, rec2
->data
.soa
.mname
) &&
1028 dns_name_equal(rec1
->data
.soa
.rname
, rec2
->data
.soa
.rname
) &&
1029 rec1
->data
.soa
.serial
== rec2
->data
.soa
.serial
&&
1030 rec1
->data
.soa
.refresh
== rec2
->data
.soa
.refresh
&&
1031 rec1
->data
.soa
.retry
== rec2
->data
.soa
.retry
&&
1032 rec1
->data
.soa
.expire
== rec2
->data
.soa
.expire
&&
1033 rec1
->data
.soa
.minimum
== rec2
->data
.soa
.minimum
;
1036 return dns_name_equal(rec1
->data
.ptr
, rec2
->data
.ptr
);
1039 return rec1
->data
.mx
.wPriority
== rec2
->data
.mx
.wPriority
&&
1040 dns_name_equal(rec1
->data
.mx
.nameTarget
, rec2
->data
.mx
.nameTarget
);
1043 if (rec1
->data
.txt
.count
!= rec2
->data
.txt
.count
) {
1047 for (i
=0; i
<rec1
->data
.txt
.count
; i
++) {
1048 status
= status
&& (strcmp(rec1
->data
.txt
.str
[i
],
1049 rec2
->data
.txt
.str
[i
]) == 0);
1054 return strcmp(rec1
->data
.ipv6
, rec2
->data
.ipv6
) == 0;
1057 return rec1
->data
.srv
.wPriority
== rec2
->data
.srv
.wPriority
&&
1058 rec1
->data
.srv
.wWeight
== rec2
->data
.srv
.wWeight
&&
1059 rec1
->data
.srv
.wPort
== rec2
->data
.srv
.wPort
&&
1060 dns_name_equal(rec1
->data
.srv
.nameTarget
, rec2
->data
.srv
.nameTarget
);
1063 DEBUG(0, ("dnsserver: unhandled record type %u", rec1
->wType
));