The branch, master has been updated via a6ed907 dsdb: Handle the case when extended rights string is NULL via c8ac367 s4-drepl: Search for application partitions in addition to main ones via 4a6410d s4-dnsserver: Check the raised exception with assertRaises via 8dca18a s4-dnsserver: Handle the case when the dns name is NULL via 6e800bf s4-dnsserver: Build a dns name tree for correct enumeration via 0d3aff7 s4-dnsserver: List dns zones matching the search filter via c1b45af s4-dnsserver: Compare two dns names using last uncommon name components via c651b4e s4-dnsserver: Set DNS_DP_AUTOCREATED flag for the zone information via 9abfaa3 samba-tool: Improve the description of dns subcommands. via 66121dc samba-tool: Enable comparison of DNS naming contexts in ldapcmp from cde73e2 Remove opendir() VFS code from ACL modules.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit a6ed9071b9aa75ff6f3ca2c3b24e6060c4d3f389 Author: Amitay Isaacs <ami...@gmail.com> Date: Wed Nov 2 14:34:41 2011 +1100 dsdb: Handle the case when extended rights string is NULL Pair-Programmed-With: Andrew Tridgell <tri...@samba.org> Signed-off-by: Andrew Tridgell <tri...@samba.org> Autobuild-User: Andrew Tridgell <tri...@samba.org> Autobuild-Date: Wed Nov 2 07:03:40 CET 2011 on sn-devel-104 commit c8ac3678ad98bc27cf08f3d14bae2aa52318c48d Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Oct 25 15:06:07 2011 +1100 s4-drepl: Search for application partitions in addition to main ones To replicate application partitions (e.g. DNS partitions) consult msDs-hasMasterNCs attribute as well. Also, make sure we don't add same partition twice in the list. hasMasterNCs and msDs-hasMasterNCs have domain, configuration and schema partitions common. Signed-off-by: Andrew Tridgell <tri...@samba.org> commit 4a6410df54fdbc8fb08b104c47010db507443def Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 24 17:37:24 2011 +1100 s4-dnsserver: Check the raised exception with assertRaises Signed-off-by: Andrew Tridgell <tri...@samba.org> commit 8dca18a71a813719e1c20b1ff909ed3aae32cf40 Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 24 17:22:21 2011 +1100 s4-dnsserver: Handle the case when the dns name is NULL Signed-off-by: Andrew Tridgell <tri...@samba.org> commit 6e800bfba708124077defab3c9379db201f4c43c Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 24 17:20:46 2011 +1100 s4-dnsserver: Build a dns name tree for correct enumeration The result of EnumRecords/EnumRecords2 RPC calls, is a list of dns records that are one level below in the name hierarchy starting from the search name. This patch builds a tree of names to get the list of records one level below the search names and correctly count the number of child records for each of those. Signed-off-by: Andrew Tridgell <tri...@samba.org> commit 0d3aff732483cf1a48cb9ea6af16537fc11be547 Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 24 17:15:27 2011 +1100 s4-dnsserver: List dns zones matching the search filter Signed-off-by: Andrew Tridgell <tri...@samba.org> commit c1b45afcf254ed0bbb36b125e440a2731c253e63 Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 24 17:07:45 2011 +1100 s4-dnsserver: Compare two dns names using last uncommon name components When search_name is not NULL, use the second last component of name instead of the last name. e.g. To compare following two names, _ldap._tcp.gc, and _ldap._tcp.Default-First-Site-Name._sites.gc with search_name=NULL, it is gc and gc with search_name=gc, it is _tcp and _sites Signed-off-by: Andrew Tridgell <tri...@samba.org> commit c651b4e99b8bd70eb3be7b3d416c329b4d506f76 Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Oct 24 16:54:16 2011 +1100 s4-dnsserver: Set DNS_DP_AUTOCREATED flag for the zone information This make the zone information similar to windows (W2K8r2). Signed-off-by: Andrew Tridgell <tri...@samba.org> commit 9abfaa3bbb45f5217b326d41aca1b68a49ca12ea Author: Amitay Isaacs <ami...@gmail.com> Date: Fri Oct 21 11:27:28 2011 +1100 samba-tool: Improve the description of dns subcommands. Signed-off-by: Andrew Tridgell <tri...@samba.org> commit 66121dc89677b4b6e91f8b4cac893d709ab63544 Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Sep 20 17:31:24 2011 +1000 samba-tool: Enable comparison of DNS naming contexts in ldapcmp Signed-off-by: Andrew Tridgell <tri...@samba.org> ----------------------------------------------------------------------- Summary of changes: source4/dsdb/common/dsdb_access.c | 11 +- source4/dsdb/repl/drepl_partitions.c | 19 +- source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 232 ++++++++++------ source4/rpc_server/dnsserver/dnsdata.c | 306 ++++++++++++++++---- source4/rpc_server/dnsserver/dnsserver.h | 12 +- source4/rpc_server/dnsserver/dnsutils.c | 2 +- source4/scripting/python/samba/netcmd/dns.py | 20 +- source4/scripting/python/samba/netcmd/ldapcmp.py | 11 +- .../python/samba/tests/dcerpc/dnsserver.py | 24 +- 9 files changed, 458 insertions(+), 179 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/dsdb/common/dsdb_access.c b/source4/dsdb/common/dsdb_access.c index b8784fc..fd75e77 100644 --- a/source4/dsdb/common/dsdb_access.c +++ b/source4/dsdb/common/dsdb_access.c @@ -152,9 +152,12 @@ int dsdb_check_access_on_dn(struct ldb_context *ldb, "objectSid", NULL }; - NTSTATUS status = GUID_from_string(ext_right, &guid); - if (!NT_STATUS_IS_OK(status)) { - return LDB_ERR_OPERATIONS_ERROR; + + if (ext_right != NULL) { + NTSTATUS status = GUID_from_string(ext_right, &guid); + if (!NT_STATUS_IS_OK(status)) { + return LDB_ERR_OPERATIONS_ERROR; + } } ret = dsdb_search_dn(ldb, mem_ctx, &acl_res, dn, acl_attrs, DSDB_SEARCH_SHOW_DELETED); @@ -168,6 +171,6 @@ int dsdb_check_access_on_dn(struct ldb_context *ldb, token, dn, access_mask, - &guid); + ext_right ? &guid : NULL); } diff --git a/source4/dsdb/repl/drepl_partitions.c b/source4/dsdb/repl/drepl_partitions.c index f2d4b13..70f9971 100644 --- a/source4/dsdb/repl/drepl_partitions.c +++ b/source4/dsdb/repl/drepl_partitions.c @@ -41,7 +41,7 @@ WERROR dreplsrv_load_partitions(struct dreplsrv_service *s) { WERROR status; - static const char *attrs[] = { "hasMasterNCs", "hasPartialReplicaNCs", "msDS-HasFullReplicaNCs", NULL }; + static const char *attrs[] = { "hasMasterNCs", "msDs-hasMasterNCs", "hasPartialReplicaNCs", "msDS-HasFullReplicaNCs", NULL }; unsigned int a; int ret; TALLOC_CTX *tmp_ctx; @@ -75,7 +75,8 @@ WERROR dreplsrv_load_partitions(struct dreplsrv_service *s) } for (i=0; i<el->num_values; i++) { struct ldb_dn *pdn; - struct dreplsrv_partition *p; + struct dreplsrv_partition *p, *tp; + bool found; pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]); if (pdn == NULL) { @@ -98,8 +99,20 @@ WERROR dreplsrv_load_partitions(struct dreplsrv_service *s) p->rodc_replica = true; } - DLIST_ADD(s->partitions, p); + /* Do not add partitions more than once */ + found = false; + for (tp = s->partitions; tp; tp = tp->next) { + if (ldb_dn_compare(tp->dn, p->dn) == 0) { + found = true; + break; + } + } + if (found) { + talloc_free(p); + continue; + } + DLIST_ADD(s->partitions, p); DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn))); } } diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index 66162c5..fd0c977 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1103,8 +1103,9 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate, union DNSSRV_RPC_UNION *rout) { int valid_operation = 0; - struct dnsserver_zone *z; - bool list_zones; + struct dnsserver_zone *z, **zlist; + int zcount; + bool found; int i; if (strcasecmp(operation, "QueryDwordProperty") == 0) { @@ -1119,45 +1120,112 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate, if (typeid_in != DNSSRV_TYPEID_DWORD) { return WERR_DNS_ERROR_INVALID_PROPERTY; } - if ((rin->Dword & (DNS_ZONE_REQUEST_PRIMARY | - DNS_ZONE_REQUEST_FORWARD | - DNS_ZONE_REQUEST_DS)) > 0) { - list_zones = true; - } else { - list_zones = false; + + zcount = 0; + zlist = talloc_zero_array(mem_ctx, struct dnsserver_zone *, 0); + for (z = dsstate->zones; z; z = z->next) { + found = false; + if (rin->Dword & DNS_ZONE_REQUEST_PRIMARY) { + if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_PRIMARY) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_SECONDARY) { + if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_SECONDARY) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_CACHE) { + if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_CACHE) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_AUTO) { + if (z->zoneinfo->fAutoCreated || z->zoneinfo->dwDpFlags & DNS_DP_AUTOCREATED) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_FORWARD) { + if (!(z->zoneinfo->Flags & DNS_RPC_ZONE_REVERSE)) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_REVERSE) { + if (z->zoneinfo->Flags & DNS_RPC_ZONE_REVERSE) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_FORWARDER) { + if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_FORWARDER) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_STUB) { + if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_STUB) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_DS) { + if (z->zoneinfo->Flags & DNS_RPC_ZONE_DSINTEGRATED) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_NON_DS) { + if (!(z->zoneinfo->Flags & DNS_RPC_ZONE_DSINTEGRATED)) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_DOMAIN_DP) { + if (z->zoneinfo->dwDpFlags & DNS_DP_DOMAIN_DEFAULT) { + found = true; + } + } + if (rin->Dword & DNS_ZONE_REQUEST_FOREST_DP) { + if (z->zoneinfo->dwDpFlags & DNS_DP_FOREST_DEFAULT) { + found = true; + } + } + + if (found) { + zlist = talloc_realloc(mem_ctx, zlist, struct dnsserver_zone *, zcount+1); + zlist[zcount] = z; + zcount++; + } + } if (client_version == DNS_CLIENT_VERSION_W2K) { *typeid_out = DNSSRV_TYPEID_ZONE_LIST_W2K; rout->ZoneListW2K = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_W2K); - if (!list_zones) { + if (zcount == 0) { rout->ZoneListW2K->dwZoneCount = 0; rout->ZoneListW2K->ZoneArray = NULL; return WERR_OK; } - rout->ZoneListW2K->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_W2K *, dsstate->zones_count); + rout->ZoneListW2K->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_W2K *, zcount); if (rout->ZoneListW2K->ZoneArray == NULL) { + talloc_free(zlist); return WERR_NOMEM; } - for (z = dsstate->zones, i=0; z; z = z->next, i++) { + for (i=0; i<zcount; i++) { rout->ZoneListW2K->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_W2K); - rout->ZoneListW2K->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, z->name); - rout->ZoneListW2K->ZoneArray[i]->Flags = z->zoneinfo->Flags; - rout->ZoneListW2K->ZoneArray[i]->ZoneType = z->zoneinfo->dwZoneType; - rout->ZoneListW2K->ZoneArray[i]->Version = z->zoneinfo->Version; + rout->ZoneListW2K->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name); + rout->ZoneListW2K->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags; + rout->ZoneListW2K->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType; + rout->ZoneListW2K->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version; } - rout->ZoneListW2K->dwZoneCount = dsstate->zones_count; + rout->ZoneListW2K->dwZoneCount = zcount; } else { *typeid_out = DNSSRV_TYPEID_ZONE_LIST; rout->ZoneList = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_DOTNET); - if (!list_zones) { + if (zcount == 0) { rout->ZoneList->dwRpcStructureVersion = 1; rout->ZoneList->dwZoneCount = 0; rout->ZoneList->ZoneArray = NULL; @@ -1165,25 +1233,27 @@ static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate, return WERR_OK; } - rout->ZoneList->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_DOTNET *, dsstate->zones_count); + rout->ZoneList->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_DOTNET *, zcount); if (rout->ZoneList->ZoneArray == NULL) { + talloc_free(zlist); return WERR_NOMEM; } - for (z = dsstate->zones, i=0; z; z = z->next, i++) { + for (i=0; i<zcount; i++) { rout->ZoneList->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_DOTNET); rout->ZoneList->ZoneArray[i]->dwRpcStructureVersion = 1; - rout->ZoneList->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, z->name); - rout->ZoneList->ZoneArray[i]->Flags = z->zoneinfo->Flags; - rout->ZoneList->ZoneArray[i]->ZoneType = z->zoneinfo->dwZoneType; - rout->ZoneList->ZoneArray[i]->Version = z->zoneinfo->Version; - rout->ZoneList->ZoneArray[i]->dwDpFlags = z->zoneinfo->dwDpFlags; - rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, z->zoneinfo->pszDpFqdn); + rout->ZoneList->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name); + rout->ZoneList->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags; + rout->ZoneList->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType; + rout->ZoneList->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version; + rout->ZoneList->ZoneArray[i]->dwDpFlags = zlist[i]->zoneinfo->dwDpFlags; + rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, zlist[i]->zoneinfo->pszDpFqdn); } rout->ZoneList->dwRpcStructureVersion = 1; - rout->ZoneList->dwZoneCount = dsstate->zones_count; + rout->ZoneList->dwZoneCount = zcount; } + talloc_free(zlist); return WERR_OK; } else if (strcasecmp(operation, "EnumZones2") == 0) { valid_operation = true; @@ -1359,7 +1429,7 @@ static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate, for (i=0; i<res->count; i++) { status = dns_fill_records_array(tmp_ctx, NULL, record_type, select_flag, NULL, - res->msgs[i], recs, + res->msgs[i], 0, recs, &add_names, &add_count); if (!W_ERROR_IS_OK(status)) { talloc_free(tmp_ctx); @@ -1387,7 +1457,7 @@ static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate, } status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A, select_flag, rname, - res->msgs[0], recs, + res->msgs[0], 0, recs, NULL, NULL); talloc_free(rname); talloc_free(res); @@ -1417,16 +1487,16 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, struct DNS_RPC_RECORDS_ARRAY **buffer) { TALLOC_CTX *tmp_ctx; - char *name, *branch_name; + char *name; const char * const attrs[] = { "name", "dnsRecord", NULL }; struct ldb_result *res; struct DNS_RPC_RECORDS_ARRAY *recs; char **add_names = NULL; - const char *ptr; char *rname; int add_count = 0; int i, ret, len; WERROR status; + struct dns_tree *tree, *base, *node; tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); @@ -1460,81 +1530,73 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name, (ldb_qsort_cmp_fn_t)dns_name_compare); - /* Add the parent record with blank name */ - ptr = ldb_msg_find_attr_as_string(res->msgs[0], "name", NULL); - if (strcmp(ptr, name) == 0 || strcmp(ptr, "@") == 0) { - /* parent record found */ - if (select_flag & DNS_RPC_VIEW_ONLY_CHILDREN) { - status = WERR_OK; - } else { - status = dns_fill_records_array(tmp_ctx, z, record_type, - select_flag, NULL, - res->msgs[0], recs, - &add_names, &add_count); - } - i = 1; + /* Build a tree of name components from dns name */ + if (strcmp(name, z->name) == 0) { + tree = dns_build_tree(tmp_ctx, "@", res); } else { - /* parent record not in the search */ - if (select_flag & DNS_RPC_VIEW_ONLY_CHILDREN) { - status = WERR_OK; - } else { - status = dns_fill_records_array(tmp_ctx, z, record_type, - select_flag, NULL, - NULL, recs, - &add_names, &add_count); - } - i = 0; + tree = dns_build_tree(tmp_ctx, name, res); } + W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx); - if (!W_ERROR_IS_OK(status)) { - talloc_free(tmp_ctx); - return status; + /* Find the parent record in the tree */ + base = tree; + while (base->level != -1) { + base = base->children[0]; + } + + /* Add the parent record with blank name */ + if (!(select_flag & DNS_RPC_VIEW_ONLY_CHILDREN)) { + status = dns_fill_records_array(tmp_ctx, z, record_type, + select_flag, NULL, + base->data, 0, + recs, &add_names, &add_count); + if (!W_ERROR_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } } /* Add all the children records */ if (!(select_flag & DNS_RPC_VIEW_NO_CHILDREN)) { - for ( ; i<res->count; i++) { - char *name2; - const char *tmp_str; - - ptr = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL); - name2 = dns_split_node_name(tmp_ctx, ptr, name); - tmp_str = strrchr(name2, '.'); - if (tmp_str == NULL) { - branch_name = talloc_strdup(tmp_ctx, name2); - } else { - /* Skip '.' */ - branch_name = talloc_strdup(tmp_ctx, &tmp_str[1]); - } - talloc_free(name2); + for (i=0; i<base->num_children; i++) { + node = base->children[i]; status = dns_fill_records_array(tmp_ctx, z, record_type, - select_flag, branch_name, - res->msgs[i], recs, - &add_names, &add_count); + select_flag, node->name, + node->data, node->num_children, + recs, &add_names, &add_count); if (!W_ERROR_IS_OK(status)) { talloc_free(tmp_ctx); return status; } - - talloc_free(branch_name); } } - talloc_free(res); + talloc_free(res); + talloc_free(tree); talloc_free(name); /* Add any additional records */ if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) { for (i=0; i<add_count; i++) { - name = dns_split_node_name(tmp_ctx, add_names[i], z->name); - ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn, - LDB_SCOPE_ONELEVEL, attrs, - "(&(objectClass=dnsNode)(name=%s))", name); - talloc_free(name); - if (ret != LDB_SUCCESS || res->count == 0) { - talloc_free(res); - continue; + struct dnsserver_zone *z2; + + /* Search all the available zones for additional name */ + for (z2 = dsstate->zones; z2; z2 = z2->next) { + name = dns_split_node_name(tmp_ctx, add_names[i], z2->name); + ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z2->zone_dn, + LDB_SCOPE_ONELEVEL, attrs, + "(&(objectClass=dnsNode)(name=%s))", name); + talloc_free(name); + if (ret != LDB_SUCCESS) { + continue; + } + if (res->count == 1) { + break; + } else { + talloc_free(res); + continue; + } } len = strlen(add_names[i]); @@ -1545,7 +1607,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, } status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A, select_flag, rname, - res->msgs[0], recs, + res->msgs[0], 0, recs, NULL, NULL); talloc_free(rname); talloc_free(res); diff --git a/source4/rpc_server/dnsserver/dnsdata.c b/source4/rpc_server/dnsserver/dnsdata.c index 486290d..d9e708f 100644 --- a/source4/rpc_server/dnsserver/dnsdata.c +++ b/source4/rpc_server/dnsserver/dnsdata.c @@ -128,6 +128,10 @@ int dns_split_name_components(TALLOC_CTX *tmp_ctx, const char *name, char ***com char *str = NULL, *ptr, **list; int count = 0; + if (name == NULL) { + return 0; + } + str = talloc_strdup(tmp_ctx, name); if (!str) { goto failed; @@ -462,6 +466,187 @@ struct dnsp_DnssrvRpcRecord *dns_to_dnsp_copy(TALLOC_CTX *mem_ctx, struct DNS_RP } +/* Intialize tree with given name as the root */ +static struct dns_tree *dns_tree_init(TALLOC_CTX *mem_ctx, const char *name, void *data) +{ + struct dns_tree *tree; + + tree = talloc_zero(mem_ctx, struct dns_tree); + if (tree == NULL) { + return NULL; + } + + tree->name = talloc_strdup(tree, name); + if (tree->name == NULL) { + talloc_free(tree); + return NULL; + } + + tree->data = data; + + return tree; +} + + +/* Add a child one level below */ +static struct dns_tree *dns_tree_add(struct dns_tree *tree, const char *name, void *data) +{ + struct dns_tree *node; + + node = talloc_zero(tree, struct dns_tree); + if (node == NULL) { + return NULL; + } + + node->name = talloc_strdup(tree, name); + if (node->name == NULL) { + talloc_free(node); + return NULL; + } + node->level = tree->level + 1; + node->num_children = 0; + node->children = NULL; + node->data = data; + + if (tree->num_children == 0) { + tree->children = talloc_zero(tree, struct dns_tree *); + } else { + tree->children = talloc_realloc(tree, tree->children, struct dns_tree *, + tree->num_children+1); + } + if (tree->children == NULL) { + talloc_free(node); + return NULL; + } + tree->children[tree->num_children] = node; -- Samba Shared Repository