[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