@@ -, +, @@ 
---
 source3/libsmb/dsgetdcname.c | 49 +++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 23 deletions(-)
--- a/source3/libsmb/dsgetdcname.c	
+++ a/source3/libsmb/dsgetdcname.c	
@@ -551,14 +551,20 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 	}
 
+	/* Check for integer wrap. */
+	if (numdcs + numdcs < numdcs) {
+		TALLOC_FREE(dcs);
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 	/*
-	 * We're only returning one address per
-	 * DC name, so just allocate size numdcs.
+	 * We're only returning up to 2 addresses per
+	 * DC name, so just allocate size numdcs x 2.
 	 */
 
 	dclist = talloc_zero_array(mem_ctx,
 				   struct ip_service_name,
-				   numdcs);
+				   numdcs * 2);
 	if (!dclist) {
 		TALLOC_FREE(dcs);
 		return NT_STATUS_NO_MEMORY;
@@ -571,17 +577,16 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
 	ret_count = 0;
 	for (i = 0; i < numdcs; i++) {
 		size_t j;
+		bool have_v4_addr = false;
+		bool have_v6_addr = false;
 
 		if (dcs[i].num_ips == 0) {
 			continue;
 		}
 
-		dclist[ret_count].hostname =
-			talloc_move(dclist, &dcs[i].hostname);
-
 		/*
-		 * Pick the first IPv4 address,
-		 * if none pick the first address.
+		 * Pick up to 1 address from each address
+		 * family (IPv4, IPv6).
 		 *
 		 * This is different from the previous
 		 * code which picked a 'next ip' address
@@ -589,8 +594,11 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
 		 * Too complex to maintain :-(.
 		 */
 		for (j = 0; j < dcs[i].num_ips; j++) {
-			if (dcs[i].ss_s[j].ss_family == AF_INET) {
+			if ((dcs[i].ss_s[j].ss_family == AF_INET && !have_v4_addr) ||
+			    (dcs[i].ss_s[j].ss_family == AF_INET6 && !have_v6_addr)) {
 				bool ok;
+				dclist[ret_count].hostname =
+					talloc_strdup(dclist, dcs[i].hostname);
 				ok = sockaddr_storage_to_samba_sockaddr(
 					&dclist[ret_count].sa,
 					&dcs[i].ss_s[j]);
@@ -599,22 +607,17 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
 					TALLOC_FREE(dclist);
 					return NT_STATUS_INVALID_PARAMETER;
 				}
-				break;
-			}
-		}
-		if (j == dcs[i].num_ips) {
-			/* No IPv4- use the first IPv6 addr. */
-			bool ok;
-			ok = sockaddr_storage_to_samba_sockaddr(
-					&dclist[ret_count].sa,
-					&dcs[i].ss_s[0]);
-			if (!ok) {
-				TALLOC_FREE(dcs);
-				TALLOC_FREE(dclist);
-				return NT_STATUS_INVALID_PARAMETER;
+				ret_count++;
+				if (dcs[i].ss_s[j].ss_family == AF_INET) {
+					have_v4_addr = true;
+				} else {
+					have_v6_addr = true;
+				}
+				if (have_v4_addr && have_v6_addr) {
+					break;
+				}
 			}
 		}
-		ret_count++;
 	}
 
 	TALLOC_FREE(dcs);
-- 
 NETLOGON_NT_VERSION_AVOID_NT4EMUL
---
 source3/libsmb/dsgetdcname.c | 5 +++++
 1 file changed, 5 insertions(+)
--- a/source3/libsmb/dsgetdcname.c	
+++ a/source3/libsmb/dsgetdcname.c	
@@ -930,6 +930,11 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
 		name_type = NBT_NAME_PDC;
 	}
 
+	/*
+	 * It's 2024 we always want an AD style response!
+	 */
+	nt_version |= NETLOGON_NT_VERSION_AVOID_NT4EMUL;
+
 	nt_version |= map_ds_flags_to_nt_version(flags);
 
 	snprintf(my_acct_name,
-- 
 response
---
 source3/libsmb/dsgetdcname.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)
--- a/source3/libsmb/dsgetdcname.c	
+++ a/source3/libsmb/dsgetdcname.c	
@@ -196,7 +196,29 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
 	/* FIXME */
 	r->sockaddr_size = 0x10; /* the w32 winsock addr size */
 	r->sockaddr.sockaddr_family = 2; /* AF_INET */
