summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/dsgetdcname.c177
1 files changed, 168 insertions, 9 deletions
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 7834632806..874a7749b7 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -391,15 +391,60 @@ static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
const char *domain_name,
uint32_t flags,
struct ip_service_name **returned_dclist,
- int *return_count)
+ int *returned_count)
{
+ NTSTATUS status;
+ enum nbt_name_type name_type = NBT_NAME_LOGON;
+ struct ip_service *iplist;
+ int i;
+ struct ip_service_name *dclist = NULL;
+ int count;
+
+ *returned_dclist = NULL;
+ *returned_count = 0;
+
if (lp_disable_netbios()) {
return NT_STATUS_NOT_SUPPORTED;
}
- /* FIXME: code here */
+ if (flags & DS_PDC_REQUIRED) {
+ name_type = NBT_NAME_PDC;
+ }
- return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+ status = internal_resolve_name(domain_name, name_type, NULL,
+ &iplist, &count,
+ "lmhosts wins bcast");
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
+ return status;
+ }
+
+ dclist = TALLOC_ZERO_ARRAY(mem_ctx, struct ip_service_name, count);
+ if (!dclist) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<count; i++) {
+
+ char addr[INET6_ADDRSTRLEN];
+ struct ip_service_name *r = &dclist[i];
+
+ print_sockaddr(addr, sizeof(addr),
+ &iplist[i].ss);
+
+ r->ss = iplist[i].ss;
+ r->port = iplist[i].port;
+ r->hostname = talloc_strdup(mem_ctx, addr);
+ if (!r->hostname) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ }
+
+ *returned_dclist = dclist;
+ *returned_count = count;
+
+ return NT_STATUS_OK;
}
/****************************************************************
@@ -688,16 +733,130 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
/****************************************************************
****************************************************************/
+static struct event_context *ev_context(void)
+{
+ static struct event_context *ctx;
+
+ if (!ctx && !(ctx = event_context_init(NULL))) {
+ smb_panic("Could not init event context");
+ }
+ return ctx;
+}
+
+/****************************************************************
+****************************************************************/
+
+static struct messaging_context *msg_context(TALLOC_CTX *mem_ctx)
+{
+ static struct messaging_context *ctx;
+
+ if (!ctx && !(ctx = messaging_init(mem_ctx, server_id_self(),
+ ev_context()))) {
+ smb_panic("Could not init messaging context");
+ }
+ return ctx;
+}
+
+/****************************************************************
+****************************************************************/
+
static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
const char *domain_name,
uint32_t flags,
- struct ip_service_name **dclist,
+ struct ip_service_name *dclist,
int num_dcs,
struct netr_DsRGetDCNameInfo **info)
{
- /* FIXME: code here */
+ struct sockaddr_storage ss;
+ struct ip_service ip_list;
+ enum nbt_name_type name_type = NBT_NAME_LOGON;
+
+ int i;
+ const char *dc_hostname, *dc_domain_name;
+ const char *dc_address;
+ uint32_t dc_address_type;
+ uint32_t dc_flags = 0;
+ const char *dc_name = NULL;
+ fstring tmp_dc_name;
+ struct messaging_context *msg_ctx = msg_context(mem_ctx);
+
+ if (flags & DS_PDC_REQUIRED) {
+ name_type = NBT_NAME_PDC;
+ }
+
+ DEBUG(10,("process_dc_netbios\n"));
+
+ for (i=0; i<num_dcs; i++) {
+
+ ip_list.ss = dclist[i].ss;
+ ip_list.port = 0;
+
+ if (!interpret_string_addr(&ss, dclist[i].hostname, AI_NUMERICHOST)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (send_getdc_request(mem_ctx, msg_ctx,
+ &dclist[i].ss, domain_name, NULL))
+ {
+ int k;
+ smb_msleep(100);
+ for (k=0; k<5; k++) {
+ if (receive_getdc_response(mem_ctx,
+ &dclist[i].ss,
+ domain_name,
+ &dc_name)) {
+ namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
+ dc_hostname = dc_name;
+ dc_domain_name = talloc_strdup_upper(mem_ctx, domain_name);
+ NT_STATUS_HAVE_NO_MEMORY(dc_domain_name);
+ goto make_reply;
+ }
+ smb_msleep(500);
+ }
+ }
+
+ if (name_status_find(domain_name,
+ name_type,
+ NBT_NAME_SERVER,
+ &dclist[i].ss,
+ tmp_dc_name))
+ {
+ dc_hostname = tmp_dc_name;
+ dc_domain_name = talloc_strdup_upper(mem_ctx, domain_name);
+ namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
+ goto make_reply;
+ }
+ }
+
+ return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+
+ make_reply:
- return NT_STATUS_NOT_SUPPORTED;
+ if (flags & DS_IP_REQUIRED) {
+ char addr[INET6_ADDRSTRLEN];
+ print_sockaddr(addr, sizeof(addr), &dclist[i].ss);
+ dc_address = talloc_asprintf(mem_ctx, "\\\\%s", addr);
+ dc_address_type = DS_ADDRESS_TYPE_INET;
+ } else {
+ dc_address = talloc_asprintf(mem_ctx, "\\\\%s", dc_hostname);
+ dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
+ }
+
+ if (flags & DS_PDC_REQUIRED) {
+ dc_flags |= NBT_SERVER_PDC | NBT_SERVER_WRITABLE;
+ }
+
+ return make_domain_controller_info(mem_ctx,
+ dc_hostname,
+ dc_address,
+ dc_address_type,
+ NULL,
+ dc_domain_name,
+ NULL,
+ dc_flags,
+ NULL,
+ NULL,
+ info);
}
/****************************************************************
@@ -711,7 +870,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
struct netr_DsRGetDCNameInfo **info)
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- struct ip_service_name *dclist;
+ struct ip_service_name *dclist = NULL;
int num_dcs;
DEBUG(10,("dsgetdcname_rediscover\n"));
@@ -723,7 +882,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
NT_STATUS_NOT_OK_RETURN(status);
return process_dc_netbios(mem_ctx, domain_name, flags,
- &dclist, num_dcs, info);
+ dclist, num_dcs, info);
}
if (flags & DS_IS_DNS_NAME) {
@@ -752,7 +911,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
&num_dcs);
NT_STATUS_NOT_OK_RETURN(status);
- return process_dc_netbios(mem_ctx, domain_name, flags, &dclist,
+ return process_dc_netbios(mem_ctx, domain_name, flags, dclist,
num_dcs, info);
}