Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fa124bd7c | ||
|
|
5753870858 | ||
|
|
b8ce93c8bd |
BIN
.downloads/ncpfs-0.15.tgz
Normal file
BIN
.downloads/ncpfs-0.15.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.16.tgz
Normal file
BIN
.downloads/ncpfs-0.16.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.17.tgz
Normal file
BIN
.downloads/ncpfs-0.17.tgz
Normal file
Binary file not shown.
20
BUGS
20
BUGS
@@ -5,12 +5,12 @@ But there are really problems that might be fixed in the future.
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
'df' returns 0:
|
'df' returns 0: Free disk space is distributed among the volumes in
|
||||||
Free disk space is distributed among the volumes in NetWare. df is
|
NetWare. df is only able to report one number per mounted
|
||||||
only able to report one number per mounted filesystem. As connections
|
filesystem. As connections are quite expensive for NetWare (with
|
||||||
are quite expensive for NetWare (with lwared that might change ...), I
|
mars_nwe and lwared that might change ...), I rejected the alternative
|
||||||
rejected the alternative to mount only a single volume for a unix
|
to mount only a single volume for a unix mount point. So I simply
|
||||||
mount point. So I simply return 0.
|
return 0.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -20,11 +20,3 @@ like
|
|||||||
Nov 25 16:09:08 lx01 kernel: alloc_skb called nonatomically from interrupt 0000002e
|
Nov 25 16:09:08 lx01 kernel: alloc_skb called nonatomically from interrupt 0000002e
|
||||||
|
|
||||||
These are a bit annoying, but completely harmless.
|
These are a bit annoying, but completely harmless.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
ncpfs has a problem with NetWare 4.1, when files are created. I think
|
|
||||||
NW4.1 does not like some of the creation mode bits. If somebody with
|
|
||||||
access to a NW4.1 server could compile the kernel module for 1.2 with
|
|
||||||
-DDEBUG_NCP=2, and send me the syslog output gzipped/uuencoded, I
|
|
||||||
might find out more about that problem.
|
|
||||||
|
|||||||
37
Changes
37
Changes
@@ -1,6 +1,43 @@
|
|||||||
I only began this file with ncpfs-0.12. If you're interested in older
|
I only began this file with ncpfs-0.12. If you're interested in older
|
||||||
versions, you can find them on linux01.gwdg.de:/pub/ncpfs/old.
|
versions, you can find them on linux01.gwdg.de:/pub/ncpfs/old.
|
||||||
|
|
||||||
|
ncpfs-0.16 -> ncpfs-0.17
|
||||||
|
|
||||||
|
- Changed the name of fsinfo to nwfsinfo, to avoid a name clash with
|
||||||
|
the X windows utility. Thanks to Henning Brockfeld
|
||||||
|
<Henning.Brockfeld@lrz.uni-muenchen.de> for this hint. (still
|
||||||
|
waiting for your scripts.. :-))
|
||||||
|
- made nwmsg available. This enables you to receive NetWare user
|
||||||
|
broadcast messages. Please note that you need at least kernel 1.3.68
|
||||||
|
for this feature.
|
||||||
|
- pserver now prints debugging output via syslog().
|
||||||
|
- Included ipxdump, a nice little utility, that has helped some
|
||||||
|
people.
|
||||||
|
|
||||||
|
- And now the big one: you can re-export ncpfs-mounted directories
|
||||||
|
with nfsd! You have to mount single volumes by specifying -V volume
|
||||||
|
to ncpmount, and call nfsd and mountd with the option --re-export.
|
||||||
|
See the manual page of ncpmount for more information. Please note
|
||||||
|
that I will send Linus the required patch on 1. March 1996, so you
|
||||||
|
will have to use kernel 1.2.13 or wait at least for 1.3.70.
|
||||||
|
|
||||||
|
ncpfs-0.15 -> ncpfs-0.16
|
||||||
|
|
||||||
|
- Included ipx-1.0, made available by Greg Page <greg@caldera.com>,
|
||||||
|
Caldera
|
||||||
|
- Made -n work for password-less accounts. Thanks to Alexander Jolk
|
||||||
|
<jolk@ap-pc513b.physik.uni-karlsruhe.de>.
|
||||||
|
- Fixed the kerneld support.
|
||||||
|
- Fixed the NetWare 4.1 problem. Many thanks to
|
||||||
|
Chatchai JANTARAPRIM <chat@ratree.psu.ac.th> and
|
||||||
|
hitesh.soneji@industry.net for their patience.
|
||||||
|
|
||||||
|
ncpfs-0.14 -> ncpfs-0.15
|
||||||
|
|
||||||
|
- A bug fixed that made normal mounting impossible. It was too late
|
||||||
|
yesterday. Sorry
|
||||||
|
- Manpage for pserver.c
|
||||||
|
|
||||||
ncpfs-0.13 -> ncpfs-0.14
|
ncpfs-0.13 -> ncpfs-0.14
|
||||||
|
|
||||||
- Improvements of manual pages by B. Galliart <bgallia@luc.edu> and
|
- Improvements of manual pages by B. Galliart <bgallia@luc.edu> and
|
||||||
|
|||||||
18
Makefile
18
Makefile
@@ -2,13 +2,13 @@
|
|||||||
# Makefile for the linux ncp-filesystem routines.
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
#
|
#
|
||||||
|
|
||||||
# KERNEL = 1.2
|
VERSION = 0.17
|
||||||
|
|
||||||
TOPDIR = $(shell pwd)
|
TOPDIR = $(shell pwd)
|
||||||
|
|
||||||
BINDIR = /usr/local/bin
|
BINDIR = /usr/local/bin
|
||||||
|
SBINDIR = /sbin
|
||||||
INTERM_BINDIR = $(TOPDIR)/bin
|
INTERM_BINDIR = $(TOPDIR)/bin
|
||||||
SUBDIRS = util ipx-0.75 man
|
SUBDIRS = util ipx-1.0 man
|
||||||
|
|
||||||
#
|
#
|
||||||
# The following 2 lines are for those who use Kernel version 1.2.x.
|
# The following 2 lines are for those who use Kernel version 1.2.x.
|
||||||
@@ -16,14 +16,14 @@ SUBDIRS = util ipx-0.75 man
|
|||||||
# the following lines. You have to recompile your kernel
|
# the following lines. You have to recompile your kernel
|
||||||
# and say 'y' when 'make config' asks you for IPX and ncpfs.
|
# and say 'y' when 'make config' asks you for IPX and ncpfs.
|
||||||
#
|
#
|
||||||
#SUBDIRS += kernel-1.2/src
|
SUBDIRS += kernel-1.2/src
|
||||||
#INCLUDES = -I$(TOPDIR)/kernel-1.2
|
INCLUDES = -I$(TOPDIR)/kernel-1.2
|
||||||
|
|
||||||
# If you are using kerneld to autoload ncp support,
|
# If you are using kerneld to autoload ncp support,
|
||||||
# uncomment this (kerneld is in linux since about 1.3.57):
|
# uncomment this (kerneld is in linux since about 1.3.57):
|
||||||
# KERNELD = -DHAVE_KERNELD
|
#KERNELD = -DHAVE_KERNELD
|
||||||
|
|
||||||
export INCLUDES BINDIR INTERM_BINDIR KERNELD
|
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
|
||||||
|
|
||||||
all:
|
all:
|
||||||
for i in $(SUBDIRS); do make -C $$i; done
|
for i in $(SUBDIRS); do make -C $$i; done
|
||||||
@@ -41,7 +41,7 @@ clean:
|
|||||||
rm -f `find . -type f -name '*.out' -print`
|
rm -f `find . -type f -name '*.out' -print`
|
||||||
for i in $(SUBDIRS); do make -C $$i clean; done
|
for i in $(SUBDIRS); do make -C $$i clean; done
|
||||||
|
|
||||||
realclean: clean
|
mrproper: clean
|
||||||
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
||||||
make -C util realclean
|
make -C util realclean
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ dist: tgz
|
|||||||
make dep
|
make dep
|
||||||
make all
|
make all
|
||||||
|
|
||||||
tgz: realclean
|
tgz: mrproper
|
||||||
(cd ..; \
|
(cd ..; \
|
||||||
tar cvf - $(SRCDIR) | \
|
tar cvf - $(SRCDIR) | \
|
||||||
gzip -9 > $(DISTFILE); \
|
gzip -9 > $(DISTFILE); \
|
||||||
|
|||||||
29
README
29
README
@@ -1,6 +1,7 @@
|
|||||||
This is ncpfs, a free NetWare client filesystem for Linux. Besides
|
This is ncpfs, a free NetWare client filesystem for Linux. Besides
|
||||||
some little utilities it also contains nprint, which enables you to
|
some little utilities it also contains nprint, which enables you to
|
||||||
print on NetWare print queues.
|
print on NetWare print queues. The opposite side, pserver, is also
|
||||||
|
provided.
|
||||||
|
|
||||||
INSTALLATION
|
INSTALLATION
|
||||||
|
|
||||||
@@ -77,6 +78,8 @@ Ales Dyrak has written lwared, which was the initial start for ncpfs.
|
|||||||
|
|
||||||
Alan Cox has found some bugs I would probably never have found.
|
Alan Cox has found some bugs I would probably never have found.
|
||||||
|
|
||||||
|
Look at the file Changes for others.
|
||||||
|
|
||||||
|
|
||||||
LIMITATIONS (compare these with smbfs :-)
|
LIMITATIONS (compare these with smbfs :-)
|
||||||
|
|
||||||
@@ -86,27 +89,7 @@ limitation is the lack of uid, gid and permission information per
|
|||||||
file. You have to assign those values once for a complete mounted
|
file. You have to assign those values once for a complete mounted
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
The second limitation is just as annoying as the first: You cannot
|
You will not be able to access servers that require packet
|
||||||
re-export a ncp-mounted directory by nfs. It is not possible because
|
signatures. This seems to be one of Novell's bigger secrets :-(.
|
||||||
the NFS protocol defines access to files through unique file handles,
|
|
||||||
which can be mapped to the device and inode numbers in unix NFS
|
|
||||||
servers. NCP does not have unique numbers per file, you only have the
|
|
||||||
path name. I implemented a caching scheme for inode numbers, which
|
|
||||||
gives unique inode numbers for every open file in the system. This is
|
|
||||||
just sufficient for local use of the files, because you can tell when
|
|
||||||
an inode number can be discarded. With NFS the situation is
|
|
||||||
different. You can never know when the client will access the file-id
|
|
||||||
you offered, so you would have to cache the inode numbers
|
|
||||||
indefinitely long. I think this should not be done in kernel mode, as
|
|
||||||
it would require an unlimited amount of RAM.
|
|
||||||
|
|
||||||
Those who looked at the kernel code a bit closer will have found out
|
|
||||||
that the last section is a little white lie. As I found out after the
|
|
||||||
first version of ncpfs, NetWare does indeed offer something like inode
|
|
||||||
numbers, although are only unique per volume. So one way to make ncpfs
|
|
||||||
re-exportable by nfs is to allocate a superblock per volume and show
|
|
||||||
the inode numbers to the user. I was just too lazy to do this
|
|
||||||
yet. Maybe once we will force Novell to make NetWare NFS
|
|
||||||
affordable... ;-)
|
|
||||||
|
|
||||||
Have fun with ncpfs!
|
Have fun with ncpfs!
|
||||||
|
|||||||
9
ipx-1.0/COPYING
Normal file
9
ipx-1.0/COPYING
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the original work is
|
||||||
|
properly attributed to Greg Page and Caldera, Inc.
|
||||||
|
Neither the name of Greg Page nor Caldera, Inc. may be used to
|
||||||
|
endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
This software is provided by Greg Page and Caldera, Inc. "AS IS"
|
||||||
|
and without any express or implied warranties.
|
||||||
|
|
||||||
24
ipx-1.0/Gregs.Makefile
Normal file
24
ipx-1.0/Gregs.Makefile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
CFLAGS = -O2 -Wall
|
||||||
|
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
|
||||||
|
all: $(UTILS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||||
|
|
||||||
|
install: $(UTILS)
|
||||||
|
for i in $(UTILS); \
|
||||||
|
do \
|
||||||
|
install --strip $$i /sbin; \
|
||||||
|
install $$i.8 /usr/man/man8; \
|
||||||
|
done
|
||||||
|
install init.ipx /etc/rc.d/init.d/ipx
|
||||||
|
install -m 0644 config.ipx /etc/sysconfig/ipx
|
||||||
|
rm -f /etc/rc.d/rc2.d/S15ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc2.d/S15ipx
|
||||||
|
rm -f /etc/rc.d/rc3.d/S15ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc3.d/S15ipx
|
||||||
|
rm -f /etc/rc.d/rc5.d/S15ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc5.d/S15ipx
|
||||||
|
rm -f /etc/rc.d/rc6.d/K55ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc6.d/K55ipx
|
||||||
|
|
||||||
@@ -5,16 +5,16 @@ UTILS = $(INTERM_BINDIR)/ipx_configure $(INTERM_BINDIR)/ipx_interface \
|
|||||||
all: $(UTILS)
|
all: $(UTILS)
|
||||||
|
|
||||||
$(INTERM_BINDIR)/ipx_configure: ipx_configure.o
|
$(INTERM_BINDIR)/ipx_configure: ipx_configure.o
|
||||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
|
$(CC) -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
|
||||||
|
|
||||||
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
|
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
|
||||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
|
$(CC) -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
|
||||||
|
|
||||||
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
|
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
|
||||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
|
$(CC) -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
|
||||||
|
|
||||||
$(INTERM_BINDIR)/ipx_route: ipx_route.o
|
$(INTERM_BINDIR)/ipx_route: ipx_route.o
|
||||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_route ipx_route.o
|
$(CC) -o $(INTERM_BINDIR)/ipx_route ipx_route.o
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
@@ -25,6 +25,6 @@ clean:
|
|||||||
install: $(UTILS)
|
install: $(UTILS)
|
||||||
for i in $(UTILS); \
|
for i in $(UTILS); \
|
||||||
do \
|
do \
|
||||||
install --strip $$i $(BINDIR); \
|
install $$i $(BINDIR); \
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ This program is used to read/write two configuration parameters:
|
|||||||
|
|
||||||
By default, these are both turned off.
|
By default, these are both turned off.
|
||||||
|
|
||||||
The following are sample IPX programs:
|
The following are sample IPX programs (found in directory Samples):
|
||||||
|
|
||||||
ipxrcv.c and ipxsend.c
|
ipxrcv.c and ipxsend.c
|
||||||
ipxsend will send a single packet to an instance of ipxrcv running on the
|
ipxsend will send a single packet to an instance of ipxrcv running on the
|
||||||
@@ -51,7 +51,7 @@ main(int argc, char **argv)
|
|||||||
htonl(sipx.sipx_network),
|
htonl(sipx.sipx_network),
|
||||||
sipx.sipx_node[0], sipx.sipx_node[1],
|
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||||
sipx.sipx_node[2], sipx.sipx_node[3],
|
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||||
sipx.sipx_node[4], sipx.sipx_node[5]);
|
sipx.sipx_node[6], sipx.sipx_node[5]);
|
||||||
bptr += 2;
|
bptr += 2;
|
||||||
rp = (struct rip_data *) bptr;
|
rp = (struct rip_data *) bptr;
|
||||||
while (result >= sizeof(struct rip_data)) {
|
while (result >= sizeof(struct rip_data)) {
|
||||||
7
ipx-1.0/config.ipx
Normal file
7
ipx-1.0/config.ipx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
IPX_AUTO_PRIMARY=on
|
||||||
|
IPX_AUTO_INTERFACE=on
|
||||||
|
IPX_CONFIGURED=no
|
||||||
|
IPX_DEVICE=eth0
|
||||||
|
IPX_FRAME=802.2
|
||||||
|
IPX_INTERNAL_NET=no
|
||||||
|
IPX_NETNUM=0
|
||||||
41
ipx-1.0/init.ipx
Normal file
41
ipx-1.0/init.ipx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# ipx Bring up/down IPX networking
|
||||||
|
#
|
||||||
|
|
||||||
|
# Source function library.
|
||||||
|
. /etc/rc.d/init.d/functions
|
||||||
|
|
||||||
|
. /etc/sysconfig/network
|
||||||
|
. /etc/sysconfig/ipx
|
||||||
|
|
||||||
|
# Check that networking is up.
|
||||||
|
[ ${NETWORKING} = "no" ] && exit 0
|
||||||
|
|
||||||
|
# See how we were called.
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
if [ ${IPX_CONFIGURED} = "yes" ]; then
|
||||||
|
if [ ${IPX_INTERNAL_NET} = "yes" ]; then
|
||||||
|
/sbin/ipx_internal_net add ${IPX_NETNUM}
|
||||||
|
else
|
||||||
|
/sbin/ipx_interface add -p ${IPX_DEVICE} \
|
||||||
|
${IPX_FRAME} ${IPX_NETNUM}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
ipx_configure \
|
||||||
|
--auto_primary=${IPX_AUTO_PRIMARY} \
|
||||||
|
--auto_interface=${IPX_AUTO_INTERFACE}
|
||||||
|
touch /var/lock/subsys/ipx
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
ipx_configure --auto_primary=off --auto_interface=off
|
||||||
|
ipx_interface delall
|
||||||
|
rm -f /var/lock/subsys/ipx
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: network {start|stop}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -19,7 +24,8 @@ usage(void)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||||
Usage: %s del device frame_type\n\
|
Usage: %s del device frame_type\n\
|
||||||
Usage: %s check device frame_type\n", progname, progname, progname);
|
Usage: %s delall\n\
|
||||||
|
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,6 +34,9 @@ struct frame_type {
|
|||||||
unsigned char ft_val;
|
unsigned char ft_val;
|
||||||
} frame_types[] = {
|
} frame_types[] = {
|
||||||
{"802.2", IPX_FRAME_8022},
|
{"802.2", IPX_FRAME_8022},
|
||||||
|
#ifdef IPX_FRAME_TR_8022
|
||||||
|
{"802.2TR", IPX_FRAME_TR_8022},
|
||||||
|
#endif
|
||||||
{"802.3", IPX_FRAME_8023},
|
{"802.3", IPX_FRAME_8023},
|
||||||
{"SNAP", IPX_FRAME_SNAP},
|
{"SNAP", IPX_FRAME_SNAP},
|
||||||
{"EtherII", IPX_FRAME_ETHERII}
|
{"EtherII", IPX_FRAME_ETHERII}
|
||||||
@@ -162,6 +171,76 @@ ipx_add_interface(int argc, char **argv)
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_delall_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
char buffer[80];
|
||||||
|
char device[20];
|
||||||
|
char frame_type[20];
|
||||||
|
int fti;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen("/proc/net/ipx_interface", "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Unable to open \"/proc/net/ipx_interface.\"\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fgets(buffer, 80, fp);
|
||||||
|
while (fscanf(fp, "%s %s %s %s %s", buffer, buffer, buffer,
|
||||||
|
device, frame_type) == 5) {
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
if (strcasecmp(device, "Internal") == 0) {
|
||||||
|
sipx->sipx_special = IPX_INTERNAL;
|
||||||
|
} else {
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
|
strcpy(id.ifr_name, device);
|
||||||
|
fti = lookup_frame_type(frame_type);
|
||||||
|
if (fti < 0) continue;
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_action = IPX_DLTITF;
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
if (result == 0) continue;
|
||||||
|
switch (errno) {
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_type);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n",
|
||||||
|
progname, device);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
|
||||||
|
progname, device, frame_type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ipx_del_interface(int argc, char **argv)
|
ipx_del_interface(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -176,6 +255,7 @@ ipx_del_interface(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sipx->sipx_network = 0L;
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
strcpy(id.ifr_name, argv[1]);
|
strcpy(id.ifr_name, argv[1]);
|
||||||
fti = lookup_frame_type(argv[2]);
|
fti = lookup_frame_type(argv[2]);
|
||||||
if (fti < 0)
|
if (fti < 0)
|
||||||
@@ -289,6 +369,10 @@ main(int argc, char **argv)
|
|||||||
for (i = 1; i < (argc-1); i++)
|
for (i = 1; i < (argc-1); i++)
|
||||||
argv[i] = argv[i+1];
|
argv[i] = argv[i+1];
|
||||||
ipx_add_interface(argc-1, argv);
|
ipx_add_interface(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "delall", 6) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_delall_interface(argc-1, argv);
|
||||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||||
for (i = 1; i < (argc-1); i++)
|
for (i = 1; i < (argc-1); i++)
|
||||||
argv[i] = argv[i+1];
|
argv[i] = argv[i+1];
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
35
ipxdump/Makefile
Normal file
35
ipxdump/Makefile
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
EXEC= ipxdump ipxparse
|
||||||
|
|
||||||
|
CFLAGS= -Wall -O2
|
||||||
|
OBJECTS= ipxutil.o
|
||||||
|
|
||||||
|
all: $(EXEC)
|
||||||
|
|
||||||
|
ipxdump: ipxdump.o $(OBJECTS)
|
||||||
|
$(CC) -o $@ ipxdump.o $(CFLAGS) $(OBJECTS)
|
||||||
|
|
||||||
|
ipxparse: ipxparse.o $(OBJECTS)
|
||||||
|
$(CC) -o $@ ipxparse.o $(CFLAGS) $(OBJECTS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o $(EXEC) *~
|
||||||
|
|
||||||
|
|
||||||
|
modules: ncpfs.o
|
||||||
|
|
||||||
|
SRCPATH=$(shell pwd)
|
||||||
|
SRCDIR=$(shell basename $(SRCPATH))
|
||||||
|
DISTFILE=$(SRCDIR).tgz
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
rm -f $(DISTFILE)
|
||||||
|
|
||||||
|
dist: tgz
|
||||||
|
make all
|
||||||
|
|
||||||
|
tgz: mrproper
|
||||||
|
(cd ..; \
|
||||||
|
tar cvf - $(SRCDIR) | \
|
||||||
|
gzip -9 > $(DISTFILE); \
|
||||||
|
mv $(DISTFILE) $(SRCDIR))
|
||||||
|
|
||||||
45
ipxdump/README
Normal file
45
ipxdump/README
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
This is a VERY stupid packet sniffer for IPX ethernet packets.
|
||||||
|
|
||||||
|
=============================================
|
||||||
|
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||||
|
! ! ! S E C U R I T Y W A R N I N G ! ! !
|
||||||
|
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
If you are using unencrypted passwords, and use this tool to send a
|
||||||
|
dump to somebody else or store it on a computer, you might very well
|
||||||
|
store passwords there. So, be VERY careful! This is exactly the kind
|
||||||
|
of tools Novell designed the encrypted passwords for (or against).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
I hacked it together to be able to help people with problems with
|
||||||
|
ncpfs. The socket handling was taken from Statnet-2.0.
|
||||||
|
|
||||||
|
You can use it to watch commercial NetWare clients when they talk to
|
||||||
|
servers. I divided the program into 2 parts, ipxdump and ipxparse.
|
||||||
|
|
||||||
|
ipxdump simply pumps all the IPX frames it receives to stdout.
|
||||||
|
|
||||||
|
If you use ipxdump to watch a workstation, you can use the simple
|
||||||
|
filter function ipxdump provides. You can call ipxdump with the node
|
||||||
|
address of the workstation you want to watch. This way only the
|
||||||
|
packets this workstation sends and receives are monitored. As an
|
||||||
|
example, I call ipxdump as
|
||||||
|
|
||||||
|
./ipxdump 00001B038B11
|
||||||
|
|
||||||
|
to look at my 286/10MHz test 'workstation'. ipxdump still generates
|
||||||
|
huge amounts of data, so you should be very careful to start it just
|
||||||
|
before you perform the operation (such as file creation for OS/2
|
||||||
|
clients with NW4.1 as a server, or a 'dir' on a directory with long
|
||||||
|
and short file names, or an encrypted password change ;-)) and stop it
|
||||||
|
directly after that. And, please gzip -9 and uuencode it before you
|
||||||
|
send it to anybody.
|
||||||
|
|
||||||
|
ipxparse will eventually take apart the dump that ipxdump
|
||||||
|
generates. They can as well be used in a pipe. Currently ipxparse does
|
||||||
|
not do anything sensible, but that will definitely change.
|
||||||
|
|
||||||
|
Volker Lendecke
|
||||||
|
<lendecke@namu01.gwdg.de>
|
||||||
247
ipxdump/ipxdump.c
Normal file
247
ipxdump/ipxdump.c
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/* ipxdump.c */
|
||||||
|
|
||||||
|
/* Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <netinet/protocols.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "ipxutil.h"
|
||||||
|
|
||||||
|
struct ipx_address
|
||||||
|
{
|
||||||
|
unsigned long net;
|
||||||
|
unsigned char node[IPX_NODE_LEN];
|
||||||
|
unsigned short sock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipx_packet
|
||||||
|
{
|
||||||
|
unsigned short ipx_checksum;
|
||||||
|
#define IPX_NO_CHECKSUM 0xFFFF
|
||||||
|
unsigned short ipx_pktsize;
|
||||||
|
unsigned char ipx_tctrl;
|
||||||
|
unsigned char ipx_type;
|
||||||
|
#define IPX_TYPE_UNKNOWN 0x00
|
||||||
|
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||||
|
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||||
|
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||||
|
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||||
|
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||||
|
struct ipx_address ipx_dest __attribute__ ((packed));
|
||||||
|
struct ipx_address ipx_source __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr);
|
||||||
|
void handle_ipx (unsigned char *buf);
|
||||||
|
|
||||||
|
static int filter = 0;
|
||||||
|
static IPXNode filter_node;
|
||||||
|
|
||||||
|
static int exit_request = 0;
|
||||||
|
static void
|
||||||
|
int_handler()
|
||||||
|
{
|
||||||
|
exit_request = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int sd;
|
||||||
|
struct ifreq ifr, oldifr;
|
||||||
|
char *device = "eth0";
|
||||||
|
struct sockaddr saddr;
|
||||||
|
int sizeaddr;
|
||||||
|
unsigned char buf[4096];
|
||||||
|
int length;
|
||||||
|
|
||||||
|
signal(SIGINT, int_handler);
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
if (ipx_sscanf_node(argv[1], filter_node) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [node]\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
filter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
|
||||||
|
{
|
||||||
|
perror ("Can't get socket");
|
||||||
|
fprintf(stderr, "You must run %s as root\n", argv[0]);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SET PROMISC */
|
||||||
|
|
||||||
|
strcpy (oldifr.ifr_name, device);
|
||||||
|
if (ioctl (sd, SIOCGIFFLAGS, &oldifr) < 0)
|
||||||
|
{
|
||||||
|
close (sd);
|
||||||
|
perror ("Can't get flags");
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should be rewritten to cooperate with other net tools */
|
||||||
|
ifr = oldifr;
|
||||||
|
ifr.ifr_flags |= IFF_PROMISC;
|
||||||
|
|
||||||
|
if (ioctl (sd, SIOCSIFFLAGS, &ifr) < 0)
|
||||||
|
{
|
||||||
|
close (sd);
|
||||||
|
perror ("Can't set flags");
|
||||||
|
exit (3);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( exit_request == 0 )
|
||||||
|
{
|
||||||
|
/* This is the main data-gathering loop; keep it small
|
||||||
|
and fast */
|
||||||
|
sizeaddr = sizeof(saddr);
|
||||||
|
length = recvfrom (sd, buf, sizeof(buf), 0,
|
||||||
|
&saddr, &sizeaddr);
|
||||||
|
if (length < 0 ) continue;
|
||||||
|
handle_frame (buf, length, &saddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should be rewritten to cooperate with other net tools */
|
||||||
|
if (ioctl (sd, SIOCSIFFLAGS, &oldifr) < 0)
|
||||||
|
{
|
||||||
|
close (sd);
|
||||||
|
perror ("Can't set flags");
|
||||||
|
exit (4);
|
||||||
|
}
|
||||||
|
|
||||||
|
close (sd);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_ipx (unsigned char *buf)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||||
|
struct sockaddr_ipx s_addr;
|
||||||
|
struct sockaddr_ipx d_addr;
|
||||||
|
int length = ntohs(h->ipx_pktsize);
|
||||||
|
|
||||||
|
|
||||||
|
memset(&s_addr, 0, sizeof(s_addr));
|
||||||
|
memset(&d_addr, 0, sizeof(d_addr));
|
||||||
|
|
||||||
|
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||||
|
s_addr.sipx_port = h->ipx_source.sock;
|
||||||
|
s_addr.sipx_network = h->ipx_source.net;
|
||||||
|
|
||||||
|
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||||
|
d_addr.sipx_port = h->ipx_dest.sock;
|
||||||
|
d_addr.sipx_network = h->ipx_dest.net;
|
||||||
|
|
||||||
|
if (filter != 0)
|
||||||
|
{
|
||||||
|
if ( (memcmp(filter_node, s_addr.sipx_node,
|
||||||
|
sizeof(filter_node)) != 0)
|
||||||
|
&& (memcmp(filter_node, d_addr.sipx_node,
|
||||||
|
sizeof(filter_node)) != 0))
|
||||||
|
{
|
||||||
|
/* Not for us */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
printf("%2.2X", buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
if (!isatty(STDOUT_FILENO))
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_other (unsigned char *buf, int length, struct sockaddr *saddr)
|
||||||
|
{
|
||||||
|
struct ethhdr *eth = (struct ethhdr *)buf;
|
||||||
|
unsigned char *p = &(buf[sizeof(struct ethhdr)]);
|
||||||
|
|
||||||
|
if (ntohs(eth->h_proto) < 1536)
|
||||||
|
{
|
||||||
|
/* This is a magic hack to spot IPX packets. Older
|
||||||
|
* Novell breaks the protocol design and runs IPX over
|
||||||
|
* 802.3 without an 802.2 LLC layer. We look for FFFF
|
||||||
|
* which isnt a used 802.2 SSAP/DSAP. This won't work
|
||||||
|
* for fault tolerant netware but does for the rest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (*(unsigned short *)p == 0xffff)
|
||||||
|
{
|
||||||
|
printf("802.3 ");
|
||||||
|
handle_ipx(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (*(unsigned short *)p == htons(0xe0e0))
|
||||||
|
&& (p[2] == 0x03))
|
||||||
|
{
|
||||||
|
printf("802.2 ");
|
||||||
|
handle_ipx(p+3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
||||||
|
{
|
||||||
|
printf("snap ");
|
||||||
|
handle_ipx(p+8);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
|
||||||
|
{
|
||||||
|
/* Ethernet packet type ID field */
|
||||||
|
unsigned short packet_type = ((struct ethhdr *)buf)->h_proto;
|
||||||
|
switch( packet_type )
|
||||||
|
{
|
||||||
|
case __constant_ntohs(ETH_P_IPX):
|
||||||
|
printf("EtherII ");
|
||||||
|
handle_ipx(&(buf[sizeof(struct ethhdr)]));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handle_other(buf, length, saddr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
345
ipxdump/ipxparse.c
Normal file
345
ipxdump/ipxparse.c
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
/* ipxparse.c */
|
||||||
|
|
||||||
|
/* Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#include <netinet/protocols.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "ipxutil.h"
|
||||||
|
|
||||||
|
struct ipx_address
|
||||||
|
{
|
||||||
|
unsigned long net;
|
||||||
|
unsigned char node[IPX_NODE_LEN];
|
||||||
|
unsigned short sock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipx_packet
|
||||||
|
{
|
||||||
|
unsigned short ipx_checksum;
|
||||||
|
#define IPX_NO_CHECKSUM 0xFFFF
|
||||||
|
unsigned short ipx_pktsize;
|
||||||
|
unsigned char ipx_tctrl;
|
||||||
|
unsigned char ipx_type;
|
||||||
|
#define IPX_TYPE_UNKNOWN 0x00
|
||||||
|
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||||
|
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||||
|
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||||
|
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||||
|
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||||
|
struct ipx_address ipx_dest __attribute__ ((packed));
|
||||||
|
struct ipx_address ipx_source __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NCP_ALLOC_SLOT_REQUEST (0x1111)
|
||||||
|
#define NCP_REQUEST (0x2222)
|
||||||
|
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
|
||||||
|
|
||||||
|
struct ncp_request_header {
|
||||||
|
__u16 type __attribute__ ((packed));
|
||||||
|
__u8 sequence __attribute__ ((packed));
|
||||||
|
__u8 conn_low __attribute__ ((packed));
|
||||||
|
__u8 task __attribute__ ((packed));
|
||||||
|
__u8 conn_high __attribute__ ((packed));
|
||||||
|
__u8 function __attribute__ ((packed));
|
||||||
|
__u8 data[0] __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NCP_REPLY (0x3333)
|
||||||
|
#define NCP_POSITIVE_ACK (0x9999)
|
||||||
|
|
||||||
|
struct ncp_reply_header {
|
||||||
|
__u16 type __attribute__ ((packed));
|
||||||
|
__u8 sequence __attribute__ ((packed));
|
||||||
|
__u8 conn_low __attribute__ ((packed));
|
||||||
|
__u8 task __attribute__ ((packed));
|
||||||
|
__u8 conn_high __attribute__ ((packed));
|
||||||
|
__u8 completion_code __attribute__ ((packed));
|
||||||
|
__u8 connection_state __attribute__ ((packed));
|
||||||
|
__u8 data[0] __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
void handle_ipx (unsigned char *buf, int length, char *frame, int no);
|
||||||
|
void handle_ncp (struct sockaddr_ipx *source,
|
||||||
|
struct sockaddr_ipx *target,
|
||||||
|
unsigned char *buf, int length, int no);
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_ipx (unsigned char *buf, int length, char *frame, int no)
|
||||||
|
{
|
||||||
|
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||||
|
struct sockaddr_ipx s_addr;
|
||||||
|
struct sockaddr_ipx d_addr;
|
||||||
|
|
||||||
|
memset(&s_addr, 0, sizeof(s_addr));
|
||||||
|
memset(&d_addr, 0, sizeof(d_addr));
|
||||||
|
|
||||||
|
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||||
|
s_addr.sipx_port = h->ipx_source.sock;
|
||||||
|
s_addr.sipx_network = h->ipx_source.net;
|
||||||
|
|
||||||
|
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||||
|
d_addr.sipx_port = h->ipx_dest.sock;
|
||||||
|
d_addr.sipx_network = h->ipx_dest.net;
|
||||||
|
|
||||||
|
printf("%6.6d %s from ", no, frame);
|
||||||
|
|
||||||
|
ipx_print_saddr(&s_addr);
|
||||||
|
printf(" to ");
|
||||||
|
ipx_print_saddr(&d_addr);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if ( (ntohs(s_addr.sipx_port) == 0x451)
|
||||||
|
|| (ntohs(d_addr.sipx_port) == 0x451))
|
||||||
|
{
|
||||||
|
handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
|
||||||
|
length - sizeof(struct ipx_packet), no);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_ncp (struct sockaddr_ipx *source,
|
||||||
|
struct sockaddr_ipx *target,
|
||||||
|
unsigned char *buf, int length, int no)
|
||||||
|
{
|
||||||
|
struct ncp_request_header *rq = (struct ncp_request_header *)buf;
|
||||||
|
struct ncp_reply_header *rs = (struct ncp_reply_header *)buf;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
int data_length = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ntohs(rq->type) == NCP_REQUEST)
|
||||||
|
{
|
||||||
|
/* Request */
|
||||||
|
printf("NCP request: conn: %-5d, seq: %-3d, task: %-3d, ",
|
||||||
|
rq->conn_low + 256 * rq->conn_high,
|
||||||
|
rq->sequence, rq->task);
|
||||||
|
|
||||||
|
data = buf + sizeof(struct ncp_request_header);
|
||||||
|
data_length = length - sizeof(struct ncp_request_header);
|
||||||
|
|
||||||
|
switch(rq->function)
|
||||||
|
{
|
||||||
|
case 87:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n",
|
||||||
|
rq->function, data[0]);
|
||||||
|
switch(data[0])
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
unsigned char *p = &(data[0]);
|
||||||
|
printf("Open Create File or Subdirectory\n");
|
||||||
|
printf("Name Space: %d\n", p[1]);
|
||||||
|
printf("Open Create Mode: %x\n", p[2]);
|
||||||
|
printf("Search Attributes: %x\n",
|
||||||
|
*(__u16 *)&(p[3]));
|
||||||
|
printf("Return Information Mask: %x\n",
|
||||||
|
(unsigned int)(*(__u32 *)&(p[5])));
|
||||||
|
printf("Desired Access Rights: %x\n",
|
||||||
|
*(__u16 *)&(p[9]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
printf("Initialize Search\n");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
printf("Search for File or Subdirectory\n");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
printf("Obtain File Or Subdirectory "
|
||||||
|
"Information\n");
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
printf("Delete a File Or Subdirectory\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data += 1;
|
||||||
|
data_length -= 1;
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n",
|
||||||
|
rq->function, data[2]);
|
||||||
|
switch(data[2])
|
||||||
|
{
|
||||||
|
case 21:
|
||||||
|
printf("Get Volume Info with handle\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||||
|
data[2]);
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("End of Job\n");
|
||||||
|
break;
|
||||||
|
case 34:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||||
|
data[2]);
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 62:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("File Search Initialize\n");
|
||||||
|
break;
|
||||||
|
case 63:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("File Search Continue\n");
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Search for a file\n");
|
||||||
|
break;
|
||||||
|
case 66:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Close File\n");
|
||||||
|
break;
|
||||||
|
case 73:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Write to File\n");
|
||||||
|
break;
|
||||||
|
case 75:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Set File Time Date Stamp\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntohs(rs->type) == NCP_REPLY)
|
||||||
|
{
|
||||||
|
printf("NCP respons: conn: %-5d, seq: %-3d, task: %-3d, ",
|
||||||
|
rs->conn_low + 256 * rs->conn_high,
|
||||||
|
rs->sequence, rs->task);
|
||||||
|
printf("compl: %-3d, conn_st: %-3d\n",
|
||||||
|
rs->completion_code, rs->connection_state);
|
||||||
|
|
||||||
|
data = buf + sizeof(struct ncp_reply_header);
|
||||||
|
data_length = length - sizeof(struct ncp_reply_header);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == NULL)
|
||||||
|
{
|
||||||
|
data = buf;
|
||||||
|
data_length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < data_length)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
for (j = i; j < i+16; j++)
|
||||||
|
{
|
||||||
|
if (j >= data_length)
|
||||||
|
{
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%-2.2X", data[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" ");
|
||||||
|
for (j = i; j < i+16; j++)
|
||||||
|
{
|
||||||
|
if (j >= data_length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isprint(data[j]))
|
||||||
|
{
|
||||||
|
printf("%c", data[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
i += 16;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned char buf[16384];
|
||||||
|
unsigned char packet[8192];
|
||||||
|
unsigned char *b;
|
||||||
|
int len;
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof(buf), stdin) != NULL)
|
||||||
|
{
|
||||||
|
if (strlen(buf) == sizeof(buf)-1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "line too long\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
b = strchr(buf, ' ');
|
||||||
|
if (b == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "illegal line format\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*b = '\0';
|
||||||
|
b += 1;
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
while ((b[0] != '\0') && (b[1] != '\0'))
|
||||||
|
{
|
||||||
|
unsigned int value;
|
||||||
|
if (sscanf(b, "%2x", &value) != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "illegal packet\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
packet[len] = value;
|
||||||
|
b += 2;
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
handle_ipx(packet, len, buf, i);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
129
ipxdump/ipxutil.c
Normal file
129
ipxdump/ipxutil.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
IPX support library - general functions
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||||
|
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include "ipxutil.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_fprint_node(FILE *file, IPXNode node)
|
||||||
|
{
|
||||||
|
fprintf(file,"%02X%02X%02X%02X%02X%02X",
|
||||||
|
(unsigned char)node[0],
|
||||||
|
(unsigned char)node[1],
|
||||||
|
(unsigned char)node[2],
|
||||||
|
(unsigned char)node[3],
|
||||||
|
(unsigned char)node[4],
|
||||||
|
(unsigned char)node[5]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_fprint_network(FILE *file, IPXNet net)
|
||||||
|
{
|
||||||
|
fprintf(file,"%08lX",net);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_fprint_port(FILE *file, IPXPort port)
|
||||||
|
{
|
||||||
|
fprintf(file,"%04X",port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_fprint_saddr(FILE *file, struct sockaddr_ipx *sipx)
|
||||||
|
{
|
||||||
|
ipx_fprint_network(file,ntohl(sipx->sipx_network));
|
||||||
|
fprintf(file,":");
|
||||||
|
ipx_fprint_node(file,sipx->sipx_node);
|
||||||
|
fprintf(file,":");
|
||||||
|
ipx_fprint_port(file,ntohs(sipx->sipx_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_print_node(IPXNode node)
|
||||||
|
{
|
||||||
|
ipx_fprint_node(stdout,node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_print_network(IPXNet net)
|
||||||
|
{
|
||||||
|
ipx_fprint_network(stdout,net);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_print_port(IPXPort port)
|
||||||
|
{
|
||||||
|
ipx_fprint_port(stdout,port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_print_saddr(struct sockaddr_ipx *sipx)
|
||||||
|
{
|
||||||
|
ipx_fprint_saddr(stdout,sipx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipx_assign_node(IPXNode dest, IPXNode src)
|
||||||
|
{
|
||||||
|
memcpy(dest,src,sizeof(IPXNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_node_equal(IPXNode n1, IPXNode n2)
|
||||||
|
{
|
||||||
|
return memcmp(n1,n2,sizeof(n1))==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_sscanf_node(char *buf, IPXNode node)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n[6];
|
||||||
|
|
||||||
|
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
||||||
|
&(n[0]), &(n[1]), &(n[2]),
|
||||||
|
&(n[3]), &(n[4]), &(n[5]))) != 6)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
node[i] = n[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_sscanf_net(char *buf, IPXNet *target)
|
||||||
|
{
|
||||||
|
if (sscanf(buf, "%8lX", target) == 1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPXNode ipx_this_node={0,0,0,0,0,0};
|
||||||
|
IPXNode ipx_broadcast_node={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||||
|
char ipx_err_string[IPX_MAX_ERROR+1]="no error detected";
|
||||||
65
ipxdump/ipxutil.h
Normal file
65
ipxdump/ipxutil.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
IPX support library
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||||
|
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef __IPXUTIL_H__
|
||||||
|
|
||||||
|
#define __IPXUTIL_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
|
||||||
|
#define IPX_MAX_ERROR (255)
|
||||||
|
#define IPX_THIS_NET (0)
|
||||||
|
#define IPX_THIS_NODE (ipx_this_node)
|
||||||
|
#define IPX_BROADCAST (ipx_broadcast_node)
|
||||||
|
#define IPX_AUTO_PORT (0)
|
||||||
|
#define IPX_USER_PTYPE (0)
|
||||||
|
#define IPX_IS_INTERNAL (1)
|
||||||
|
|
||||||
|
typedef unsigned char IPXNode[6];
|
||||||
|
typedef unsigned long int IPXNet;
|
||||||
|
typedef unsigned short int IPXPort;
|
||||||
|
typedef unsigned short int hop_t;
|
||||||
|
typedef unsigned short int tick_t;
|
||||||
|
|
||||||
|
void ipx_print_node(IPXNode node);
|
||||||
|
void ipx_print_network(IPXNet net);
|
||||||
|
void ipx_print_port(IPXPort port);
|
||||||
|
void ipx_print_saddr(struct sockaddr_ipx* sipx);
|
||||||
|
|
||||||
|
void ipx_fprint_node(FILE* file,IPXNode node);
|
||||||
|
void ipx_fprint_network(FILE* file,IPXNet net);
|
||||||
|
void ipx_fprint_port(FILE* file,IPXPort port);
|
||||||
|
void ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx);
|
||||||
|
|
||||||
|
int ipx_sscanf_node(char *buf, IPXNode node);
|
||||||
|
int ipx_sscanf_net(char *buf, IPXNet *target);
|
||||||
|
|
||||||
|
void ipx_assign_node(IPXNode dest,IPXNode src);
|
||||||
|
int ipx_node_equal(IPXNode n1,IPXNode n2);
|
||||||
|
|
||||||
|
extern IPXNode ipx_this_node;
|
||||||
|
extern IPXNode ipx_broadcast_node;
|
||||||
|
|
||||||
|
extern char ipx_err_string[IPX_MAX_ERROR+1];
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* ncp_fs.h
|
* ncp.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 1995 by Volker Lendecke
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ struct ncp_fs_info {
|
|||||||
|
|
||||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
||||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
||||||
|
#define NCP_IOC_CONN_LOGGED_IN _IO('l', 1)
|
||||||
|
|
||||||
#define NCP_GET_FS_INFO_VERSION (1)
|
#define NCP_GET_FS_INFO_VERSION (1)
|
||||||
#define NCP_IOC_GET_FS_INFO _IOWR('i', 1, unsigned char *)
|
#define NCP_IOC_GET_FS_INFO _IOWR('i', 1, unsigned char *)
|
||||||
@@ -126,9 +127,12 @@ extern struct inode_operations ncp_dir_inode_operations;
|
|||||||
void ncp_free_inode_info(struct ncp_inode_info *i);
|
void ncp_free_inode_info(struct ncp_inode_info *i);
|
||||||
void ncp_free_all_inodes(struct ncp_server *server);
|
void ncp_free_all_inodes(struct ncp_server *server);
|
||||||
void ncp_init_root(struct ncp_server *server);
|
void ncp_init_root(struct ncp_server *server);
|
||||||
|
int ncp_conn_logged_in(struct ncp_server *server);
|
||||||
int ncp_stat_root(struct ncp_server *server);
|
int ncp_stat_root(struct ncp_server *server);
|
||||||
void ncp_init_dir_cache(void);
|
void ncp_init_dir_cache(void);
|
||||||
void ncp_invalid_dir_cache(unsigned long ino);
|
void ncp_invalid_dir_cache(struct inode *ino);
|
||||||
|
struct ncp_inode_info *ncp_find_inode(struct inode *inode);
|
||||||
|
ino_t ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info);
|
||||||
void ncp_invalidate_all_inodes(struct ncp_server *server);
|
void ncp_invalidate_all_inodes(struct ncp_server *server);
|
||||||
void ncp_free_dir_cache(void);
|
void ncp_free_dir_cache(void);
|
||||||
int ncp_date_dos2unix(__u16 time, __u16 date);
|
int ncp_date_dos2unix(__u16 time, __u16 date);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ struct ncp_inode_info {
|
|||||||
number of references in memory */
|
number of references in memory */
|
||||||
struct ncp_inode_info *dir;
|
struct ncp_inode_info *dir;
|
||||||
struct ncp_inode_info *next, *prev;
|
struct ncp_inode_info *next, *prev;
|
||||||
|
struct inode *inode;
|
||||||
struct nw_file_info finfo;
|
struct nw_file_info finfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ struct ncp_server {
|
|||||||
it completely. */
|
it completely. */
|
||||||
|
|
||||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
struct file *ncp_filp; /* File pointer to ncp socket */
|
||||||
|
|
||||||
struct file *wdog_filp; /* File pointer to wdog socket */
|
struct file *wdog_filp; /* File pointer to wdog socket */
|
||||||
void *data_ready; /* The wdog socket gets a new
|
void *data_ready; /* The wdog socket gets a new
|
||||||
data_ready callback. We store the
|
data_ready callback. We store the
|
||||||
@@ -35,7 +34,8 @@ struct ncp_server {
|
|||||||
|
|
||||||
u8 completion; /* Status message from server */
|
u8 completion; /* Status message from server */
|
||||||
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
|
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
|
||||||
requests allowed anymore */
|
requests allowed anymore.
|
||||||
|
Bit 0 = 1 ==> Server is down. */
|
||||||
|
|
||||||
int buffer_size; /* Negotiated bufsize */
|
int buffer_size; /* Negotiated bufsize */
|
||||||
|
|
||||||
@@ -56,6 +56,18 @@ struct ncp_server {
|
|||||||
char root_path; /* '\0' */
|
char root_path; /* '\0' */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ncp_conn_valid(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
return ((server->conn_status & 0x11) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ncp_invalidate_conn(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
server->conn_status |= 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <linux/ncp.h>
|
#include <linux/ncp.h>
|
||||||
#include <linux/ncp_fs_i.h>
|
#include <linux/ncp_fs_i.h>
|
||||||
|
|
||||||
#define NCP_MOUNT_VERSION 1
|
#define NCP_MOUNT_VERSION 2
|
||||||
|
|
||||||
#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
|
#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
|
||||||
#define NCP_PASSWORD_LEN 20
|
#define NCP_PASSWORD_LEN 20
|
||||||
@@ -26,14 +26,14 @@ struct ncp_mount_data {
|
|||||||
int version;
|
int version;
|
||||||
unsigned int ncp_fd; /* The socket to the ncp port */
|
unsigned int ncp_fd; /* The socket to the ncp port */
|
||||||
unsigned int wdog_fd; /* Watchdog packets come here */
|
unsigned int wdog_fd; /* Watchdog packets come here */
|
||||||
unsigned int message_fd; /* Not used yet, maybe for messages */
|
unsigned int message_fd; /* Message notifications come here */
|
||||||
uid_t mounted_uid; /* Who may umount() this filesystem? */
|
uid_t mounted_uid; /* Who may umount() this filesystem? */
|
||||||
|
|
||||||
struct sockaddr_ipx serv_addr;
|
struct sockaddr_ipx serv_addr;
|
||||||
unsigned char server_name[49];
|
unsigned char server_name[NCP_BINDERY_NAME_LEN];
|
||||||
|
|
||||||
unsigned char username[NCP_USERNAME_LEN+1];
|
unsigned char mount_point[PATH_MAX+1];
|
||||||
unsigned char password[NCP_PASSWORD_LEN+1];
|
unsigned char mounted_vol[NCP_VOLNAME_LEN+1];
|
||||||
|
|
||||||
unsigned int time_out; /* How long should I wait after
|
unsigned int time_out; /* How long should I wait after
|
||||||
sending a NCP request? */
|
sending a NCP request? */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||||
$(INCLUDES) \
|
$(INCLUDES) -DNCPFS_VERSION=\"$(VERSION)\"\
|
||||||
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
||||||
# -DDEBUG_NCP_MALLOC
|
# -DDEBUG_NCP_MALLOC
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ static struct inode *
|
|||||||
ncp_iget(struct inode *dir, struct nw_file_info *finfo);
|
ncp_iget(struct inode *dir, struct nw_file_info *finfo);
|
||||||
|
|
||||||
static struct ncp_inode_info *
|
static struct ncp_inode_info *
|
||||||
ncp_find_inode(struct inode *dir, const char *name);
|
ncp_find_dir_inode(struct inode *dir, const char *name);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncp_lookup(struct inode *dir, const char *__name,
|
ncp_lookup(struct inode *dir, const char *__name,
|
||||||
@@ -102,7 +102,7 @@ static struct file_operations ncp_dir_operations = {
|
|||||||
NULL, /* write - bad */
|
NULL, /* write - bad */
|
||||||
ncp_readdir, /* readdir */
|
ncp_readdir, /* readdir */
|
||||||
NULL, /* select - default */
|
NULL, /* select - default */
|
||||||
ncp_ioctl, /* ioctl - default */
|
ncp_ioctl, /* ioctl */
|
||||||
NULL, /* mmap */
|
NULL, /* mmap */
|
||||||
NULL, /* no special open code */
|
NULL, /* no special open code */
|
||||||
NULL, /* no special release code */
|
NULL, /* no special release code */
|
||||||
@@ -129,6 +129,58 @@ struct inode_operations ncp_dir_inode_operations = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Here we encapsulate the inode number handling that depends upon the
|
||||||
|
* mount mode: When we mount a complete server, the memory address of
|
||||||
|
* the npc_inode_info is used as an inode. When only a single volume
|
||||||
|
* is mounted, then the DosDirNum is used as the inode number. As this
|
||||||
|
* is unique for the complete volume, this should enable the NFS
|
||||||
|
* exportability of a ncpfs-mounted volume.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ncp_single_volume(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
return (server->m.mounted_vol[0] != '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ino_t
|
||||||
|
ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info)
|
||||||
|
{
|
||||||
|
return ncp_single_volume(server)
|
||||||
|
? info->finfo.i.DosDirNum : (ino_t)info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ncp_is_server_root(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct ncp_server *s = NCP_SERVER(inode);
|
||||||
|
|
||||||
|
return ( (!ncp_single_volume(s))
|
||||||
|
&& (inode->i_ino == ncp_info_ino(s, &(s->root))));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ncp_inode_info *
|
||||||
|
ncp_find_inode(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct ncp_server *server = NCP_SERVER(inode);
|
||||||
|
struct ncp_inode_info *root = &(server->root);
|
||||||
|
struct ncp_inode_info *this = root;
|
||||||
|
|
||||||
|
ino_t ino = inode->i_ino;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (ino == ncp_info_ino(server, this))
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
this = this->next;
|
||||||
|
}
|
||||||
|
while (this != root);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
||||||
{
|
{
|
||||||
@@ -142,6 +194,7 @@ ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
|||||||
all inodes that are in memory. That's why it's enough to index the
|
all inodes that are in memory. That's why it's enough to index the
|
||||||
directory cache by the inode number. */
|
directory cache by the inode number. */
|
||||||
|
|
||||||
|
static int c_dev = 0;
|
||||||
static unsigned long c_ino = 0;
|
static unsigned long c_ino = 0;
|
||||||
static int c_size;
|
static int c_size;
|
||||||
static int c_seen_eof;
|
static int c_seen_eof;
|
||||||
@@ -156,7 +209,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
struct ncp_dirent *entry = NULL;
|
struct ncp_dirent *entry = NULL;
|
||||||
struct ncp_server *server = NCP_SERVER(inode);
|
struct ncp_server *server = NCP_SERVER(inode);
|
||||||
struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
|
struct ncp_inode_info *dir = NCP_INOP(inode);
|
||||||
|
|
||||||
int filldir(struct dirent *dirent,
|
int filldir(struct dirent *dirent,
|
||||||
const char *name, int len,
|
const char *name, int len,
|
||||||
@@ -170,9 +223,9 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
|
DPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
|
||||||
DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
|
DPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
|
||||||
inode->i_ino, c_ino);
|
inode->i_ino, c_ino);
|
||||||
|
|
||||||
if (!inode || !S_ISDIR(inode->i_mode))
|
if (!inode || !S_ISDIR(inode->i_mode))
|
||||||
{
|
{
|
||||||
@@ -180,6 +233,11 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ncp_conn_valid(server))
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (c_entry == NULL)
|
if (c_entry == NULL)
|
||||||
{
|
{
|
||||||
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
||||||
@@ -193,8 +251,9 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
|
|
||||||
if (filp->f_pos == 0)
|
if (filp->f_pos == 0)
|
||||||
{
|
{
|
||||||
ncp_invalid_dir_cache(inode->i_ino);
|
ncp_invalid_dir_cache(inode);
|
||||||
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
|
if (filldir(dirent,".",1, filp->f_pos,
|
||||||
|
ncp_info_ino(server, dir)) < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -204,7 +263,8 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
|
|
||||||
if (filp->f_pos == 1)
|
if (filp->f_pos == 1)
|
||||||
{
|
{
|
||||||
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
|
if (filldir(dirent,"..",2, filp->f_pos,
|
||||||
|
ncp_info_ino(server, dir->dir)) < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -212,7 +272,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inode->i_ino == c_ino)
|
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
|
||||||
{
|
{
|
||||||
for (i = 0; i < c_size; i++)
|
for (i = 0; i < c_size; i++)
|
||||||
{
|
{
|
||||||
@@ -234,7 +294,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
{
|
{
|
||||||
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
||||||
|
|
||||||
if (inode->i_ino == (int)&(server->root))
|
if (ncp_is_server_root(inode))
|
||||||
{
|
{
|
||||||
result = ncp_read_volume_list(server, filp->f_pos,
|
result = ncp_read_volume_list(server, filp->f_pos,
|
||||||
NCP_READDIR_CACHE_SIZE);
|
NCP_READDIR_CACHE_SIZE);
|
||||||
@@ -251,6 +311,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
|
c_dev = 0;
|
||||||
c_ino = 0;
|
c_ino = 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -258,6 +319,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
if (result > 0)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
|
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
|
||||||
|
c_dev = inode->i_dev;
|
||||||
c_ino = inode->i_ino;
|
c_ino = inode->i_ino;
|
||||||
c_size = result;
|
c_size = result;
|
||||||
entry = c_entry;
|
entry = c_entry;
|
||||||
@@ -282,24 +344,35 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
/* We found it. For getwd(), we have to return the
|
/* We found it. For getwd(), we have to return the
|
||||||
correct inode in d_ino if the inode is currently in
|
correct inode in d_ino if the inode is currently in
|
||||||
use. Otherwise the inode number does not
|
use. Otherwise the inode number does not
|
||||||
matter. (You can argue a lot about this..) */
|
matter. (You can argue a lot about this..) */
|
||||||
|
|
||||||
struct ncp_inode_info *ino_info;
|
ino_t ino;
|
||||||
ino_info = ncp_find_inode(inode, entry->i.entryName);
|
|
||||||
|
|
||||||
/* Some programs seem to be confused about a zero
|
if (ncp_single_volume(server))
|
||||||
inode number, so we set it to one. Thanks to
|
|
||||||
Gordon Chaffee for this one. */
|
|
||||||
if (ino_info == NULL)
|
|
||||||
{
|
{
|
||||||
ino_info = (struct ncp_inode_info *) 1;
|
ino = (ino_t)(entry->i.DosDirNum);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct ncp_inode_info *ino_info;
|
||||||
|
ino_info = ncp_find_dir_inode(inode,
|
||||||
|
entry->i.entryName);
|
||||||
|
|
||||||
DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
|
/* Some programs seem to be confused about a
|
||||||
DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
|
* zero inode number, so we set it to one.
|
||||||
|
* Thanks to Gordon Chaffee for this one. */
|
||||||
|
if (ino_info == NULL)
|
||||||
|
{
|
||||||
|
ino_info = (struct ncp_inode_info *) 1;
|
||||||
|
}
|
||||||
|
ino = (ino_t)(ino_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
|
||||||
|
DPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
|
||||||
|
|
||||||
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
||||||
entry->f_pos, (ino_t)ino_info) < 0)
|
entry->f_pos, ino) < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -353,9 +426,9 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
|||||||
DPRINTK("ncp_read_volumes: found vol: %s\n",
|
DPRINTK("ncp_read_volumes: found vol: %s\n",
|
||||||
info.volume_name);
|
info.volume_name);
|
||||||
|
|
||||||
if (ncp_do_lookup(server, NULL,
|
if (ncp_lookup_volume(server,
|
||||||
info.volume_name,
|
info.volume_name,
|
||||||
&(entry->i)) != 0)
|
&(entry->i)) != 0)
|
||||||
{
|
{
|
||||||
printk("ncpfs: could not lookup vol "
|
printk("ncpfs: could not lookup vol "
|
||||||
"%s\n", info.volume_name);
|
"%s\n", info.volume_name);
|
||||||
@@ -438,15 +511,17 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
|||||||
void
|
void
|
||||||
ncp_init_dir_cache(void)
|
ncp_init_dir_cache(void)
|
||||||
{
|
{
|
||||||
|
c_dev = 0;
|
||||||
c_ino = 0;
|
c_ino = 0;
|
||||||
c_entry = NULL;
|
c_entry = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ncp_invalid_dir_cache(unsigned long ino)
|
ncp_invalid_dir_cache(struct inode *inode)
|
||||||
{
|
{
|
||||||
if (ino == c_ino)
|
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
|
||||||
{
|
{
|
||||||
|
c_dev = 0;
|
||||||
c_ino = 0;
|
c_ino = 0;
|
||||||
c_seen_eof = 0;
|
c_seen_eof = 0;
|
||||||
}
|
}
|
||||||
@@ -517,7 +592,8 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
|||||||
root->next->prev = new_inode_info;
|
root->next->prev = new_inode_info;
|
||||||
root->next = new_inode_info;
|
root->next = new_inode_info;
|
||||||
|
|
||||||
if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
|
if (!(inode = iget(dir->i_sb, ncp_info_ino(NCP_SERVER(dir),
|
||||||
|
new_inode_info))))
|
||||||
{
|
{
|
||||||
printk("ncp_iget: iget failed!");
|
printk("ncp_iget: iget failed!");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -567,6 +643,7 @@ ncp_init_root(struct ncp_server *server)
|
|||||||
root->finfo.opened = 0;
|
root->finfo.opened = 0;
|
||||||
i->attributes = aDIR;
|
i->attributes = aDIR;
|
||||||
i->dataStreamSize = 1024;
|
i->dataStreamSize = 1024;
|
||||||
|
i->DosDirNum = 0;
|
||||||
i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
|
i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
|
||||||
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
|
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
|
||||||
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
|
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
|
||||||
@@ -581,6 +658,25 @@ ncp_init_root(struct ncp_server *server)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_conn_logged_in(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
if (server->m.mounted_vol[0] == '\0')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
str_upper(server->m.mounted_vol);
|
||||||
|
if (ncp_lookup_volume(server, server->m.mounted_vol,
|
||||||
|
&(server->root.finfo.i)) != 0)
|
||||||
|
{
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
str_lower(server->root.finfo.i.entryName);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ncp_free_all_inodes(struct ncp_server *server)
|
ncp_free_all_inodes(struct ncp_server *server)
|
||||||
{
|
{
|
||||||
@@ -611,7 +707,7 @@ ncp_free_all_inodes(struct ncp_server *server)
|
|||||||
complete linear search through the inodes belonging to this
|
complete linear search through the inodes belonging to this
|
||||||
filesystem. This has to be fixed. */
|
filesystem. This has to be fixed. */
|
||||||
static struct ncp_inode_info *
|
static struct ncp_inode_info *
|
||||||
ncp_find_inode(struct inode *dir, const char *name)
|
ncp_find_dir_inode(struct inode *dir, const char *name)
|
||||||
{
|
{
|
||||||
struct ncp_server *server = NCP_SERVER(dir);
|
struct ncp_server *server = NCP_SERVER(dir);
|
||||||
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
|
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
|
||||||
@@ -658,9 +754,14 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
|
|
||||||
|
|
||||||
server = NCP_SERVER(dir);
|
server = NCP_SERVER(dir);
|
||||||
|
if (!ncp_conn_valid(server))
|
||||||
|
{
|
||||||
|
iput(dir);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
|
||||||
|
|
||||||
/* Fast cheat for . */
|
/* Fast cheat for . */
|
||||||
if (len == 0 || (len == 1 && __name[0] == '.'))
|
if (len == 0 || (len == 1 && __name[0] == '.'))
|
||||||
@@ -679,7 +780,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
parent->state = NCP_INODE_LOOKED_UP;
|
parent->state = NCP_INODE_LOOKED_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = iget(dir->i_sb, (int)parent);
|
*result = iget(dir->i_sb, ncp_info_ino(server, parent));
|
||||||
iput(dir);
|
iput(dir);
|
||||||
if (*result == 0)
|
if (*result == 0)
|
||||||
{
|
{
|
||||||
@@ -694,7 +795,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
memcpy(name, __name, len);
|
memcpy(name, __name, len);
|
||||||
name[len] = 0;
|
name[len] = 0;
|
||||||
|
|
||||||
result_info = ncp_find_inode(dir, name);
|
result_info = ncp_find_dir_inode(dir, name);
|
||||||
|
|
||||||
if (result_info != 0)
|
if (result_info != 0)
|
||||||
{
|
{
|
||||||
@@ -706,7 +807,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
/* Here we convert the inode_info address into an
|
/* Here we convert the inode_info address into an
|
||||||
inode number */
|
inode number */
|
||||||
|
|
||||||
*result = iget(dir->i_sb, (int)result_info);
|
*result = iget(dir->i_sb, ncp_info_ino(server, result_info));
|
||||||
iput(dir);
|
iput(dir);
|
||||||
|
|
||||||
if (*result == NULL)
|
if (*result == NULL)
|
||||||
@@ -722,7 +823,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
|
|
||||||
found_in_cache = 0;
|
found_in_cache = 0;
|
||||||
|
|
||||||
if (dir->i_ino == c_ino)
|
if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
|
||||||
{
|
{
|
||||||
int first = c_last_returned_index;
|
int first = c_last_returned_index;
|
||||||
int i;
|
int i;
|
||||||
@@ -747,15 +848,24 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
|
|
||||||
if (found_in_cache == 0)
|
if (found_in_cache == 0)
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
str_upper(name);
|
str_upper(name);
|
||||||
|
|
||||||
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
|
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
|
||||||
NCP_ISTRUCT(dir)->entryName, name);
|
NCP_ISTRUCT(dir)->entryName, name);
|
||||||
|
|
||||||
if (ncp_do_lookup(server,
|
if (ncp_is_server_root(dir))
|
||||||
dir->i_ino == (int)&(NCP_SERVER(dir)->root)
|
{
|
||||||
? NULL : NCP_ISTRUCT(dir),
|
res = ncp_lookup_volume(server, name, &(finfo.i));
|
||||||
name, &(finfo.i)) != 0)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = ncp_obtain_info(server,
|
||||||
|
NCP_ISTRUCT(dir)->volNumber,
|
||||||
|
NCP_ISTRUCT(dir)->DosDirNum,
|
||||||
|
name, &(finfo.i));
|
||||||
|
}
|
||||||
|
if (res != 0)
|
||||||
{
|
{
|
||||||
iput(dir);
|
iput(dir);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@@ -790,6 +900,11 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
|||||||
iput(dir);
|
iput(dir);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||||
|
{
|
||||||
|
iput(dir);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(_name, name, len);
|
strncpy(_name, name, len);
|
||||||
_name[len] = '\0';
|
_name[len] = '\0';
|
||||||
@@ -797,7 +912,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
|||||||
|
|
||||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||||
NCP_ISTRUCT(dir), _name,
|
NCP_ISTRUCT(dir), _name,
|
||||||
OC_MODE_CREATE|OC_MODE_OPEN,
|
OC_MODE_CREATE|OC_MODE_OPEN|
|
||||||
|
OC_MODE_REPLACE,
|
||||||
0, AR_READ|AR_WRITE,
|
0, AR_READ|AR_WRITE,
|
||||||
&finfo) != 0)
|
&finfo) != 0)
|
||||||
{
|
{
|
||||||
@@ -805,7 +921,7 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
|||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_invalid_dir_cache(dir->i_ino);
|
ncp_invalid_dir_cache(dir);
|
||||||
|
|
||||||
str_lower(finfo.i.entryName);
|
str_lower(finfo.i.entryName);
|
||||||
finfo.access = O_RDWR;
|
finfo.access = O_RDWR;
|
||||||
@@ -846,6 +962,11 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
|||||||
iput(dir);
|
iput(dir);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||||
|
{
|
||||||
|
iput(dir);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||||
NCP_ISTRUCT(dir), _name,
|
NCP_ISTRUCT(dir), _name,
|
||||||
@@ -857,7 +978,7 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = 0;
|
error = 0;
|
||||||
ncp_invalid_dir_cache(dir->i_ino);
|
ncp_invalid_dir_cache(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
iput(dir);
|
iput(dir);
|
||||||
@@ -876,8 +997,14 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
|
|||||||
iput(dir);
|
iput(dir);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
if (ncp_find_inode(dir, name) != NULL)
|
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||||
{
|
{
|
||||||
|
iput(dir);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (ncp_find_dir_inode(dir, name) != NULL)
|
||||||
|
{
|
||||||
|
iput(dir);
|
||||||
error = -EBUSY;
|
error = -EBUSY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -891,11 +1018,11 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
|
|||||||
NCP_ISTRUCT(dir),
|
NCP_ISTRUCT(dir),
|
||||||
_name)) == 0)
|
_name)) == 0)
|
||||||
{
|
{
|
||||||
ncp_invalid_dir_cache(dir->i_ino);
|
ncp_invalid_dir_cache(dir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = -EINVAL;
|
error = -EACCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iput(dir);
|
iput(dir);
|
||||||
@@ -914,8 +1041,14 @@ ncp_unlink(struct inode *dir, const char *name, int len)
|
|||||||
iput(dir);
|
iput(dir);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
if (ncp_find_inode(dir, name) != NULL)
|
if (!ncp_conn_valid(NCP_SERVER(dir)))
|
||||||
{
|
{
|
||||||
|
iput(dir);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
if (ncp_find_dir_inode(dir, name) != NULL)
|
||||||
|
{
|
||||||
|
iput(dir);
|
||||||
error = -EBUSY;
|
error = -EBUSY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -928,11 +1061,11 @@ ncp_unlink(struct inode *dir, const char *name, int len)
|
|||||||
NCP_ISTRUCT(dir),
|
NCP_ISTRUCT(dir),
|
||||||
_name)) == 0)
|
_name)) == 0)
|
||||||
{
|
{
|
||||||
ncp_invalid_dir_cache(dir->i_ino);
|
ncp_invalid_dir_cache(dir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = -EINVAL;
|
error = -EACCES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iput(dir);
|
iput(dir);
|
||||||
@@ -954,6 +1087,12 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
|||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(old_dir)))
|
||||||
|
{
|
||||||
|
res = -EIO;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
if (!new_dir || !S_ISDIR(new_dir->i_mode))
|
if (!new_dir || !S_ISDIR(new_dir->i_mode))
|
||||||
{
|
{
|
||||||
printk("ncp_rename: new inode is NULL or not a directory\n");
|
printk("ncp_rename: new inode is NULL or not a directory\n");
|
||||||
@@ -961,8 +1100,8 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
|||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (ncp_find_inode(old_dir, old_name) != NULL)
|
if ( (ncp_find_dir_inode(old_dir, old_name) != NULL)
|
||||||
|| (ncp_find_inode(new_dir, new_name) != NULL))
|
|| (ncp_find_dir_inode(new_dir, new_name) != NULL))
|
||||||
{
|
{
|
||||||
res = -EBUSY;
|
res = -EBUSY;
|
||||||
goto finished;
|
goto finished;
|
||||||
@@ -982,8 +1121,8 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
|||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
ncp_invalid_dir_cache(old_dir->i_ino);
|
ncp_invalid_dir_cache(old_dir);
|
||||||
ncp_invalid_dir_cache(new_dir->i_ino);
|
ncp_invalid_dir_cache(new_dir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -99,6 +99,10 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
DPRINTK("ncp_file_read: inode = NULL\n");
|
DPRINTK("ncp_file_read: inode = NULL\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (!S_ISREG(inode->i_mode))
|
if (!S_ISREG(inode->i_mode))
|
||||||
{
|
{
|
||||||
@@ -178,6 +182,10 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
|||||||
DPRINTK("ncp_file_write: inode = NULL\n");
|
DPRINTK("ncp_file_write: inode = NULL\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (!S_ISREG(inode->i_mode))
|
if (!S_ISREG(inode->i_mode))
|
||||||
{
|
{
|
||||||
@@ -239,6 +247,7 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
|||||||
if (pos > inode->i_size)
|
if (pos > inode->i_size)
|
||||||
{
|
{
|
||||||
inode->i_size = pos;
|
inode->i_size = pos;
|
||||||
|
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||||
|
|||||||
@@ -61,50 +61,25 @@ ncp_read_inode(struct inode *inode)
|
|||||||
inode->i_ino. Just to make sure everything went well, we
|
inode->i_ino. Just to make sure everything went well, we
|
||||||
check it's there. */
|
check it's there. */
|
||||||
|
|
||||||
struct ncp_inode_info *inode_info
|
struct ncp_inode_info *inode_info = ncp_find_inode(inode);
|
||||||
= (struct ncp_inode_info *)(inode->i_ino);
|
|
||||||
|
|
||||||
#if 1
|
if (inode_info == NULL)
|
||||||
struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
|
|
||||||
struct ncp_inode_info *check_info = root;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
if (inode_info == check_info)
|
/* Ok, now we're in trouble. The inode info is not there. What
|
||||||
{
|
should we do now??? */
|
||||||
if (check_info->state == NCP_INODE_LOOKED_UP)
|
printk("ncp_read_inode: inode info not found\n");
|
||||||
{
|
return;
|
||||||
DDPRINTK("ncp_read_inode: found it!\n");
|
}
|
||||||
goto good;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printk("ncp_read_inode: "
|
|
||||||
"state != NCP_INODE_LOOKED_UP\n");
|
|
||||||
goto good;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
check_info = check_info->next;
|
|
||||||
}
|
|
||||||
while (check_info != root);
|
|
||||||
|
|
||||||
/* Ok, now we're in trouble. The inode info is not there. What
|
|
||||||
should we do now??? */
|
|
||||||
printk("ncp_read_inode: inode info not found\n");
|
|
||||||
return;
|
|
||||||
|
|
||||||
good:
|
|
||||||
DDPRINTK("ncp_read_inode: read entry %s\n",
|
|
||||||
inode_info->finfo.i.entryName);
|
|
||||||
#endif
|
|
||||||
inode_info->state = NCP_INODE_VALID;
|
inode_info->state = NCP_INODE_VALID;
|
||||||
|
|
||||||
NCP_INOP(inode) = inode_info;
|
NCP_INOP(inode) = inode_info;
|
||||||
|
inode_info->inode = inode;
|
||||||
|
|
||||||
if (NCP_ISTRUCT(inode)->attributes & aDIR)
|
if (NCP_ISTRUCT(inode)->attributes & aDIR)
|
||||||
{
|
{
|
||||||
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
|
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
|
||||||
/* for directories in dataStreamSize seems to be some
|
/* for directories dataStreamSize seems to be some
|
||||||
Object ID ??? */
|
Object ID ??? */
|
||||||
inode->i_size = 512;
|
inode->i_size = 512;
|
||||||
}
|
}
|
||||||
@@ -176,7 +151,7 @@ ncp_put_inode(struct inode *inode)
|
|||||||
{
|
{
|
||||||
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
||||||
inode->i_ino);
|
inode->i_ino);
|
||||||
ncp_invalid_dir_cache(inode->i_ino);
|
ncp_invalid_dir_cache(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_inode(inode);
|
clear_inode(inode);
|
||||||
@@ -204,6 +179,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
printk("ncp warning: mount version %s than kernel\n",
|
printk("ncp warning: mount version %s than kernel\n",
|
||||||
(data->version < NCP_MOUNT_VERSION) ?
|
(data->version < NCP_MOUNT_VERSION) ?
|
||||||
"older" : "newer");
|
"older" : "newer");
|
||||||
|
sb->s_dev = 0;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (data->ncp_fd >= NR_OPEN)
|
if ( (data->ncp_fd >= NR_OPEN)
|
||||||
@@ -253,6 +230,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
server->wait = NULL;
|
server->wait = NULL;
|
||||||
server->packet = NULL;
|
server->packet = NULL;
|
||||||
server->buffer_size = 0;
|
server->buffer_size = 0;
|
||||||
|
server->conn_status = 0;
|
||||||
|
|
||||||
server->m = *data;
|
server->m = *data;
|
||||||
server->m.file_mode = (server->m.file_mode &
|
server->m.file_mode = (server->m.file_mode &
|
||||||
@@ -302,7 +280,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
|
|
||||||
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
|
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
|
||||||
|
|
||||||
if (!(sb->s_mounted = iget(sb, (int)&(server->root))))
|
if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
|
||||||
{
|
{
|
||||||
sb->s_dev = 0;
|
sb->s_dev = 0;
|
||||||
printk("ncp_read_super: get root inode failed\n");
|
printk("ncp_read_super: get root inode failed\n");
|
||||||
@@ -393,6 +371,11 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
|||||||
int info_mask;
|
int info_mask;
|
||||||
struct nw_modify_dos_info info;
|
struct nw_modify_dos_info info;
|
||||||
|
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if ((result = inode_change_ok(inode, attr)) < 0)
|
if ((result = inode_change_ok(inode, attr)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -480,7 +463,7 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
|||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
|
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -510,6 +493,7 @@ init_module( void)
|
|||||||
|
|
||||||
ncp_init_dir_cache();
|
ncp_init_dir_cache();
|
||||||
register_filesystem(&ncp_fs_type);
|
register_filesystem(&ncp_fs_type);
|
||||||
|
printk("ncpfs version %s loaded\n", NCPFS_VERSION);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,16 @@ ncp_ioctl (struct inode * inode, struct file * filp,
|
|||||||
|
|
||||||
return server->reply_size;
|
return server->reply_size;
|
||||||
|
|
||||||
|
case NCP_IOC_CONN_LOGGED_IN:
|
||||||
|
|
||||||
|
if ( (permission(inode, MAY_WRITE) != 0)
|
||||||
|
&& (current->uid != server->m.mounted_uid))
|
||||||
|
{
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ncp_conn_logged_in(server);
|
||||||
|
|
||||||
case NCP_IOC_GET_FS_INFO:
|
case NCP_IOC_GET_FS_INFO:
|
||||||
|
|
||||||
if ( (permission(inode, MAY_WRITE) != 0)
|
if ( (permission(inode, MAY_WRITE) != 0)
|
||||||
|
|||||||
@@ -135,6 +135,11 @@ ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
|
|||||||
{
|
{
|
||||||
DPRINTK("ncp_mmap: called\n");
|
DPRINTK("ncp_mmap: called\n");
|
||||||
|
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/* only PAGE_COW or read-only supported now */
|
/* only PAGE_COW or read-only supported now */
|
||||||
if (vma->vm_flags & VM_SHARED)
|
if (vma->vm_flags & VM_SHARED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -266,56 +266,19 @@ ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
|||||||
target->entryName[*name_len] = '\0';
|
target->entryName[*name_len] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_do_lookup(struct ncp_server *server,
|
ncp_obtain_info(struct ncp_server *server,
|
||||||
struct nw_info_struct *dir,
|
__u8 vol_num, __u32 dir_base,
|
||||||
char *path, /* may only be one component */
|
char *path, /* At most 1 component */
|
||||||
struct nw_info_struct *target)
|
struct nw_info_struct *target)
|
||||||
{
|
{
|
||||||
__u8 vol_num;
|
|
||||||
__u32 dir_base;
|
|
||||||
int result;
|
int result;
|
||||||
char *volname = NULL;
|
|
||||||
|
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir == NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
|
|
||||||
|
|
||||||
/* Access a volume's root directory */
|
|
||||||
ncp_init_request(server);
|
|
||||||
ncp_add_byte(server, 22); /* subfunction */
|
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
|
||||||
ncp_add_byte(server, 0); /* reserved */
|
|
||||||
ncp_add_byte(server, 0); /* reserved */
|
|
||||||
ncp_add_byte(server, 0); /* reserved */
|
|
||||||
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
|
|
||||||
path);
|
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0)
|
|
||||||
{
|
|
||||||
ncp_unlock_server(server);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir_base = ncp_reply_dword(server, 4);
|
|
||||||
vol_num = ncp_reply_byte (server, 8);
|
|
||||||
ncp_unlock_server(server);
|
|
||||||
volname = path;
|
|
||||||
path = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vol_num = dir->volNumber;
|
|
||||||
dir_base = dir->DosDirNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, 6); /* subfunction */
|
||||||
@@ -323,8 +286,7 @@ ncp_do_lookup(struct ncp_server *server,
|
|||||||
ncp_add_byte(server, 0); /* dos name space as dest */
|
ncp_add_byte(server, 0); /* dos name space as dest */
|
||||||
ncp_add_word(server, 0xff); /* get all */
|
ncp_add_word(server, 0xff); /* get all */
|
||||||
ncp_add_dword(server, RIM_ALL);
|
ncp_add_dword(server, RIM_ALL);
|
||||||
ncp_add_handle_path(server, vol_num, dir_base, 1,
|
ncp_add_handle_path(server, vol_num, dir_base, 1, path);
|
||||||
path);
|
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0)
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
{
|
{
|
||||||
@@ -333,14 +295,54 @@ ncp_do_lookup(struct ncp_server *server,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (volname != NULL)
|
int
|
||||||
|
ncp_lookup_volume(struct ncp_server *server,
|
||||||
|
char *volname,
|
||||||
|
struct nw_info_struct *target)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
__u8 vol_num;
|
||||||
|
__u32 dir_base;
|
||||||
|
|
||||||
|
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
||||||
|
ncp_add_byte(server, 0); /* DOS name space */
|
||||||
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
|
|
||||||
|
ncp_add_byte(server, 0); /* faked volume number */
|
||||||
|
ncp_add_dword(server, 0); /* faked dir_base */
|
||||||
|
ncp_add_byte(server, 0xff); /* Don't have a dir_base */
|
||||||
|
ncp_add_byte(server, 1); /* 1 path component */
|
||||||
|
ncp_add_pstring(server, volname);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
{
|
{
|
||||||
target->nameLen = strlen(volname);
|
ncp_unlock_server(server);
|
||||||
strcpy(target->entryName, volname);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir_base = ncp_reply_dword(server, 4);
|
||||||
|
vol_num = ncp_reply_byte(server, 8);
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
|
|
||||||
|
if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
|
||||||
|
target)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
|
||||||
|
|
||||||
|
target->nameLen = strlen(volname);
|
||||||
|
strcpy(target->entryName, volname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,12 +419,18 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
|||||||
struct nw_file_info *target)
|
struct nw_file_info *target)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
__u16 search_attribs = 0x0006;
|
||||||
|
|
||||||
|
if ((create_attributes & aDIR) != 0)
|
||||||
|
{
|
||||||
|
search_attribs |= 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 1); /* subfunction */
|
ncp_add_byte(server, 1); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, 0); /* dos name space */
|
||||||
ncp_add_byte(server, open_create_mode);
|
ncp_add_byte(server, open_create_mode);
|
||||||
ncp_add_word(server, 0x8006);
|
ncp_add_word(server, search_attribs);
|
||||||
ncp_add_dword(server, RIM_ALL);
|
ncp_add_dword(server, RIM_ALL);
|
||||||
ncp_add_dword(server, create_attributes);
|
ncp_add_dword(server, create_attributes);
|
||||||
/* The desired acc rights seem to be the inherited rights mask
|
/* The desired acc rights seem to be the inherited rights mask
|
||||||
|
|||||||
@@ -114,10 +114,16 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
|||||||
const char *source, int *bytes_written);
|
const char *source, int *bytes_written);
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_do_lookup(struct ncp_server *server,
|
ncp_obtain_info(struct ncp_server *server,
|
||||||
struct nw_info_struct *dir,
|
__u8 vol_num, __u32 dir_base,
|
||||||
char *path, /* may only be one component */
|
char *path, /* At most 1 component */
|
||||||
struct nw_info_struct *target);
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_lookup_volume(struct ncp_server *server,
|
||||||
|
char *volname,
|
||||||
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ ncp_request(struct ncp_server *server, int function)
|
|||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
DPRINTK("ncp_completion_code: %d\n", result);
|
DPRINTK("ncp_completion_code: %x\n", result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.TH IPX_CONFIGURE 8 "IPX Utilities" "Caldera, Inc."
|
.TH IPX_CONFIGURE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ipx_configure \- display/configure IPX behavior
|
ipx_configure \- query/configure IPX behavior
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ipx_configure
|
.B ipx_configure
|
||||||
[\-\-help]
|
[\-\-help]
|
||||||
@@ -8,7 +8,7 @@ ipx_configure \- display/configure IPX behavior
|
|||||||
[\-\-auto_primary=[on|off]]
|
[\-\-auto_primary=[on|off]]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B ipx_configure
|
.B ipx_configure
|
||||||
displays or configures IPX behavior with respect to automatic IPX
|
queries or configures IPX behavior with respect to automatic IPX
|
||||||
interface detection. IPX can be configured to automatically create
|
interface detection. IPX can be configured to automatically create
|
||||||
interfaces as they are detected. It can also be configured to
|
interfaces as they are detected. It can also be configured to
|
||||||
automatically select a primary interface when none is explicitly
|
automatically select a primary interface when none is explicitly
|
||||||
@@ -23,20 +23,15 @@ arguments is described in the section
|
|||||||
.SS OPTIONS
|
.SS OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.I "\-\-auto_interface=[on|off]"
|
.I "\-\-auto_interface=[on|off]"
|
||||||
This argument enables or disables the feature that will automatically detect
|
This argument either turns on or off the behavior of automatically creating
|
||||||
whether IPX is use on a network interface. If
|
interfaces.
|
||||||
.B on
|
|
||||||
and IPX packets are seen on an interface that interface will be automatically
|
|
||||||
flagged as an IPX interface. The default setting is
|
|
||||||
.B off.
|
|
||||||
.TP
|
.TP
|
||||||
.I "\-\-auto_primary=[on|off]"
|
.I "\-\-auto_primary=[on|off]"
|
||||||
This argument enables or disables the feature that will automatically select
|
This argument either turns on or off the behavior of automatically selecting
|
||||||
which IPX interface will be the primary IPX interface. The default setting is
|
a primary interface.
|
||||||
.B off.
|
|
||||||
.TP
|
.TP
|
||||||
.I "\-\-help"
|
.I "\-\-help"
|
||||||
Displays summarised usage instructions.
|
Print out information about utility.
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.I /proc/net/ipx_interface
|
.I /proc/net/ipx_interface
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ipx_interface \- add, delete, or display IPX interface configuration.
|
ipx_interface \- add, delete, or display an IPX interface
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ipx_interface
|
.B ipx_interface
|
||||||
add [-p] device frame_type [network number]
|
add [-p] device frame_type [network number]
|
||||||
@@ -9,17 +9,20 @@ add [-p] device frame_type [network number]
|
|||||||
del device frame_type
|
del device frame_type
|
||||||
.LP
|
.LP
|
||||||
.B ipx_interface
|
.B ipx_interface
|
||||||
|
delall
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
check device frame_type
|
check device frame_type
|
||||||
.LP
|
.LP
|
||||||
.B ipx_interface
|
.B ipx_interface
|
||||||
help
|
help
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B ipx_interface
|
.B ipx_interface
|
||||||
adds, deletes, or displays the configuration of the specified IPX interface.
|
adds, deletes, or displays IPX interfaces depending on the option selected.
|
||||||
.P
|
.P
|
||||||
An IPX interface is the item to which IPX sockets are bound.
|
An IPX interface is the item to which IPX sockets are bound.
|
||||||
An IPX interface has an associated IPX Network Number, a physical device
|
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||||
and frame type. A sample IPX Interface might look like:
|
to a physical device and frame type. A sample IPX Interface would be:
|
||||||
.LP
|
.LP
|
||||||
Network Number: 0x00ABCDEF
|
Network Number: 0x00ABCDEF
|
||||||
.LP
|
.LP
|
||||||
@@ -35,21 +38,25 @@ or default interface.
|
|||||||
.I add
|
.I add
|
||||||
This option is used to create an IPX interface. If the
|
This option is used to create an IPX interface. If the
|
||||||
.B -p
|
.B -p
|
||||||
flag is used, the interface is flagged as the
|
flag is used, the interface is made
|
||||||
.B PRIMARY
|
.B
|
||||||
interface. The IPX network number may optionally be specified. If it is not
|
PRIMARY.
|
||||||
specified it is set to 0 which indicates it should be automatically detected
|
The network number can be optionally assigned. If it is not assigned, it
|
||||||
by analysis of the existing IPX traffic on the network.
|
is set to 0 which indicates it should be detected from the traffic on the
|
||||||
|
network.
|
||||||
.TP
|
.TP
|
||||||
.I del
|
.I del
|
||||||
This option is used to delete an IPX interface.
|
This option is used to delete an IPX interface.
|
||||||
.TP
|
.TP
|
||||||
|
.I delall
|
||||||
|
This option is used to delete all IPX interfaces.
|
||||||
|
.TP
|
||||||
.I check
|
.I check
|
||||||
This option is used to display the network number associated with a specified
|
This option is used to display the device, frame type, and network number
|
||||||
device and frame type combination.
|
of an IPX interface.
|
||||||
.TP
|
.TP
|
||||||
.I help
|
.I help
|
||||||
This option displays summarised usage instructions.
|
This option displays information about the utility.
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc."
|
.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ipx_route \- add or delete an IPX route.
|
ipx_route \- add or delete IPX route
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ipx_route
|
.B ipx_route
|
||||||
add target_network router_network router_node
|
add target_network router_network router_node
|
||||||
@@ -10,11 +10,11 @@ del target_network
|
|||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B ipx_route
|
.B ipx_route
|
||||||
adds or deletes an IPX route.
|
adds or deletes an IPX route.
|
||||||
The kernel IPX software stores only one route to any target network.
|
The kernel IPX stores only one route per target network at a time.
|
||||||
.SS OPTIONS
|
.SS OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.I add
|
.I add
|
||||||
This option is used to configure a route to a target network.
|
This option is used to set up the route to a target network.
|
||||||
.TP
|
.TP
|
||||||
.I del
|
.I del
|
||||||
This option is used to delete the route to a target network.
|
This option is used to delete the route to a target network.
|
||||||
|
|||||||
@@ -33,7 +33,12 @@ ncpmount \- mount all volumes of a specified Novell fileserver.
|
|||||||
] [
|
] [
|
||||||
.B -d
|
.B -d
|
||||||
.I dir mode
|
.I dir mode
|
||||||
]
|
] [
|
||||||
|
.B -V
|
||||||
|
.I volume
|
||||||
|
] [
|
||||||
|
.B -v
|
||||||
|
]
|
||||||
mount-point
|
mount-point
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@@ -186,6 +191,41 @@ can very well choose a file mode that tells that you have. This
|
|||||||
certainly cannot override the restrictions imposed by the server.
|
certainly cannot override the restrictions imposed by the server.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
.B -V
|
||||||
|
.I volume
|
||||||
|
.RS 3
|
||||||
|
There are 2 general ways you can mount a NetWare server's disk space:
|
||||||
|
Either you can mount all volumes under one directory, or you can mount
|
||||||
|
only a single volume.
|
||||||
|
|
||||||
|
When you choose to mount the complete disk space at once, you have the
|
||||||
|
advantage that only one Linux mount point and only one
|
||||||
|
NetWare connection is used for all the volumes of this server. Both of
|
||||||
|
these are limited resources. (Although raising the number of Linux
|
||||||
|
mount points is significantly cheaper than raising the number of
|
||||||
|
available NetWare connections ;-))
|
||||||
|
|
||||||
|
When you specify to mount a single volume by using the option
|
||||||
|
.B -V
|
||||||
|
.I volume,
|
||||||
|
you have the big advantage that nfsd is able to re-export this mounted
|
||||||
|
directory. You must invoke
|
||||||
|
.B nfsd
|
||||||
|
and
|
||||||
|
.B mountd
|
||||||
|
with the option
|
||||||
|
.I --re-export
|
||||||
|
to make nfsd re-export ncpfs mounted directories. This uses one Linux
|
||||||
|
mount point and one NetWare connection per mounted volume. Maybe
|
||||||
|
sometime in the future I will make it possible to mount all volumes on
|
||||||
|
different mount points, using only one connection.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -v
|
||||||
|
.RS 3
|
||||||
|
Print ncpfs version number
|
||||||
|
.RE
|
||||||
|
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
You must configure the IPX subsystem before ncpmount will work.
|
You must configure the IPX subsystem before ncpmount will work.
|
||||||
It is especially important that there is a route to the internal network
|
It is especially important that there is a route to the internal network
|
||||||
@@ -205,7 +245,7 @@ Most diagnostics issued by ncpfs are logged by syslogd. Normally
|
|||||||
nothing is printed, only error situations are logged there.
|
nothing is printed, only error situations are logged there.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.B syslogd(8), ncpumount(8)
|
.B syslogd(8), ncpumount(8), nfsd(8), mountd(8)
|
||||||
|
|
||||||
.SH CREDITS
|
.SH CREDITS
|
||||||
ncpfs would not have been possible without lwared, written by Ales
|
ncpfs would not have been possible without lwared, written by Ales
|
||||||
|
|||||||
33
man/nwmsg.8
Normal file
33
man/nwmsg.8
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
.TH NWMSG 8 02/29/1996 nwmsg nwmsg
|
||||||
|
.SH NAME
|
||||||
|
nwmsg \- Deliver NetWare user broadcast messages
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B nwmsg
|
||||||
|
.I mount-point
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B nwmsg
|
||||||
|
is called by kerneld when a broadcast message arrives from a NetWare
|
||||||
|
server.
|
||||||
|
.B nwmsg
|
||||||
|
fetches this message via the mount point and delivers it to
|
||||||
|
the user using the same way write(1) uses.
|
||||||
|
|
||||||
|
Please note that
|
||||||
|
.I kerneld
|
||||||
|
must run when broadcast messages should be delivered to users.
|
||||||
|
|
||||||
|
NetWare servers can send asynchronous broadcast messages to users,
|
||||||
|
either on explicit request by another user, or when the server is
|
||||||
|
shutdown. The client workstation is informed about this event by an
|
||||||
|
IPX packet on a special socket, the message socket.
|
||||||
|
|
||||||
|
This can happen at any time, so the user has to be informed about this
|
||||||
|
event whenever it appears. I chose to use the kerneld feature of the
|
||||||
|
Linux kernel to call the program nwmsg. For nwmsg, I used the relevant
|
||||||
|
parts of the
|
||||||
|
.I write
|
||||||
|
program, so you can expect the NetWare broadcast
|
||||||
|
messages to appear where user messages would appear.
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
ncpmount(8), kerneld(8), write(1)
|
||||||
142
man/pserver.1
Normal file
142
man/pserver.1
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
.TH PSERVER 1 02/10/1996 pserver pserver
|
||||||
|
.SH NAME
|
||||||
|
pserver \- NetWare print server
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B pserver
|
||||||
|
[
|
||||||
|
.B -S
|
||||||
|
.I server
|
||||||
|
] [
|
||||||
|
.B -h
|
||||||
|
] [
|
||||||
|
.B -U
|
||||||
|
.I user name
|
||||||
|
] [
|
||||||
|
.B -P
|
||||||
|
.I password
|
||||||
|
|
|
||||||
|
.B -n
|
||||||
|
] [
|
||||||
|
.B -C
|
||||||
|
] [
|
||||||
|
.B -q
|
||||||
|
.I queue name
|
||||||
|
] [
|
||||||
|
.B -c
|
||||||
|
.I command
|
||||||
|
] [
|
||||||
|
.B -j
|
||||||
|
.I job type
|
||||||
|
] [
|
||||||
|
.B -t
|
||||||
|
.I timeout
|
||||||
|
] [
|
||||||
|
.B -d
|
||||||
|
]
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B pserver
|
||||||
|
is a program that connects to print queues on NetWare servers and
|
||||||
|
feeds incoming print jobs to the Linux printing system.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.B -h
|
||||||
|
.RS 3
|
||||||
|
.B -h
|
||||||
|
is used to print out a short help text.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -S
|
||||||
|
.I server
|
||||||
|
.RS 3
|
||||||
|
.B server
|
||||||
|
is the name of the server you want to use.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -U
|
||||||
|
.I user
|
||||||
|
.RS 3
|
||||||
|
.B user
|
||||||
|
is the print server name at the server.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -P
|
||||||
|
.I password
|
||||||
|
.RS 3
|
||||||
|
.B password
|
||||||
|
is the password to use for the print server at the server. If neither
|
||||||
|
.B -n
|
||||||
|
nor
|
||||||
|
.B -P
|
||||||
|
are given, and the user has no open connection to the server, pserver
|
||||||
|
prompts for a password.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -n
|
||||||
|
.RS 3
|
||||||
|
.B -n
|
||||||
|
should be given if the print server does not require a password.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -C
|
||||||
|
.RS 3
|
||||||
|
By default, passwords are converted to uppercase before they are sent
|
||||||
|
to the server, because most servers require this. You can turn off
|
||||||
|
this conversion by
|
||||||
|
.B -C.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -q
|
||||||
|
.I queue name
|
||||||
|
.RS 3
|
||||||
|
.B queue name
|
||||||
|
is the name of the print queue you want to service.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -c
|
||||||
|
.I command
|
||||||
|
.RS 3
|
||||||
|
When a job is received from the print queue, pserver forks off a new
|
||||||
|
process, and feeds the job file to stdin.
|
||||||
|
.I command
|
||||||
|
is the printing command that is executed for each job. The default
|
||||||
|
command is 'lpr'.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -j
|
||||||
|
.I job type
|
||||||
|
.RS 3
|
||||||
|
Each job in a NetWare print queue has a job type. For print jobs, this
|
||||||
|
corresponds to the number of the form the job should be printed
|
||||||
|
on. You can tell pserver that it should only receive jobs for one
|
||||||
|
specific form from the queue. The default is -1, which means that
|
||||||
|
everything is received.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -t
|
||||||
|
.I timeout
|
||||||
|
.RS 3
|
||||||
|
Pserver is not informed by NetWare servers when new jobs arrive. So a
|
||||||
|
polling scheme has to be used. When there are no jobs to service,
|
||||||
|
.I timeout
|
||||||
|
tells pserver how long to wait between two requests. The default is 30
|
||||||
|
seconds. When a job is finished, pserver asks the NetWare server
|
||||||
|
immediately for a new job, and does not wait
|
||||||
|
.I timeout
|
||||||
|
seconds.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -d
|
||||||
|
.RS 3
|
||||||
|
Normally, pserver daemonizes itself.
|
||||||
|
.B -d
|
||||||
|
tells it not to do so. This is useful if you want to see the
|
||||||
|
diagnostic messages that are printed when a error occurs.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
|
||||||
|
|
||||||
|
.SH CREDITS
|
||||||
|
pserver was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
Begin3
|
|
||||||
Title: ncpfs
|
|
||||||
Version: 0.14
|
|
||||||
Entered-date: 09. February 1996
|
|
||||||
Description: With ncpfs you can mount volumes of your novell
|
|
||||||
server under Linux. 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.
|
|
||||||
Keywords: filesystem kernel ncp novell netware
|
|
||||||
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
|
||||||
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
|
||||||
Primary-site: linux01.gwdg.de:/pub/ncpfs
|
|
||||||
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
|
|
||||||
~70k ncpfs-0.14.tgz
|
|
||||||
~ 1k ncpfs-0.14.lsm
|
|
||||||
Copying-policy: GPL
|
|
||||||
End
|
|
||||||
19
ncpfs-0.17.lsm
Normal file
19
ncpfs-0.17.lsm
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Begin3
|
||||||
|
Title: ncpfs
|
||||||
|
Version: 0.17
|
||||||
|
Entered-date: 29. February 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.
|
||||||
|
Keywords: filesystem ncp novell netware printing
|
||||||
|
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||||
|
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||||
|
Primary-site: linux01.gwdg.de:/pub/ncpfs
|
||||||
|
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
|
||||||
|
~81k ncpfs-0.17.tgz
|
||||||
|
~ 1k ncpfs-0.17.lsm
|
||||||
|
Copying-policy: GPL
|
||||||
|
End
|
||||||
@@ -2,20 +2,26 @@
|
|||||||
# Makefile for the linux ncp-filesystem routines.
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
#
|
#
|
||||||
|
|
||||||
UTIL_EXECS = ncpmount ncpumount nprint slist pqlist fsinfo pserver
|
USERUTILS = slist pqlist nwfsinfo pserver
|
||||||
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
|
|
||||||
UIDUTILS = ncpmount ncpumount
|
UIDUTILS = ncpmount ncpumount
|
||||||
|
SBINUTILS = nwmsg
|
||||||
|
|
||||||
# CFLAGS = -Wall $(INCLUDES) -O2 $(KERNELD)
|
UTIL_EXECS = $(USERUTILS) $(UIDUTILS) $(SBINUTILS)
|
||||||
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2
|
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
|
||||||
|
|
||||||
|
#CFLAGS = -Wall $(INCLUDES) $(KERNELD) -g -DNCPFS_VERSION=\"$(VERSION)\"
|
||||||
|
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2 -DNCPFS_VERSION=\"$(VERSION)\"
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
all: $(UTILS) ncptest
|
all: $(UTILS) ncptest
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
for i in $(UTIL_EXECS); \
|
for i in $(UTIL_EXECS); \
|
||||||
do install --strip $(INTERM_BINDIR)/$$i -m 755 $(BINDIR); done
|
do install $(INTERM_BINDIR)/$$i -m 755 $(BINDIR); done
|
||||||
for i in $(UIDUTILS); do chmod 4755 $(BINDIR)/$$i; done
|
for i in $(UIDUTILS); \
|
||||||
|
do install $(INTERM_BINDIR)/$$i -m 4755 $(BINDIR); done
|
||||||
|
for i in $(SBINUTILS); \
|
||||||
|
do install $(INTERM_BINDIR)/$$i -m 755 $(SBINDIR); done
|
||||||
|
|
||||||
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) ncplib.o
|
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) ncplib.o
|
||||||
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) ncplib.o
|
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) ncplib.o
|
||||||
|
|||||||
142
util/ncplib.c
142
util/ncplib.c
@@ -1201,6 +1201,7 @@ ncp_find_conn_spec(const char *server, const char *user, const char *password,
|
|||||||
|
|
||||||
str_upper(spec.server);
|
str_upper(spec.server);
|
||||||
str_upper(spec.user);
|
str_upper(spec.user);
|
||||||
|
spec.login_type = NCP_BINDERY_USER;
|
||||||
|
|
||||||
if (ncp_open_permanent(&conn, &spec) == 0)
|
if (ncp_open_permanent(&conn, &spec) == 0)
|
||||||
{
|
{
|
||||||
@@ -1236,35 +1237,36 @@ ncp_find_conn_spec(const char *server, const char *user, const char *password,
|
|||||||
}
|
}
|
||||||
fclose(nwc);
|
fclose(nwc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (strlen(spec.user) == 0)
|
|
||||||
|
if (strlen(spec.user) == 0)
|
||||||
|
{
|
||||||
|
return &spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(spec.password) == 0)
|
||||||
|
{
|
||||||
|
char *password;
|
||||||
|
if (!(isatty(0) && isatty(1)))
|
||||||
{
|
{
|
||||||
return &spec;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
printf("Logging into %s as %s\n",
|
||||||
|
spec.server, spec.user);
|
||||||
|
|
||||||
if (strlen(spec.password) == 0)
|
password = getpass("Password: ");
|
||||||
|
if (strlen(password) > sizeof(spec.password))
|
||||||
{
|
{
|
||||||
char *password;
|
return NULL;
|
||||||
if (!(isatty(0) && isatty(1)))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
printf("Logging into %s as %s\n",
|
|
||||||
spec.server, spec.user);
|
|
||||||
|
|
||||||
password = getpass("Password: ");
|
|
||||||
if (strlen(password) > sizeof(spec.password))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
strcpy(spec.password, password);
|
|
||||||
}
|
}
|
||||||
else
|
strcpy(spec.password, password);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strcmp(spec.password, NWC_NOPASSWORD) == 0)
|
||||||
{
|
{
|
||||||
if (strcmp(spec.password, NWC_NOPASSWORD) == 0)
|
*spec.password = '\0';
|
||||||
{
|
|
||||||
*spec.password = '\0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1348,6 +1350,7 @@ ncp_initialize_as(struct ncp_conn *conn,
|
|||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
password = NWC_NOPASSWORD;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -2738,3 +2741,98 @@ ncp_write(struct ncp_conn *conn, const char *file_id,
|
|||||||
}
|
}
|
||||||
return already_written;
|
return already_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_copy_file(struct ncp_conn *conn,
|
||||||
|
const char source_file[6],
|
||||||
|
const char target_file[6],
|
||||||
|
__u32 source_offset,
|
||||||
|
__u32 target_offset,
|
||||||
|
__u32 count,
|
||||||
|
__u32 *copied_count)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(conn);
|
||||||
|
|
||||||
|
ncp_add_byte(conn, 0); /* reserved */
|
||||||
|
ncp_add_mem(conn, source_file, 6);
|
||||||
|
ncp_add_mem(conn, target_file, 6);
|
||||||
|
ncp_add_dword(conn, source_offset);
|
||||||
|
ncp_add_dword(conn, target_offset);
|
||||||
|
ncp_add_dword(conn, count);
|
||||||
|
|
||||||
|
if ((result = ncp_request(conn, 74)) != 0)
|
||||||
|
{
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*copied_count = ncp_reply_dword(conn, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_get_broadcast_message(struct ncp_conn *conn, char message[256])
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
ncp_init_request_s(conn, 1);
|
||||||
|
|
||||||
|
if ((result = ncp_request(conn, 21)) != 0)
|
||||||
|
{
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = ncp_reply_byte(conn, 0);
|
||||||
|
message[length] = 0;
|
||||||
|
memcpy(message, ncp_reply_data(conn, 1), length);
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request_s(conn, 20);
|
||||||
|
ncp_add_byte(conn, dir_handle);
|
||||||
|
|
||||||
|
if ((result = ncp_request(conn, 22)) != 0)
|
||||||
|
{
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_alloc_short_dir_handle(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *dir,
|
||||||
|
word alloc_mode,
|
||||||
|
byte *target)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(conn);
|
||||||
|
ncp_add_byte(conn, 12); /* subfunction */
|
||||||
|
ncp_add_byte(conn, 0); /* dos name space */
|
||||||
|
ncp_add_byte(conn, 0); /* reserved */
|
||||||
|
ncp_add_word(conn, htons(alloc_mode));
|
||||||
|
ncp_add_handle_path(conn, dir->volNumber, dir->DosDirNum,
|
||||||
|
1, NULL);
|
||||||
|
|
||||||
|
if ((result = ncp_request(conn, 87)) != 0)
|
||||||
|
{
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*target = ncp_reply_byte(conn, 0);
|
||||||
|
ncp_unlock_conn(conn);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -257,6 +257,15 @@ int
|
|||||||
ncp_write(struct ncp_conn *conn, const char *file_id,
|
ncp_write(struct ncp_conn *conn, const char *file_id,
|
||||||
off_t offset, size_t count, const char *source);
|
off_t offset, size_t count, const char *source);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_copy_file(struct ncp_conn *conn,
|
||||||
|
const char source_file[6],
|
||||||
|
const char target_file[6],
|
||||||
|
__u32 source_offset,
|
||||||
|
__u32 target_offset,
|
||||||
|
__u32 count,
|
||||||
|
__u32 *copied_count);
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_do_lookup(struct ncp_conn *conn,
|
ncp_do_lookup(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *dir,
|
struct nw_info_struct *dir,
|
||||||
@@ -328,4 +337,20 @@ int
|
|||||||
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||||
__u32 job_number);
|
__u32 job_number);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle);
|
||||||
|
|
||||||
|
#define NCP_ALLOC_PERMANENT (0x0000)
|
||||||
|
#define NCP_ALLOC_TEMPORARY (0x0001)
|
||||||
|
#define NCP_ALLOC_SPECIAL (0x0002)
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_alloc_short_dir_handle(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *dir,
|
||||||
|
__u16 alloc_mode,
|
||||||
|
__u8 *target);
|
||||||
|
|
||||||
#endif /* _NCPLIB_H */
|
#endif /* _NCPLIB_H */
|
||||||
|
|||||||
@@ -191,10 +191,11 @@ main(int argc, char *argv[])
|
|||||||
umask(um);
|
umask(um);
|
||||||
data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
|
data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
|
||||||
data.dir_mode = 0;
|
data.dir_mode = 0;
|
||||||
|
data.flags |= NCP_MOUNT_SOFT;
|
||||||
|
|
||||||
upcase_password = 1;
|
upcase_password = 1;
|
||||||
|
|
||||||
while ((opt = getopt (argc, argv, "CS:U:c:u:g:f:d:P:nh")) != EOF)
|
while ((opt = getopt (argc, argv, "CS:U:c:u:g:f:d:P:nhvV:")) != EOF)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
@@ -284,12 +285,23 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
password = optarg;
|
password = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'V':
|
||||||
|
if (strlen(optarg) >= sizeof(data.mounted_vol))
|
||||||
|
{
|
||||||
|
printf("Volume too long: %s\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
strcpy(data.mounted_vol, optarg);
|
||||||
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
password = "";
|
password = "";
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help();
|
||||||
exit(1);
|
exit(1);
|
||||||
|
case 'v':
|
||||||
|
fprintf(stderr, "ncpfs version %s\n", NCPFS_VERSION);
|
||||||
|
exit(1);
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -330,7 +342,7 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_KERNEL
|
#ifndef HAVE_KERNELD
|
||||||
/* Check if the ncpfs filesystem is in the kernel. If not, attempt
|
/* Check if the ncpfs filesystem is in the kernel. If not, attempt
|
||||||
* to load the ncpfs module */
|
* to load the ncpfs module */
|
||||||
if (load_ncpfs() != 0)
|
if (load_ncpfs() != 0)
|
||||||
@@ -342,6 +354,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
data.version = NCP_MOUNT_VERSION;
|
data.version = NCP_MOUNT_VERSION;
|
||||||
data.mounted_uid = conn_uid;
|
data.mounted_uid = conn_uid;
|
||||||
|
memcpy(data.server_name, spec->server, sizeof(data.server_name));
|
||||||
|
|
||||||
if (data.dir_mode == 0)
|
if (data.dir_mode == 0)
|
||||||
{
|
{
|
||||||
@@ -423,6 +436,31 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NCP_MOUNT_VERSION>1
|
||||||
|
|
||||||
|
data.message_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||||
|
if (data.message_fd == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "could not open message socket: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.sipx_port = htons(ntohs(addr.sipx_port) + 1);
|
||||||
|
|
||||||
|
if (bind(data.message_fd, (struct sockaddr *)&addr,sizeof(addr)) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bind(message_sock, ): %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(mount_point) < sizeof(data.mount_point))
|
||||||
|
{
|
||||||
|
strcpy(data.mount_point, mount_point);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
flags = MS_MGC_VAL;
|
flags = MS_MGC_VAL;
|
||||||
|
|
||||||
data.time_out = 20;
|
data.time_out = 20;
|
||||||
@@ -437,7 +475,8 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( (ncp_open_mount(&conn, mount_point) != 0)
|
if ( (ncp_open_mount(&conn, mount_point) != 0)
|
||||||
|| (ncp_login_user(&conn, spec->user, spec->password) != 0))
|
|| (ncp_login_user(&conn, spec->user, spec->password) != 0)
|
||||||
|
|| (ioctl(conn.mount_fid, NCP_IOC_CONN_LOGGED_IN, NULL) != 0))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: login failed\n", strerror(errno));
|
fprintf(stderr, "%s: login failed\n", strerror(errno));
|
||||||
ncp_close(&conn);
|
ncp_close(&conn);
|
||||||
@@ -518,5 +557,6 @@ help(void)
|
|||||||
" If neither -P nor -n are given, you are\n"
|
" If neither -P nor -n are given, you are\n"
|
||||||
" asked for a password.\n"
|
" asked for a password.\n"
|
||||||
"-h print this help text\n"
|
"-h print this help text\n"
|
||||||
|
"-v print ncpfs version number\n"
|
||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,47 @@ test_connlist(struct ncp_conn *conn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_create(struct ncp_conn *conn)
|
||||||
|
{
|
||||||
|
struct nw_info_struct sys;
|
||||||
|
struct nw_info_struct me;
|
||||||
|
__u8 dir_handle;
|
||||||
|
struct ncp_file_info new_file;
|
||||||
|
|
||||||
|
if (ncp_do_lookup(conn, NULL, "SYS", &sys) != 0)
|
||||||
|
{
|
||||||
|
printf("lookup error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ncp_do_lookup(conn, &sys, "ME", &me) != 0)
|
||||||
|
{
|
||||||
|
printf("lookup public error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_alloc_short_dir_handle(conn, &me, NCP_ALLOC_TEMPORARY,
|
||||||
|
&dir_handle) != 0)
|
||||||
|
{
|
||||||
|
printf("alloc_dir_handle error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_create_file(conn, dir_handle, "BLUB.TXT", 0,
|
||||||
|
&new_file) != 0)
|
||||||
|
{
|
||||||
|
printf("create error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_dealloc_dir_handle(conn, dir_handle) != 0)
|
||||||
|
{
|
||||||
|
printf("dealloc error\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -158,7 +199,7 @@ main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
test_connlist(&conn);
|
test_create(&conn);
|
||||||
ncp_close(&conn);
|
ncp_close(&conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,20 +178,3 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
|
||||||
* Emacs will notice this stuff at the end of the file and automatically
|
|
||||||
* adjust the settings for this buffer only. This must remain at the end
|
|
||||||
* of the file.
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* Local variables:
|
|
||||||
* c-indent-level: 8
|
|
||||||
* c-brace-imaginary-offset: 0
|
|
||||||
* c-brace-offset: -8
|
|
||||||
* c-argdecl-indent: 8
|
|
||||||
* c-label-offset: -8
|
|
||||||
* c-continued-statement-offset: 8
|
|
||||||
* c-continued-brace-offset: 0
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* nwprint.c
|
* nprint.c
|
||||||
*
|
*
|
||||||
* Send data to a NetWare print queue.
|
* Send data to a NetWare print queue.
|
||||||
*
|
*
|
||||||
@@ -316,7 +316,7 @@ static void
|
|||||||
help(void)
|
help(void)
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("usage: %s [options] mount-point\n", progname);
|
printf("usage: %s [options] file\n", progname);
|
||||||
printf("\n"
|
printf("\n"
|
||||||
"-S server Server name to be used\n"
|
"-S server Server name to be used\n"
|
||||||
"-U username Username sent to server\n"
|
"-U username Username sent to server\n"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* fsinfo.c
|
* nwfsinfo.c
|
||||||
*
|
*
|
||||||
* Print the info strings of a server, maybe sometime more.
|
* Print the info strings of a server, maybe sometime more.
|
||||||
*
|
*
|
||||||
219
util/nwmsg.c
Normal file
219
util/nwmsg.c
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* nwmsg.c
|
||||||
|
*
|
||||||
|
* Fetch NetWare broadcast messages and write to the user
|
||||||
|
*
|
||||||
|
* Copyright (C) 1996 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <mntent.h>
|
||||||
|
#include "ncplib.h"
|
||||||
|
|
||||||
|
static int search_utmp(char *user, char *tty);
|
||||||
|
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct ncp_conn conn;
|
||||||
|
char message[256];
|
||||||
|
struct ncp_fs_info info;
|
||||||
|
struct passwd *pwd;
|
||||||
|
char tty[256];
|
||||||
|
char tty_path[256];
|
||||||
|
FILE *tty_file;
|
||||||
|
FILE *mtab;
|
||||||
|
struct mntent *mnt;
|
||||||
|
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
openlog("nwmsg", LOG_PID, LOG_LPR);
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s mount-point\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_open_mount(&conn, argv[1]) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: could not open connection %s\n",
|
||||||
|
progname, argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_get_broadcast_message(&conn, message) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: could not get broadcast message\n",
|
||||||
|
progname);
|
||||||
|
ncp_close(&conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(message) == 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_DEBUG, "no message");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
syslog(LOG_DEBUG, "message: %s", message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
info.version = NCP_GET_FS_INFO_VERSION;
|
||||||
|
if (ioctl(conn.mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: could not ioctl on connection: %s\n",
|
||||||
|
progname, strerror(errno));
|
||||||
|
ncp_close(&conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_close(&conn);
|
||||||
|
|
||||||
|
if ((pwd = getpwuid(info.mounted_uid)) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: user %d not known\n",
|
||||||
|
progname, info.mounted_uid);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mtab = fopen(MOUNTED, "r")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: can't open %s\n",
|
||||||
|
progname, MOUNTED);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((mnt = getmntent(mtab)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(mnt->mnt_dir, conn.mount_point) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnt == NULL)
|
||||||
|
{
|
||||||
|
syslog(LOG_DEBUG, "cannot find mtab entry\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search_utmp(pwd->pw_name, tty) != 0)
|
||||||
|
{
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(tty_path, "/dev/%s", tty);
|
||||||
|
if ((tty_file = fopen(tty_path, "w")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: cannot open %s: %s\n",
|
||||||
|
progname, tty_path, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(tty_file, "\r\n\007\007\007Message from NetWare Server: %s\n",
|
||||||
|
mnt->mnt_fsname);
|
||||||
|
fprintf(tty_file, "%s\n", message);
|
||||||
|
fclose(tty_file);
|
||||||
|
fclose(mtab);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following routines have been taken from util-linux-2.5's write.c */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* term_chk - check that a terminal exists, and get the message bit
|
||||||
|
* and the access time
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
term_chk(char *tty, int *msgsokP, time_t *atimeP, int *showerror)
|
||||||
|
{
|
||||||
|
struct stat s;
|
||||||
|
char path[MAXPATHLEN];
|
||||||
|
|
||||||
|
(void)sprintf(path, "/dev/%s", tty);
|
||||||
|
if (stat(path, &s) < 0) {
|
||||||
|
if (showerror)
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"write: %s: %s\n", path, strerror(errno));
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
*msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */
|
||||||
|
*atimeP = s.st_atime;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* search_utmp - search utmp for the "best" terminal to write to
|
||||||
|
*
|
||||||
|
* Ignores terminals with messages disabled, and of the rest, returns
|
||||||
|
* the one with the most recent access time. Returns as value the number
|
||||||
|
* of the user's terminals with messages enabled, or -1 if the user is
|
||||||
|
* not logged in at all.
|
||||||
|
*
|
||||||
|
* Special case for writing to yourself - ignore the terminal you're
|
||||||
|
* writing from, unless that's the only terminal with messages enabled.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
search_utmp(char *user, char *tty)
|
||||||
|
{
|
||||||
|
struct utmp u;
|
||||||
|
time_t bestatime, atime;
|
||||||
|
int ufd, nloggedttys, nttys, msgsok, user_is_me;
|
||||||
|
|
||||||
|
char atty[sizeof(u.ut_line) + 1];
|
||||||
|
|
||||||
|
if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) {
|
||||||
|
perror("utmp");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nloggedttys = nttys = 0;
|
||||||
|
bestatime = 0;
|
||||||
|
user_is_me = 0;
|
||||||
|
while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u))
|
||||||
|
if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) {
|
||||||
|
++nloggedttys;
|
||||||
|
|
||||||
|
(void)strncpy(atty, u.ut_line, sizeof(u.ut_line));
|
||||||
|
atty[sizeof(u.ut_line)] = '\0';
|
||||||
|
|
||||||
|
if (term_chk(atty, &msgsok, &atime, 0))
|
||||||
|
continue; /* bad term? skip */
|
||||||
|
if (!msgsok)
|
||||||
|
continue; /* skip ttys with msgs off */
|
||||||
|
|
||||||
|
if (u.ut_type != USER_PROCESS)
|
||||||
|
continue; /* it's not a valid entry */
|
||||||
|
|
||||||
|
++nttys;
|
||||||
|
if (atime > bestatime) {
|
||||||
|
bestatime = atime;
|
||||||
|
(void)strcpy(tty, atty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)close(ufd);
|
||||||
|
if (nloggedttys == 0) {
|
||||||
|
(void)fprintf(stderr, "write: %s is not logged in\n", user);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
printf("%-52s", q.object_name);
|
printf("%-52s", q.object_name);
|
||||||
printf("%08x\n", q.object_id);
|
printf("%08X\n", (unsigned int)q.object_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((found == 0) && (isatty(1)))
|
if ((found == 0) && (isatty(1)))
|
||||||
|
|||||||
120
util/pserver.c
120
util/pserver.c
@@ -9,10 +9,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "ncplib.h"
|
#include "ncplib.h"
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ struct nw_queue {
|
|||||||
static struct nw_queue q;
|
static struct nw_queue q;
|
||||||
|
|
||||||
static int term_request;
|
static int term_request;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
init_queue(struct ncp_conn *conn, char *queue_name,
|
init_queue(struct ncp_conn *conn, char *queue_name,
|
||||||
@@ -37,11 +40,31 @@ init_queue(struct ncp_conn *conn, char *queue_name,
|
|||||||
static int
|
static int
|
||||||
poll_queue(struct nw_queue *q);
|
poll_queue(struct nw_queue *q);
|
||||||
|
|
||||||
void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
/* Obviously, there's more to do */
|
fprintf(stderr, "usage: %s [options] file\n", progname);
|
||||||
return;
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
help(void)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("usage: %s [options]\n", progname);
|
||||||
|
printf("\n"
|
||||||
|
"-S server Server name to be used\n"
|
||||||
|
"-U username Print Server name sent to server\n"
|
||||||
|
"-P password Use this password\n"
|
||||||
|
"-n Do not use any password\n"
|
||||||
|
"-C Don't convert password to uppercase\n"
|
||||||
|
"-q queue name Name of the printing queue to use\n"
|
||||||
|
"-c command Name of print command, default: 'lpr'\n"
|
||||||
|
"-j job type Type of job (Form number) to service\n"
|
||||||
|
"-t timeout Polling interval, default: 30 sec\n"
|
||||||
|
"-d Debug: don't daemonize\n"
|
||||||
|
"-h print this help text\n"
|
||||||
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NCP_BINDERY_PSERVER
|
#ifndef NCP_BINDERY_PSERVER
|
||||||
@@ -52,32 +75,34 @@ static void
|
|||||||
terminate_handler()
|
terminate_handler()
|
||||||
{
|
{
|
||||||
signal(SIGTERM,terminate_handler);
|
signal(SIGTERM,terminate_handler);
|
||||||
|
signal(SIGINT, terminate_handler);
|
||||||
term_request=1;
|
term_request=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/* Daemon_init is taken from Stevens, Adv. Unix programming */
|
||||||
static void
|
static int
|
||||||
daemonize()
|
daemon_init(void)
|
||||||
{
|
{
|
||||||
int fd,c;
|
pid_t pid;
|
||||||
|
|
||||||
if ((c = fork()) > 0) exit(0);
|
if ((pid = fork()) < 0)
|
||||||
if (c < 0)
|
{
|
||||||
{
|
return -1;
|
||||||
fprintf(stderr, "ipxripd: can't fork: %s\n",strerror(errno));
|
}
|
||||||
exit(1);
|
else if (pid != 0)
|
||||||
|
{
|
||||||
|
exit(0); /* parent vanishes */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* child process */
|
||||||
|
setsid();
|
||||||
|
chdir("/");
|
||||||
|
umask(0);
|
||||||
close(0);
|
close(0);
|
||||||
close(1);
|
close(1);
|
||||||
close(2);
|
close(2);
|
||||||
if ((fd = open("/dev/tty", O_RDWR)) >= 0)
|
return 0;
|
||||||
{
|
|
||||||
ioctl(fd, TIOCNOTTY, NULL);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
@@ -87,19 +112,47 @@ main(int argc, char *argv[])
|
|||||||
int opt;
|
int opt;
|
||||||
int job_type = 0xffff;
|
int job_type = 0xffff;
|
||||||
int debug = 0;
|
int debug = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
char *queue_name = NULL;
|
char *queue_name = NULL;
|
||||||
|
|
||||||
char default_command[] = "lpr";
|
char default_command[] = "lpr";
|
||||||
char *command = default_command;
|
char *command = default_command;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i += 1)
|
||||||
|
{
|
||||||
|
if ( (strcmp(argv[i], "-h") == 0)
|
||||||
|
|| (strcmp(argv[i], "-?") == 0))
|
||||||
|
{
|
||||||
|
help();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i += 1)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[i], "-d") == 0)
|
||||||
|
{
|
||||||
|
debug = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug == 0)
|
||||||
|
{
|
||||||
|
daemon_init();
|
||||||
|
openlog("pserver", LOG_PID, LOG_LPR);
|
||||||
|
}
|
||||||
|
|
||||||
if (ncp_initialize_as(&conn, &argc, argv, 1, NCP_BINDERY_PSERVER) != 0)
|
if (ncp_initialize_as(&conn, &argc, argv, 1, NCP_BINDERY_PSERVER) != 0)
|
||||||
{
|
{
|
||||||
perror("Could not open connection");
|
perror("Could not open connection");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "q:c:j:t:d")) != EOF)
|
while ((opt = getopt(argc, argv, "q:c:j:t:dh")) != EOF)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
@@ -118,18 +171,26 @@ main(int argc, char *argv[])
|
|||||||
case 'd':
|
case 'd':
|
||||||
debug = 1;
|
debug = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'h':
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc != optind)
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memzero(q);
|
memzero(q);
|
||||||
|
|
||||||
if (debug == 0)
|
if (queue_name == NULL)
|
||||||
{
|
{
|
||||||
/* We can not daemonize after ncp_initialize, sorry */
|
fprintf(stderr, "You must specify a queue\n");
|
||||||
/* daemonize(); */
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_queue(&conn, queue_name, command, &q) != 0)
|
if (init_queue(&conn, queue_name, command, &q) != 0)
|
||||||
@@ -143,6 +204,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
term_request = 0;
|
term_request = 0;
|
||||||
signal(SIGTERM,terminate_handler);
|
signal(SIGTERM,terminate_handler);
|
||||||
|
signal(SIGINT, terminate_handler);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -212,13 +274,13 @@ poll_queue(struct nw_queue *q)
|
|||||||
|
|
||||||
if (pipe(fd) < 0)
|
if (pipe(fd) < 0)
|
||||||
{
|
{
|
||||||
perror("pipe");
|
syslog(LOG_ERR, "pipe error: %m");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pid = fork()) < 0)
|
if ((pid = fork()) < 0)
|
||||||
{
|
{
|
||||||
perror("fork");
|
syslog(LOG_ERR, "fork error: %m");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +307,7 @@ poll_queue(struct nw_queue *q)
|
|||||||
|
|
||||||
if (waitpid(pid, NULL, 0) < 0)
|
if (waitpid(pid, NULL, 0) < 0)
|
||||||
{
|
{
|
||||||
perror("waitpid");
|
syslog(LOG_ERR, "waitpid: %m\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -258,7 +320,7 @@ poll_queue(struct nw_queue *q)
|
|||||||
{
|
{
|
||||||
if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
|
if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
|
||||||
{
|
{
|
||||||
perror("dup2");
|
syslog(LOG_ERR, "dup2 error: %m\n");
|
||||||
close(fd[0]);
|
close(fd[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -266,7 +328,7 @@ poll_queue(struct nw_queue *q)
|
|||||||
}
|
}
|
||||||
|
|
||||||
execl("/bin/sh", "sh", "-c", q->command, NULL);
|
execl("/bin/sh", "sh", "-c", q->command, NULL);
|
||||||
perror("exec");
|
syslog(LOG_ERR, "exec error: %m\n");
|
||||||
close(fd[0]);
|
close(fd[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user