-	r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
+	if (is_ipaddress_v4(addr)) {
+		r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
+		if (r->sockaddr.pdc_ip == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	} else {
+		/*
+		 * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX will
+		 * fail with an ipv6 address.
+		 *
+		 * This matches windows behaviour in the CLDAP
+		 * response when NETLOGON_NT_VERSION_5EX_WITH_IP
+		 * is used.
+		 *
+		 * Windows returns the ipv4 address of the ipv6
+		 * server interface and falls back to 127.0.0.1
+		 * if there's no ipv4 address.
+		 */
+		r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, "127.0.0.1");
+		if (r->sockaddr.pdc_ip == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
 
 	ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
 		       (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
-- 
 DOMAIN_CONTROLLER_NOT_FOUND
---
 source3/libsmb/dsgetdcname.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
--- a/source3/libsmb/dsgetdcname.c	
+++ a/source3/libsmb/dsgetdcname.c	
@@ -483,7 +483,19 @@ static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
 					&count,
 					resolve_order);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
+		NTSTATUS raw_status = status;
+
+		if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+			status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+		}
+		if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_ADDRESS)) {
+			status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+		}
+
+		DBG_DEBUG("failed to find DC for %s: %s => %s\n",
+			  domain_name,
+			  nt_errstr(raw_status),
+			  nt_errstr(status));
 		return status;
 	}
 
-- 
 'talloc_strdup failed'
---
 source3/winbindd/winbindd_cm.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
--- a/source3/winbindd/winbindd_cm.c	
+++ a/source3/winbindd/winbindd_cm.c	
@@ -540,7 +540,8 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
 			tmp = talloc_strdup(
 				mem_ctx, domain_info->dc_unc);
 			if (tmp == NULL) {
-				DEBUG(0, ("talloc_strdup failed\n"));
+				DBG_ERR("talloc_strdup failed for dc_unc[%s]\n",
+					domain_info->dc_unc);
 				talloc_destroy(mem_ctx);
 				return false;
 			}
@@ -548,7 +549,9 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
 				domain->alt_name = talloc_strdup(domain,
 								 domain_info->domain_name);
 				if (domain->alt_name == NULL) {
-					DEBUG(0, ("talloc_strdup failed\n"));
+					DBG_ERR("talloc_strdup failed for "
+						"domain_info->domain_name[%s]\n",
+						domain_info->domain_name);
 					talloc_destroy(mem_ctx);
 					return false;
 				}
@@ -557,7 +560,9 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
 				domain->forest_name = talloc_strdup(domain,
 								    domain_info->forest_name);
 				if (domain->forest_name == NULL) {
-					DEBUG(0, ("talloc_strdup failed\n"));
+					DBG_ERR("talloc_strdup failed for "
+						"domain_info->forest_name[%s]\n",
+						domain_info->forest_name);
 					talloc_destroy(mem_ctx);
 					return false;
 				}
-- 
 name
---
 source3/winbindd/winbindd_cm.c       | 150 ---------------------------
 source3/winbindd/winbindd_dual_srv.c | 105 +------------------
 2 files changed, 5 insertions(+), 250 deletions(-)
--- a/source3/winbindd/winbindd_cm.c	
+++ a/source3/winbindd/winbindd_cm.c	
@@ -475,140 +475,6 @@ static bool cm_is_ipc_credentials(struct cli_credentials *creds)
 	return ret;
 }
 
