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"
30 struct IP4_ARRAY *ip4_array_copy(TALLOC_CTX *mem_ctx, struct IP4_ARRAY *ip4)
32 struct IP4_ARRAY *ret;
38 ret = talloc_zero(mem_ctx, struct IP4_ARRAY);
43 ret->AddrCount = ip4->AddrCount;
44 if (ip4->AddrCount > 0) {
45 ret->AddrArray = talloc_zero_array(mem_ctx, unsigned int, ip4->AddrCount);
47 memcpy(ret->AddrArray, ip4->AddrArray,
48 sizeof(unsigned int) * ip4->AddrCount);
58 struct DNS_ADDR_ARRAY *ip4_array_to_dns_addr_array(TALLOC_CTX *mem_ctx,
59 struct IP4_ARRAY *ip4)
61 struct DNS_ADDR_ARRAY *ret;
68 ret = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY);
73 ret->MaxCount = ip4->AddrCount;
74 ret->AddrCount = ip4->AddrCount;
75 ret->Family = AF_INET;
76 if (ip4->AddrCount > 0) {
77 ret->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR, ip4->AddrCount);
79 for (i=0; i<ip4->AddrCount; i++) {
80 ret->AddrArray[i].MaxSa[0] = 0x02;
81 ret->AddrArray[i].MaxSa[3] = 53;
82 memcpy(&ret->AddrArray[i].MaxSa[4], ip4->AddrArray,
83 sizeof(unsigned int));
84 ret->AddrArray[i].DnsAddrUserDword[0] = 6;
95 struct IP4_ARRAY *dns_addr_array_to_ip4_array(TALLOC_CTX *mem_ctx,
96 struct DNS_ADDR_ARRAY *ip)
98 struct IP4_ARRAY *ret;
99 size_t i, count, curr;
104 /* We must only return IPv4 addresses.
105 The passed DNS_ADDR_ARRAY may contain:
106 - only ipv4 addresses
107 - only ipv6 addresses
111 ret = talloc_zero(mem_ctx, struct IP4_ARRAY);
115 if (ip->AddrCount == 0 || ip->Family == AF_INET6) {
119 /* Now only ipv4 addresses or a mixture are left */
121 for (i = 0; i < ip->AddrCount; i++) {
122 if (ip->AddrArray[i].MaxSa[0] == 0x02) {
128 /* should not happen */
132 ret->AddrArray = talloc_zero_array(mem_ctx, uint32_t, count);
133 if (ret->AddrArray) {
135 for (i = 0; i < ip->AddrCount; i++) {
136 if (ip->AddrArray[i].MaxSa[0] == 0x02) {
138 memcpy(&ret->AddrArray[curr],
139 &ip->AddrArray[i].MaxSa[4],
148 ret->AddrCount = curr;
152 struct DNS_ADDR_ARRAY *dns_addr_array_copy(TALLOC_CTX *mem_ctx,
153 struct DNS_ADDR_ARRAY *addr)
155 struct DNS_ADDR_ARRAY *ret;
161 ret = talloc_zero(mem_ctx, struct DNS_ADDR_ARRAY);
166 ret->MaxCount = addr->MaxCount;
167 ret->AddrCount = addr->AddrCount;
168 ret->Family = addr->Family;
169 if (addr->AddrCount > 0) {
170 ret->AddrArray = talloc_zero_array(mem_ctx, struct DNS_ADDR, addr->AddrCount);
171 if (ret->AddrArray) {
172 memcpy(ret->AddrArray, addr->AddrArray,
173 sizeof(struct DNS_ADDR) * addr->AddrCount);
183 int dns_split_name_components(TALLOC_CTX *tmp_ctx, const char *name, char ***components)
185 char *str = NULL, *ptr, **list;
192 str = talloc_strdup(tmp_ctx, name);
197 list = talloc_zero_array(tmp_ctx, char *, 0);
202 ptr = strtok(str, ".");
203 while (ptr != NULL) {
205 list = talloc_realloc(tmp_ctx, list, char *, count);
209 list[count-1] = talloc_strdup(tmp_ctx, ptr);
210 if (list[count-1] == NULL) {
213 ptr = strtok(NULL, ".");
227 char *dns_split_node_name(TALLOC_CTX *tmp_ctx, const char *node_name, const char *zone_name)
229 char **nlist, **zlist;
231 int ncount, zcount, i, match;
234 * If node_name is "@", return the zone_name
235 * If node_name is ".", return NULL
236 * If there is no '.' in node_name, return the node_name as is.
238 * If node_name does not have zone_name in it, return the node_name as is.
240 * If node_name has additional components as compared to zone_name
241 * return only the additional components as a prefix.
244 if (strcmp(node_name, "@") == 0) {
245 prefix = talloc_strdup(tmp_ctx, zone_name);
246 } else if (strcmp(node_name, ".") == 0) {
248 } else if (strchr(node_name, '.') == NULL) {
249 prefix = talloc_strdup(tmp_ctx, node_name);
251 zcount = dns_split_name_components(tmp_ctx, zone_name, &zlist);
252 ncount = dns_split_name_components(tmp_ctx, node_name, &nlist);
253 if (zcount < 0 || ncount < 0) {
257 if (ncount < zcount) {
258 prefix = talloc_strdup(tmp_ctx, node_name);
261 for (i=1; i<=zcount; i++) {
262 if (strcasecmp(nlist[ncount-i], zlist[zcount-i]) != 0) {
268 if (match == ncount) {
269 prefix = talloc_strdup(tmp_ctx, zone_name);
271 prefix = talloc_strdup(tmp_ctx, nlist[0]);
272 if (prefix != NULL) {
273 for (i=1; i<ncount-match; i++) {
274 prefix = talloc_asprintf_append(prefix, ".%s", nlist[i]);
275 if (prefix == NULL) {
291 void dnsp_to_dns_copy(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *dnsp,
292 struct DNS_RPC_RECORD *dns)
298 dns->wDataLength = dnsp->wDataLength;
299 dns->wType = dnsp->wType;
300 dns->dwFlags = dnsp->rank;
301 dns->dwSerial = dnsp->dwSerial;
302 dns->dwTtlSeconds = dnsp->dwTtlSeconds;
303 dns->dwTimeStamp = dnsp->dwTimeStamp;
305 switch (dnsp->wType) {
307 case DNS_TYPE_TOMBSTONE:
308 dns->data.timestamp = dnsp->data.timestamp;
312 dns->data.ipv4 = talloc_strdup(mem_ctx, dnsp->data.ipv4);
316 len = strlen(dnsp->data.ns);
317 if (dnsp->data.ns[len-1] == '.') {
318 dns->data.name.len = len;
319 dns->data.name.str = talloc_strdup(mem_ctx, dnsp->data.ns);
321 dns->data.name.len = len+1;
322 dns->data.name.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.ns);
327 len = strlen(dnsp->data.cname);
328 if (dnsp->data.cname[len-1] == '.') {
329 dns->data.name.len = len;
330 dns->data.name.str = talloc_strdup(mem_ctx, dnsp->data.cname);
332 dns->data.name.len = len+1;
333 dns->data.name.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.cname);
338 dns->data.soa.dwSerialNo = dnsp->data.soa.serial;
339 dns->data.soa.dwRefresh = dnsp->data.soa.refresh;
340 dns->data.soa.dwRetry = dnsp->data.soa.retry;
341 dns->data.soa.dwExpire = dnsp->data.soa.expire;
342 dns->data.soa.dwMinimumTtl = dnsp->data.soa.minimum;
344 len = strlen(dnsp->data.soa.mname);
345 if (dnsp->data.soa.mname[len-1] == '.') {
346 dns->data.soa.NamePrimaryServer.len = len;
347 dns->data.soa.NamePrimaryServer.str = talloc_strdup(mem_ctx, dnsp->data.soa.mname);
349 dns->data.soa.NamePrimaryServer.len = len+1;
350 dns->data.soa.NamePrimaryServer.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.soa.mname);
353 len = strlen(dnsp->data.soa.rname);
354 if (dnsp->data.soa.rname[len-1] == '.') {
355 dns->data.soa.ZoneAdministratorEmail.len = len;
356 dns->data.soa.ZoneAdministratorEmail.str = talloc_strdup(mem_ctx, dnsp->data.soa.rname);
358 dns->data.soa.ZoneAdministratorEmail.len = len+1;
359 dns->data.soa.ZoneAdministratorEmail.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.soa.rname);
364 dns->data.ptr.len = strlen(dnsp->data.ptr);
365 dns->data.ptr.str = talloc_strdup(mem_ctx, dnsp->data.ptr);
369 dns->data.mx.wPreference = dnsp->data.mx.wPriority;
370 len = strlen(dnsp->data.mx.nameTarget);
371 if (dnsp->data.mx.nameTarget[len-1] == '.') {
372 dns->data.mx.nameExchange.len = len;
373 dns->data.mx.nameExchange.str = talloc_strdup(mem_ctx, dnsp->data.mx.nameTarget);
375 dns->data.mx.nameExchange.len = len+1;
376 dns->data.mx.nameExchange.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.mx.nameTarget);
381 dns->data.txt.count = dnsp->data.txt.count;
382 dns->data.txt.str = talloc_array(mem_ctx, struct DNS_RPC_NAME, dnsp->data.txt.count);
383 for (i=0; i<dnsp->data.txt.count; i++) {
384 dns->data.txt.str[i].str = talloc_strdup(mem_ctx, dnsp->data.txt.str[i]);
385 dns->data.txt.str[i].len = strlen(dnsp->data.txt.str[i]);
390 dns->data.ipv6 = talloc_strdup(mem_ctx, dnsp->data.ipv6);
394 dns->data.srv.wPriority = dnsp->data.srv.wPriority;
395 dns->data.srv.wWeight = dnsp->data.srv.wWeight;
396 dns->data.srv.wPort = dnsp->data.srv.wPort;
397 len = strlen(dnsp->data.srv.nameTarget);
398 if (dnsp->data.srv.nameTarget[len-1] == '.') {
399 dns->data.srv.nameTarget.len = len;
400 dns->data.srv.nameTarget.str = talloc_strdup(mem_ctx, dnsp->data.srv.nameTarget);
402 dns->data.srv.nameTarget.len = len+1;
403 dns->data.srv.nameTarget.str = talloc_asprintf(mem_ctx, "%s.", dnsp->data.srv.nameTarget);
408 memcpy(&dns->data, &dnsp->data, sizeof(union DNS_RPC_DATA));
409 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dnsp->wType));
414 WERROR dns_to_dnsp_convert(TALLOC_CTX *mem_ctx, struct DNS_RPC_RECORD *dns,
415 struct dnsp_DnssrvRpcRecord **out_dnsp, bool check_name)
420 char *talloc_res = NULL;
421 struct dnsp_DnssrvRpcRecord *dnsp = NULL;
423 dnsp = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
425 return WERR_NOT_ENOUGH_MEMORY;
428 dnsp->wDataLength = dns->wDataLength;
429 dnsp->wType = dns->wType;
431 dnsp->rank = dns->dwFlags & 0x000000FF;
432 dnsp->dwSerial = dns->dwSerial;
433 dnsp->dwTtlSeconds = dns->dwTtlSeconds;
434 dnsp->dwTimeStamp = dns->dwTimeStamp;
436 switch (dns->wType) {
438 case DNS_TYPE_TOMBSTONE:
439 dnsp->data.timestamp = dns->data.timestamp;
443 talloc_res = talloc_strdup(mem_ctx, dns->data.ipv4);
444 if (talloc_res == NULL) {
447 dnsp->data.ipv4 = talloc_res;
451 name = dns->data.name.str;
452 len = dns->data.name.len;
455 res = dns_name_check(mem_ctx, len, name);
456 if (!W_ERROR_IS_OK(res)) {
461 if (len > 0 && name[len-1] == '.') {
462 talloc_res = talloc_strndup(mem_ctx, name, len-1);
463 if (talloc_res == NULL) {
466 dnsp->data.ns = talloc_res;
468 talloc_res = talloc_strdup(mem_ctx, name);
469 if (talloc_res == NULL) {
472 dnsp->data.ns = talloc_res;
478 name = dns->data.name.str;
479 len = dns->data.name.len;
482 res = dns_name_check(mem_ctx, len, name);
483 if (!W_ERROR_IS_OK(res)) {
488 if (len > 0 && name[len-1] == '.') {
489 talloc_res = talloc_strndup(mem_ctx, name, len-1);
490 if (talloc_res == NULL) {
493 dnsp->data.cname = talloc_res;
495 talloc_res = talloc_strdup(mem_ctx, name);
496 if (talloc_res == NULL) {
499 dnsp->data.cname = talloc_res;
505 dnsp->data.soa.serial = dns->data.soa.dwSerialNo;
506 dnsp->data.soa.refresh = dns->data.soa.dwRefresh;
507 dnsp->data.soa.retry = dns->data.soa.dwRetry;
508 dnsp->data.soa.expire = dns->data.soa.dwExpire;
509 dnsp->data.soa.minimum = dns->data.soa.dwMinimumTtl;
511 name = dns->data.soa.NamePrimaryServer.str;
512 len = dns->data.soa.NamePrimaryServer.len;
515 res = dns_name_check(mem_ctx, len, name);
516 if (!W_ERROR_IS_OK(res)) {
521 if (len > 0 && name[len-1] == '.') {
522 talloc_res = talloc_strndup(mem_ctx, name, len-1);
523 if (talloc_res == NULL) {
526 dnsp->data.soa.mname = talloc_res;
528 talloc_res = talloc_strdup(mem_ctx, name);
529 if (talloc_res == NULL) {
532 dnsp->data.soa.mname = talloc_res;
535 name = dns->data.soa.ZoneAdministratorEmail.str;
536 len = dns->data.soa.ZoneAdministratorEmail.len;
538 res = dns_name_check(mem_ctx, len, name);
539 if (!W_ERROR_IS_OK(res)) {
543 if (len > 0 && name[len-1] == '.') {
544 talloc_res = talloc_strndup(mem_ctx, name, len-1);
545 if (talloc_res == NULL) {
548 dnsp->data.soa.rname = talloc_res;
550 talloc_res = talloc_strdup(mem_ctx, name);
551 if (talloc_res == NULL) {
554 dnsp->data.soa.rname = talloc_res;
560 name = dns->data.ptr.str;
561 len = dns->data.ptr.len;
564 res = dns_name_check(mem_ctx, len, name);
565 if (!W_ERROR_IS_OK(res)) {
570 talloc_res = talloc_strdup(mem_ctx, name);
571 if (talloc_res == NULL) {
574 dnsp->data.ptr = talloc_res;
579 dnsp->data.mx.wPriority = dns->data.mx.wPreference;
581 name = dns->data.mx.nameExchange.str;
582 len = dns->data.mx.nameExchange.len;
585 res = dns_name_check(mem_ctx, len, name);
586 if (!W_ERROR_IS_OK(res)) {
591 if (len > 0 && name[len-1] == '.') {
592 talloc_res = talloc_strndup(mem_ctx, name, len-1);
593 if (talloc_res == NULL) {
596 dnsp->data.mx.nameTarget = talloc_res;
598 talloc_res = talloc_strdup(mem_ctx, name);
599 if (talloc_res == NULL) {
602 dnsp->data.mx.nameTarget = talloc_res;
608 dnsp->data.txt.count = dns->data.txt.count;
609 dnsp->data.txt.str = talloc_array(mem_ctx, const char *, dns->data.txt.count);
610 for (i=0; i<dns->data.txt.count; i++) {
611 talloc_res = talloc_strdup(mem_ctx, dns->data.txt.str[i].str);
612 if (talloc_res == NULL) {
615 dnsp->data.txt.str[i] = talloc_res;
620 dnsp->data.ipv6 = talloc_strdup(mem_ctx, dns->data.ipv6);
624 dnsp->data.srv.wPriority = dns->data.srv.wPriority;
625 dnsp->data.srv.wWeight = dns->data.srv.wWeight;
626 dnsp->data.srv.wPort = dns->data.srv.wPort;
628 name = dns->data.srv.nameTarget.str;
629 len = dns->data.srv.nameTarget.len;
632 res = dns_name_check(mem_ctx, len, name);
633 if (!W_ERROR_IS_OK(res)) {
638 if (len > 0 && name[len-1] == '.') {
639 talloc_res = talloc_strndup(mem_ctx, name, len-1);
640 if (talloc_res == NULL) {
643 dnsp->data.srv.nameTarget = talloc_res;
645 talloc_res = talloc_strdup(mem_ctx, name);
646 if (talloc_res == NULL) {
649 dnsp->data.srv.nameTarget = talloc_res;
655 memcpy(&dnsp->data, &dns->data, sizeof(union dnsRecordData));
656 DEBUG(0, ("dnsserver: Found Unhandled DNS record type=%d", dns->wType));
663 return WERR_NOT_ENOUGH_MEMORY;
666 /* Intialize tree with given name as the root */
667 static struct dns_tree *dns_tree_init(TALLOC_CTX *mem_ctx, const char *name, void *data)
669 struct dns_tree *tree;
671 tree = talloc_zero(mem_ctx, struct dns_tree);
676 tree->name = talloc_strdup(tree, name);
677 if (tree->name == NULL) {
688 /* Add a child one level below */
689 static struct dns_tree *dns_tree_add(struct dns_tree *tree, const char *name, void *data)
691 struct dns_tree *node;
693 node = talloc_zero(tree, struct dns_tree);
698 node->name = talloc_strdup(tree, name);
699 if (node->name == NULL) {
703 node->level = tree->level + 1;
704 node->num_children = 0;
705 node->children = NULL;
708 if (tree->num_children == 0) {
709 tree->children = talloc_zero(tree, struct dns_tree *);
711 tree->children = talloc_realloc(tree, tree->children, struct dns_tree *,
712 tree->num_children+1);
714 if (tree->children == NULL) {
718 tree->children[tree->num_children] = node;
719 tree->num_children++;
724 /* Find a node that matches the name components */
725 static struct dns_tree *dns_tree_find(struct dns_tree *tree, int ncount, char **nlist, int *match_count)
727 struct dns_tree *node, *next;
732 if (strcmp(tree->name, "@") == 0) {
735 if (strcasecmp(tree->name, nlist[ncount-1]) != 0) {
743 for (i=start; i<ncount; i++) {
744 if (node->num_children == 0) {
748 for (j=0; j<node->num_children; j++) {
749 if (strcasecmp(nlist[(ncount-1)-i], node->children[j]->name) == 0) {
750 next = node->children[j];
765 /* Build a 2-level tree for resulting dns names */
766 struct dns_tree *dns_build_tree(TALLOC_CTX *mem_ctx, const char *name, struct ldb_result *res)
768 struct dns_tree *root, *base, *tree, *node;
770 int rootcount, ncount;
772 int i, level, match_count;
774 rootcount = dns_split_name_components(mem_ctx, name, &nlist);
775 if (rootcount <= 0) {
779 root = dns_tree_init(mem_ctx, nlist[rootcount-1], NULL);
786 for (i=rootcount-2; i>=0; i--) {
787 tree = dns_tree_add(tree, nlist[i], NULL);
795 /* Add all names in the result in a tree */
796 for (i=0; i<res->count; i++) {
797 ptr = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
799 DBG_ERR("dnsserver: dns record has no name (%s)",
800 ldb_dn_get_linearized(res->msgs[i]->dn));
804 if (strcmp(ptr, "@") == 0) {
805 base->data = res->msgs[i];
807 } else if (strcasecmp(ptr, name) == 0) {
808 base->data = res->msgs[i];
812 ncount = dns_split_name_components(root, ptr, &nlist);
817 /* Find matching node */
818 tree = dns_tree_find(root, ncount, nlist, &match_count);
823 /* If the node is on leaf, then add record data */
824 if (match_count+1 == ncount) {
825 tree->data = res->msgs[i];
828 /* Add missing name components */
829 for (level=match_count+1; level<ncount; level++) {
830 if (tree->level == rootcount+1) {
833 if (level == ncount-1) {
834 node = dns_tree_add(tree, nlist[(ncount-1)-level], res->msgs[i]);
836 node = dns_tree_add(tree, nlist[(ncount-1)-level], NULL);
847 /* Mark the base record, so it can be found easily */
859 static void _dns_add_name(TALLOC_CTX *mem_ctx, const char *name, char ***add_names, int *add_count)
862 char **ptr = *add_names;
863 int count = *add_count;
865 for (i=0; i<count; i++) {
866 if (strcasecmp(ptr[i], name) == 0) {
871 ptr = talloc_realloc(mem_ctx, ptr, char *, count+1);
876 ptr[count] = talloc_strdup(mem_ctx, name);
877 if (ptr[count] == NULL) {
883 *add_count = count+1;
887 static void dns_find_additional_names(TALLOC_CTX *mem_ctx, struct dnsp_DnssrvRpcRecord *rec, char ***add_names, int *add_count)
889 if (add_names == NULL) {
893 switch (rec->wType) {
896 _dns_add_name(mem_ctx, rec->data.ns, add_names, add_count);
900 _dns_add_name(mem_ctx, rec->data.cname, add_names, add_count);
904 _dns_add_name(mem_ctx, rec->data.soa.mname, add_names, add_count);
908 _dns_add_name(mem_ctx, rec->data.mx.nameTarget, add_names, add_count);
912 _dns_add_name(mem_ctx, rec->data.srv.nameTarget, add_names, add_count);
921 WERROR dns_fill_records_array(TALLOC_CTX *mem_ctx,
922 struct dnsserver_zone *z,
923 enum dns_record_type record_type,
924 unsigned int select_flag,
925 const char *branch_name,
926 struct ldb_message *msg,
928 struct DNS_RPC_RECORDS_ARRAY *recs,
932 struct ldb_message_element *el;
937 if (recs->count == 0) {
938 recs->rec = talloc_zero(recs, struct DNS_RPC_RECORDS);
940 recs->rec = talloc_realloc(recs, recs->rec, struct DNS_RPC_RECORDS, recs->count+1);
942 if (recs->rec == NULL) {
943 return WERR_NOT_ENOUGH_MEMORY;
946 recs->rec[i].wLength = 0;
947 recs->rec[i].wRecordCount = 0;
948 recs->rec[i].dwChildCount = num_children;
949 recs->rec[i].dwFlags = 0;
951 /* The base records returned with empty name */
952 /* Children records returned with names */
953 if (branch_name == NULL) {
954 recs->rec[i].dnsNodeName.str = talloc_strdup(recs, "");
955 recs->rec[i].dnsNodeName.len = 0;
957 recs->rec[i].dnsNodeName.str = talloc_strdup(recs, branch_name);
958 recs->rec[i].dnsNodeName.len = strlen(branch_name);
960 recs->rec[i].records = talloc_zero_array(recs, struct DNS_RPC_RECORD, 0);
963 /* Allow empty records */
968 /* Do not return RR records, if the node has children */
969 if (branch_name != NULL && num_children > 0) {
973 ptr = ldb_msg_find_attr_as_string(msg, "name", NULL);
975 DBG_ERR("dnsserver: dns record has no name (%s)",
976 ldb_dn_get_linearized(msg->dn));
977 return WERR_INTERNAL_DB_ERROR;
980 el = ldb_msg_find_element(msg, "dnsRecord");
981 if (el == NULL || el->values == 0) {
986 for (j=0; j<el->num_values; j++) {
987 struct dnsp_DnssrvRpcRecord dnsp_rec;
988 struct DNS_RPC_RECORD *dns_rec;
989 enum ndr_err_code ndr_err;
991 ndr_err = ndr_pull_struct_blob(&el->values[j], mem_ctx, &dnsp_rec,
992 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
993 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
994 DEBUG(0, ("dnsserver: Unable to parse dns record (%s)", ldb_dn_get_linearized(msg->dn)));
995 return WERR_INTERNAL_DB_ERROR;
998 /* Match the records based on search criteria */
999 if (record_type == DNS_TYPE_ALL || dnsp_rec.wType == record_type) {
1002 if (select_flag & DNS_RPC_VIEW_AUTHORITY_DATA) {
1003 if (dnsp_rec.rank == DNS_RANK_ZONE) {
1005 } else if (dnsp_rec.rank == DNS_RANK_NS_GLUE) {
1007 * If branch_name is NULL, we're
1008 * explicitly asked to also return
1009 * DNS_RANK_NS_GLUE records
1011 if (branch_name == NULL) {
1016 if (select_flag & DNS_RPC_VIEW_CACHE_DATA) {
1017 if (dnsp_rec.rank == DNS_RANK_ZONE) {
1021 if (select_flag & DNS_RPC_VIEW_GLUE_DATA) {
1022 if (dnsp_rec.rank == DNS_RANK_GLUE) {
1026 if (select_flag & DNS_RPC_VIEW_ROOT_HINT_DATA) {
1027 if (dnsp_rec.rank == DNS_RANK_ROOT_HINT) {
1033 recs->rec[i].records = talloc_realloc(recs,
1034 recs->rec[i].records,
1035 struct DNS_RPC_RECORD,
1036 recs->rec[i].wRecordCount+1);
1037 if (recs->rec[i].records == NULL) {
1038 return WERR_NOT_ENOUGH_MEMORY;
1041 dns_rec = &recs->rec[i].records[recs->rec[i].wRecordCount];
1042 dnsp_to_dns_copy(recs, &dnsp_rec, dns_rec);
1044 /* Fix record flags */
1045 if (strcmp(ptr, "@") == 0) {
1046 dns_rec->dwFlags |= DNS_RPC_FLAG_ZONE_ROOT;
1048 if (dnsp_rec.rank == DNS_RANK_ZONE) {
1049 dns_rec->dwFlags |= DNS_RPC_FLAG_AUTH_ZONE_ROOT;
1053 if (dns_rec->dwFlags == DNS_RANK_NS_GLUE) {
1054 dns_rec->dwFlags |= DNS_RPC_FLAG_ZONE_ROOT;
1057 recs->rec[i].wRecordCount++;
1059 dns_find_additional_names(mem_ctx, &dnsp_rec, add_names, add_count);
1068 int dns_name_compare(const struct ldb_message **m1, const struct ldb_message **m2,
1071 const char *name1, *name2;
1072 const char *ptr1, *ptr2;
1074 name1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
1075 name2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
1076 if (name1 == NULL || name2 == NULL) {
1080 /* '@' record and the search_name record gets preference */
1081 if (name1[0] == '@') {
1084 if (search_name && strcasecmp(name1, search_name) == 0) {
1088 if (name2[0] == '@') {
1091 if (search_name && strcasecmp(name2, search_name) == 0) {
1095 /* Compare the last components of names.
1096 * If search_name is not NULL, compare the second last components of names */
1097 ptr1 = strrchr(name1, '.');
1101 if (search_name && strcasecmp(ptr1+1, search_name) == 0) {
1103 while (ptr1 != name1) {
1115 ptr2 = strrchr(name2, '.');
1119 if (search_name && strcasecmp(ptr2+1, search_name) == 0) {
1121 while (ptr2 != name2) {
1133 return strcasecmp(ptr1, ptr2);
1136 bool dns_record_match(struct dnsp_DnssrvRpcRecord *rec1, struct dnsp_DnssrvRpcRecord *rec2)
1141 if (rec1->wType != rec2->wType) {
1145 switch(rec1->wType) {
1146 case DNS_TYPE_TOMBSTONE:
1150 return strcmp(rec1->data.ipv4, rec2->data.ipv4) == 0;
1153 return dns_name_equal(rec1->data.ns, rec2->data.ns);
1155 case DNS_TYPE_CNAME:
1156 return dns_name_equal(rec1->data.cname, rec2->data.cname);
1159 return dns_name_equal(rec1->data.soa.mname, rec2->data.soa.mname) &&
1160 dns_name_equal(rec1->data.soa.rname, rec2->data.soa.rname) &&
1161 rec1->data.soa.serial == rec2->data.soa.serial &&
1162 rec1->data.soa.refresh == rec2->data.soa.refresh &&
1163 rec1->data.soa.retry == rec2->data.soa.retry &&
1164 rec1->data.soa.expire == rec2->data.soa.expire &&
1165 rec1->data.soa.minimum == rec2->data.soa.minimum;
1168 return dns_name_equal(rec1->data.ptr, rec2->data.ptr);
1171 return rec1->data.mx.wPriority == rec2->data.mx.wPriority &&
1172 dns_name_equal(rec1->data.mx.nameTarget, rec2->data.mx.nameTarget);
1175 if (rec1->data.txt.count != rec2->data.txt.count) {
1179 for (i=0; i<rec1->data.txt.count; i++) {
1180 status = status && (strcmp(rec1->data.txt.str[i],
1181 rec2->data.txt.str[i]) == 0);
1186 return strcmp(rec1->data.ipv6, rec2->data.ipv6) == 0;
1189 return rec1->data.srv.wPriority == rec2->data.srv.wPriority &&
1190 rec1->data.srv.wWeight == rec2->data.srv.wWeight &&
1191 rec1->data.srv.wPort == rec2->data.srv.wPort &&
1192 dns_name_equal(rec1->data.srv.nameTarget, rec2->data.srv.nameTarget);
1195 DEBUG(0, ("dnsserver: unhandled record type %u", rec1->wType));