--- a/source3/modules/vfs_dfs_samba4.c 2014-01-07 16:22:59.876000000 +0100 +++ b/source3/modules/vfs_dfs_samba4.c.orig 2014-01-08 16:44:12.220000000 +0100 @@ -106,6 +106,7 @@ { struct dfs_samba4_handle_data *data; NTSTATUS status; + const char *preferred_DC = NULL; SMB_VFS_HANDLE_GET_DATA(handle, data, struct dfs_samba4_handle_data, @@ -115,8 +116,15 @@ r->in.req.servername, (unsigned int)strlen_m(r->in.req.servername)*2)); + if (lp_parm_bool(SNUM(handle->conn), "dfs_samba4", "preferLogonDC", false)) { + preferred_DC = handle->conn->session_info->info->logon_server; + DEBUG(8, ("dfs_samba4: Preferred DC: %s\n", + preferred_DC)); + } + status = dfs_server_ad_get_referrals(data->lp_ctx, data->sam_ctx, + preferred_DC, handle->conn->sconn->remote_address, r); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { --- a/dfs_server/dfs_server_ad.c 2014-01-07 16:23:00.516000000 +0100 +++ b/dfs_server/dfs_server_ad.c.orig 2014-01-08 16:22:14.996000000 +0100 @@ -261,7 +293,10 @@ /* get all DCs */ -static NTSTATUS get_dcs(TALLOC_CTX *ctx, struct ldb_context *ldb, +static NTSTATUS get_dcs(TALLOC_CTX *ctx, + struct loadparm_context *lp_ctx, + struct ldb_context *ldb, + const char *logon_server, const char *searched_site, bool need_fqdn, struct dc_set ***pset_list, uint32_t flags) { @@ -285,6 +320,74 @@ subctx = talloc_new(ctx); NT_STATUS_HAVE_NO_MEMORY(subctx); + if (logon_server != NULL) { + + DEBUG(2,(__location__ ": dfs_server_ad: get_dcs realloc\n")); + set_list = talloc_realloc(subctx, set_list, struct dc_set *, current_pos+2); + DEBUG(2,(__location__ ": dfs_server_ad: get_dcs realloc done\n")); + if (set_list == NULL) { + TALLOC_FREE(subctx); + return NT_STATUS_NO_MEMORY; + } + set_list[current_pos] = talloc(set_list, struct dc_set); + if (set_list[current_pos] == NULL) { + TALLOC_FREE(subctx); + return NT_STATUS_NO_MEMORY; + } + set_list[current_pos]->names = NULL; + set_list[current_pos]->count = 0; + + set_list[current_pos+1] = NULL; + + DEBUG(2,(__location__ ": dfs_server_ad: get_dcs realloc names\n")); + set_list[current_pos]->names = talloc_realloc(set_list, set_list[current_pos]->names, const char *, 1); + DEBUG(2,(__location__ ": dfs_server_ad: get_dcs realloc names done\n")); + if (set_list[current_pos]->names == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (need_fqdn) { + struct ldb_result *r; + struct ldb_dn *domaindn = ldb_get_default_basedn(ldb); + static const char *attrs[] = { "dNSHostName", NULL }; + const char *searchfilter = talloc_asprintf(subctx, "(&(objectClass=computer)(sAMAccountName=%s$))", logon_server); + + ret = ldb_search(ldb, subctx, &r, domaindn, LDB_SCOPE_SUBTREE, attrs, searchfilter); + if (ret != LDB_SUCCESS) { + DEBUG(2,(__location__ ": Search for computer %s failed - %s\n", + logon_server, ldb_errstring(ldb))); + talloc_free(subctx); + return NT_STATUS_INTERNAL_ERROR; + } + + const char *dns = ldb_msg_find_attr_as_string(r->msgs[0], "dNSHostName", NULL); + if (dns == NULL) { + DEBUG(2,(__location__ ": dNSHostName missing on %s\n", + ldb_dn_get_linearized(r->msgs[0]->dn))); + talloc_free(subctx); + talloc_free(r); + return NT_STATUS_INTERNAL_ERROR; + } + + set_list[current_pos]->names[0] = talloc_strdup(set_list, dns); + if (set_list[current_pos]->names[0] == NULL) { + talloc_free(subctx); + talloc_free(r); + return NT_STATUS_NO_MEMORY; + } + talloc_free(r); + } else { + set_list[current_pos]->names[0] = talloc_strdup(set_list, logon_server); + if (set_list[current_pos]->names[0] == NULL) { + talloc_free(subctx); + return NT_STATUS_NO_MEMORY; + } + } + + set_list[current_pos]->count = 1; + current_pos++; + } + configdn = ldb_get_config_basedn(ldb); /* Let's search for the Site container */ @@ -556,7 +676,7 @@ site_name = samdb_client_site_name(sam_ctx, r, client_str, NULL); - status = get_dcs(r, sam_ctx, site_name, need_fqdn, &set, 0); + status = get_dcs(r, lp_ctx, sam_ctx, NULL, site_name, need_fqdn, &set, 0); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("Unable to get list of DCs - %s\n", nt_errstr(status))); @@ -629,6 +749,7 @@ static NTSTATUS dosysvol_referral(struct loadparm_context *lp_ctx, struct ldb_context *sam_ctx, const struct tsocket_address *client, + const char *logon_server, struct dfs_GetDFSReferral *r, const char *domain_name, const char *dfs_name) @@ -667,7 +788,7 @@ site_name = samdb_client_site_name(sam_ctx, r, client_str, NULL); - status = get_dcs(r, sam_ctx, site_name, need_fqdn, &set, 0); + status = get_dcs(r, lp_ctx, sam_ctx, logon_server, site_name, need_fqdn, &set, 0); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("Unable to get list of DCs - %s\n", nt_errstr(status))); @@ -741,6 +862,7 @@ */ NTSTATUS dfs_server_ad_get_referrals(struct loadparm_context *lp_ctx, struct ldb_context *sam_ctx, + const char *logon_server, const struct tsocket_address *client, struct dfs_GetDFSReferral *r) { @@ -889,7 +1011,7 @@ */ if (strcasecmp(dfs_name, "sysvol") == 0 || strcasecmp(dfs_name, "netlogon") == 0) { - return dosysvol_referral(lp_ctx, sam_ctx, client, r, + return dosysvol_referral(lp_ctx, sam_ctx, client, logon_server, r, server_name, dfs_name); } --- a/dfs_server/dfs_server_ad.h 2014-01-07 16:23:00.516000000 +0100 +++ b/dfs_server/dfs_server_ad.h.orig 2014-01-07 20:48:40.764000000 +0100 @@ -19,5 +19,6 @@ NTSTATUS dfs_server_ad_get_referrals(struct loadparm_context *lp_ctx, struct ldb_context *sam_ctx, + const char *logon_server, const struct tsocket_address *client, struct dfs_GetDFSReferral *r);