-static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
-				     fstring dcname,
-				     struct sockaddr_storage *dc_ss,
-				     uint32_t request_flags)
-{
-	struct winbindd_domain *our_domain = NULL;
-	struct rpc_pipe_client *netlogon_pipe = NULL;
-	NTSTATUS result;
-	WERROR werr;
-	TALLOC_CTX *mem_ctx;
-	unsigned int orig_timeout;
-	const char *tmp = NULL;
-	const char *p;
-	struct dcerpc_binding_handle *b;
-
-	/* Hmmmm. We can only open one connection to the NETLOGON pipe at the
-	 * moment.... */
-
-	if (IS_DC) {
-		return False;
-	}
-
-	if (domain->primary) {
-		return False;
-	}
-
-	our_domain = find_our_domain();
-
-	if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
-		return False;
-	}
-
-	result = cm_connect_netlogon(our_domain, &netlogon_pipe);
-	if (!NT_STATUS_IS_OK(result)) {
-		talloc_destroy(mem_ctx);
-		return False;
-	}
-
-	b = netlogon_pipe->binding_handle;
-
-	/* This call can take a long time - allow the server to time out.
-	   35 seconds should do it. */
-
-	orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
-
-	if (our_domain->active_directory) {
-		struct netr_DsRGetDCNameInfo *domain_info = NULL;
-
-		/*
-		 * TODO request flags are not respected in the server
-		 * (and in some cases, like REQUIRE_PDC, causes an error)
-		 */
-		result = dcerpc_netr_DsRGetDCName(b,
-						  mem_ctx,
-						  our_domain->dcname,
-						  domain->name,
-						  NULL,
-						  NULL,
-						  request_flags|DS_RETURN_DNS_NAME,
-						  &domain_info,
-						  &werr);
-		if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
-			tmp = talloc_strdup(
-				mem_ctx, domain_info->dc_unc);
-			if (tmp == NULL) {
-				DBG_ERR("talloc_strdup failed for dc_unc[%s]\n",
-					domain_info->dc_unc);
-				talloc_destroy(mem_ctx);
-				return false;
-			}
-			if (domain->alt_name == NULL) {
-				domain->alt_name = talloc_strdup(domain,
-								 domain_info->domain_name);
-				if (domain->alt_name == NULL) {
-					DBG_ERR("talloc_strdup failed for "
-						"domain_info->domain_name[%s]\n",
-						domain_info->domain_name);
-					talloc_destroy(mem_ctx);
-					return false;
-				}
-			}
-			if (domain->forest_name == NULL) {
-				domain->forest_name = talloc_strdup(domain,
-								    domain_info->forest_name);
-				if (domain->forest_name == NULL) {
-					DBG_ERR("talloc_strdup failed for "
-						"domain_info->forest_name[%s]\n",
-						domain_info->forest_name);
-					talloc_destroy(mem_ctx);
-					return false;
-				}
-			}
-		}
-	} else {
-		result = dcerpc_netr_GetAnyDCName(b, mem_ctx,
-						  our_domain->dcname,
-						  domain->name,
-						  &tmp,
-						  &werr);
-	}
-
-	/* And restore our original timeout. */
-	rpccli_set_timeout(netlogon_pipe, orig_timeout);
-
-	if (!NT_STATUS_IS_OK(result)) {
-		DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
-			nt_errstr(result)));
-		talloc_destroy(mem_ctx);
-		return false;
-	}
-
-	if (!W_ERROR_IS_OK(werr)) {
-		DEBUG(10,("dcerpc_netr_GetAnyDCName failed: %s\n",
-			   win_errstr(werr)));
-		talloc_destroy(mem_ctx);
-		return false;
-	}
-
-	/* dcerpc_netr_GetAnyDCName gives us a name with \\ */
-	p = strip_hostname(tmp);
-
-	fstrcpy(dcname, p);
-
-	talloc_destroy(mem_ctx);
-
-	DEBUG(10,("dcerpc_netr_GetAnyDCName returned %s\n", dcname));
-
-	if (!resolve_name(dcname, dc_ss, 0x20, true)) {
-		return False;
-	}
-
-	return True;
-}
-
 /**
  * Helper function to assemble trust password and account name
  */
@@ -1243,24 +1109,8 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
 	struct  samba_sockaddr *sa_list = NULL;
 	size_t     salist_size = 0;
 	size_t     i;
-	bool    is_our_domain;
 	enum security_types sec = (enum security_types)lp_security();
 
