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.

source/include/ads_dns.h
source/libads/dns.c
source/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