s3:dsgetdcname: Inline dsgetdcname_cache_refresh
[obnox/samba-ctdb.git] / source / libsmb / dsgetdcname.c
index 43c9699ce7e99209fb656c844327a2eccf1e9159..8c20d967410f7ba2053eededb6a44a6b2561b4b3 100644 (file)
@@ -202,8 +202,10 @@ static NTSTATUS map_logon29_from_cldap_reply(TALLOC_CTX *mem_ctx,
        ZERO_STRUCTP(p);
 
        print_sockaddr(addr, sizeof(addr), ss);
-       p->dc_sock_addr_size = 0x10;
-       p->dc_sock_addr.sa_family = 2;
+
+       /* FIXME */
+       p->dc_sock_addr_size = 0x10; /* the w32 winsock addr size */
+       p->dc_sock_addr.family = 2; /* AF_INET */
        p->dc_sock_addr.pdc_ip = talloc_strdup(mem_ctx, addr);
 
        switch (nt_version & 0x0000001f) {
@@ -340,14 +342,22 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
                if (!NT_STATUS_IS_OK(status)) {
                        goto done;
                }
+               if (logon29.client_site) {
+                       sitename_store(logon29.domain, logon29.client_site);
+               }
        }
        if (logon29.dns_domain) {
                status = dsgetdcname_cache_store(mem_ctx, logon29.dns_domain, &blob);
                if (!NT_STATUS_IS_OK(status)) {
                        goto done;
                }
+               if (logon29.client_site) {
+                       sitename_store(logon29.dns_domain, logon29.client_site);
+               }
        }
 
+       status = NT_STATUS_OK;
+
  done:
        data_blob_free(&blob);
 
@@ -357,28 +367,6 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
 /****************************************************************
 ****************************************************************/
 
-static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx,
-                                         struct messaging_context *msg_ctx,
-                                         const char *domain_name,
-                                         struct GUID *domain_guid,
-                                         uint32_t flags,
-                                         const char *site_name,
-                                         struct netr_DsRGetDCNameInfo *info)
-{
-       struct netr_DsRGetDCNameInfo *dc_info;
-
-       return dsgetdcname(mem_ctx,
-                          msg_ctx,
-                          domain_name,
-                          domain_guid,
-                          site_name,
-                          flags | DS_FORCE_REDISCOVERY,
-                          &dc_info);
-}
-
-/****************************************************************
-****************************************************************/
-
 static uint32_t get_cldap_reply_server_flags(union nbt_cldap_netlogon *r,
                                             uint32_t nt_version)
 {
@@ -429,7 +417,7 @@ static uint32_t get_cldap_reply_server_flags(union nbt_cldap_netlogon *r,
 /****************************************************************
 ****************************************************************/
 
-#define RETURN_ON_FALSE(x) if (!x) return false;
+#define RETURN_ON_FALSE(x) if (!(x)) return false;
 
 static bool check_cldap_reply_required_flags(uint32_t ret_flags,
                                             uint32_t req_flags)
@@ -565,10 +553,13 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
        }
 
        if (expired) {
-               status = dsgetdcname_cache_refresh(mem_ctx, msg_ctx,
-                                                  domain_name,
-                                                  domain_guid, flags,
-                                                  site_name, *info);
+               struct netr_DsRGetDCNameInfo *dc_info;
+
+               status = dsgetdcname(mem_ctx, msg_ctx, domain_name,
+                                    domain_guid, site_name,
+                                    flags | DS_FORCE_REDISCOVERY,
+                                    &dc_info);
+
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -580,7 +571,8 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
 /****************************************************************
 ****************************************************************/
 
-static bool check_allowed_required_flags(uint32_t flags)
+static bool check_allowed_required_flags(uint32_t flags,
+                                        const char *site_name)
 {
        uint32_t return_type = flags & (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME);
        uint32_t offered_type = flags & (DS_IS_FLAT_NAME|DS_IS_DNS_NAME);
@@ -591,6 +583,10 @@ static bool check_allowed_required_flags(uint32_t flags)
 
        debug_dsdcinfo_flags(10, flags);
 
+       if ((flags & DS_TRY_NEXTCLOSEST_SITE) && site_name) {
+               return false;
+       }
+
        if (return_type == (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME)) {
                return false;
        }
@@ -907,7 +903,8 @@ static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
                                              union nbt_cldap_netlogon *r,
                                              struct netr_DsRGetDCNameInfo **info)
 {
-       const char *dc_hostname, *dc_domain_name;
+       const char *dc_hostname = NULL;
+       const char *dc_domain_name = NULL;
        const char *dc_address = NULL;
        const char *dc_forest = NULL;
        uint32_t dc_address_type = 0;
@@ -1221,6 +1218,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
        const char *dc_name = NULL;
        fstring tmp_dc_name;
        union nbt_cldap_netlogon *r = NULL;
+       bool store_cache = false;
        uint32_t nt_version = NETLOGON_VERSION_1 |
                              NETLOGON_VERSION_5 |
                              NETLOGON_VERSION_5EX_WITH_IP;
@@ -1259,6 +1257,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
                                                           &nt_version,
                                                           &dc_name,
                                                           &r)) {
+                                       store_cache = true;
                                        namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
                                        goto make_reply;
                                }
@@ -1300,7 +1299,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
 
        status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].ss,
                                               nt_version, r, info);