-	is_our_domain = strequal(domain->name, lp_workgroup());
-
-	/* If not our domain, get the preferred DC, by asking our primary DC */
-	if ( !is_our_domain
-		&& get_dc_name_via_netlogon(domain, dcname, &ss, request_flags)
-		&& add_one_dc_unique(mem_ctx, domain->name, dcname, &ss, dcs,
-		       num_dcs) )
-	{
-		char addr[INET6_ADDRSTRLEN];
-		print_sockaddr(addr, sizeof(addr), &ss);
-		DEBUG(10, ("Retrieved DC %s at %s via netlogon\n",
-			   dcname, addr));
-		return True;
-	}
-
 	if ((sec == SEC_ADS) && (domain->alt_name != NULL)) {
 		char *sitename = NULL;
 
--- a/source3/winbindd/winbindd_dual_srv.c	
+++ a/source3/winbindd/winbindd_dual_srv.c	
@@ -592,106 +592,11 @@ NTSTATUS _wbint_QueryUserRidList(struct pipes_struct *p,
 
 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
 {
-	struct winbindd_domain *domain = wb_child_domain();
-	struct rpc_pipe_client *netlogon_pipe;
-	struct netr_DsRGetDCNameInfo *dc_info;
-	NTSTATUS status;
-	WERROR werr;
-	unsigned int orig_timeout;
-	struct dcerpc_binding_handle *b;
-	bool retry = false;
-	bool try_dsrgetdcname = false;
-
-	if (domain == NULL) {
-		return dsgetdcname(p->mem_ctx, global_messaging_context(),
-				   r->in.domain_name, r->in.domain_guid,
-				   r->in.site_name ? r->in.site_name : "",
-				   r->in.flags,
-				   r->out.dc_info);
-	}
-
-	if (domain->active_directory) {
-		try_dsrgetdcname = true;
-	}
-
-reconnect:
-	status = cm_connect_netlogon(domain, &netlogon_pipe);
-
-	reset_cm_connection_on_error(domain, NULL, status);
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
-		return status;
-	}
-
-	b = netlogon_pipe->binding_handle;
-
-	/* This call can take a long time - allow the server to time out.
-	   35 seconds should do it. */
-
-	orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
-
-	if (try_dsrgetdcname) {
-		status = dcerpc_netr_DsRGetDCName(b,
-			p->mem_ctx, domain->dcname,
-			r->in.domain_name, NULL, r->in.domain_guid,
-			r->in.flags, r->out.dc_info, &werr);
-		if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
-			goto done;
-		}
-		if (!retry &&
-		    reset_cm_connection_on_error(domain, NULL, status))
-		{
-			retry = true;
-			goto reconnect;
-		}
-		try_dsrgetdcname = false;
-		retry = false;
-	}
-
-	/*
-	 * Fallback to less capable methods
-	 */
-
-	dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
-	if (dc_info == NULL) {
-		status = NT_STATUS_NO_MEMORY;
-		goto done;
-	}
-
-	if (r->in.flags & DS_PDC_REQUIRED) {
-		status = dcerpc_netr_GetDcName(b,
-			p->mem_ctx, domain->dcname,
-			r->in.domain_name, &dc_info->dc_unc, &werr);
-	} else {
-		status = dcerpc_netr_GetAnyDCName(b,
-			p->mem_ctx, domain->dcname,
-			r->in.domain_name, &dc_info->dc_unc, &werr);
-	}
-
-	if (!retry && reset_cm_connection_on_error(domain, b, status)) {
-		retry = true;
-		goto reconnect;
-	}
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
-			   nt_errstr(status)));
-		goto done;
-	}
-	if (!W_ERROR_IS_OK(werr)) {
-		DEBUG(10, ("dcerpc_netr_Get[Any]DCName failed: %s\n",
-			   win_errstr(werr)));
-		status = werror_to_ntstatus(werr);
-		goto done;
-	}
-
-	*r->out.dc_info = dc_info;
-	status = NT_STATUS_OK;
-
-done:
-	/* And restore our original timeout. */
-	rpccli_set_timeout(netlogon_pipe, orig_timeout);
-
-	return status;
+	return dsgetdcname(p->mem_ctx, global_messaging_context(),
+			   r->in.domain_name, r->in.domain_guid,
+			   r->in.site_name ? r->in.site_name : "",
+			   r->in.flags,
+			   r->out.dc_info);
 }
 
 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
-- 
 w.r.t. domain name
---
 source3/winbindd/wb_queryuser.c   | 18 ++++++++++++++----
 source3/winbindd/wb_sids2xids.c   | 16 +++++++++++++---
 source3/winbindd/wb_xids2sids.c   | 12 +++++++++---
 source3/winbindd/winbindd_dual.c  |  6 +++++-
 source3/winbindd/winbindd_proto.h |  1 +
 source3/winbindd/winbindd_util.c  | 19 +++++++++++++++++++
 6 files changed, 61 insertions(+), 11 deletions(-)
--- a/source3/winbindd/wb_queryuser.c	
+++ a/source3/winbindd/wb_queryuser.c	
@@ -359,9 +359,19 @@ static void wb_queryuser_got_nssinfo(struct tevent_req *subreq)
 
 	if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) &&
 	    !state->tried_dclookup) {
-		subreq = wb_dsgetdcname_send(
-			state, state->ev, state->info->domain_name, NULL, NULL,
-			DS_RETURN_DNS_NAME);
+		const char *domain_name = find_dns_domain_name(
+			state->info->domain_name);
+
+		D_DEBUG("GetNssInfo got DOMAIN_CONTROLLER_NOT_FOUND, calling "
+			"wb_dsgetdcname_send(%s)\n",
+			domain_name);
+
+		subreq = wb_dsgetdcname_send(state,
+					     state->ev,
+					     domain_name,
+					     NULL,
+					     NULL,
+					     DS_RETURN_DNS_NAME);
 		if (tevent_req_nomem(subreq, req)) {
 			return;
 		}
@@ -526,4 +536,4 @@ NTSTATUS wb_queryuser_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
 	}
 	*pinfo = talloc_move(mem_ctx, &state->info);
 	return NT_STATUS_OK;
