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 "dns_server/dnsserver_common.h"
25 #include "lib/replace/system/network.h"
26 #include "librpc/gen_ndr/ndr_dnsp.h"
27 #include "librpc/gen_ndr/ndr_dnsserver.h"
31 struct IP4_ARRAY
*ip4_array_copy(TALLOC_CTX
*mem_ctx
, struct IP4_ARRAY
*ip4
)
33 struct IP4_ARRAY
*ret
;
39 ret
= talloc_zero(mem_ctx
, struct IP4_ARRAY
);
44 ret
->AddrCount
= ip4
->AddrCount
;
45 if (ip4
->AddrCount
> 0) {
46 ret
->AddrArray
= talloc_zero_array(mem_ctx
, unsigned int, ip4
->AddrCount
);
48 memcpy(ret
->AddrArray
, ip4
->AddrArray
,
49 sizeof(unsigned int) * ip4
->AddrCount
);
59 struct DNS_ADDR_ARRAY
*ip4_array_to_dns_addr_array(TALLOC_CTX
*mem_ctx
,
60 struct IP4_ARRAY
*ip4
)
62 struct DNS_ADDR_ARRAY
*ret
;
69 ret
= talloc_zero(mem_ctx
, struct DNS_ADDR_ARRAY
);
74 ret
->MaxCount
= ip4
->AddrCount
;
75 ret
->AddrCount
= ip4
->AddrCount
;
76 ret
->Family
= AF_INET
;
77 if (ip4
->AddrCount
> 0) {
78 ret
->AddrArray
= talloc_zero_array(mem_ctx
, struct DNS_ADDR
, ip4
->AddrCount
);
80 for (i
=0; i
<ip4
->AddrCount
; i
++) {
81 ret
->AddrArray
[i
].MaxSa
[0] = 0x02;
82 ret
->AddrArray
[i
].MaxSa
[3] = 53;
83 memcpy(&ret
->AddrArray
[i
].MaxSa
[4], ip4
->AddrArray
,
84 sizeof(unsigned int));
85 ret
->AddrArray
[i
].DnsAddrUserDword
[0] = 6;
96 struct IP4_ARRAY
*dns_addr_array_to_ip4_array(TALLOC_CTX
*mem_ctx
,
97 struct DNS_ADDR_ARRAY
*ip
)
99 struct IP4_ARRAY
*ret
;
100 size_t i
, count
, curr
;
105 /* We must only return IPv4 addresses.
106 The passed DNS_ADDR_ARRAY may contain:
107 - only ipv4 addresses
108 - only ipv6 addresses
112 ret
= talloc_zero(mem_ctx
, struct IP4_ARRAY
);
116 if (ip
->AddrCount
== 0 || ip
->Family
== AF_INET6
) {
120 /* Now only ipv4 addresses or a mixture are left */
122 for (i
= 0; i
< ip
->AddrCount
; i
++) {
123 if (ip
->AddrArray
[i
].MaxSa
[0] == 0x02) {
129 /* should not happen */
133 ret
->AddrArray
= talloc_zero_array(mem_ctx
, uint32_t, count
);
134 if (ret
->AddrArray
) {
136 for (i
= 0; i
< ip
->AddrCount
; i
++) {
137 if (ip
->AddrArray
[i
].MaxSa
[0] == 0x02) {
139 memcpy(&ret
->AddrArray
[curr
],
140 &ip
->AddrArray
[i
].MaxSa
[4],
149 ret
->AddrCount
= curr
;
153 struct DNS_ADDR_ARRAY
*dns_addr_array_copy(TALLOC_CTX
*mem_ctx
,
154 struct DNS_ADDR_ARRAY
*addr
)
156 struct DNS_ADDR_ARRAY
*ret
;
162 ret
= talloc_zero(mem_ctx
, struct DNS_ADDR_ARRAY
);
167 ret
->MaxCount
= addr
->MaxCount
;
168 ret
->AddrCount
= addr
->AddrCount
;
169 ret
->Family
= addr
->Family
;
170 if (addr
->AddrCount
> 0) {
171 ret
->AddrArray
= talloc_zero_array(mem_ctx
, struct DNS_ADDR
, addr
->AddrCount
);
172 if (ret
->AddrArray
) {
173 memcpy(ret
->AddrArray
, addr
->AddrArray
,
174 sizeof(struct DNS_ADDR
) * addr
->AddrCount
);
184 int dns_split_name_components(TALLOC_CTX
*tmp_ctx
, const char *name
, char ***components
)
186 char *str
= NULL
, *ptr
, **list
;
193 str
= talloc_strdup(tmp_ctx
, name
);
198 list
= talloc_zero_array(tmp_ctx
, char *, 0);
203 ptr
= strtok(str
, ".");
204 while (ptr
!= NULL
) {
206 list
= talloc_realloc(tmp_ctx
, list
, char *, count
);
210 list
[count
-1] = talloc_strdup(tmp_ctx
, ptr
);
211 if (list
[count
-1] == NULL
) {
214 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
.EntombedTime
= dnsp
->data
.EntombedTime
;
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_RECORD_DATA
));
410 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d\n", dnsp
->wType
));
415 WERROR
dns_to_dnsp_convert(TALLOC_CTX
*mem_ctx
, struct DNS_RPC_RECORD
*dns
,
416 struct dnsp_DnssrvRpcRecord
**out_dnsp
, bool check_name
)
421 char *talloc_res
= NULL
;
422 struct dnsp_DnssrvRpcRecord
*dnsp
= NULL
;
424 dnsp
= talloc_zero(mem_ctx
, struct dnsp_DnssrvRpcRecord
);
426 return WERR_NOT_ENOUGH_MEMORY
;
429 dnsp
->wDataLength
= dns
->wDataLength
;
430 dnsp
->wType
= dns
->wType
;
432 dnsp
->rank
= dns
->dwFlags
& 0x000000FF;
433 dnsp
->dwSerial
= dns
->dwSerial
;
434 dnsp
->dwTtlSeconds
= dns
->dwTtlSeconds
;
435 dnsp
->dwTimeStamp
= dns
->dwTimeStamp
;
437 switch (dns
->wType
) {
439 case DNS_TYPE_TOMBSTONE
:
440 dnsp
->data
.EntombedTime
= dns
->data
.EntombedTime
;
444 talloc_res
= talloc_strdup(mem_ctx
, dns
->data
.ipv4
);
445 if (talloc_res
== NULL
) {
448 dnsp
->data
.ipv4
= talloc_res
;
452 name
= dns
->data
.name
.str
;
453 len
= dns
->data
.name
.len
;
456 res
= dns_name_check(mem_ctx
, len
, name
);
457 if (!W_ERROR_IS_OK(res
)) {
462 if (len
> 0 && name
[len
-1] == '.') {
463 talloc_res
= talloc_strndup(mem_ctx
, name
, len
-1);
464 if (talloc_res
== NULL
) {
467 dnsp
->data
.ns
= talloc_res
;
469 talloc_res
= talloc_strdup(mem_ctx
, name
);
470 if (talloc_res
== NULL
) {
473 dnsp
->data
.ns
= talloc_res
;
479 name
= dns
->data
.name
.str
;
480 len
= dns
->data
.name
.len
;
483 res
= dns_name_check(mem_ctx
, len
, name
);
484 if (!W_ERROR_IS_OK(res
)) {
489 if (len
> 0 && name
[len
-1] == '.') {
490 talloc_res
= talloc_strndup(mem_ctx
, name
, len
-1);
491 if (talloc_res
== NULL
) {
494 dnsp
->data
.cname
= talloc_res
;
496 talloc_res
= talloc_strdup(mem_ctx
, name
);
497 if (talloc_res
== NULL
) {
500 dnsp
->data
.cname
= talloc_res
;
506 dnsp
->data
.soa
.serial
= dns
->data
.soa
.dwSerialNo
;
507 dnsp
->data
.soa
.refresh
= dns
->data
.soa
.dwRefresh
;
508 dnsp
->data
.soa
.retry
= dns
->data
.soa
.dwRetry
;
509 dnsp
->data
.soa
.expire
= dns
->data
.soa
.dwExpire
;
510 dnsp
->data
.soa
.minimum
= dns
->data
.soa
.dwMinimumTtl
;
512 name
= dns
->data
.soa
.NamePrimaryServer
.str
;
513 len
= dns
->data
.soa
.NamePrimaryServer
.len
;
516 res
= dns_name_check(mem_ctx
, len
, name
);
517 if (!W_ERROR_IS_OK(res
)) {
522 if (len
> 0 && name
[len
-1] == '.') {
523 talloc_res
= talloc_strndup(mem_ctx
, name
, len
-1);
524 if (talloc_res
== NULL
) {
527 dnsp
->data
.soa
.mname
= talloc_res
;
529 talloc_res
= talloc_strdup(mem_ctx
, name
);
530 if (talloc_res
== NULL
) {
533 dnsp
->data
.soa
.mname
= talloc_res
;
536 name
= dns
->data
.soa
.ZoneAdministratorEmail
.str
;
537 len
= dns
->data
.soa
.ZoneAdministratorEmail
.len
;
539 res
= dns_name_check(mem_ctx
, len
, name
);
540 if (!W_ERROR_IS_OK(res
)) {
544 if (len
> 0 && name
[len
-1] == '.') {
545 talloc_res
= talloc_strndup(mem_ctx
, name
, len
-1);
546 if (talloc_res
== NULL
) {
549 dnsp
->data
.soa
.rname
= talloc_res
;
551 talloc_res
= talloc_strdup(mem_ctx
, name
);
552 if (talloc_res
== NULL
) {
555 dnsp
->data
.soa
.rname
= talloc_res
;
561 name
= dns
->data
.ptr
.str
;
562 len
= dns
->data
.ptr
.len
;
565 res
= dns_name_check(mem_ctx
, len
, name
);
566 if (!W_ERROR_IS_OK(res
)) {
571 talloc_res
= talloc_strdup(mem_ctx
, name
);
572 if (talloc_res
== NULL
) {
575 dnsp
->data
.ptr
= talloc_res
;
580 dnsp
->data
.mx
.wPriority
= dns
->data
.mx
.wPreference
;
582 name
= dns
->data
.mx
.nameExchange
.str
;
583 len
= dns
->data
.mx
.nameExchange
.len
;
586 res
= dns_name_check(mem_ctx
, len
, name
);
587 if (!W_ERROR_IS_OK(res
)) {
592 if (len
> 0 && name
[len
-1] == '.') {
593 talloc_res
= talloc_strndup(mem_ctx
, name
, len
-1);
594 if (talloc_res
== NULL
) {
597 dnsp
->data
.mx
.nameTarget
= talloc_res
;
599 talloc_res
= talloc_strdup(mem_ctx
, name
);
600 if (talloc_res
== NULL
) {
603 dnsp
->data
.mx
.nameTarget
= talloc_res
;
609 dnsp
->data
.txt
.count
= dns
->data
.txt
.count
;
610 dnsp
->data
.txt
.str
= talloc_array(mem_ctx
, const char *, dns
->data
.txt
.count
);
611 for (i
=0; i
<dns
->data
.txt
.count
; i
++) {
612 talloc_res
= talloc_strdup(mem_ctx
, dns
->data
.txt
.str
[i
].str
);
613 if (talloc_res
== NULL
) {
616 dnsp
->data
.txt
.str
[i
] = talloc_res
;
621 dnsp
->data
.ipv6
= talloc_strdup(mem_ctx
, dns
->data
.ipv6
);
625 dnsp
->data
.srv
.wPriority
= dns
->data
.srv
.wPriority
;
626 dnsp
->data
.srv
.wWeight
= dns
->data
.srv
.wWeight
;
627 dnsp
->data
.srv
.wPort
= dns
->data
.srv
.wPort
;
629 name
= dns
->data
.srv
.nameTarget
.str
;
630 len
= dns
->data
.srv
.nameTarget
.len
;
633 res
= dns_name_check(mem_ctx
, len
, name
);
634 if (!W_ERROR_IS_OK(res
)) {
639 if (len
> 0 && name
[len
-1] == '.') {
640 talloc_res
= talloc_strndup(mem_ctx
, name
, len
-1);
641 if (talloc_res
== NULL
) {
644 dnsp
->data
.srv
.nameTarget
= talloc_res
;
646 talloc_res
= talloc_strdup(mem_ctx
, name
);
647 if (talloc_res
== NULL
) {
650 dnsp
->data
.srv
.nameTarget
= talloc_res
;
656 memcpy(&dnsp
->data
, &dns
->data
, sizeof(union dnsRecordData
));
657 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d\n", dns
->wType
));
664 return WERR_NOT_ENOUGH_MEMORY
;
667 /* Initialize tree with given name as the root */
668 static struct dns_tree
*dns_tree_init(TALLOC_CTX
*mem_ctx
, const char *name
, void *data
)
670 struct dns_tree
*tree
;
672 tree
= talloc_zero(mem_ctx
, struct dns_tree
);
677 tree
->name
= talloc_strdup(tree
, name
);
678 if (tree
->name
== NULL
) {
689 /* Add a child one level below */
690 static struct dns_tree
*dns_tree_add(struct dns_tree
*tree
, const char *name
, void *data
)
692 struct dns_tree
*node
;
694 node
= talloc_zero(tree
, struct dns_tree
);
699 node
->name
= talloc_strdup(tree
, name
);
700 if (node
->name
== NULL
) {
704 node
->level
= tree
->level
+ 1;
705 node
->num_children
= 0;
706 node
->children
= NULL
;
709 if (tree
->num_children
== 0) {
710 tree
->children
= talloc_zero(tree
, struct dns_tree
*);
712 tree
->children
= talloc_realloc(tree
, tree
->children
, struct dns_tree
*,
713 tree
->num_children
+1);
715 if (tree
->children
== NULL
) {
719 tree
->children
[tree
->num_children
] = node
;
720 tree
->num_children
++;
725 /* Find a node that matches the name components */
726 static struct dns_tree
*dns_tree_find(struct dns_tree
*tree
, int ncount
, char **nlist
, int *match_count
)
728 struct dns_tree
*node
, *next
;
733 if (strcmp(tree
->name
, "@") == 0) {
736 if (strcasecmp(tree
->name
, nlist
[ncount
-1]) != 0) {
744 for (i
=start
; i
<ncount
; i
++) {
745 if (node
->num_children
== 0) {
749 for (j
=0; j
<node
->num_children
; j
++) {
750 if (strcasecmp(nlist
[(ncount
-1)-i
], node
->children
[j
]->name
) == 0) {
751 next
= node
->children
[j
];
766 /* Build a 2-level tree for resulting dns names */
767 struct dns_tree
*dns_build_tree(TALLOC_CTX
*mem_ctx
, const char *name
, struct ldb_result
*res
)
769 struct dns_tree
*root
, *base
, *tree
, *node
;
771 int rootcount
, ncount
;
773 int i
, level
, match_count
;
775 rootcount
= dns_split_name_components(mem_ctx
, name
, &nlist
);
776 if (rootcount
<= 0) {
780 root
= dns_tree_init(mem_ctx
, nlist
[rootcount
-1], NULL
);
787 for (i
=rootcount
-2; i
>=0; i
--) {
788 tree
= dns_tree_add(tree
, nlist
[i
], NULL
);
796 /* Add all names in the result in a tree */
797 for (i
=0; i
<res
->count
; i
++) {
798 ptr
= ldb_msg_find_attr_as_string(res
->msgs
[i
], "name", NULL
);
800 DBG_ERR("dnsserver: dns record has no name (%s)\n",
801 ldb_dn_get_linearized(res
->msgs
[i
]->dn
));
806 * This might be the sub-domain in the zone being
807 * requested, or @ for the root of the zone
809 if (strcasecmp(ptr
, name
) == 0) {
810 base
->data
= res
->msgs
[i
];
814 ncount
= dns_split_name_components(root
, ptr
, &nlist
);
819 /* Find matching node */
820 tree
= dns_tree_find(root
, ncount
, nlist
, &match_count
);
825 /* If the node is on leaf, then add record data */
826 if (match_count
+1 == ncount
) {
827 tree
->data
= res
->msgs
[i
];
830 /* Add missing name components */
831 for (level
=match_count
+1; level
<ncount
; level
++) {
832 if (tree
->level
== rootcount
+1) {
835 if (level
== ncount
-1) {
836 node
= dns_tree_add(tree
, nlist
[(ncount
-1)-level
], res
->msgs
[i
]);
838 node
= dns_tree_add(tree
, nlist
[(ncount
-1)-level
], NULL
);
849 /* Mark the base record, so it can be found easily */
861 static void _dns_add_name(TALLOC_CTX
*mem_ctx
, const char *name
, char ***add_names
, int *add_count
)
864 char **ptr
= *add_names
;
865 int count
= *add_count
;
867 for (i
=0; i
<count
; i
++) {
868 if (strcasecmp(ptr
[i
], name
) == 0) {
873 ptr
= talloc_realloc(mem_ctx
, ptr
, char *, count
+1);
878 ptr
[count
] = talloc_strdup(mem_ctx
, name
);
879 if (ptr
[count
] == NULL
) {
885 *add_count
= count
+1;
889 static void dns_find_additional_names(TALLOC_CTX
*mem_ctx
, struct dnsp_DnssrvRpcRecord
*rec
, char ***add_names
, int *add_count
)
891 if (add_names
== NULL
) {
895 switch (rec
->wType
) {
898 _dns_add_name(mem_ctx
, rec
->data
.ns
, add_names
, add_count
);
902 _dns_add_name(mem_ctx
, rec
->data
.cname
, add_names
, add_count
);
906 _dns_add_name(mem_ctx
, rec
->data
.soa
.mname
, add_names
, add_count
);
910 _dns_add_name(mem_ctx
, rec
->data
.mx
.nameTarget
, add_names
, add_count
);
914 _dns_add_name(mem_ctx
, rec
->data
.srv
.nameTarget
, add_names
, add_count
);
923 WERROR
dns_fill_records_array(TALLOC_CTX
*mem_ctx
,
924 struct dnsserver_zone
*z
,
925 enum dns_record_type record_type
,
926 unsigned int select_flag
,
927 const char *branch_name
,
928 struct ldb_message
*msg
,
930 struct DNS_RPC_RECORDS_ARRAY
*recs
,
934 struct ldb_message_element
*el
;
939 if (recs
->count
== 0) {
940 recs
->rec
= talloc_zero(recs
, struct DNS_RPC_RECORDS
);
942 recs
->rec
= talloc_realloc(recs
, recs
->rec
, struct DNS_RPC_RECORDS
, recs
->count
+1);
944 if (recs
->rec
== NULL
) {
945 return WERR_NOT_ENOUGH_MEMORY
;
948 recs
->rec
[i
].wLength
= 0;
949 recs
->rec
[i
].wRecordCount
= 0;
950 recs
->rec
[i
].dwChildCount
= num_children
;
951 recs
->rec
[i
].dwFlags
= 0;
953 /* The base records returned with empty name */
954 /* Children records returned with names */
955 if (branch_name
== NULL
) {
956 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, "");
957 recs
->rec
[i
].dnsNodeName
.len
= 0;
959 recs
->rec
[i
].dnsNodeName
.str
= talloc_strdup(recs
, branch_name
);
960 recs
->rec
[i
].dnsNodeName
.len
= strlen(branch_name
);
962 recs
->rec
[i
].records
= talloc_zero_array(recs
, struct DNS_RPC_RECORD
, 0);
965 /* Allow empty records */
970 /* Do not return RR records, if the node has children */
971 if (branch_name
!= NULL
&& num_children
> 0) {
975 ptr
= ldb_msg_find_attr_as_string(msg
, "name", NULL
);
977 DBG_ERR("dnsserver: dns record has no name (%s)\n",
978 ldb_dn_get_linearized(msg
->dn
));
979 return WERR_INTERNAL_DB_ERROR
;
982 el
= ldb_msg_find_element(msg
, "dnsRecord");
983 if (el
== NULL
|| el
->values
== 0) {
988 for (j
=0; j
<el
->num_values
; j
++) {
989 struct dnsp_DnssrvRpcRecord dnsp_rec
;
990 struct DNS_RPC_RECORD
*dns_rec
;
991 enum ndr_err_code ndr_err
;
993 ndr_err
= ndr_pull_struct_blob(&el
->values
[j
], mem_ctx
, &dnsp_rec
,
994 (ndr_pull_flags_fn_t
)ndr_pull_dnsp_DnssrvRpcRecord
);
995 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
996 DEBUG(0, ("dnsserver: Unable to parse dns record (%s)\n", ldb_dn_get_linearized(msg
->dn
)));
997 return WERR_INTERNAL_DB_ERROR
;
1000 /* Match the records based on search criteria */
1001 if (record_type
== DNS_TYPE_ALL
|| dnsp_rec
.wType
== record_type
) {
1004 if (select_flag
& DNS_RPC_VIEW_AUTHORITY_DATA
) {
1005 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
1007 } else if (dnsp_rec
.rank
== DNS_RANK_NS_GLUE
) {
1009 * If branch_name is NULL, we're
1010 * explicitly asked to also return
1011 * DNS_RANK_NS_GLUE records
1013 if (branch_name
== NULL
) {
1018 if (select_flag
& DNS_RPC_VIEW_CACHE_DATA
) {
1019 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
1023 if (select_flag
& DNS_RPC_VIEW_GLUE_DATA
) {
1024 if (dnsp_rec
.rank
== DNS_RANK_GLUE
) {
1028 if (select_flag
& DNS_RPC_VIEW_ROOT_HINT_DATA
) {
1029 if (dnsp_rec
.rank
== DNS_RANK_ROOT_HINT
) {
1035 recs
->rec
[i
].records
= talloc_realloc(recs
,
1036 recs
->rec
[i
].records
,
1037 struct DNS_RPC_RECORD
,
1038 recs
->rec
[i
].wRecordCount
+1);
1039 if (recs
->rec
[i
].records
== NULL
) {
1040 return WERR_NOT_ENOUGH_MEMORY
;
1043 dns_rec
= &recs
->rec
[i
].records
[recs
->rec
[i
].wRecordCount
];
1044 dnsp_to_dns_copy(recs
, &dnsp_rec
, dns_rec
);
1046 /* Fix record flags */
1047 if (strcmp(ptr
, "@") == 0) {
1048 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
1050 if (dnsp_rec
.rank
== DNS_RANK_ZONE
) {
1051 dns_rec
->dwFlags
|= DNS_RPC_FLAG_AUTH_ZONE_ROOT
;
1055 if (dns_rec
->dwFlags
== DNS_RANK_NS_GLUE
) {
1056 dns_rec
->dwFlags
|= DNS_RPC_FLAG_ZONE_ROOT
;
1059 recs
->rec
[i
].wRecordCount
++;
1061 dns_find_additional_names(mem_ctx
, &dnsp_rec
, add_names
, add_count
);
1070 int dns_name_compare(struct ldb_message
* const *m1
, struct ldb_message
* const *m2
,
1071 const char *search_name
)
1073 const char *name1
, *name2
;
1074 const char *ptr1
, *ptr2
;
1076 name1
= ldb_msg_find_attr_as_string(*m1
, "name", NULL
);
1077 name2
= ldb_msg_find_attr_as_string(*m2
, "name", NULL
);
1079 * We sort NULL names to the start of the list, because the only
1080 * caller of this function, dnsserver_enumerate_records() will call
1081 * dns_build_tree() with the sorted list, which will always return an
1082 * error when it hits a NULL, so we might as well make that happen
1085 if (name1
== name2
) {
1086 /* this includes the both NULL case */
1089 if (name1
== NULL
) {
1092 if (name2
== NULL
) {
1096 /* Compare the last components of names.
1097 * If search_name is not NULL, compare the second last components of names */
1098 ptr1
= strrchr(name1
, '.');
1102 if (search_name
&& strcasecmp(ptr1
+1, search_name
) == 0) {
1104 while (ptr1
!= name1
) {
1116 ptr2
= strrchr(name2
, '.');
1120 if (search_name
&& strcasecmp(ptr2
+1, search_name
) == 0) {
1122 while (ptr2
!= name2
) {
1134 return strcasecmp(ptr1
, ptr2
);