libads: further split resolve_and_ping into dns and netbios implementations
authorUri Simchoni <urisimchoni@gmail.com>
Thu, 11 Jun 2015 11:24:36 +0000 (14:24 +0300)
committerJeremy Allison <jra@samba.org>
Mon, 15 Jun 2015 23:29:24 +0000 (01:29 +0200)
split the resolve_and_ping function, which does name lookup followed by
cldap ping, into two variants:
- resolve_and_ping_dns() which uses AD name resolution
- resolve_and_ping_netbios() which uses pre-AD name resolution

Signed-off-by: Uri Simchoni <urisimchoni@gmail.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
source3/libads/ldap.c

index 52a890d8563f6eb72037609d642a2dafb726d5a5..5c53c6326e0a51f999303e4038a1e05fe8a131e0 100644 (file)
@@ -313,71 +313,111 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
 }
 
 /**********************************************************************
- resolve a name and perform an "ldap ping"
+ send a cldap ping to list of servers, one at a time, until one of
+ them answers it's an ldap server. Record success in the ADS_STRUCT.
+ Take note of and update negative connection cache.
 **********************************************************************/
 
-static NTSTATUS resolve_and_ping(ADS_STRUCT *ads, const char *sitename,
-                                const char *resolve_target, bool use_dns,
-                                const char *realm)
+static NTSTATUS cldap_ping_list(ADS_STRUCT *ads,const char *domain,
+                               struct ip_service *ip_list, int count)
 {
-       int count, i = 0;
+       int i;
+       bool ok;
+
+       for (i = 0; i < count; i++) {
+               char server[INET6_ADDRSTRLEN];
+
+               print_sockaddr(server, sizeof(server), &ip_list[i].ss);
+
+               if (!NT_STATUS_IS_OK(
+                       check_negative_conn_cache(domain, server)))
+                       continue;
+
+               ok = ads_try_connect(ads, false, &ip_list[i].ss);
+               if (ok) {
+                       return NT_STATUS_OK;
+               }
+
+               /* keep track of failures */
+               add_failed_connection_entry(domain, server,
+                                           NT_STATUS_UNSUCCESSFUL);
+       }
+
+       return NT_STATUS_NO_LOGON_SERVERS;
+}
+
+/***************************************************************************
+ resolve a name and perform an "ldap ping" using NetBIOS and related methods
+****************************************************************************/
+
+static NTSTATUS resolve_and_ping_netbios(ADS_STRUCT *ads,
+                                        const char *domain, const char *realm)
+{
+       int count, i;
        struct ip_service *ip_list;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-       bool ok = false;
 
-       DEBUG(6, ("resolve_and_ping: (cldap) looking for %s '%s'\n",
-                 (use_dns ? "realm" : "domain"), resolve_target));
+       DEBUG(6, ("resolve_and_ping_netbios: (cldap) looking for domain '%s'\n",
+                 domain));
 
-       status = get_sorted_dc_list(resolve_target, sitename, &ip_list, &count,
-                                   use_dns);
+       status = get_sorted_dc_list(domain, NULL, &ip_list, &count,
+                                   false);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       /* if we fail this loop, then giveup since all the IP addresses returned
-        * were dead */
-       for (i = 0; i < count; i++) {
-               char server[INET6_ADDRSTRLEN];
+       /* remove servers which are known to be dead based on
+          the corresponding DNS method */
+       if (*realm) {
+               for (i = 0; i < count; ++i) {
+                       char server[INET6_ADDRSTRLEN];
 
-               print_sockaddr(server, sizeof(server), &ip_list[i].ss);
+                       print_sockaddr(server, sizeof(server), &ip_list[i].ss);
 
-               if (!NT_STATUS_IS_OK(
-                       check_negative_conn_cache(resolve_target, server)))
-                       continue;
-
-               if (!use_dns) {
-                       /* resolve_target in this case is a workgroup name. We
-                          need
-                          to ignore any IP addresses in the negative connection
-                          cache that match ip addresses returned in the ad
-                          realm
-                          case.. */
-                       if (realm && *realm &&
-                           !NT_STATUS_IS_OK(
+                       if(!NT_STATUS_IS_OK(
                                check_negative_conn_cache(realm, server))) {
                                /* Ensure we add the workgroup name for this
                                   IP address as negative too. */
                                add_failed_connection_entry(
-                                   resolve_target, server,
+                                   domain, server,
                                    NT_STATUS_UNSUCCESSFUL);
-                               continue;
                        }
                }
+       }
 
-               ok = ads_try_connect(ads, false, &ip_list[i].ss);
-               if (ok) {
-                       SAFE_FREE(ip_list);
-                       return NT_STATUS_OK;
-               }
+       status = cldap_ping_list(ads, domain, ip_list, count);
 
-               /* keep track of failures */
-               add_failed_connection_entry(resolve_target, server,
-                                           NT_STATUS_UNSUCCESSFUL);
+       SAFE_FREE(ip_list);
+
+       return status;
+}
+
+
+/**********************************************************************
+ resolve a name and perform an "ldap ping" using DNS
+**********************************************************************/
+
+static NTSTATUS resolve_and_ping_dns(ADS_STRUCT *ads, const char *sitename,
+                                    const char *realm)
+{
+       int count;
+       struct ip_service *ip_list;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+       DEBUG(6, ("resolve_and_ping_dns: (cldap) looking for realm '%s'\n",
+                 realm));
+
+       status = get_sorted_dc_list(realm, sitename, &ip_list, &count,
+                                   true);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
+       status = cldap_ping_list(ads, realm, ip_list, count);
+
        SAFE_FREE(ip_list);
 
-       return NT_STATUS_NO_LOGON_SERVERS;
+       return status;
 }
 
 /**********************************************************************
@@ -461,7 +501,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
 
        if (*c_realm) {
                sitename = sitename_fetch(talloc_tos(), c_realm);
-               status = resolve_and_ping(ads, sitename, c_realm, true, c_realm);
+               status = resolve_and_ping_dns(ads, sitename, c_realm);
 
                if (NT_STATUS_IS_OK(status)) {
                        TALLOC_FREE(sitename);
@@ -481,7 +521,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
                                  sitename));
                        namecache_delete(c_realm, 0x1C);
                        status =
-                           resolve_and_ping(ads, NULL, c_realm, true, c_realm);
+                           resolve_and_ping_dns(ads, NULL, c_realm);
 
                        if (NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(sitename);
@@ -501,7 +541,7 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
                                  c_domain));
                }
 
-               status = resolve_and_ping(ads, NULL, c_domain, false, c_realm);
+               status = resolve_and_ping_netbios(ads, c_domain, c_realm);
        }
 
        return status;