-       if (NT_STATUS_IS_OK(status)) {
+       if (NT_STATUS_IS_OK(status) && store_cache) {
                return store_cldap_reply(mem_ctx, flags, &dclist[i].ss,
                                         nt_version, r);
        }
@@ -1365,6 +1364,27 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
                                  num_dcs, info);
 }
 
+static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
+{
+       if (info->dc_flags & DS_SERVER_CLOSEST) {
+               return true;
+       }
+
+       if (!info->client_site_name) {
+               return true;
+       }
+
+       if (!info->dc_site_name) {
+               return false;
+       }
+
+       if (strcmp(info->client_site_name, info->dc_site_name) == 0) {
+               return true;
+       }
+
+       return false;
+}
+
 /********************************************************************
  dsgetdcname.
 
@@ -1381,6 +1401,9 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
        struct netr_DsRGetDCNameInfo *myinfo = NULL;
+       char *query_site = NULL;
+       bool first = true;
+       struct netr_DsRGetDCNameInfo *first_info = NULL;
 
        DEBUG(10,("dsgetdcname: domain_name: %s, "
                  "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
@@ -1390,34 +1413,57 @@ NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
 
        *info = NULL;
 
-       if (!check_allowed_required_flags(flags)) {
+       if (!check_allowed_required_flags(flags, site_name)) {
                DEBUG(0,("invalid flags specified\n"));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       if (!site_name) {
+               query_site = sitename_fetch(domain_name);
+       } else {
+               query_site = SMB_STRDUP(site_name);
+       }
+
        if (flags & DS_FORCE_REDISCOVERY) {
                goto rediscover;
        }
 
        status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
-                                   flags, site_name, &myinfo);
+                                   flags, query_site, &myinfo);
        if (NT_STATUS_IS_OK(status)) {
-               *info = myinfo;
-               return status;
+               goto done;
        }
 
        if (flags & DS_BACKGROUND_ONLY) {
-               return status;
+               goto done;
        }
 
  rediscover:
        status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
-                                       domain_guid, flags, site_name,
+                                       domain_guid, flags, query_site,
                                        &myinfo);
 
-       if (NT_STATUS_IS_OK(status)) {
-               *info = myinfo;
+ done:
+       SAFE_FREE(query_site);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               if (!first) {
+                       *info = first_info;
+                       return NT_STATUS_OK;
+               }
+               return status;
        }
 
-       return status;
+       if (!first) {
+               TALLOC_FREE(first_info);
+       } else if (!is_closest_site(myinfo)) {
+               first = false;
+               first_info = myinfo;
+               /* TODO: may use the next_closest_site here */
+               query_site = SMB_STRDUP(myinfo->client_site_name);
+               goto rediscover;
+       }
+
+       *info = myinfo;
+       return NT_STATUS_OK;
 }