summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Dieter Wallnöfer <mdw@samba.org>2010-04-13 18:28:53 +0200
committerAndrew Tridgell <tridge@samba.org>2010-04-27 15:24:41 +1000
commit093d35661d25d7fd89ce46fef5922768c0c0ace7 (patch)
tree7ed0b265e283b0176d173d2b03499fa1d19d75b6
parent725e48c22c92e284bb55567f2116c8ddc82a0529 (diff)
downloadsamba-093d35661d25d7fd89ce46fef5922768c0c0ace7.tar.gz
samba-093d35661d25d7fd89ce46fef5922768c0c0ace7.tar.bz2
samba-093d35661d25d7fd89ce46fef5922768c0c0ace7.zip
s4:util - add a function which finds the matching client site using the client address
The lookup of the client site is done using the subnets in the configuration partition. If no one matches we use the Windows Server fallback mechansim. This means: if only one site is available just use it. If they're more set the output variable to "". Signed-off-by: Andrew Tridgell <tridge@samba.org>
-rw-r--r--source4/dsdb/common/util.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 3a04797f82..7dd68b8b99 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -40,6 +40,7 @@
#include "system/locale.h"
#include "lib/util/tsort.h"
#include "dsdb/common/util.h"
+#include "lib/socket/socket.h"
/*
search the sam for the specified attributes in a specific domain, filter on
@@ -1593,6 +1594,95 @@ const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
}
/*
+ * Finds the client site by using the client's IP address.
+ * The "subnet_name" returns the name of the subnet if parameter != NULL
+ */
+const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ const char *ip_address, char **subnet_name)
+{
+ const char *attrs[] = { "cn", "siteObject", NULL };
+ struct ldb_dn *sites_container_dn, *subnets_dn, *sites_dn;
+ struct ldb_result *res;
+ const struct ldb_val *val;
+ const char *site_name = NULL, *l_subnet_name = NULL;
+ const char *allow_list[2] = { NULL, NULL };
+ unsigned int i;
+ int cnt, ret;
+
+ sites_container_dn = samdb_sites_dn(ldb, mem_ctx);
+ if (sites_container_dn == NULL) {
+ return NULL;
+ }
+
+ subnets_dn = ldb_dn_copy(mem_ctx, sites_container_dn);
+ if ( ! ldb_dn_add_child_fmt(subnets_dn, "CN=Subnets")) {
+ talloc_free(sites_container_dn);
+ talloc_free(subnets_dn);
+ return NULL;
+ }
+
+ ret = ldb_search(ldb, mem_ctx, &res, subnets_dn, LDB_SCOPE_ONELEVEL,
+ attrs, NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(sites_container_dn);
+ talloc_free(subnets_dn);
+ return NULL;
+ }
+
+ for (i = 0; i < res->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(mem_ctx, 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) {
+ /* 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 "". */
+ cnt = samdb_search_count(ldb, sites_container_dn,
+ "(objectClass=site)");
+ 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);
+ }
+
+ talloc_free(sites_container_dn);
+ talloc_free(subnets_dn);
+ talloc_free(res);
+
+ return site_name;
+}
+
+/*
work out if we are the PDC for the domain of the current open ldb
*/
bool samdb_is_pdc(struct ldb_context *ldb)