diff options
Diffstat (limited to 'src/db/sysdb_iphosts.c')
-rw-r--r-- | src/db/sysdb_iphosts.c | 875 |
1 files changed, 875 insertions, 0 deletions
diff --git a/src/db/sysdb_iphosts.c b/src/db/sysdb_iphosts.c new file mode 100644 index 0000000..d3ee8f1 --- /dev/null +++ b/src/db/sysdb_iphosts.c @@ -0,0 +1,875 @@ +/* + SSSD + + Authors: + Samuel Cabrero <scabrero@suse.com> + + Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <arpa/inet.h> + +#include "db/sysdb.h" +#include "db/sysdb_private.h" +#include "db/sysdb_iphosts.h" + +static errno_t +sysdb_host_update(struct sysdb_ctx *sysdb, + struct ldb_dn *dn, + const char **aliases, + const char **addresses); + +static errno_t +sysdb_host_remove_alias(struct sysdb_ctx *sysdb, + struct ldb_dn *dn, + const char *alias); + +errno_t +sysdb_gethostbyname(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **_res) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + static const char *attrs[] = { + SYSDB_NAME, + SYSDB_NAME_ALIAS, + SYSDB_IP_HOST_ATTR_ADDRESS, + SYSDB_DEFAULT_ATTRS, + NULL, + }; + char *sanitized_name; + char *subfilter; + struct ldb_result *res = NULL; + struct ldb_message **msgs; + size_t msgs_count; + + DEBUG(SSSDBG_TRACE_FUNC, "Searching host by name [%s] in domain [%s]\n", + name, domain->name); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name); + if (ret != EOK) { + goto done; + } + + subfilter = talloc_asprintf(tmp_ctx, SYSDB_IP_HOST_BYNAME_SUBFILTER, + sanitized_name, sanitized_name); + if (subfilter == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_search_hosts(mem_ctx, domain, subfilter, + attrs, &msgs_count, &msgs); + if (ret == EOK) { + res = talloc_zero(mem_ctx, struct ldb_result); + if (res == NULL) { + ret = ENOMEM; + goto done; + } + res->count = msgs_count; + res->msgs = talloc_steal(res, msgs); + } + + *_res = res; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +errno_t sysdb_gethostbyaddr(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *address, + struct ldb_result **_res) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + static const char *attrs[] = { + SYSDB_NAME, + SYSDB_NAME_ALIAS, + SYSDB_IP_HOST_ATTR_ADDRESS, + NULL, + }; + char *sanitized_address; + char *subfilter; + struct ldb_result *res = NULL; + struct ldb_message **msgs; + size_t msgs_count; + char *canonical_address; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + /* IP addresses are stored in canonical form, canonicalize the given + * address before search */ + ret = sss_canonicalize_ip_address(tmp_ctx, address, &canonical_address); + if (ret != EOK) { + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Searching host by address [%s] in domain [%s]\n", + canonical_address, domain->name); + + ret = sss_filter_sanitize(tmp_ctx, canonical_address, &sanitized_address); + if (ret != EOK) { + goto done; + } + + subfilter = talloc_asprintf(tmp_ctx, SYSDB_IP_HOST_BYADDR_SUBFILTER, + sanitized_address); + if (subfilter == NULL) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_search_hosts(mem_ctx, domain, subfilter, + attrs, &msgs_count, &msgs); + if (ret == EOK) { + res = talloc_zero(mem_ctx, struct ldb_result); + if (res == NULL) { + ret = ENOMEM; + goto done; + } + res->count = msgs_count; + res->msgs = talloc_steal(res, msgs); + } + + *_res = res; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +errno_t +sysdb_store_host(struct sss_domain_info *domain, + const char *primary_name, + const char **aliases, + const char **addresses, + struct sysdb_attrs *extra_attrs, + char **remove_attrs, + uint64_t cache_timeout, + time_t now) +{ + errno_t ret; + errno_t sret; + TALLOC_CTX *tmp_ctx; + bool in_transaction = false; + struct ldb_result *res = NULL; + const char *name; + unsigned int i, j; + struct ldb_dn *update_dn = NULL; + struct sysdb_attrs *attrs; + struct sysdb_ctx *sysdb; + size_t len; + + DEBUG(SSSDBG_TRACE_FUNC, "Storing host [%s] into cache, domain [%s]\n", + primary_name, domain->name); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + sysdb = domain->sysdb; + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); + goto done; + } + + in_transaction = true; + + /* Check that the addresses are unique. If the address appears for any + * host other than the one matching the primary_name, we need to + * remove them so that gethostbyaddr() can work properly. + * Last entry saved to the cache should always "win". + */ + len = talloc_array_length(addresses); + for (i = 0; i < len && addresses[i] != NULL; i++) { + ret = sysdb_gethostbyaddr(tmp_ctx, domain, addresses[i], &res); + if (ret != EOK && ret != ENOENT) { + goto done; + } else if (ret != ENOENT) { + if (res->count != 1) { + /* Somehow the cache has multiple entries with the same + * address. This is corrupted. We'll delete them all to + * sort it out. + */ + for (j = 0; j < res->count; j++) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Corrupt cache entry [%s] detected. Deleting\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[j]->dn)); + + ret = sysdb_delete_entry(sysdb, res->msgs[j]->dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not delete corrupt cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[j]->dn)); + goto done; + } + } + } else { + /* Check whether this is the same name as we're currently + * saving to the cache. + */ + name = ldb_msg_find_attr_as_string(res->msgs[0], + SYSDB_NAME, + NULL); + if (name == NULL || strcmp(name, primary_name) != 0) { + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "A host with no name?\n"); + /* Corrupted */ + } + + /* Either this is a corrupt entry or it's another host + * claiming ownership of this address. In order to account + * for address reassignments, we need to delete the old + * entry. + */ + DEBUG(SSSDBG_TRACE_FUNC, + "Corrupt or replaced cache entry [%s] detected. " + "Deleting\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[0]->dn)); + + ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[0]->dn)); + } + } + } + } + talloc_zfree(res); + } + + /* Ok, addresses should now be unique. Now look the host up by name + * to determine if we need to update existing entries or modify aliases. + */ + ret = sysdb_gethostbyname(tmp_ctx, domain, primary_name, &res); + if (ret != EOK && ret != ENOENT) { + goto done; + } else if (ret != ENOENT) { /* Found entries */ + for (i = 0; i < res->count; i++) { + /* Check whether this is the same name as we're currently + * saving to the cache. + */ + name = ldb_msg_find_attr_as_string(res->msgs[i], + SYSDB_NAME, + NULL); + if (name == NULL) { + /* Corrupted */ + DEBUG(SSSDBG_CRIT_FAILURE, + "A host with no name?\n"); + DEBUG(SSSDBG_TRACE_FUNC, + "Corrupt cache entry [%s] detected. Deleting\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[i]->dn)); + + ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not delete corrupt cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[i]->dn)); + goto done; + } + } else if (strcmp(name, primary_name) == 0) { + /* This is the same host name, so we need + * to update this entry with the values + * provided. + */ + if (update_dn) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Two existing hosts with the same name: [%s]? " + "Deleting both.\n", + primary_name); + + /* Delete the entry from the previous pass */ + ret = sysdb_delete_entry(sysdb, update_dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + update_dn)); + goto done; + } + + /* Delete the new entry as well */ + ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[i]->dn)); + goto done; + } + + update_dn = NULL; + } else { + update_dn = talloc_steal(tmp_ctx, res->msgs[i]->dn); + } + } else { + /* Another host is claiming this name as an alias. + * In order to account for aliases being promoted to + * primary names, we need to make sure to remove the + * old alias entry. + */ + ret = sysdb_host_remove_alias(sysdb, + res->msgs[i]->dn, + primary_name); + if (ret != EOK) { + goto done; + } + } + } + talloc_zfree(res); + } + + if (update_dn) { + /* Update the existing entry */ + ret = sysdb_host_update(sysdb, update_dn, aliases, addresses); + } else { + /* Add a new entry */ + ret = sysdb_host_add(tmp_ctx, domain, primary_name, + aliases, addresses, &update_dn); + } + + if (ret != EOK) { + goto done; + } + + if (extra_attrs == NULL) { + attrs = sysdb_new_attrs(tmp_ctx); + if (attrs == NULL) { + ret = ENOMEM; + goto done; + } + } else { + attrs = extra_attrs; + } + + ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); + if (ret) { + goto done; + } + + ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, + ((cache_timeout) ? + (now + cache_timeout) : 0)); + if (ret) { + goto done; + } + + ret = sysdb_set_entry_attr(sysdb, update_dn, attrs, SYSDB_MOD_REP); + if (ret != EOK) { + goto done; + } + + if (remove_attrs) { + ret = sysdb_remove_attrs(domain, primary_name, + SYSDB_MEMBER_HOST, + remove_attrs); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not remove missing attributes: [%s]\n", + strerror(ret)); + goto done; + } + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); + goto done; + } + in_transaction = false; + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); + } + } + talloc_free(tmp_ctx); + return ret; +} +struct ldb_dn *sysdb_host_dn(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name) +{ + errno_t ret; + char *clean_name; + struct ldb_dn *dn; + + ret = sysdb_dn_sanitize(NULL, name, &clean_name); + if (ret != EOK) { + return NULL; + } + + dn = ldb_dn_new_fmt(mem_ctx, domain->sysdb->ldb, SYSDB_TMPL_IP_HOST, + clean_name, domain->name); + talloc_free(clean_name); + + return dn; +} + +errno_t sysdb_host_add(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *primary_name, + const char **aliases, + const char **addresses, + struct ldb_dn **dn) +{ + errno_t ret; + int lret; + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; + unsigned long i; + size_t len; + + DEBUG(SSSDBG_TRACE_FUNC, "Adding host [%s] to domain [%s]\n", + primary_name, domain->name); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + /* host dn */ + msg->dn = sysdb_host_dn(msg, domain, primary_name); + if (msg->dn == NULL) { + ret = ENOMEM; + goto done; + } + + /* Objectclass */ + ret = sysdb_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_HOST_CLASS); + if (ret != EOK) { + goto done; + } + + /* Set the primary name */ + ret = sysdb_add_string(msg, SYSDB_NAME, primary_name); + if (ret != EOK) { + goto done; + } + + /* If this iphost has any aliases, include them */ + if (aliases != NULL && aliases[0] != NULL) { + /* Set the name aliases */ + lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS, + LDB_FLAG_MOD_ADD, NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + len = talloc_array_length(aliases); + for (i = 0; i < len && aliases[i] != NULL ; i++) { + lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + } + } + + /* Set the addresses */ + lret = ldb_msg_add_empty(msg, SYSDB_IP_HOST_ATTR_ADDRESS, + LDB_FLAG_MOD_ADD, NULL); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + + len = talloc_array_length(addresses); + for (i = 0; i < len && addresses[i] != NULL; i++) { + char *addr = NULL; + + ret = sss_canonicalize_ip_address(msg, addresses[i], &addr); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to canonicalize address [%s]: %s\n", + addresses[i], sss_strerror(ret)); + goto done; + } + + lret = ldb_msg_add_string(msg, SYSDB_IP_HOST_ATTR_ADDRESS, addr); + if (lret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(lret); + goto done; + } + } + + /* creation time */ + ret = sysdb_add_ulong(msg, SYSDB_CREATE_TIME, (unsigned long)time(NULL)); + if (ret != 0) { + goto done; + } + + lret = ldb_add(domain->sysdb->ldb, msg); + ret = sysdb_error_to_errno(lret); + + if (ret == EOK && dn != NULL) { + *dn = talloc_steal(mem_ctx, msg->dn); + } + +done: + if (ret != 0) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Error: %d (%s)\n", ret, strerror(ret)); + } + talloc_free(tmp_ctx); + return ret; +} + +static errno_t +sysdb_host_update(struct sysdb_ctx *sysdb, + struct ldb_dn *dn, + const char **aliases, + const char **addresses) +{ + errno_t ret; + struct ldb_message *msg; + int lret; + unsigned int i; + size_t len; + + if (dn == NULL || addresses[0] == NULL) { + return EINVAL; + } + + msg = ldb_msg_new(NULL); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = dn; + + if (aliases != NULL && aliases[0] != NULL) { + /* Update the aliases */ + lret = ldb_msg_add_empty(msg, SYSDB_NAME_ALIAS, SYSDB_MOD_REP, NULL); + if (lret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + len = talloc_array_length(aliases); + for (i = 0; i < len && aliases[i] != NULL; i++) { + lret = ldb_msg_add_string(msg, SYSDB_NAME_ALIAS, aliases[i]); + if (lret != LDB_SUCCESS) { + ret = EINVAL; + goto done; + } + } + } + + /* Update the addresses */ + lret = ldb_msg_add_empty(msg, SYSDB_IP_HOST_ATTR_ADDRESS, + SYSDB_MOD_REP, NULL); + if (lret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + len = talloc_array_length(addresses); + for (i = 0; i < len && addresses[i] != NULL; i++) { + lret = ldb_msg_add_string(msg, SYSDB_IP_HOST_ATTR_ADDRESS, + addresses[i]); + if (lret != LDB_SUCCESS) { + ret = EINVAL; + goto done; + } + } + + lret = ldb_modify(sysdb->ldb, msg); + if (lret != LDB_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, + "ldb_modify failed: [%s](%d)[%s]\n", + ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)); + } + ret = sysdb_error_to_errno(lret); + +done: + if (ret) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Error: %d (%s)\n", ret, strerror(ret)); + } + talloc_free(msg); + return ret; +} + + +errno_t +sysdb_host_remove_alias(struct sysdb_ctx *sysdb, + struct ldb_dn *dn, + const char *alias) +{ + errno_t ret; + struct ldb_message *msg; + int lret; + + msg = ldb_msg_new(NULL); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = dn; + + ret = sysdb_delete_string(msg, SYSDB_NAME_ALIAS, alias); + if (ret != EOK) { + goto done; + } + + lret = ldb_modify(sysdb->ldb, msg); + if (lret != LDB_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, + "ldb_modify failed: [%s](%d)[%s]\n", + ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)); + } + ret = sysdb_error_to_errno(lret); + +done: + if (ret) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Error: %d (%s)\n", ret, strerror(ret)); + } + talloc_zfree(msg); + return ret; +} + + +errno_t sysdb_host_delete(struct sss_domain_info *domain, + const char *name, + const char *address) +{ + errno_t ret, sret; + TALLOC_CTX *tmp_ctx; + struct ldb_result *res; + unsigned int i; + bool in_transaction = false; + struct sysdb_ctx *sysdb = domain->sysdb; + + DEBUG(SSSDBG_TRACE_FUNC, "Deleting host [%s] - [%s] from domain [%s]\n", + name, address, domain->name); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); + goto done; + } + + in_transaction = true; + + if (name != NULL) { + ret = sysdb_gethostbyname(tmp_ctx, domain, name, &res); + if (ret != EOK && ret != ENOENT) { + goto done; + } + + if (ret == ENOENT) { + /* Doesn't exist in the DB. Nothing to do */ + ret = EOK; + goto done; + } + } else if (address != NULL) { + ret = sysdb_gethostbyaddr(tmp_ctx, domain, address, &res); + if (ret != EOK && ret != ENOENT) { + goto done; + } + + if (ret == ENOENT) { + /* Doesn't exist in the DB. Nothing to do */ + ret = EOK; + goto done; + } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "Host name or address needed\n"); + ret = EINVAL; + goto done; + } + + /* There should only be one matching entry, + * but if there are multiple, we should delete + * them all to de-corrupt the DB. + */ + for (i = 0; i < res->count; i++) { + ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, false); + if (ret != EOK) { + goto done; + } + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); + goto done; + } + in_transaction = false; + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not cancel transaction\n"); + } + } + + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Error: %d (%s)\n", ret, strerror(ret)); + } + talloc_free(tmp_ctx); + return ret; +} + +errno_t sysdb_search_hosts(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *sub_filter, + const char **attrs, + size_t *msgs_count, + struct ldb_message ***msgs) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_dn *basedn; + char *filter; + int ret; + + DEBUG(SSSDBG_TRACE_FUNC, "Searching hosts with subfilter [%s] in " + "domain [%s]\n", sub_filter, domain->name); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to allocate memory\n"); + return ENOMEM; + } + + basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, + SYSDB_TMPL_IP_HOST_BASE, domain->name); + if (basedn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to build base dn\n"); + ret = ENOMEM; + goto fail; + } + + filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_IP_HOST_CLASS_FILTER, + sub_filter); + if (filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n"); + ret = ENOMEM; + goto fail; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, "Searching hosts with filter [%s] in " + "domain [%s]\n", filter, domain->name); + + ret = sysdb_search_entry(mem_ctx, domain->sysdb, basedn, + LDB_SCOPE_SUBTREE, filter, attrs, + msgs_count, msgs); + if (ret) { + goto fail; + } + + talloc_free(tmp_ctx); + + return EOK; + +fail: + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_INTERNAL, "No such entry\n"); + } + else if (ret) { + DEBUG(SSSDBG_MINOR_FAILURE, "Error: %d (%s)\n", ret, strerror(ret)); + } + + talloc_free(tmp_ctx); + + return ret; +} + +errno_t +sysdb_enumhostent(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + struct ldb_result **_res) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + static const char *attrs[] = { + SYSDB_NAME, + SYSDB_NAME_ALIAS, + SYSDB_IP_HOST_ATTR_ADDRESS, + NULL, + }; + struct ldb_result *res = NULL; + struct ldb_message **msgs; + size_t msgs_count; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sysdb_search_hosts(mem_ctx, domain, "", + attrs, &msgs_count, &msgs); + if (ret == EOK) { + res = talloc_zero(mem_ctx, struct ldb_result); + if (res == NULL) { + ret = ENOMEM; + goto done; + } + res->count = msgs_count; + res->msgs = talloc_steal(res, msgs); + } + + *_res = res; + +done: + talloc_free(tmp_ctx); + return ret; +} |