[jcifs] [bug+workaround] When multiple hosts are available, only the first is retried
Glen Wallace
Glen.Wallace at transpower.co.nz
Thu May 4 07:43:30 UTC 2017
Hi
When multiple addresses are available for a DNS name and the first one fails JCIFS intends to try the next address, but instead retries the initial failing address multiple times.
In the case of a DFS share where the DNS name may resolve to a list of domain controllers, an outage of a single domain controller may make the DFS share unavailable to a client using JCIFS.
Detail
--------
In jcifs.smb.SmbFile when there are multiple addresses available for the service, see the getAddress() implementation, the doConnect() method may be called multiple times. It appears the intention is that the doConnect() method will get called for each available address until it either it succeeds or all addresses have been attempted. The result of getAddress() is incremented by a getNextAddress() call.
What currently happens (in the 1.3.18 codebase) is when the first address fails the doConnect() method will be called multiple times (equal to the number of available addresses), but the first address will be used on every attempt. This is because the address is only set on transport creation, but if a tree already exists it will be reused rather than a new transport created using the next address.
Reproducing the Issue
----------------------------
The easiest way to reproduce this issue (short of running a local DNS service with a specifically crafted entry) is to
a) temporarily patch the RESOLVER_DNS switch case in jcifs.UniAddress#getAllByName and have it insert a non-existent IP as the first item
b) set the system property -Djcifs.resolveOrder=DNS to ensure the above patched code is used
Something like:
case RESOLVER_DNS:
if( isAllDigits( hostname )) {
throw new UnknownHostException( hostname );
}
InetAddress[] iaddrs = InetAddress.getAllByName( hostname )
UniAddress[] addrs = new UniAddress[iaddrs.length + 1];
addrs[0] = new UniAddress(InetAddress.getByName("10.9.9.9")); // bad first address
for (int ii = 0; ii < iaddrs.length; ii++) {
addrs[ii + 1] = new UniAddress(iaddrs[ii]);
}
return addrs; // Success
Workaround
------------
I have implemented a workaround that seems to address the immediate issue we were seeing, however I am not convinced it is correct in all cases.
A patch is attached or see the following commit:
https://github.com/wallaceg-tp/samba-jcifs/commit/386763ec5e9960d508c1dbcddcc7218e86fe949d
Regards
Glen
---
www.transpower.co.nz
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SmbFile.patch
Type: application/octet-stream
Size: 1729 bytes
Desc: SmbFile.patch
URL: <http://lists.samba.org/pipermail/jcifs/attachments/20170504/ef45bb1e/SmbFile.obj>
More information about the jCIFS
mailing list