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