Quantcast

[bug+workaround] When multiple hosts are available, only the first is retried

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[bug+workaround] When multiple hosts are available, only the first is retried

Samba - jcifs mailing list
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


SmbFile.patch (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [bug+workaround] When multiple hosts are available, only the first is retried

Samba - jcifs mailing list
Hi Glen,

Yes, this has been on the TODO list for about 10 years which is to say
I don't know if it will be fixed. Some folks have actually been
disabling SMB1 (there was a bug in Windows no too long ago that
prompted MS to recommend disabling SMB1) so the SMB parts of JCIFS
might be obsolete at some point. Really need SMB2/3 to keep it alive
but that's about 14 plates down in the stack of stuff-to-do.

Mike

On Thu, May 4, 2017 at 3:43 AM, Glen Wallace via jCIFS
<[hidden email]> wrote:

> 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
>



--
Michael B Allen
Java Active Directory Integration
http://www.ioplex.com/

Loading...