-}
+}
--- a/source3/winbindd/wb_sids2xids.c	
+++ a/source3/winbindd/wb_sids2xids.c	
@@ -566,12 +566,22 @@ static void wb_sids2xids_done(struct tevent_req *subreq)
 	    !state->tried_dclookup) {
 
 		struct lsa_DomainInfo *d;
+		const char *domain_name = NULL;
 
 		d = &state->idmap_doms.domains[state->dom_index];
 
-		subreq = wb_dsgetdcname_send(
-			state, state->ev, d->name.string, NULL, NULL,
-			DS_RETURN_DNS_NAME);
+		domain_name = find_dns_domain_name(d->name.string);
+
+		D_DEBUG("Domain controller not found. Calling "
+			"wb_dsgetdcname_send(%s) to get it.\n",
+			domain_name);
+
+		subreq = wb_dsgetdcname_send(state,
+					     state->ev,
+					     domain_name,
+					     NULL,
+					     NULL,
+					     DS_RETURN_DNS_NAME);
 		if (tevent_req_nomem(subreq, req)) {
 			return;
 		}
--- a/source3/winbindd/wb_xids2sids.c	
+++ a/source3/winbindd/wb_xids2sids.c	
@@ -130,9 +130,15 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq)
 	if (NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) &&
 	    !state->tried_dclookup) {
 
-		subreq = wb_dsgetdcname_send(
-			state, state->ev, state->dom_map->name, NULL, NULL,
-			DS_RETURN_DNS_NAME);
+		const char *domain_name = find_dns_domain_name(
+			state->dom_map->name);
+
+		subreq = wb_dsgetdcname_send(state,
+					     state->ev,
+					     domain_name,
+					     NULL,
+					     NULL,
+					     DS_RETURN_DNS_NAME);
 		if (tevent_req_nomem(subreq, req)) {
 			return;
 		}
--- a/source3/winbindd/winbindd_dual.c	
+++ a/source3/winbindd/winbindd_dual.c	
@@ -523,6 +523,7 @@ static void wb_domain_request_trigger(struct tevent_req *req,
 	struct wb_domain_request_state *state = tevent_req_data(
 		req, struct wb_domain_request_state);
 	struct winbindd_domain *domain = state->domain;
+	const char *domain_name = NULL;
 	struct tevent_req *subreq = NULL;
 	size_t shortest_queue_length;
 
@@ -593,8 +594,11 @@ static void wb_domain_request_trigger(struct tevent_req *req,
 	 * which is indicated by DS_RETURN_DNS_NAME.
 	 * For NT4 domains we still get the netbios name.
 	 */
+
+	domain_name = find_dns_domain_name(state->domain->name);
+
 	subreq = wb_dsgetdcname_send(state, state->ev,
-				     state->domain->name,
+				     domain_name,
 				     NULL, /* domain_guid */
 				     NULL, /* site_name */
 				     DS_RETURN_DNS_NAME); /* flags */
--- a/source3/winbindd/winbindd_proto.h	
+++ a/source3/winbindd/winbindd_proto.h	
@@ -548,6 +548,7 @@ bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
 		   struct dom_sid **sids, uint32_t *num_sids);
 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
 		   struct unixid **pxids, uint32_t *pnum_xids);
+const char *find_dns_domain_name(const char *domain_name);
 
 /* The following definitions come from winbindd/winbindd_wins.c  */
 
--- a/source3/winbindd/winbindd_util.c	
+++ a/source3/winbindd/winbindd_util.c	
@@ -2314,3 +2314,22 @@ fail:
 	TALLOC_FREE(xids);
 	return false;
 }
+
+/**
+ * Helper to extract the DNS Domain Name from a struct winbindd_domain
+ */
+const char *find_dns_domain_name(const char *domain_name)
+{
+	struct winbindd_domain *wbdom = NULL;
+
+	wbdom = find_domain_from_name(domain_name);
+	if (wbdom == NULL) {
+		return domain_name;
+	}
+
+	if (wbdom->active_directory && wbdom->alt_name != NULL) {
+		return wbdom->alt_name;
+	}
+
+	return wbdom->name;
+}
-- 

