Implement NetBIOS resolution for UNC pathnames.

This commit is contained in:
Mike McCormack 2002-05-05 20:29:15 +00:00 committed by Alexandre Julliard
parent 887ed6228a
commit 9414adf75e
1 changed files with 107 additions and 63 deletions

View File

@ -67,6 +67,9 @@
#ifdef HAVE_ARPA_INET_H #ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include "winerror.h" #include "winerror.h"
#include "windef.h" #include "windef.h"
@ -169,9 +172,9 @@ static BOOL UNC_SplitName(LPSTR unc, LPSTR *hostname, LPSTR *share, LPSTR *file)
static BOOL NB_Lookup(LPCSTR host, struct sockaddr_in *addr) static BOOL NB_Lookup(LPCSTR host, struct sockaddr_in *addr)
{ {
int fd,on=1,r,len; int fd,on=1,r,len,i,fromsize;
struct pollfd fds; struct pollfd fds;
struct sockaddr_in sin; struct sockaddr_in sin,fromaddr;
unsigned char buffer[256]; unsigned char buffer[256];
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
@ -180,38 +183,67 @@ static BOOL NB_Lookup(LPCSTR host, struct sockaddr_in *addr)
r = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof on); r = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof on);
if(r<0) if(r<0)
return FALSE; goto err;
if(0==inet_aton("255.255.255.255", (struct in_addr *)&sin.sin_addr.s_addr)) if(0==inet_aton("255.255.255.255", (struct in_addr *)&sin.sin_addr.s_addr))
{ {
FIXME("Error getting bcast address\n"); FIXME("Error getting bcast address\n");
return FALSE; goto err;
} }
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_port = htons(137); sin.sin_port = htons(137);
len = NB_NameReq(host,buffer,sizeof buffer); len = NB_NameReq(host,buffer,sizeof buffer);
if(len<=0) if(len<=0)
return FALSE; goto err;
r = sendto(fd, buffer, len, 0, &sin, sizeof sin); r = sendto(fd, buffer, len, 0, &sin, sizeof sin);
if(r<0) if(r<0)
{ {
FIXME("Error sending packet\n"); FIXME("Error sending packet\n");
return FALSE; goto err;
} }
fds.fd = fd; fds.fd = fd;
fds.events = POLLIN; fds.events = POLLIN;
fds.revents = 0; fds.revents = 0;
/* FIXME: this is simple and easily fooled logic
* we should loop until we receive the correct packet or timeout
*/
r = poll(&fds,1,NB_TIMEOUT); r = poll(&fds,1,NB_TIMEOUT);
if(r!=1) if(r!=1)
return FALSE; goto err;
TRACE("Got response!\n");
fromsize = sizeof (fromaddr);
r = recvfrom(fd, buffer, sizeof buffer, 0, &fromaddr, &fromsize);
if(r<0)
goto err;
ERR("%d bytes received\n",r);
if(r!=62)
goto err;
for(i=0; i<r; i++)
DPRINTF("%02X%c",buffer[i],(((i+1)!=r)&&((i+1)%16))?' ':'\n');
DPRINTF("\n");
if(0x0f & buffer[3])
goto err;
ERR("packet is OK\n");
memcpy(&addr->sin_addr, &buffer[58], sizeof addr->sin_addr);
close(fd); close(fd);
TRACE("Got response!\n");
return TRUE; return TRUE;
err:
close(fd);
return FALSE;
} }
#define NB_FIRST 0x40 #define NB_FIRST 0x40
@ -837,64 +869,77 @@ static BOOL SMB_Read(int fd, USHORT tree_id, USHORT user_id, USHORT dialect, USH
return TRUE; return TRUE;
} }
static int SMB_LoginAndConnect(LPCSTR host, LPCSTR share, USHORT *tree_id, USHORT *user_id, USHORT *dialect) static int SMB_GetSocket(LPCSTR host)
{ {
int fd=-1,r; int fd=-1,r;
struct sockaddr_in sin; struct sockaddr_in sin;
struct hostent *he;
ERR("host %s\n",host);
if(NB_Lookup(host,&sin))
goto connect;
he = gethostbyname(host);
if(he)
{
memcpy(&sin.sin_addr,he->h_addr, sizeof (sin.sin_addr));
goto connect;
}
/* FIXME: resolve by WINS too */
ERR("couldn't resolve SMB host %s\n", host);
return -1;
connect:
sin.sin_family = AF_INET;
sin.sin_port = htons(139); /* netbios session */
fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(fd<0)
return fd;
{
unsigned char *x = (unsigned char *)&sin.sin_addr;
ERR("Connecting to %d.%d.%d.%d ...\n", x[0],x[1],x[2],x[3]);
}
r = connect(fd, &sin, sizeof sin);
if(!NB_SessionReq(fd, "*SMBSERVER", "WINE"))
{
close(fd);
return -1;
}
return fd;
}
static BOOL SMB_LoginAndConnect(int fd, LPCSTR host, LPCSTR share, USHORT *tree_id, USHORT *user_id, USHORT *dialect)
{
LPSTR name=NULL; LPSTR name=NULL;
ERR("host %s share %s\n",host,share); ERR("host %s share %s\n",host,share);
/* FIXME: use various lookup methods */
if(0)
NB_Lookup(host,&sin);
else
{
if(0==inet_aton("127.0.0.1", (struct in_addr *)&sin.sin_addr.s_addr))
{
FIXME("Error getting localhost address\n");
SetLastError( ERROR_PATH_NOT_FOUND );
return INVALID_HANDLE_VALUE;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(139); /* netbios session */
}
fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(fd<0)
goto fail;
ERR("Connecting...\n");
r = connect(fd, &sin, sizeof sin);
if(r<0)
goto fail;
if(!NB_SessionReq(fd, "*SMBSERVER", "WINE"))
goto fail;
if(!SMB_NegotiateProtocol(fd, dialect)) if(!SMB_NegotiateProtocol(fd, dialect))
goto fail; return FALSE;
if(!SMB_SessionSetup(fd, user_id)) if(!SMB_SessionSetup(fd, user_id))
goto fail; return FALSE;
name = HeapAlloc(GetProcessHeap(),0,strlen(host)+strlen(share)+5); name = HeapAlloc(GetProcessHeap(),0,strlen(host)+strlen(share)+5);
if(!name) if(!name)
goto fail; return FALSE;
sprintf(name,"\\\\%s\\%s",host,share); sprintf(name,"\\\\%s\\%s",host,share);
if(!SMB_TreeConnect(fd,*user_id,name,tree_id)) if(!SMB_TreeConnect(fd,*user_id,name,tree_id))
goto fail; {
HeapFree(GetProcessHeap(),0,name); HeapFree(GetProcessHeap(),0,name);
return FALSE;
}
return fd; return TRUE;
fail:
if(name)
HeapFree(GetProcessHeap(),0,name);
ERR("Failed\n");
if(fd>=0)
close(fd);
return -1;
} }
static HANDLE SMB_RegisterFile( int fd, USHORT tree_id, USHORT user_id, USHORT dialect, USHORT file_id) static HANDLE SMB_RegisterFile( int fd, USHORT tree_id, USHORT user_id, USHORT dialect, USHORT file_id)
@ -932,11 +977,11 @@ HANDLE WINAPI SMB_CreateFileA( LPCSTR uncname, DWORD access, DWORD sharing,
int fd; int fd;
USHORT tree_id=0, user_id=0, dialect=0, file_id=0; USHORT tree_id=0, user_id=0, dialect=0, file_id=0;
LPSTR name,host,share,file; LPSTR name,host,share,file;
HANDLE handle = 0; HANDLE handle = INVALID_HANDLE_VALUE;
name = HeapAlloc(GetProcessHeap(),0,lstrlenA(uncname)); name = HeapAlloc(GetProcessHeap(),0,lstrlenA(uncname));
if(!name) if(!name)
return -1; return handle;
lstrcpyA(name,uncname); lstrcpyA(name,uncname);
@ -947,34 +992,31 @@ HANDLE WINAPI SMB_CreateFileA( LPCSTR uncname, DWORD access, DWORD sharing,
} }
ERR("server is %s, share is %s, file is %s\n", host, share, file); ERR("server is %s, share is %s, file is %s\n", host, share, file);
fd = SMB_LoginAndConnect(host, share, &tree_id, &user_id, &dialect);
fd = SMB_GetSocket(host);
if(fd < 0) if(fd < 0)
{ goto done;
HeapFree(GetProcessHeap(),0,name);
return handle; if(!SMB_LoginAndConnect(fd, host, share, &tree_id, &user_id, &dialect))
} goto done;
#if 0 #if 0
if(!SMB_NtCreateOpen(fd, tree_id, user_id, dialect, file, if(!SMB_NtCreateOpen(fd, tree_id, user_id, dialect, file,
access, sharing, sa, creation, attributes, template, &file_id )) access, sharing, sa, creation, attributes, template, &file_id ))
{ {
close(fd); close(fd);
HeapFree(GetProcessHeap(),0,name);
ERR("CreateOpen failed\n"); ERR("CreateOpen failed\n");
return handle; goto done;
} }
#endif #endif
if(!SMB_Open(fd, tree_id, user_id, dialect, file, if(!SMB_Open(fd, tree_id, user_id, dialect, file,
access, sharing, creation, attributes, &file_id )) access, sharing, creation, attributes, &file_id ))
{ {
close(fd); close(fd);
HeapFree(GetProcessHeap(),0,name);
ERR("CreateOpen failed\n"); ERR("CreateOpen failed\n");
return handle; goto done;
} }
HeapFree(GetProcessHeap(),0,name);
handle = SMB_RegisterFile(fd, tree_id, user_id, dialect, file_id); handle = SMB_RegisterFile(fd, tree_id, user_id, dialect, file_id);
if(!handle) if(!handle)
{ {
@ -982,6 +1024,8 @@ HANDLE WINAPI SMB_CreateFileA( LPCSTR uncname, DWORD access, DWORD sharing,
close(fd); close(fd);
} }
done:
HeapFree(GetProcessHeap(),0,name);
return handle; return handle;
} }