r17795: Finally track down the "ads_connect: Interrupted system call"
authorGerald Carter <jerry@samba.org>
Thu, 24 Aug 2006 12:13:57 +0000 (12:13 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:38:47 +0000 (11:38 -0500)
error.  Fix our DNS SRV lookup code to deal with multi-homed hosts.
We were noly remembering one IP address per host from the Additional
records section in the SRV response which could have been an unreachable
address.
(This used to be commit 899179d2b9fba13cc6f4dab6efc3c22e44e062bc)

source3/include/ads_dns.h
source3/libads/dns.c
source3/libsmb/namequery.c

index 74762a92427cc937d4db88396087b6a7e432de6e..6c3430e21b067e8ec0a4160d0c9120249008901b 100644 (file)
@@ -47,10 +47,11 @@ struct dns_rr_srv {
        uint16 priority;
        uint16 weight;
        uint16 port;
-       struct in_addr ip;
+       size_t num_ips;
+       struct in_addr *ips;    /* support multi-homed hosts */
 };
 
-/* SRV records */
+/* NS records */
 
 struct dns_rr_ns {
        const char *hostname;
index 903d19b7530a338be50e0881f8a590cb187e515f..c946ab0bdddab993b0d9bbfc8d8dd058099f5d04 100644 (file)
@@ -398,14 +398,45 @@ static NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dn
                }
 
                /* only interested in A records as a shortcut for having to come 
-                  back later and lookup the name */
+                  back later and lookup the name.  For multi-homed hosts, the 
+                  number of additional records and exceed the number of answer 
+                  records. */
+                 
 
                if ( (rr.type != T_A) || (rr.rdatalen != 4) ) 
                        continue;
 
+               /* FIX ME!!! Should this be a list of IP addresses for 
+                  each host? */ 
+                  
                for ( i=0; i<idx; i++ ) {
                        if ( strcmp( rr.hostname, dcs[i].hostname ) == 0 ) {
-                               uint8 *buf = (uint8*)&dcs[i].ip.s_addr;
+                               int num_ips = dcs[i].num_ips;
+                               uint8 *buf;
+                               struct in_addr *tmp_ips;
+
+                               /* allocate new memory */
+                               
+                               if ( dcs[i].num_ips == 0 ) {
+                                       if ( (dcs[i].ips = TALLOC_ARRAY( dcs, 
+                                               struct in_addr, 1 )) == NULL ) 
+                                       {
+                                               return NT_STATUS_NO_MEMORY;
+                                       }
+                               } else {
+                                       if ( (tmp_ips = TALLOC_REALLOC_ARRAY( dcs, dcs[i].ips,
+                                               struct in_addr, dcs[i].num_ips+1)) == NULL ) 
+                                       {
+                                               return NT_STATUS_NO_MEMORY;
+                                       }
+                                       
+                                       dcs[i].ips = tmp_ips;
+                               }
+                               dcs[i].num_ips++;
+                               
+                               /* copy the new IP address */
+                               
+                               buf = (uint8*)&dcs[i].ips[num_ips].s_addr;
                                memcpy( buf, rr.rdata, 4 );
                        }
                }
index 0bd8bc7cb2962b687e9b1c17dec3dd52c26ed755..14dfd5082965fb7438984b7701f90959c38359b5 100644 (file)
@@ -1024,11 +1024,12 @@ static BOOL resolve_hosts(const char *name, int name_type,
 static BOOL resolve_ads(const char *name, int name_type,
                          struct ip_service **return_iplist, int *return_count)
 {
-       int                     i = 0;
+       int                     i, j;
        NTSTATUS                status;
        TALLOC_CTX              *ctx;
        struct dns_rr_srv       *dcs = NULL;
        int                     numdcs = 0;
+       int                     numaddrs = 0;
 
        if ( name_type != 0x1c )
                return False;
@@ -1045,24 +1046,44 @@ static BOOL resolve_ads(const char *name, int name_type,
        if ( !NT_STATUS_IS_OK( status ) ) {
                return False;
        }
+
+       for (i=0;i<numdcs;i++) {
+               numaddrs += MAX(dcs[i].num_ips,1);
+       }
                
-       if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numdcs)) == NULL ) {
-               DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numdcs ));
+       if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) == NULL ) {
+               DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numaddrs ));
                return False;
        }
+       
+       /* now unroll the list of IP addresses */
 
        *return_count = 0;
-
-       for (i=0;i<numdcs;i++) {
+       i = 0;
+       j = 0;
+       while ( i < numdcs && (*return_count<numaddrs) ) {
                struct ip_service *r = &(*return_iplist)[*return_count];
 
-               /* use the IP address from the SRV structure if we have one */
-               if ( is_zero_ip( dcs[i].ip ) )
-                       r->ip   = *interpret_addr2(dcs[i].hostname);
-               else
-                       r->ip = dcs[i].ip;
-
                r->port = dcs[i].port;
+               
+               /* If we don't have an IP list for a name, lookup it up */
+               
+               if ( !dcs[i].ips ) {
+                       r->ip = *interpret_addr2(dcs[i].hostname);
+                       i++;
+                       j = 0;
+               } else {
+                       /* use the IP addresses from the SRV sresponse */
+                       
+                       if ( j >= dcs[i].num_ips ) {
+                               i++;
+                               j = 0;
+                               continue;
+                       }
+                       
+                       r->ip = dcs[i].ips[j];
+                       j++;
+               }
                        
                /* make sure it is a valid IP.  I considered checking the negative
                   connection cache, but this is the wrong place for it.  Maybe only
@@ -1358,7 +1379,6 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
 
        *ordered = False;
 
-
        /* if we are restricted to solely using DNS for looking
           up a domain controller, make sure that host lookups
           are enabled for the 'name resolve order'.  If host lookups
@@ -1374,9 +1394,9 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
                        /* DNS SRV lookups used by the ads resolver
                           are already sorted by priority and weight */
                        *ordered = True;
+               } else {
+                        fstrcpy( resolve_order, "NULL" );
                }
-               else
-                       fstrcpy( resolve_order, "NULL" );
        }
 
        /* fetch the server we have affinity for.  Add the