diff --git a/.downloads/ncpfs-0.22.tgz b/.downloads/ncpfs-0.22.tgz new file mode 100644 index 0000000..c9eb687 Binary files /dev/null and b/.downloads/ncpfs-0.22.tgz differ diff --git a/Changes b/Changes index 8704372..3088516 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,12 @@ I only began this file with ncpfs-0.12. If you're interested in older versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old. +ncpfs-0.21 -> ncpfs-0.22 +- removed a bad race condition in kernel-1.2/src/dir.c. +- handle 0x9999-responses from the ncp server correctly. +- Bindery functions in ncplib.c by Brian G. Reid (breid@tim.com) +- set blocksize to 512 to satisfy 'du -k' + ncpfs-0.20 -> ncpfs-0.21 - Included two bugfixes in ncplib.c found by Jeff Buhrt . diff --git a/FAQ b/FAQ index 0cd53d4..5c7c4db 100644 --- a/FAQ +++ b/FAQ @@ -4,6 +4,18 @@ enough. ------------------------------------------------------------------------------- +Q: I have difficulties with NetWare 4.1. What can I do? + +To be honest, I do not really know. Currently my only test equipment +is a NetWare 3.11 server. You should make your 4.1 Server as +3.x-compatible as it can be. As I do not know 4.1, you are on your own +doing this. + +A promising hint that has already helped some people is to switch off +packet signatures on the 4.1 server, as ncpfs does not support them. + +------------------------------------------------------------------------------- + Q: Does ncpfs support long file names, using the OS/2 namespace? No. Not yet. I still have to sort out how that really works. But it should diff --git a/Makefile b/Makefile index f0d93f6..1868f1e 100644 --- a/Makefile +++ b/Makefile @@ -2,31 +2,29 @@ # Makefile for the linux ncp-filesystem routines. # -VERSION = 0.21 -TOPDIR = $(shell pwd) - -BINDIR = /usr/local/bin -SBINDIR = /sbin -INTERM_BINDIR = $(TOPDIR)/bin -SUBDIRS = util ipx-1.0 man - -# -# The following 2 lines are for those who use Kernel version 1.2.x. -# If you have a kernel later than 1.3.53, please comment out the -# the following lines. You have to recompile your kernel -# and say 'y' when 'make config' asks you for IPX and ncpfs. -# -SUBDIRS += kernel-1.2/src -INCLUDES = -I$(TOPDIR)/kernel-1.2 +VERSION = 0.22 # If you are using kerneld to autoload ncp support, # uncomment this (kerneld is in linux since about 1.3.57): #KERNELD = -DHAVE_KERNELD +TOPDIR = $(shell pwd) +BINDIR = /usr/local/bin +SBINDIR = /sbin +INTERM_BINDIR = $(TOPDIR)/bin +SUBDIRS = util ipx-1.0 man + +KVERSION=$(shell uname -r | cut -b3) + +ifeq ($(KVERSION),2) +SUBDIRS += kernel-1.2/src +INCLUDES = -I$(TOPDIR)/kernel-1.2 +endif + export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION all: - for i in $(SUBDIRS); do make -C $$i; done + for i in $(SUBDIRS); do make -C $$i all; done dep: for i in $(SUBDIRS); do make -C $$i dep; done @@ -44,6 +42,7 @@ clean: mrproper: clean rm -fr $(INTERM_BINDIR)/* ncpfs.tgz make -C util mrproper + (cd ncpd; make clean) modules: ncpfs.o diff --git a/README b/README index c8eab2a..971d622 100644 --- a/README +++ b/README @@ -22,11 +22,8 @@ asks for ncpfs. After you have rebooted with the new kernel, 'cat /proc/filesystems' should show you a line saying that the kernel knows ncpfs. -With Kernel 1.3.71 or later you also have to modify the Makefile in the -directory you found this README in. Please see the Makefile for the -necessary modifications. Then typing 'make' should work with no -problem. - +If you are running kerneld, please uncomment the corresponding line in +the Makefile to reflect this. HELP diff --git a/ipxdump/ipxdump b/ipxdump/ipxdump new file mode 100755 index 0000000..b6c3cbb Binary files /dev/null and b/ipxdump/ipxdump differ diff --git a/ipxdump/ipxdump.c b/ipxdump/ipxdump.c index 4fd3605..105c5ae 100644 --- a/ipxdump/ipxdump.c +++ b/ipxdump/ipxdump.c @@ -236,7 +236,7 @@ handle_frame (unsigned char *buf, int length, struct sockaddr *saddr) switch( packet_type ) { case __constant_ntohs(ETH_P_IPX): - handle_ipx("EtherII ", &(buf[sizeof(struct ethhdr)])); + handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)])); break; default: handle_other(buf, length, saddr); diff --git a/ipxdump/ipxparse b/ipxdump/ipxparse new file mode 100755 index 0000000..f98b146 Binary files /dev/null and b/ipxdump/ipxparse differ diff --git a/kernel-1.2/linux/ncp_fs.h b/kernel-1.2/linux/ncp_fs.h index 8215817..309ec11 100644 --- a/kernel-1.2/linux/ncp_fs.h +++ b/kernel-1.2/linux/ncp_fs.h @@ -61,7 +61,7 @@ struct ncp_fs_info { #define NCP_READDIR_CACHE_SIZE 64 -#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */ +#define NCP_MAX_RPC_TIMEOUT (6*HZ) /* Guess, what 0x564c is :-) */ #define NCP_SUPER_MAGIC 0x564c diff --git a/kernel-1.2/src/dir.c b/kernel-1.2/src/dir.c index 92cfd2a..da45557 100644 --- a/kernel-1.2/src/dir.c +++ b/kernel-1.2/src/dir.c @@ -200,12 +200,30 @@ static int c_size; static int c_seen_eof; static int c_last_returned_index; static struct ncp_dirent* c_entry = NULL; +static int c_lock = 0; +static struct wait_queue *c_wait = NULL; + +static inline void +ncp_lock_dircache(void) +{ + while (c_lock) + sleep_on(&c_wait); + c_lock = 1; +} + +static inline void +ncp_unlock_dircache(void) +{ + c_lock = 0; + wake_up(&c_wait); +} static int ncp_readdir(struct inode *inode, struct file *filp, struct dirent *dirent, int count) { - int result, i = 0; + int result = 0; + int i = 0; int index = 0; struct ncp_dirent *entry = NULL; struct ncp_server *server = NCP_SERVER(inode); @@ -238,6 +256,7 @@ ncp_readdir(struct inode *inode, struct file *filp, return -EIO; } + ncp_lock_dircache(); if (c_entry == NULL) { i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE; @@ -245,7 +264,8 @@ ncp_readdir(struct inode *inode, struct file *filp, if (c_entry == NULL) { printk("ncp_readdir: no MEMORY for cache\n"); - return -ENOMEM; + result = -ENOMEM; + goto finished; } } @@ -255,10 +275,11 @@ ncp_readdir(struct inode *inode, struct file *filp, if (filldir(dirent,".",1, filp->f_pos, ncp_info_ino(server, dir)) < 0) { - return 0; + goto finished; } filp->f_pos += 1; - return ROUND_UP(NAME_OFFSET(dirent)+i+1); + result = ROUND_UP(NAME_OFFSET(dirent)+i+1); + goto finished; } if (filp->f_pos == 1) @@ -266,10 +287,11 @@ ncp_readdir(struct inode *inode, struct file *filp, if (filldir(dirent,"..",2, filp->f_pos, ncp_info_ino(server, dir->dir)) < 0) { - return 0; + goto finished; } filp->f_pos += 1; - return ROUND_UP(NAME_OFFSET(dirent)+i+1); + result = ROUND_UP(NAME_OFFSET(dirent)+i+1); + goto finished; } if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino)) @@ -286,42 +308,44 @@ ncp_readdir(struct inode *inode, struct file *filp, } if ((entry == NULL) && c_seen_eof) { - return 0; + goto finished; } } if (entry == NULL) { + int entries; DDPRINTK("ncp_readdir: Not found in cache.\n"); if (ncp_is_server_root(inode)) { - result = ncp_read_volume_list(server, filp->f_pos, - NCP_READDIR_CACHE_SIZE); - DPRINTK("ncp_read_volume_list returned %d\n", result); + entries = ncp_read_volume_list(server, filp->f_pos, + NCP_READDIR_CACHE_SIZE); + DPRINTK("ncp_read_volume_list returned %d\n", entries); } else { - result = ncp_do_readdir(server, inode, filp->f_pos, - NCP_READDIR_CACHE_SIZE, - c_entry); - DPRINTK("ncp_readdir returned %d\n", result); + entries = ncp_do_readdir(server, inode, filp->f_pos, + NCP_READDIR_CACHE_SIZE, + c_entry); + DPRINTK("ncp_readdir returned %d\n", entries); } - if (result < 0) + if (entries < 0) { c_dev = 0; c_ino = 0; - return result; + result = entries; + goto finished; } - if (result > 0) + if (entries > 0) { - c_seen_eof = (result < NCP_READDIR_CACHE_SIZE); + c_seen_eof = (entries < NCP_READDIR_CACHE_SIZE); c_dev = inode->i_dev; c_ino = inode->i_ino; - c_size = result; + c_size = entries; entry = c_entry; c_last_returned_index = 0; index = 0; @@ -336,7 +360,7 @@ ncp_readdir(struct inode *inode, struct file *filp, if (entry == NULL) { /* Nothing found, even from a ncp call */ - return 0; + goto finished; } if (index < c_size) @@ -374,15 +398,18 @@ ncp_readdir(struct inode *inode, struct file *filp, if (filldir(dirent, entry->i.entryName, entry->i.nameLen, entry->f_pos, ino) < 0) { - return 0; + goto finished; } filp->f_pos += 1; index += 1; entry += 1; - return ROUND_UP(NAME_OFFSET(dirent)+i+1); + result = ROUND_UP(NAME_OFFSET(dirent)+i+1); + goto finished; } - return 0; + finished: + ncp_unlock_dircache(); + return result; } static int @@ -828,7 +855,9 @@ ncp_lookup(struct inode *dir, const char *__name, int len, server. */ found_in_cache = 0; - + + ncp_lock_dircache(); + if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino)) { int first = c_last_returned_index; @@ -851,6 +880,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len, } while (i != first); } + ncp_unlock_dircache(); if (found_in_cache == 0) { diff --git a/kernel-1.2/src/inode.c b/kernel-1.2/src/inode.c index 0add779..4ebaa49 100644 --- a/kernel-1.2/src/inode.c +++ b/kernel-1.2/src/inode.c @@ -94,7 +94,7 @@ ncp_read_inode(struct inode *inode) inode->i_nlink = 1; inode->i_uid = NCP_SERVER(inode)->m.uid; inode->i_gid = NCP_SERVER(inode)->m.gid; - inode->i_blksize = 1024; + inode->i_blksize = 512; inode->i_rdev = 0; if ((inode->i_blksize != 0) && (inode->i_size != 0)) diff --git a/kernel-1.2/src/sock.c b/kernel-1.2/src/sock.c index e5faf13..12e2a51 100644 --- a/kernel-1.2/src/sock.c +++ b/kernel-1.2/src/sock.c @@ -222,6 +222,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size) int timeout; int retrans; int major_timeout_seen; + int acknowledge_seen; int n; int addrlen; unsigned long old_mask; @@ -243,7 +244,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size) return -EBADF; } init_timeout = server->m.time_out; - max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10; + max_timeout = NCP_MAX_RPC_TIMEOUT; + acknowledge_seen = 0; retrans = server->m.retry_count; major_timeout_seen = 0; old_mask = current->blocked; @@ -296,11 +298,14 @@ do_ncp_rpc_call(struct ncp_server *server, int size) { if (timeout > max_timeout) { - /* JEJB/JSP 2/7/94 - * This is useful to see if the system is - * hanging */ - printk("NCP max timeout reached\n"); - timeout = max_timeout; + /* JEJB/JSP 2/7/94 + * This is useful to see if the system is + * hanging */ + if (acknowledge_seen == 0) + { + printk("NCP max timeout reached\n"); + } + timeout = max_timeout; } current->timeout = jiffies + timeout; schedule(); @@ -373,6 +378,9 @@ do_ncp_rpc_call(struct ncp_server *server, int size) sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL, &addrlen); + n = 0; + timeout = max_timeout; + acknowledge_seen = 1; goto re_select; } diff --git a/ncpfs-0.21.lsm b/ncpfs-0.22.lsm similarity index 73% rename from ncpfs-0.21.lsm rename to ncpfs-0.22.lsm index 94d74a5..0cf7a46 100644 --- a/ncpfs-0.21.lsm +++ b/ncpfs-0.22.lsm @@ -1,19 +1,19 @@ Begin3 Title: ncpfs -Version: 0.21 -Entered-date: 26. March 1996 +Version: 0.22 +Entered-date: 17. April 1996 Description: With ncpfs you can mount volumes of your netware server under Linux. You can also print to netware print queues and spool netware print queues to the Linux printing system. You need kernel 1.2.x or - 1.3.54 and above. ncpfs does NOT work with any 1.3.x - kernel below 1.3.54. + 1.3.71 and above. ncpfs does NOT work with any 1.3.x + kernel below 1.3.71. Keywords: filesystem ncp novell netware printing Author: lendecke@namu01.gwdg.de (Volker Lendecke) Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke) Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/ - ~111k ncpfs-0.21.tgz - ~ 1k ncpfs-0.21.lsm + ~120k ncpfs-0.22.tgz + ~ 1k ncpfs-0.22.lsm Copying-policy: GPL End diff --git a/util/Makefile b/util/Makefile index 4c856b7..2202269 100644 --- a/util/Makefile +++ b/util/Makefile @@ -13,6 +13,9 @@ UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS)) CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2 -DNCPFS_VERSION=\"$(VERSION)\" CC = gcc +default: + make -C .. + all: $(UTILS) ncptest install: all diff --git a/util/ncplib.c b/util/ncplib.c index 9bb6ea0..6fe2982 100644 --- a/util/ncplib.c +++ b/util/ncplib.c @@ -1878,6 +1878,27 @@ ncp_get_bindery_object_id(struct ncp_conn *conn, return 0; } +long +ncp_get_bindery_object_name(struct ncp_conn *conn, + __u32 object_id, + struct ncp_bindery_object *target) +{ + long result; + ncp_init_request_s(conn, 54); + ncp_add_dword(conn, htonl(object_id)); + + if ((result = ncp_request(conn, 23)) != 0) { + ncp_unlock_conn(conn); + return result; + } + + target->object_id = ntohl(ncp_reply_dword(conn, 0)); + target->object_type = ntohs(ncp_reply_word (conn, 4)); + memcpy(target->object_name, ncp_reply_data(conn, 6), 48); + ncp_unlock_conn(conn); + return 0; +} + long ncp_scan_bindery_object(struct ncp_conn *conn, __u32 last_id, __u16 object_type, char *search_string, @@ -1906,6 +1927,37 @@ ncp_scan_bindery_object(struct ncp_conn *conn, return 0; } +long +ncp_create_bindery_object(struct ncp_conn *conn, + struct ncp_bindery_object *source) +{ + long result; + ncp_init_request_s(conn, 50); + ncp_add_byte(conn, source->object_flags); + ncp_add_byte(conn, source->object_security); + ncp_add_word(conn, htons(source->object_type)); + ncp_add_pstring(conn, source->object_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + + +long +ncp_delete_bindery_object(struct ncp_conn *conn, + __u16 object_type, + const char *object_name) +{ + long result; + ncp_init_request_s(conn, 51); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} long ncp_read_property_value(struct ncp_conn *conn, @@ -1932,6 +1984,149 @@ ncp_read_property_value(struct ncp_conn *conn, return 0; } + +long +ncp_scan_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + __u32 last_id, char *search_string, + struct ncp_property_info *property_info) +{ + long result; + ncp_init_request_s(conn, 60); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_dword(conn, htonl(last_id)); + ncp_add_pstring(conn, search_string); + + if ((result = ncp_request(conn, 23)) != 0) { + ncp_unlock_conn(conn); + return result; + } + + memcpy(property_info->property_name,ncp_reply_data(conn, 0), 16); + property_info->property_flags = ncp_reply_byte(conn,16); + property_info->property_security = ncp_reply_byte(conn,17); + property_info->search_instance = ntohl(ncp_reply_dword(conn,18)); + property_info->value_available_flag = ncp_reply_byte(conn,22); + property_info->more_properties_flag = ncp_reply_byte(conn,23); + ncp_unlock_conn(conn); + return 0; +} + +long +ncp_add_object_to_set(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u16 member_type, + const char *member_name) +{ + long result; + ncp_init_request_s(conn, 65); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_pstring(conn, property_name); + ncp_add_word(conn, htons(member_type)); + ncp_add_pstring(conn, member_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + +long +ncp_change_property_security(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 property_security) +{ + long result; + ncp_init_request_s(conn, 59); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_byte(conn, property_security); + ncp_add_pstring(conn, property_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + +long +ncp_create_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 property_flags, __u8 property_security) +{ + long result; + ncp_init_request_s(conn, 57); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_byte(conn, property_flags); + ncp_add_byte(conn, property_security); + ncp_add_pstring(conn, property_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + +long +ncp_delete_object_from_set(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u16 member_type, + const char *member_name) +{ + long result; + ncp_init_request_s(conn, 66); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_pstring(conn, property_name); + ncp_add_word(conn, htons(member_type)); + ncp_add_pstring(conn, member_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + +long +ncp_delete_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name) +{ + long result; + ncp_init_request_s(conn, 58); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_pstring(conn, property_name); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + +long +ncp_write_property_value(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 segment, + struct nw_property *property_value) +{ + long result; + ncp_init_request_s(conn, 62); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); + ncp_add_byte(conn,segment); + ncp_add_byte(conn, property_value->more_flag); + ncp_add_pstring(conn, property_name); + ncp_add_mem(conn, property_value->value, 128); + + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + long ncp_login_encrypted(struct ncp_conn *conn, const struct ncp_bindery_object *object, diff --git a/util/ncplib.h b/util/ncplib.h index 7a3633d..51f81ce 100644 --- a/util/ncplib.h +++ b/util/ncplib.h @@ -79,6 +79,15 @@ struct ncp_search_seq { int namespace; }; +struct ncp_property_info { + __u8 property_name[16]; + __u8 property_flags; + __u8 property_security; + __u32 search_instance; + __u8 value_available_flag; + __u8 more_properties_flag; +}; + /* ncp_initialize is the main entry point for user programs which want to connect to a NetWare Server. It looks for -S, -U, -P and -n in the argument list, opens the connection and removes the arguments @@ -165,9 +174,20 @@ ncp_get_bindery_object_id(struct ncp_conn *conn, const char *object_name, struct ncp_bindery_object *target); long +ncp_get_bindery_object_name(struct ncp_conn *conn, + __u32 object_id, + struct ncp_bindery_object *target); +long ncp_scan_bindery_object(struct ncp_conn *conn, __u32 last_id, __u16 object_type, char *search_string, struct ncp_bindery_object *target); +long +ncp_create_bindery_object(struct ncp_conn *conn, + struct ncp_bindery_object *source); +long +ncp_delete_bindery_object(struct ncp_conn *conn, + __u16 object_type, + const char *object_name); struct ncp_prop_login_control { __u8 AccountExpireDate[3] __attribute__ ((packed)); @@ -194,6 +214,43 @@ ncp_read_property_value(struct ncp_conn *conn, int segment, const char *prop_name, struct nw_property *target); long +ncp_scan_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + __u32 last_id, char *search_string, + struct ncp_property_info *property_info); +long +ncp_add_object_to_set(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u16 member_type, + const char *member_name); +long +ncp_change_property_security(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 property_security); +long +ncp_create_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 property_flags, __u8 property_security); +long +ncp_delete_object_from_set(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u16 member_type, + const char *member_name); +long +ncp_delete_property(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name); +long +ncp_write_property_value(struct ncp_conn *conn, + __u16 object_type, const char *object_name, + const char *property_name, + __u8 segment, + struct nw_property *property_value); +long ncp_login_encrypted(struct ncp_conn *conn, const struct ncp_bindery_object *object, const unsigned char *key, diff --git a/util/ncplib_err.et b/util/ncplib_err.et index 5f7f691..66afe25 100644 --- a/util/ncplib_err.et +++ b/util/ncplib_err.et @@ -18,4 +18,10 @@ ec NCPL_ET_MSG_TOO_LONG, ec NCPL_ET_NO_SPEC, "Could not find valid connection spec" +ec NCPL_ET_INVALID_MODE, + "$HOME/.nwclient has invalid mode" + +ec NCPL_ET_LOGIN_FAILED, + "Login failed" + end \ No newline at end of file