[jcifs] How DFS works in jCIFS

Michael B Allen mba2000 at ioplex.com
Mon Oct 20 13:35:46 EST 2003

After much thinking and a little codeing I've narrowed down how DFS will
work in jCIFS (indeed it works like this right now):

As it is, all requests are funneled through SmbFile.send(). This is were
most of the work occurs (see code below). When a request is sent, we enter
a loop, connect0, and check to see if the tree is "inDfs" (bit 2 of
OptionalSupport field in SMB_COM_TREE_CONNECT_ANDX response). If it's not,
it's business as usual. If it is, we try to lookup an existing referral
which initially will not be found so we send the existing request as is.
If this generates a STATUS_PATH_NOT_COVERED error (actually ERRreserved
for us since jCIFS uses DOS error codes) in the transport layer, we do the
TRANS2_GET_DFS_REFERRAL, and throw a DfsReferral Exception which contains
the referral information. SmbTree.send() catches it, adds it to the list
of referrals, and then re-throws it. This is caught again in
SmbFile.send() which escapes the break statement and we loop around. This
time the lookupReferral call will succeed in matching the referral path to
the beginning of the unc path. The returned DfsReferral is used to switch
the underlying SmbTree associated with this SmbFile and we also graft the
referral information together to come up with a new UNC path. Recall
SmbFiles are immutable so there should they should not emit any indication
that the underlying tree, session, transport, or whatever has been
switched out from under their feet. I expect a few nik-naks to pop-up over
this fact but so far it's working. Then we send the request again which
should succeed unless that tree is also in DFS in which case we loop
again. Subsequent requests will successfully lookup previous DfsReferrals,
a path is fully resolved when inDfs == false, and the unc and tree members
are inherited by derived SmbFiles so I think this is about as optimal as
it gets.

    void send( ServerMessageBlock request,
                    ServerMessageBlock response ) throws SmbException {
        for( ;; ) {
            if( tree.inDfs ) {
                DfsReferral dr = tree.lookupReferral( unc );
                if( dr != null ) {
                    tree = dr.tree;
                    unc = request.path = dr.nodepath + unc.substring(
dr.path.length() );
            try {
                tree.send( request, response );
            } catch( DfsReferral dr ) {

Incedentally there is a DFS bug in Samba 2.2.7 at least (bug 588). It will
not *initially* resolve DFS paths that exceed one subdirectory. After
successfully triggering the STATUS_PATH_NOT_COVERED/ERRreserved deep paths
are resolved properly.


A program should be written to  model the concepts of the task it
performs rather than the physical world or a process because this
maximizes the  potential for it  to be applied  to tasks that are
conceptually similar and, more  important, to tasks that have not
yet been conceived.

More information about the jcifs mailing list