const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
				   const char *ip_address, char **subnet_name,
				   bool fallback)
{
	const char *attrs[] = { "cn", "siteObject", NULL };
	struct ldb_dn *sites_container_dn = NULL;
	struct ldb_dn *subnets_dn = NULL;
	struct ldb_dn *sites_dn = NULL;
	struct ldb_result *res = NULL;
	const struct ldb_val *val = NULL;
	const char *site_name = NULL;
	const char *l_subnet_name = NULL;
	const char *allow_list[2] = { NULL, NULL };
	unsigned int i, count;
	int ret;

	/*
	 * if we don't have a client ip e.g. ncalrpc
	 * the server site is the client site
	 */
	if (ip_address == NULL) {
		return samdb_server_site_name(ldb, mem_ctx);
	}

	sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
	if (sites_container_dn == NULL) {
		goto exit;
	}

	subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
	if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
		goto exit;
	}

	ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
			 attrs, NULL);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		count = 0;
	} else if (ret != LDB_SUCCESS) {
		goto exit;
	} else {
		count = res->count;
	}

	for (i = 0; i < count; i++) {
		l_subnet_name = ldb_msg_find_attr_as_string(res->msgs[i], "cn",
							    NULL);

		allow_list[0] = l_subnet_name;

		if (allow_access_nolog(NULL, allow_list, "", ip_address)) {
			sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
							   res->msgs[i],
							   "siteObject");
			if (sites_dn == NULL) {
				/* No reference, maybe another subnet matches */
				continue;
			}

			/* "val" cannot be NULL here since "sites_dn" != NULL */
			val = ldb_dn_get_rdn_val(sites_dn);
			site_name = talloc_strdup(mem_ctx,
						  (const char *) val->data);

			TALLOC_FREE(sites_dn);

			break;
		}
	}

	if (site_name == NULL && fallback) {
		/* This is the Windows Server fallback rule: when no subnet
		 * exists and we have only one site available then use it (it
		 * is for sure the same as our server site). If more sites do
		 * exist then we don't know which one to use and set the site
		 * name to "". */
		size_t cnt = 0;
		ret = dsdb_domain_count(
			ldb,
			&cnt,
			sites_container_dn,
			NULL,
			LDB_SCOPE_SUBTREE,
			"(objectClass=site)");
		if (ret != LDB_SUCCESS) {
			goto exit;
		}
		if (cnt == 1) {
			site_name = samdb_server_site_name(ldb, mem_ctx);
		} else {
			site_name = talloc_strdup(mem_ctx, "");
		}
		l_subnet_name = NULL;
	}

	if (subnet_name != NULL) {
		*subnet_name = talloc_strdup(mem_ctx, l_subnet_name);
	}

exit:
	TALLOC_FREE(sites_container_dn);
	TALLOC_FREE(subnets_dn);
	TALLOC_FREE(res);

	return site_name;
}
const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
				   const char *ip_address, char **subnet_name,
				   bool fallback)
{
	const char *attrs[] = { "cn", "siteObject", NULL };
	struct ldb_dn *sites_container_dn = NULL;
	struct ldb_dn *subnets_dn = NULL;
	struct ldb_dn *sites_dn = NULL;
	struct ldb_result *res = NULL;
	const struct ldb_val *val = NULL;
	const char *site_name = NULL;
	const char *l_subnet_name = NULL;
	const char *allow_list[2] = { NULL, NULL };
	unsigned int i, count;
	int ret;

	 
	if (ip_address == NULL) {
		return samdb_server_site_name(ldb, mem_ctx);
	}

	sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
	if (sites_container_dn == NULL) {
		goto exit;
	}

	subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
	if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
		goto exit;
	}

	ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
			 attrs, NULL);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		count = 0;
	} else if (ret != LDB_SUCCESS) {
		goto exit;
	} else {
		count = res->count;
	}

	for (i = 0; i < count; i++) {
		l_subnet_name = ldb_msg_find_attr_as_string(res->msgs[i], "cn",
							    NULL);

		allow_list[0] = l_subnet_name;

		if (allow_access_nolog(NULL, allow_list, "", ip_address)) {
			sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
							   res->msgs[i],
							   "siteObject");
			if (sites_dn == NULL) {
				 
				continue;
			}

			 
			val = ldb_dn_get_rdn_val(sites_dn);
			site_name = talloc_strdup(mem_ctx,
						  (const char *) val->data);

			TALLOC_FREE(sites_dn);

			break;
		}
	}

	if (site_name == NULL && fallback) {
		 
		size_t cnt = 0;
		ret = dsdb_domain_count(
			ldb,
			&cnt,
			sites_container_dn,
			NULL,
			LDB_SCOPE_SUBTREE,
			"(objectClass=site)");
		if (ret != LDB_SUCCESS) {
			goto exit;
		}
		if (cnt == 1) {
			site_name = samdb_server_site_name(ldb, mem_ctx);
		} else {
			site_name = talloc_strdup(mem_ctx, "");
		}
		l_subnet_name = NULL;
	}

	if (subnet_name != NULL) {
		*subnet_name = talloc_strdup(mem_ctx, l_subnet_name);
	}

exit:
	TALLOC_FREE(sites_container_dn);
	TALLOC_FREE(subnets_dn);
	TALLOC_FREE(res);

	return site_name;
}