/*
* DNS referrals give two main fields: the path to connect to in
* /Netbios-host-name/share-name/path... form and a network
* address of how to find this path of the form domain.dom.
*
* The domain.dom is resolved in XP/Win2k etc using AD to do
* a lookup (this is a consensus view, I don't think anyone
* has proved it). I cannot do this as AD needs Kerberos and
* LDAP which I don't have.
*
* Instead I just use the NetBios names passed in the paths
* and assume that the servers are in the same DNS domain as me
* and have their DNS hostname set the same as their netbios
* called-name; thankfully this always seems to be the case (so far).
*
* I have not added support for starting another instance of
* cifs to connect to other servers referenced in DFS links,
* this is not a problem for me and I think it hides a load
* of problems of its own wrt plan9's private namespaces.
*
* The expiry of my test server (AD enabled) is always 0 but some
* systems may report more meaningful values.
*
* If the redirection points to a "hidden" share (i.e., its name
* ends in a $) then the type of the redirection is 0 (unknown) even
* though it is a CIFS share.
*
* It would be nice to add a check for which subnet a server is on
* so our first choice is always the the server on the same subnet
* as us which replies to a ping (i.e., is up). This could short-
* circuit the tests as the a server on the same subnet will always
* be the fastest to get to.
*
* If I set Flags2_DFS then I don't see DFS links, I just get
* path not found (?!).
*
* If I do a QueryFileInfo of a DFS link point (IE when I'am doing a walk)
* Then I just see a directory, its not until I try to walk another level
* That I get "IO reparse tag not handled" error rather than
* "Path not covered".
*
* If I check the extended attributes of the QueryFileInfo in walk() then I can
* see this is a reparse point and so I can get the referral. The only
* problem here is that samba and the like may not support this.
*/
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <libsec.h>
#include <ctype.h>
#include <9p.h>
#include "cifs.h"
enum {
Nomatch, /* not found in cache */
Exactmatch, /* perfect match found */
Badmatch /* matched but wrong case */
};
#define SINT_MAX 0x7fffffff
typedef struct Dfscache Dfscache;
struct Dfscache {
Dfscache*next; /* next entry */
char *src;
char *host;
char *share;
char *path;
long expiry; /* expiry time in sec */
long rtt; /* round trip time, nsec */
};
for(sp = Shares; sp < Shares+Nshares; sp++){
s = trimshare(sp->name);
if(cistrcmp(cp->share, s) != 0)
continue;
if(Checkcase && strcmp(cp->share, s) != 0)
continue;
if(Debug && strstr(Debug, "dfs") != nil)
print("mapshare, already connected, src=%q => dst=%q\n", path, sp->name);
*osp = sp;
return 0;
}
/*
* Try to autoconnect to share if it is not known. Note even if you
* didn't specify any shares and let the system autoconnect you may
* not already have the share you need as RAP (which we use) throws
* away names > 12 chars long. If we where to use RPC then this block
* of code would be less important, though it would still be useful
* to catch Shares added since cifs(1) was started.
*/
sp = Shares + Nshares;
for(i = 0; i < 2; i++){
try = smprint("%s%s", cp->share, tail[i]);
if(CIFStreeconnect(Sess, Sess->cname, try, sp) == 0){
sp->name = try;
*osp = sp;
Nshares++;
if(Debug && strstr(Debug, "dfs") != nil)
print("mapshare connected, src=%q dst=%q\n",
path, cp->share);
return 0;
}
free(try);
}
/*
* Rtt_tol is the fractional tollerance for RTT comparisons.
* If a later (further down the list) host's RTT is less than
* 1/Rtt_tol better than my current best then I don't bother
* with it. This biases me towards entries at the top of the list
* which Active Directory has already chosen for me and prevents
* noise in RTTs from pushing me to more distant machines.
*/
static int
remap(Dfscache *cp, Refer *re)
{
int n;
long rtt;
char *p, *a[4];
enum {
Hostname = 1,
Sharename = 2,
Pathname = 3,
/*
* We can afford to ignore the used count returned by redir
* because of the semantics of 9p - we always walk to directories
* ome and we a time and we always walk before any other file operations
*/
int
redirect(Session *s, Share *sp, char *path)
{
int match;
char *unc;
Dfscache *cp;