Author: jerry
Date: 2006-08-24 12:13:57 +0000 (Thu, 24 Aug 2006)
New Revision: 17795

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17795

Log:
Finally track down the "ads_connect: Interrupted system call"
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.


Modified:
   branches/SAMBA_3_0/source/include/ads_dns.h
   branches/SAMBA_3_0/source/libads/dns.c
   branches/SAMBA_3_0/source/libsmb/namequery.c
   branches/SAMBA_3_0_23/source/include/ads_dns.h
   branches/SAMBA_3_0_23/source/libads/dns.c
   branches/SAMBA_3_0_23/source/libsmb/namequery.c


Changeset:
Modified: branches/SAMBA_3_0/source/include/ads_dns.h
===================================================================
--- branches/SAMBA_3_0/source/include/ads_dns.h 2006-08-24 12:13:41 UTC (rev 
17794)
+++ branches/SAMBA_3_0/source/include/ads_dns.h 2006-08-24 12:13:57 UTC (rev 
17795)
@@ -47,10 +47,11 @@
        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;

Modified: branches/SAMBA_3_0/source/libads/dns.c
===================================================================
--- branches/SAMBA_3_0/source/libads/dns.c      2006-08-24 12:13:41 UTC (rev 
17794)
+++ branches/SAMBA_3_0/source/libads/dns.c      2006-08-24 12:13:57 UTC (rev 
17795)
@@ -398,14 +398,45 @@
                }
 
                /* 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 );
                        }
                }

Modified: branches/SAMBA_3_0/source/libsmb/namequery.c
===================================================================
--- branches/SAMBA_3_0/source/libsmb/namequery.c        2006-08-24 12:13:41 UTC 
(rev 17794)
+++ branches/SAMBA_3_0/source/libsmb/namequery.c        2006-08-24 12:13:57 UTC 
(rev 17795)
@@ -1024,11 +1024,12 @@
 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,25 +1046,45 @@
        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
                   as a hac.  After think about it, if all of the IP addresses 
retuend
@@ -1358,7 +1379,6 @@
 
        *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 @@
                        /* 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 

Modified: branches/SAMBA_3_0_23/source/include/ads_dns.h
===================================================================
--- branches/SAMBA_3_0_23/source/include/ads_dns.h      2006-08-24 12:13:41 UTC 
(rev 17794)
+++ branches/SAMBA_3_0_23/source/include/ads_dns.h      2006-08-24 12:13:57 UTC 
(rev 17795)
@@ -46,8 +46,9 @@
        const char *hostname;
        uint16 priority;
        uint16 weight;
-       uint16 port;
-       struct in_addr ip;
+       size_t num_ips;
+       struct in_addr *ips;    /* support multi-homed hosts */
+
 };
 
 

Modified: branches/SAMBA_3_0_23/source/libads/dns.c
===================================================================
--- branches/SAMBA_3_0_23/source/libads/dns.c   2006-08-24 12:13:41 UTC (rev 
17794)
+++ branches/SAMBA_3_0_23/source/libads/dns.c   2006-08-24 12:13:57 UTC (rev 
17795)
@@ -334,14 +334,45 @@
                }
 
                /* 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 );
                        }
                }

Modified: branches/SAMBA_3_0_23/source/libsmb/namequery.c
===================================================================
--- branches/SAMBA_3_0_23/source/libsmb/namequery.c     2006-08-24 12:13:41 UTC 
(rev 17794)
+++ branches/SAMBA_3_0_23/source/libsmb/namequery.c     2006-08-24 12:13:57 UTC 
(rev 17795)
@@ -1024,11 +1024,12 @@
 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,25 +1046,45 @@
        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
                   as a hac.  After think about it, if all of the IP addresses 
retuend
@@ -1358,7 +1379,6 @@
 
        *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 @@
                        /* 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 

Reply via email to