Implement NetBIOS resolution for UNC pathnames.
diff --git a/files/smb.c b/files/smb.c
index 3053876..881106e 100644
--- a/files/smb.c
+++ b/files/smb.c
@@ -67,6 +67,9 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
#include "winerror.h"
#include "windef.h"
@@ -169,9 +172,9 @@
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 sockaddr_in sin;
+ struct sockaddr_in sin,fromaddr;
unsigned char buffer[256];
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
@@ -180,38 +183,67 @@
r = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof on);
if(r<0)
- return FALSE;
+ goto err;
if(0==inet_aton("255.255.255.255", (struct in_addr *)&sin.sin_addr.s_addr))
{
FIXME("Error getting bcast address\n");
- return FALSE;
+ goto err;
}
sin.sin_family = AF_INET;
sin.sin_port = htons(137);
len = NB_NameReq(host,buffer,sizeof buffer);
if(len<=0)
- return FALSE;
+ goto err;
r = sendto(fd, buffer, len, 0, &sin, sizeof sin);
if(r<0)
{
FIXME("Error sending packet\n");
- return FALSE;
+ goto err;
}
fds.fd = fd;
fds.events = POLLIN;
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);
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);
- TRACE("Got response!\n");
return TRUE;
+
+err:
+ close(fd);
+ return FALSE;
}
#define NB_FIRST 0x40
@@ -837,64 +869,77 @@
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;
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;
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))
- goto fail;
+ return FALSE;
if(!SMB_SessionSetup(fd, user_id))
- goto fail;
+ return FALSE;
name = HeapAlloc(GetProcessHeap(),0,strlen(host)+strlen(share)+5);
if(!name)
- goto fail;
+ return FALSE;
+
sprintf(name,"\\\\%s\\%s",host,share);
if(!SMB_TreeConnect(fd,*user_id,name,tree_id))
- goto fail;
- HeapFree(GetProcessHeap(),0,name);
-
- return fd;
-
-fail:
- if(name)
+ {
HeapFree(GetProcessHeap(),0,name);
- ERR("Failed\n");
- if(fd>=0)
- close(fd);
- return -1;
+ return FALSE;
+ }
+
+ return TRUE;
}
static HANDLE SMB_RegisterFile( int fd, USHORT tree_id, USHORT user_id, USHORT dialect, USHORT file_id)
@@ -932,11 +977,11 @@
int fd;
USHORT tree_id=0, user_id=0, dialect=0, file_id=0;
LPSTR name,host,share,file;
- HANDLE handle = 0;
+ HANDLE handle = INVALID_HANDLE_VALUE;
name = HeapAlloc(GetProcessHeap(),0,lstrlenA(uncname));
if(!name)
- return -1;
+ return handle;
lstrcpyA(name,uncname);
@@ -947,34 +992,31 @@
}
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)
- {
- HeapFree(GetProcessHeap(),0,name);
- return handle;
- }
+ goto done;
+
+ if(!SMB_LoginAndConnect(fd, host, share, &tree_id, &user_id, &dialect))
+ goto done;
#if 0
if(!SMB_NtCreateOpen(fd, tree_id, user_id, dialect, file,
access, sharing, sa, creation, attributes, template, &file_id ))
{
close(fd);
- HeapFree(GetProcessHeap(),0,name);
ERR("CreateOpen failed\n");
- return handle;
+ goto done;
}
#endif
if(!SMB_Open(fd, tree_id, user_id, dialect, file,
access, sharing, creation, attributes, &file_id ))
{
close(fd);
- HeapFree(GetProcessHeap(),0,name);
ERR("CreateOpen failed\n");
- return handle;
+ goto done;
}
- HeapFree(GetProcessHeap(),0,name);
-
handle = SMB_RegisterFile(fd, tree_id, user_id, dialect, file_id);
if(!handle)
{
@@ -982,6 +1024,8 @@
close(fd);
}
+done:
+ HeapFree(GetProcessHeap(),0,name);
return handle;
}