client: browse doesn't work with only win98 in workgroup
Derrell.Lipman at UnwiredUniverse.com
Derrell.Lipman at UnwiredUniverse.com
Fri Feb 28 19:47:50 GMT 2003
"Christopher R. Hertel" <crh at ubiqx.mn.org> writes:
> I am interested in looking into this, but I won't have time until the
> weekend.
Great. Thanks for the response!
In the mean time, I have modified smbw_dir.c to include a new function
smbw_browse_workgroup_alternate() with the following patch. The code is
basically stolen from nmblookup.c.
Since there is now some duplicated code pertaining to allocating and
initializing the smbw_dir structure, I also created a function to do that,
which is called from a couple of places.
This modification affects only the opendir()/readdir() functionality. I think
that it does not solve the problem in the more generic case. From smbsh, "ls
/smb/WORKGROUP" still fails although my test program (attached at bottom)
which uses opendir() and readdir() now succeeds. I haven't looked at the 'ls'
source code, but I suspect that it is doing stat() calls after the readdir,
and that is failing.
------------------------------------------------------------------------------
diff -u samba-2.2.7.sandbox-orig/source/smbwrapper/smbw_dir.c samba-2.2.7.sandbox-test/source/smbwrapper/smbw_dir.c
--- samba-2.2.7.sandbox-orig/source/smbwrapper/smbw_dir.c Wed Jan 29 11:24:58 2003
+++ samba-2.2.7.sandbox-test/source/smbwrapper/smbw_dir.c Fri Feb 28 11:57:01 2003
@@ -27,9 +27,10 @@
extern struct bitmap *smbw_file_bmap;
extern int smbw_busy;
-static struct smbw_dir *smbw_dirs;
+static struct smbw_dir *smbw_dirs = NULL;
static int ServerFD= -1;
+static void *smbw_browse_workgroup_alternate(char *path, char *workgroup);
/*****************************************************
map a fd to a smbw_dir structure
@@ -72,6 +73,11 @@
SAFE_FREE(dir);
}
+void smbw_free_dir(void *dir)
+{
+ free_dir((struct smbw_dir *) dir);
+}
+
static struct smbw_dir *cur_dir;
@@ -113,8 +119,8 @@
/*****************************************************
add a entry to a directory listing
*******************************************************/
-static void smbw_share_add(const char *share, uint32 type,
- const char *comment, void *state)
+void smbw_share_add(const char *share, uint32 type,
+ const char *comment, void *state)
{
struct smbw_file_info finfo;
@@ -157,8 +163,8 @@
/*****************************************************
add a server to a directory listing
*******************************************************/
-static void smbw_server_add(const char *name, uint32 type,
- const char *comment, void *state)
+void smbw_server_add(const char *name, uint32 type,
+ const char *comment, void *state)
{
int count;
struct smbw_file_info finfo;
@@ -195,6 +201,31 @@
}
+
+/******************************************************
+allocate an smbw_dir structure and initialize it.
+*******************************************************/
+void *smbw_dir_alloc(struct smbw_server *srv, int fd, char *path)
+{
+ struct smbw_dir *dir;
+
+ dir = (struct smbw_dir *)malloc(sizeof(*dir));
+ if (!dir)
+ return NULL;
+
+ ZERO_STRUCTP(dir);
+
+ dir->srv = srv;
+ dir->fd = fd;
+ dir->path = (path == NULL ? NULL : strdup(path));
+ bitmap_set(smbw_file_bmap, fd);
+
+ cur_dir = dir;
+
+ return dir;
+}
+
+
/*****************************************************
open a directory on the server
*******************************************************/
@@ -223,22 +254,24 @@
/* get a connection to the server */
srv = smbw_server(server, share);
if (!srv) {
- /* smbw_server sets errno */
- goto failed;
+ /* smbw_server sets errno. try alt method if workgroup */
+ if ((p=strstr(server,"#1D"))) {
+ DEBUG(4, ("dir_open workgroup: trying alternate method"));
+ *p = '\0';
+ if (p > server && p[-1] == ':')
+ p[-1] = '\0';
+ if ((dir = smbw_browse_workgroup_alternate((char *) fname, server)))
+ return dir->fd;
+ }
+ goto failed;
}
- dir = (struct smbw_dir *)malloc(sizeof(*dir));
+ dir = smbw_dir_alloc(srv, 0, NULL);
if (!dir) {
errno = ENOMEM;
goto failed;
}
- ZERO_STRUCTP(dir);
-
- cur_dir = dir;
-
- dir->srv = srv;
-
slprintf(mask, sizeof(mask)-1, "%s\\*", path);
all_string_sub(mask,"\\\\","\\",0);
@@ -772,3 +805,74 @@
return smbw_dir_lseek(d->fd,0,SEEK_CUR);
}
+
+
+/*
+ * smbw_browse_workgroup_alternate()
+ *
+ * The normal smbwrapper method of browsing for host names doesn't work if the
+ * master browser for the workgroup is a Windows 98 or Windows 95 system.
+ * This function tries a different method of enumerating hosts.
+ */
+static void *smbw_browse_workgroup_alternate(char *path, char *workgroup)
+{
+ int i;
+ int j;
+ int fd;
+ int count;
+ int flags;
+ struct in_addr * ip_list = NULL;
+ struct in_addr * bcast;
+ struct nmb_name nname;
+ struct node_status *status;
+ struct smbw_dir * dir;
+
+ if ((fd = open_socket_in(SOCK_DGRAM, 137, 0,
+ interpret_addr("0.0.0.0"),
+ TRUE)) == -1)
+ return NULL;
+
+ set_socket_options(fd, "SO_BROADCAST");
+
+ for (j = iface_count() - 1; ip_list == NULL && j >= 0; j--) {
+ bcast = iface_n_bcast(j);
+ ip_list = name_query(fd, workgroup, 0x0,
+ TRUE, TRUE,
+ *bcast, &count, &flags);
+ }
+
+ if (ip_list == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ /*
+ * We can only do find_status if the ip address returned was valid -
+ * ie. name_query returned true.
+ */
+ make_nmb_name(&nname, workgroup, 0x0);
+ if ((status = node_status_query(fd, &nname, ip_list[0], &count)) != NULL) {
+ if (count > 0) {
+ /* Allocate a dir structure */
+ if ((dir = smbw_dir_alloc(NULL, fd, path)) == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ DLIST_ADD(smbw_dirs, dir);
+
+ for (i = 0; i < count; i++)
+ if (status[i].type == 0x0 && (status[i].flags & 0x80) == 0)
+ smbw_server_add(status[i].name, 0, "", NULL);
+ } else {
+ close(fd);
+ }
+
+
+ SAFE_FREE(status);
+ }
+
+ SAFE_FREE(ip_list);
+
+ return (count > 0 ? dir : NULL);
+}
------------------------------------------------------------------------------
Here's my very simple test program...
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
int main(int argc, char * argv[])
{
DIR * hDir;
struct dirent * pDirent;
if (argc != 2)
{
printf("usage: %s <path>\n", argv[0]);
return 1;
}
if ((hDir = opendir(argv[1])) == NULL)
{
printf("Could not open %s (%s)\n", argv[1], strerror(errno));
return 1;
}
while ((pDirent = readdir(hDir)) != NULL)
{
printf("%s\n", pDirent->d_name);
}
closedir(hDir);
return 0;
}
More information about the samba-technical
mailing list