Implement NetBIOS resolution for UNC pathnames.
This commit is contained in:
parent
887ed6228a
commit
9414adf75e
168
files/smb.c
168
files/smb.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue