Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4d2144d0d | ||
|
|
134b5d6ebf | ||
|
|
ab78307868 | ||
|
|
3019bba627 | ||
|
|
011a5107c5 | ||
|
|
7179281575 | ||
|
|
b8d830f9a3 | ||
|
|
b36a27bedb | ||
|
|
7d0e3d011b | ||
|
|
84cb1f167d | ||
|
|
64f006632a | ||
|
|
92f749a943 | ||
|
|
6cb56005ea | ||
|
|
0520c1d2f7 | ||
|
|
d5ac4601b1 | ||
|
|
1fa124bd7c | ||
|
|
5753870858 | ||
|
|
b8ce93c8bd | ||
|
|
7bef99df0f | ||
|
|
d31ec2ab61 | ||
|
|
1ee60bade6 | ||
|
|
20589ca203 | ||
|
|
517e207709 | ||
|
|
5d4b23a5c1 | ||
|
|
c6124785a9 | ||
|
|
f2bcb2c71e |
BIN
.downloads/ncpfs-0.10.tgz
Normal file
BIN
.downloads/ncpfs-0.10.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.11.tgz
Normal file
BIN
.downloads/ncpfs-0.11.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.12.tgz
Normal file
BIN
.downloads/ncpfs-0.12.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.13.tgz
Normal file
BIN
.downloads/ncpfs-0.13.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.14.tgz
Normal file
BIN
.downloads/ncpfs-0.14.tgz
Normal file
Binary file not shown.
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.
BIN
.downloads/ncpfs-0.18.tgz
Normal file
BIN
.downloads/ncpfs-0.18.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.19.tgz
Normal file
BIN
.downloads/ncpfs-0.19.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.20.tgz
Normal file
BIN
.downloads/ncpfs-0.20.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.21.tgz
Normal file
BIN
.downloads/ncpfs-0.21.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.22.tgz
Normal file
BIN
.downloads/ncpfs-0.22.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.23.tgz
Normal file
BIN
.downloads/ncpfs-0.23.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.24.tgz
Normal file
BIN
.downloads/ncpfs-0.24.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.7.tgz
Normal file
BIN
.downloads/ncpfs-0.7.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.8.tgz
Normal file
BIN
.downloads/ncpfs-0.8.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.9.tgz
Normal file
BIN
.downloads/ncpfs-0.9.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.0.tgz
Normal file
BIN
.downloads/ncpfs-2.0.0.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.1.tgz
Normal file
BIN
.downloads/ncpfs-2.0.1.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.2.tgz
Normal file
BIN
.downloads/ncpfs-2.0.2.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.3.tgz
Normal file
BIN
.downloads/ncpfs-2.0.3.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.4.tgz
Normal file
BIN
.downloads/ncpfs-2.0.4.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.5.tgz
Normal file
BIN
.downloads/ncpfs-2.0.5.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.6.tgz
Normal file
BIN
.downloads/ncpfs-2.0.6.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.7.tgz
Normal file
BIN
.downloads/ncpfs-2.0.7.tgz
Normal file
Binary file not shown.
35
BUGS
35
BUGS
@@ -3,17 +3,34 @@ them to be bugs.
|
|||||||
|
|
||||||
But there are really problems that might be fixed in the future.
|
But there are really problems that might be fixed in the future.
|
||||||
|
|
||||||
'df' returns 0:
|
-------------------------------------------------------------------------------
|
||||||
Free disk space is distributed among the volumes in NetWare. df is
|
|
||||||
only able to report one number per mounted filesystem. As connections
|
|
||||||
are quite expensive for NetWare (with lwared that might change ...), I
|
|
||||||
rejected the alternative to mount only a single volume for a unix
|
|
||||||
mount point. So I simply return 0.
|
|
||||||
|
|
||||||
|
You might experience lockups of ncpfs volumes. It happens especially
|
||||||
|
under high network traffic, not necessarily only IPX traffic. I am not
|
||||||
|
able to reproduce this problem on my machine, so I'm sorry I can not
|
||||||
|
do anything about that. When such a lockup happens, you have to shut
|
||||||
|
down the complete ipx subsystem by deleting all ipx interfaces,
|
||||||
|
unmounting all ncpfs volumes (in this order!) and restarting all
|
||||||
|
again.
|
||||||
|
|
||||||
In your kernel log, there will appear messages like
|
For the kernel hackers who want to look at the problem: The routine
|
||||||
|
ipx_sendmsg in net/ipx/af_ipx.c sometimes locks forever if called with
|
||||||
|
nonblock=0. I DO NOT KNOW WHY!!! HELP ME, PLEASE!
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
'df' returns 0: Free disk space is distributed among the volumes in
|
||||||
|
NetWare. df is only able to report one number per mounted
|
||||||
|
filesystem. As connections are quite expensive for NetWare (with
|
||||||
|
mars_nwe and lwared that might change ...), I rejected the alternative
|
||||||
|
to mount only a single volume for a unix mount point. So I simply
|
||||||
|
return 0.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
If you use Linux 1.2.x, In your kernel log there will appear messages
|
||||||
|
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. Maybe this will be
|
These are a bit annoying, but completely harmless.
|
||||||
fixed in the future.
|
|
||||||
|
|||||||
189
Changes
Normal file
189
Changes
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
I only began this file with ncpfs-0.12. If you're interested in older
|
||||||
|
versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old.
|
||||||
|
|
||||||
|
ncpfs-2.0.6 -> ncpfs-2.0.7
|
||||||
|
- Hopefully removed one security problem in ncpumount.
|
||||||
|
- Added command line flag to pserver.c
|
||||||
|
- Heavily reconstructed ncpfs utils. Created the lib/ dir.
|
||||||
|
- Separated the uid utils in sutil
|
||||||
|
- Add nwsfind to enable users to use ncpfs safely without setting
|
||||||
|
the utils setuid root.
|
||||||
|
|
||||||
|
ncpfs-2.0.5 -> ncpfs-2.0.6
|
||||||
|
- Added a short description of a problem that I need help with to the
|
||||||
|
file BUGS. If you know a bit of the linux networking code, please
|
||||||
|
take a look at it. Thanks a lot.
|
||||||
|
- Added canonic output format to nwpbvalues and the command nwbpset. I
|
||||||
|
would like to invite you to help building capable bindery management
|
||||||
|
utilities. For little examples, look at the manual page of nwbpset.
|
||||||
|
- Added some values to ipxparse. Those interested in NDS should take a
|
||||||
|
look at it. It's really not much, but maybe it's a beginning.
|
||||||
|
|
||||||
|
ncpfs-2.0.4 -> ncpfs-2.0.5
|
||||||
|
- Removed another bug in nwbpvalues.
|
||||||
|
- Cleaned up man/Makefile
|
||||||
|
- Some manpage typos fixed. Thanks to Jim Van Zandt
|
||||||
|
<jrv@mbunix.mitre.org>
|
||||||
|
- added nwrights
|
||||||
|
|
||||||
|
ncpfs-2.0.3 -> ncpfs-2.0.4
|
||||||
|
- Changed name of npasswd to nwpasswd, as npasswd collides with
|
||||||
|
RedHat. Thanks to Mike Slater <mslater@nfinity.com> for pointing me
|
||||||
|
at this one.
|
||||||
|
- Put '\r\n' into nwmsg, because sometimes it did not print
|
||||||
|
correctly. Thanks to Petr Vandrovec Ing. VTEI
|
||||||
|
<VANDROVE@vcnet.vc.cvut.cz> for this one.
|
||||||
|
- Improved the ELF Makefile for ELF support. Thanks to Uwe Bonnes
|
||||||
|
<bon@elektron.ikp.physik.th-darmstadt.de>.
|
||||||
|
- Removed a very embarassing bug in nwpvalues :-(.
|
||||||
|
- Added a some routines to nwbpvalues.
|
||||||
|
|
||||||
|
ncpfs-2.0.2 -> ncpfs-2.0.3
|
||||||
|
- Removed the kernel-2.0 directory. Linus took the patch into 2.0.8.
|
||||||
|
So, if you want to use long file name support, upgrade to Linux
|
||||||
|
kernel version 2.0.8.
|
||||||
|
- Applied the lfn patch to the kernel-1.2 module with some light
|
||||||
|
testing. If you experience problems, tell it to me, and use the
|
||||||
|
ncpfs-2.0.2 kernel module, or upgrade to Linux 2.0.8.
|
||||||
|
- Added unencrypted login when no crypt key is returned.
|
||||||
|
- Hopefully improved error messages a bit
|
||||||
|
- Added some values to ipxparse
|
||||||
|
- For ELF systems, moved ncplib to /lib/libncp.so.1.x. This saves
|
||||||
|
about 1MB of disk space. As ncpfs grows, the saving will
|
||||||
|
increase. Please look at the Makefile to enable this.
|
||||||
|
- Enhanced nwfsinfo a bit. (Even with a manpage!)
|
||||||
|
- Added nwuserlist.
|
||||||
|
|
||||||
|
ncpfs-2.0.1 -> ncpfs-2.0.2
|
||||||
|
- Added some values to ipxparse.
|
||||||
|
- Added a patch against 2.0.7 for long file names support. I did not
|
||||||
|
apply this change to the 1.2-module. Please upgrade to 2.0.7 if you
|
||||||
|
want to use long file names.
|
||||||
|
- nwbpvalues can print ITEM properties
|
||||||
|
|
||||||
|
ncpfs-2.0.0 -> ncpfs-2.0.1
|
||||||
|
- Added some values to ipxparse.
|
||||||
|
- Added the little bindery utilities. Maybe someone has the time to
|
||||||
|
write a shellscript named 'nwadduser' ?
|
||||||
|
- Fixed a bug that made the __255 message reappear. Many thanks to
|
||||||
|
Guntram Blom for his detailed bug report.
|
||||||
|
- Fixed a bug that made ncpfs incompatible with W95's server
|
||||||
|
capabilities. Thanks to Tomasz Babczynski
|
||||||
|
<faster@dino.ict.pwr.wroc.pl> for this one.
|
||||||
|
|
||||||
|
ncpfs-0.24 -> ncpfs-2.0.0
|
||||||
|
- Changed the numbering scheme :-).
|
||||||
|
- Added npasswd. Many thanks to Guntram Blom for his work!
|
||||||
|
- Hopefully improved error messages a bit
|
||||||
|
- Hopefully made slist a bit more robust
|
||||||
|
|
||||||
|
ncpfs-0.23 -> ncpfs-0.24
|
||||||
|
- Fixed a bug that made it impossible to umount a filesystem after you
|
||||||
|
tried 'mkdir .' or 'mkdir ..'.
|
||||||
|
- Fixed a bad race condition when opening files.
|
||||||
|
- Made the default timeout values more robust.
|
||||||
|
|
||||||
|
ncpfs-0.22 -> ncpfs-0.23
|
||||||
|
- Fixed a memory allocation problem in nwmsg.c. Thanks to
|
||||||
|
Andrew Ross <anr1001@hermes.cam.ac.uk>
|
||||||
|
- slist hopefully does not ask for a password anymore.
|
||||||
|
- cleaned up error messages a bit.
|
||||||
|
- ncpmount now calls modprobe instead of insmod.
|
||||||
|
|
||||||
|
ncpfs-0.21 -> ncpfs-0.22
|
||||||
|
- removed a bad race condition in kernel-1.2/src/dir.c.
|
||||||
|
- handle 0x9999-responses from the ncp server correctly.
|
||||||
|
- Bindery functions in ncplib.c by Brian G. Reid (breid@tim.com)
|
||||||
|
- set blocksize to 512 to satisfy 'du -k'
|
||||||
|
|
||||||
|
ncpfs-0.20 -> ncpfs-0.21
|
||||||
|
- Included two bugfixes in ncplib.c found by Jeff Buhrt
|
||||||
|
<buhrt@iquest.net>.
|
||||||
|
- Included a bugfix in kernel code that could only show for servers
|
||||||
|
that do not support namespace calls. I should have tried ncpfs
|
||||||
|
against lwared... Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for
|
||||||
|
this fix.
|
||||||
|
|
||||||
|
ncpfs-0.19 -> ncpfs-0.20
|
||||||
|
- Changed the home site for ncpfs from linux01.gwdg.de:/pub/ncpfs
|
||||||
|
to ftp.gwdg.de:/pub/linux/misc/ncpfs. linux01 will remain available,
|
||||||
|
but we would like to reduce the load on that machine. Sites
|
||||||
|
mirroring linux01 please redirect your mirror software to
|
||||||
|
ftp.gwdg.de. Thanks.
|
||||||
|
- Removed a bug in ncplib.c that made slist require a full
|
||||||
|
login. Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for the hint.
|
||||||
|
- The first real user contribution: ncopy by Brian G. Reid
|
||||||
|
(breid@tim.com) and Tom C. Henderson (thenderson@tim.com). Many
|
||||||
|
thanks to you! If you find bugs in ncopy, tell them, not me ;-)
|
||||||
|
- Handle expired passwords. Thanks to "Mathew Lim" <M.Lim@sp.ac.sg>
|
||||||
|
for the hint.
|
||||||
|
|
||||||
|
ncpfs-0.18 -> ncpfs-0.19
|
||||||
|
|
||||||
|
- hacked around in ncplib.[ch] quite heavily.
|
||||||
|
- SAP handling in ipxparse.c. Thanks to Jeff Buhrt <buhrt@iquest.net>
|
||||||
|
- Changed error handling to use the com_err library. This should
|
||||||
|
eventually provide better error messages, because it's now much
|
||||||
|
easier to define nice messages.
|
||||||
|
- If no server is active, report this correctly
|
||||||
|
- added nsend
|
||||||
|
|
||||||
|
ncpfs-0.17 -> ncpfs-0.18
|
||||||
|
|
||||||
|
- Another attempt at solving the problem that -n is not working.
|
||||||
|
- Forgot nprint in 0.17 util/Makefile.
|
||||||
|
- nprint left connections open when it fails
|
||||||
|
- added options -r and -t to ncpmount to tune ncpfs connections.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- Improvements of manual pages by B. Galliart <bgallia@luc.edu> and
|
||||||
|
Terry Dawson <terry@perf.no.itg.telecom.com.au>
|
||||||
|
- fsinfo
|
||||||
|
- pserver.c. Please see this as ALPHA software. There is no
|
||||||
|
documentation, and it is not tested enough. But it might be useful for
|
||||||
|
you.
|
||||||
|
|
||||||
|
ncpfs-0.12 -> ncpfs-0.13
|
||||||
|
|
||||||
|
- support for automatic loading of ncpfs.o by kerneld.
|
||||||
|
Thanks to Steven N. Hirsch <hirsch@emba.uvm.edu>.
|
||||||
|
- A subtle problem in the read routines has been removed by Uwe Bonnes
|
||||||
|
<bon@elektron.ikp.physik.th-darmstadt.de>. Thanks a lot.
|
||||||
67
FAQ
Normal file
67
FAQ
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
There is certainly not enough material to call this an FAQ, but some
|
||||||
|
questions reach me regularly. Probably the documentation is not clear
|
||||||
|
enough.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Q: The ncpfs utilities like slist or ncpmount tell me that they can
|
||||||
|
not find a server, although I'm sure there are servers on my
|
||||||
|
net. What's wrong?
|
||||||
|
|
||||||
|
You probably used
|
||||||
|
|
||||||
|
ipx_configure --auto_interface=on --auto_primary=on
|
||||||
|
|
||||||
|
and you have Windows (95?) workstations on your network. Windows 95
|
||||||
|
makes Linux configure IPX interfaces for non-existent frame types. To
|
||||||
|
solve this problem, you have to configure your IPX interface manually
|
||||||
|
with the command
|
||||||
|
|
||||||
|
ipx_interface add -p <device> <frame>
|
||||||
|
|
||||||
|
For <device> use eth0, eth1 or whatever you network adapter is
|
||||||
|
called. The value for <frame> must match the frame type used on your
|
||||||
|
network. Possible values are 802.2, 802.3, SNAP and EtherII.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Q: I have difficulties with NetWare 4.1. What can I do?
|
||||||
|
|
||||||
|
To be honest, I do not really know. Currently my only test equipment
|
||||||
|
is a NetWare 3.11 server. You should make your 4.1 Server as
|
||||||
|
3.x-compatible as it can be. As I do not know 4.1, you are on your own
|
||||||
|
doing this.
|
||||||
|
|
||||||
|
A promising hint that has already helped some people is to switch off
|
||||||
|
packet signatures on the 4.1 server, as ncpfs does not support them.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Q: When I re-export ncpfs-mounted directories via nfs, I get messages like
|
||||||
|
'pwd: cannot get current directory', and other strange things happen to
|
||||||
|
the nfs clients. What's wrong?
|
||||||
|
|
||||||
|
When you want to export a directory via NFS, you have to do two things:
|
||||||
|
|
||||||
|
- You have to invoke mountd and nfsd with the option --re-export. On my
|
||||||
|
computer, both are invoked at system startup from the file
|
||||||
|
/etc/rc.d/rc.inet2.
|
||||||
|
|
||||||
|
- You can not export a complete NetWare server hierarchy with all volumes
|
||||||
|
under a single mount point. You have to mount a single server volume to
|
||||||
|
make it re-exportable. Invoke ncpmount with the option -V volume to do
|
||||||
|
this.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Q: When I compile ncpfs, I get a message like the following:
|
||||||
|
|
||||||
|
make[1]: Entering directory `/home/me/netware/ncpfs/kernel-1.2/src'
|
||||||
|
gcc -D__KERNEL__ -I. -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer -I/home/me/netware/ncpfs/kernel-1.2 -DNCPFS_VERSION=\"0.17\" -c dir.c
|
||||||
|
dir.c:36: warning: `struct dirent' declared inside parameter list
|
||||||
|
dir.c:36: warning: its scope is only this definition or declaration,
|
||||||
|
...
|
||||||
|
|
||||||
|
You try to compile the part of ncpfs that is meant for kernel 1.2.13 under
|
||||||
|
kernel 1.3.x. Please look at the Makefile and comment out the
|
||||||
|
corresponding lines.
|
||||||
86
Makefile
86
Makefile
@@ -2,37 +2,69 @@
|
|||||||
# Makefile for the linux ncp-filesystem routines.
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
#
|
#
|
||||||
|
|
||||||
KERNEL = 1.3
|
VERSION = 2.0.7
|
||||||
|
|
||||||
INCLUDES = -I/usr/src/linux/include -Ikernel
|
# If you are using kerneld to autoload ncp support,
|
||||||
BINDIR = ./bin
|
# uncomment this (kerneld is in linux since about 1.3.57):
|
||||||
|
#KERNELD = -DHAVE_KERNELD
|
||||||
|
|
||||||
CFLAGS = -Wall $(INCLUDES)
|
# If your system is ELF, either also do a 'make install', or append the util/
|
||||||
CC = gcc
|
# directory where the dynamic library resides to the environment
|
||||||
|
# variable LD_LIBRARY_PATH
|
||||||
|
HAVE_ELF=$(shell file `whereis gcc|cut -d ' ' -f 2`| \
|
||||||
|
grep ELF >/dev/null && echo -n yes )
|
||||||
|
|
||||||
all: kernel
|
TOPDIR = $(shell pwd)
|
||||||
make -C util
|
BINDIR = /usr/bin
|
||||||
make -C kernel/src ncpfs.o
|
SBINDIR = /sbin
|
||||||
cp kernel/src/ncpfs.o bin
|
SUBDIRS = lib sutil util ipx-1.0 man
|
||||||
|
|
||||||
kernel:
|
KVERSION=$(shell uname -r | cut -b1-3)
|
||||||
rm -f kernel
|
|
||||||
ln -s kernel-$(KERNEL) kernel
|
INCLUDES=-I$(TOPDIR)/include
|
||||||
|
|
||||||
|
ifeq ($(KVERSION),1.2)
|
||||||
|
SUBDIRS += kernel-1.2/src
|
||||||
|
INCLUDES += -I$(TOPDIR)/kernel-1.2
|
||||||
|
endif
|
||||||
|
|
||||||
|
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -DNCPFS_VERSION=\"$(VERSION)\"
|
||||||
|
|
||||||
|
#CFLAGS += -g
|
||||||
|
CFLAGS += -O2
|
||||||
|
|
||||||
|
export INCLUDES BINDIR SBINDIR KERNELD VERSION HAVE_ELF CFLAGS
|
||||||
|
|
||||||
|
all:
|
||||||
|
for i in $(SUBDIRS); do make -C $$i all; done
|
||||||
|
@if [ "$(HAVE_ELF)" = yes ] ;\
|
||||||
|
then \
|
||||||
|
echo ; echo ; echo ;\
|
||||||
|
echo Please add \'`pwd`/lib\' to the environment ; \
|
||||||
|
echo variable LD_LIBRARY_PATH by executing ; \
|
||||||
|
echo ;\
|
||||||
|
echo export LD_LIBRARY_PATH=\"\$$LD_LIBRARY_PATH:`pwd`/lib\" ; \
|
||||||
|
echo ;\
|
||||||
|
echo or do a \'make install\'. ;\
|
||||||
|
echo ;\
|
||||||
|
fi
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
for i in $(SUBDIRS); do make -C $$i dep; done
|
||||||
|
|
||||||
clean:
|
install:
|
||||||
rm -f kernel
|
for i in $(SUBDIRS); do make -C $$i install; done
|
||||||
rm -f `find . -type f -name '*.o' -print`
|
|
||||||
rm -f `find . -type f -name '*~' -print`
|
|
||||||
rm -f `find . -type f -name '.depend' -print`
|
|
||||||
rm -f `find . -type f -name '*.out' -print`
|
|
||||||
|
|
||||||
|
clean_me:
|
||||||
|
rm -f `find -name '*.out'`
|
||||||
|
rm -f `find -name '*~'`
|
||||||
|
rm -f ncpfs.tgz
|
||||||
|
|
||||||
realclean: clean
|
clean: clean_me
|
||||||
rm -fr bin/* ncpfs.tgz util/mnt
|
for i in $(SUBDIRS); do make -C $$i clean; done
|
||||||
make -C util realclean
|
|
||||||
|
mrproper: clean_me
|
||||||
|
for i in $(SUBDIRS) ipxdump; do make -C $$i mrproper; done
|
||||||
|
|
||||||
modules: ncpfs.o
|
modules: ncpfs.o
|
||||||
|
|
||||||
@@ -40,7 +72,15 @@ SRCPATH=$(shell pwd)
|
|||||||
SRCDIR=$(shell basename $(SRCPATH))
|
SRCDIR=$(shell basename $(SRCPATH))
|
||||||
DISTFILE=$(SRCDIR).tgz
|
DISTFILE=$(SRCDIR).tgz
|
||||||
|
|
||||||
dist: realclean
|
dist: mrproper
|
||||||
|
(cd ..; \
|
||||||
|
tar cvf - $(SRCDIR) | \
|
||||||
|
gzip -9 > $(DISTFILE); \
|
||||||
|
mv $(DISTFILE) $(SRCDIR))
|
||||||
|
make dep
|
||||||
|
make all
|
||||||
|
|
||||||
|
tgz: mrproper
|
||||||
(cd ..; \
|
(cd ..; \
|
||||||
tar cvf - $(SRCDIR) | \
|
tar cvf - $(SRCDIR) | \
|
||||||
gzip -9 > $(DISTFILE); \
|
gzip -9 > $(DISTFILE); \
|
||||||
|
|||||||
129
README
129
README
@@ -1,11 +1,83 @@
|
|||||||
This is version 0.6 of ncpfs, a free NetWare client for Linux. You
|
This is ncpfs, a free NetWare client filesystem for Linux. Besides
|
||||||
need at least kernel 1.3.44 for this version. It does NOT work with
|
some little utilities it also contains nprint, which enables you to
|
||||||
any lower one, especially not with version 1.2.x.
|
print on NetWare print queues. The opposite side, pserver, is also
|
||||||
|
provided.
|
||||||
|
|
||||||
To install ncpfs, just type 'make'. After that, you find the
|
ncpfs works with NetWare versions 3.x and following. It does NOT work
|
||||||
neccessary kernel module and the mounting tools in ./bin. Type 'insmod
|
with NetWare version 2.x. Some of the NetWare look-alikes, such as
|
||||||
ncpfs.o' and then 'ncpmount server mount-point'. For further
|
CD-ROM servers WinNT 3.51 Server are also NOT supported. This
|
||||||
information, please look at the manual pages in ./man.
|
restriction comes from the fact that ncpfs relies heavily on the name
|
||||||
|
space facilities NetWare supports since version 3. When you want to
|
||||||
|
mount volumes that have been exported by mars_nwe, you have to
|
||||||
|
activate the name space calls in mars_nwe's config.h file, although
|
||||||
|
probably it's more clever to use nfs between two Linux machines.
|
||||||
|
|
||||||
|
The user-space utilities such as nprint and the bindery utils should
|
||||||
|
work with all versions of NetWare.
|
||||||
|
|
||||||
|
ncpfs does NOT support access to the NDS, so if you want to mount
|
||||||
|
volumes exported by a NetWare 4.x server, you will have to install the
|
||||||
|
bindery emulation on that server. If you need access to the NDS, ask
|
||||||
|
Caldera for their CND. See http://www.caldera.com for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
|
||||||
|
INSTALLATION
|
||||||
|
|
||||||
|
Before you start the installation, make sure that your kernel has IPX
|
||||||
|
support compiled in. When 'make config' asks you for
|
||||||
|
|
||||||
|
The IPX protocol (CONFIG_IPX) [N/y/m/?]
|
||||||
|
|
||||||
|
simply answer 'y'. Probably you do not need the full internal net that
|
||||||
|
you are asked for next.
|
||||||
|
|
||||||
|
The installation of ncpfs depends on the kernel version you are
|
||||||
|
using. For kernel 1.2, you should simply type 'make' and look at
|
||||||
|
what's in the bin/ directory after that. Please be sure that your
|
||||||
|
kernel resides in /usr/src/linux, because the file
|
||||||
|
kernel-1.2/src/sock.c has to refer directly to it.
|
||||||
|
|
||||||
|
If you use Kernel 1.3, please be sure that you use at least
|
||||||
|
1.3.71. ncpfs does NOT work with any earlier 1.3.x kernel.
|
||||||
|
|
||||||
|
If you use Kernel 1.3.71 or later, you might have to recompile your
|
||||||
|
kernel. With these kernels, the kernel part of ncpfs is already
|
||||||
|
included in the main source tree. If you want to use ncpfs, you should
|
||||||
|
say 'y' to 'make config' when you are asked for IPX, and again when it
|
||||||
|
asks for ncpfs. After you have rebooted with the new kernel, 'cat
|
||||||
|
/proc/filesystems' should show you a line saying that the kernel knows
|
||||||
|
ncpfs.
|
||||||
|
|
||||||
|
If you are running kerneld, please uncomment the corresponding line in
|
||||||
|
the Makefile to reflect this.
|
||||||
|
|
||||||
|
If your system is ELF, please enable the use of the shared ncp-library
|
||||||
|
in the Makefile. This will save at least 1MB of disk space.
|
||||||
|
|
||||||
|
After you adapted your Makefile, type 'make' and, as root, 'make install'.
|
||||||
|
|
||||||
|
|
||||||
|
HELP
|
||||||
|
|
||||||
|
In the meantime my mail volume has grown considerably, so the response
|
||||||
|
time might be better at the LinWare mailing list than at my personal
|
||||||
|
email address. You can mail to and/or subscribe to the LinWare mailing
|
||||||
|
list:
|
||||||
|
|
||||||
|
Topics for the list:
|
||||||
|
- discussing LinWare server, its features, installation problems and bugs
|
||||||
|
- using IPX protocol under Linux
|
||||||
|
- IPX routing and router daemons under Linux
|
||||||
|
- mars_nwe
|
||||||
|
- ncpfs
|
||||||
|
|
||||||
|
You can subscribe to the list by sending the command "add linware" in
|
||||||
|
the mail message body to address: "listserv@sh.cvut.cz". Your
|
||||||
|
postings should be sent to: "linware@sh.cvut.cz".
|
||||||
|
|
||||||
|
|
||||||
|
USING NCPFS
|
||||||
|
|
||||||
Please note that your IPX system has to be configured correctly. If
|
Please note that your IPX system has to be configured correctly. If
|
||||||
you want to take the 'Plug-and-Play' route, you can simply say
|
you want to take the 'Plug-and-Play' route, you can simply say
|
||||||
@@ -19,8 +91,8 @@ hand, note that there has to be a route to the internal network of
|
|||||||
your server. Please see the file util/start_ipx for an example.
|
your server. Please see the file util/start_ipx for an example.
|
||||||
|
|
||||||
I use tools written by Greg Page, Caldera. I hope I did not do too
|
I use tools written by Greg Page, Caldera. I hope I did not do too
|
||||||
much harm to their business. For your convenience I included the file
|
much harm to their business. For your convenience I included the
|
||||||
ipx.tar made available by Caldera.
|
contents of the file ipx.tar made available by Caldera.
|
||||||
|
|
||||||
My main source of information is a book written in german by Manfred
|
My main source of information is a book written in german by Manfred
|
||||||
Hill and Ralf Zessin, "Netzwerkprogrammierung in C", IWT Verlag GmbH,
|
Hill and Ralf Zessin, "Netzwerkprogrammierung in C", IWT Verlag GmbH,
|
||||||
@@ -30,7 +102,7 @@ programming. If you know about the concepts and possibilities of NCP,
|
|||||||
Ralph Brown's interrupt list becomes much more readable. It's much
|
Ralph Brown's interrupt list becomes much more readable. It's much
|
||||||
easier to find undocumented information if you know what to look for!
|
easier to find undocumented information if you know what to look for!
|
||||||
|
|
||||||
For the curious: the file ncplib_user.[ch] is a library that makes it
|
For the curious: the files ncplib.[ch] are a library that makes it
|
||||||
possible to send NCP requests to the server over a mounted
|
possible to send NCP requests to the server over a mounted
|
||||||
directory. I use it to keep the encryption stuff out of the kernel by
|
directory. I use it to keep the encryption stuff out of the kernel by
|
||||||
logging in from user space. Look at the file ncptest.c for other
|
logging in from user space. Look at the file ncptest.c for other
|
||||||
@@ -40,6 +112,23 @@ free NetWare API for Linux! I would be happy to receive your comments
|
|||||||
on this.
|
on this.
|
||||||
|
|
||||||
|
|
||||||
|
THANKS
|
||||||
|
|
||||||
|
I do not want to leave those unmentioned, who have helped me with
|
||||||
|
ncpfs.
|
||||||
|
|
||||||
|
The most enthusiastic user and tester is certainly Uwe Bonnes
|
||||||
|
<bon@elektron.ikp.physik.th-darmstadt.de>. So far he's the only one
|
||||||
|
who has contributed something, namely manpages and corretions to
|
||||||
|
existing manpages.
|
||||||
|
|
||||||
|
Ales Dyrak has written lwared, which was the initial start for ncpfs.
|
||||||
|
|
||||||
|
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 :-)
|
||||||
|
|
||||||
The limitations ncpfs has are the natural limitations of the NCP
|
The limitations ncpfs has are the natural limitations of the NCP
|
||||||
@@ -48,16 +137,10 @@ 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
|
Have fun with ncpfs!
|
||||||
servers. NCP does not have unique numbers per file, you only have the
|
|
||||||
path name. I implemented a caching scheme for inode numbers, which
|
Volker
|
||||||
gives unique inode numbers for every open file in the system. This is
|
lendecke@namu01.gwdg.de
|
||||||
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.
|
|
||||||
|
|||||||
12
TODO
Normal file
12
TODO
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Here's a list of things I want to do. Feel free to send suggestions,
|
||||||
|
or even help me ;-).
|
||||||
|
|
||||||
|
- do rtt estimation, like tcp does.
|
||||||
|
|
||||||
|
- Do better connection management. I imagine to create a ncpd.
|
||||||
|
|
||||||
|
- When ncpd is done, one can think about mounting several volumes over
|
||||||
|
a single NCP connection. This should make the trade-off mentioned in
|
||||||
|
ncpmount.8 unnecessary.
|
||||||
|
|
||||||
|
- Do some kind of mapping of NCP uid's to unix uid's
|
||||||
24
bin/nwbpsecurity
Executable file
24
bin/nwbpsecurity
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
SECURITY=`nwbpvalues $* -c | head -3 | tail -1`
|
||||||
|
WRITE=`echo $SECURITY | cut -b1`
|
||||||
|
READ=`echo $SECURITY | cut -b2`
|
||||||
|
|
||||||
|
function print_sec () {
|
||||||
|
case "$1" in
|
||||||
|
0 ) echo "Everyone"
|
||||||
|
;;
|
||||||
|
1 ) echo "Logged in"
|
||||||
|
;;
|
||||||
|
2 ) echo "Object"
|
||||||
|
;;
|
||||||
|
3 ) echo "Supervisor"
|
||||||
|
;;
|
||||||
|
* ) echo "Bindery"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
echo -n "Write security: "
|
||||||
|
print_sec $WRITE
|
||||||
|
echo -n "Read security : "
|
||||||
|
print_sec $READ
|
||||||
@@ -3,6 +3,5 @@
|
|||||||
# abcd is my ipx network number and 1234 my server's internal network number.
|
# abcd is my ipx network number and 1234 my server's internal network number.
|
||||||
# 00001b038b11 is the server's node number.
|
# 00001b038b11 is the server's node number.
|
||||||
#
|
#
|
||||||
ipx_interface add -p eth0 EtherII 10
|
ipx_interface add -p eth0 EtherII 1234
|
||||||
ipx_route add 1992 10 00001b3bc0c9
|
ipx_route add 10 1234 00001b039949
|
||||||
ipx_route add 1234 10 00001b038b11
|
|
||||||
40
include/com_err.h
Normal file
40
include/com_err.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Header file for common error description library.
|
||||||
|
*
|
||||||
|
* Copyright 1988, Student Information Processing Board of the
|
||||||
|
* Massachusetts Institute of Technology.
|
||||||
|
*
|
||||||
|
* For copyright and distribution info, see the documentation supplied
|
||||||
|
* with this package.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COM_ERR_H
|
||||||
|
|
||||||
|
typedef long errcode_t;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* ANSI C -- use prototypes etc */
|
||||||
|
void com_err (const char *, long, const char *, ...);
|
||||||
|
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||||
|
va_list args);
|
||||||
|
char const *error_message (long);
|
||||||
|
extern void (*com_err_hook) (const char *, long, const char *, va_list);
|
||||||
|
void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
|
||||||
|
(const char *, long, const char *, va_list);
|
||||||
|
void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
|
||||||
|
int init_error_table(const char * const *msgs, int base, int count);
|
||||||
|
#else
|
||||||
|
/* no prototypes */
|
||||||
|
void com_err ();
|
||||||
|
void com_err_va ();
|
||||||
|
char *error_message ();
|
||||||
|
extern void (*com_err_hook) ();
|
||||||
|
void (*set_com_err_hook ()) ();
|
||||||
|
void (*reset_com_err_hook ()) ();
|
||||||
|
int init_error_table();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __COM_ERR_H
|
||||||
|
#endif /* ! defined(__COM_ERR_H) */
|
||||||
93
include/ipxlib.h
Normal file
93
include/ipxlib.h
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* ipxlib.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IPXLIB_H
|
||||||
|
#define _IPXLIB_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/ncp.h>
|
||||||
|
#include <linux/ncp_fs.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef unsigned long IPXNet;
|
||||||
|
typedef unsigned short IPXPort;
|
||||||
|
typedef unsigned char IPXNode[IPX_NODE_LEN];
|
||||||
|
|
||||||
|
#define IPX_USER_PTYPE (0x00)
|
||||||
|
#define IPX_RIP_PTYPE (0x01)
|
||||||
|
#define IPX_SAP_PTYPE (0x04)
|
||||||
|
#define IPX_AUTO_PORT (0x0000)
|
||||||
|
#define IPX_SAP_PORT (0x0452)
|
||||||
|
#define IPX_RIP_PORT (0x0453)
|
||||||
|
|
||||||
|
#define IPX_SAP_GENERAL_QUERY (0x0001)
|
||||||
|
#define IPX_SAP_GENERAL_RESPONSE (0x0002)
|
||||||
|
#define IPX_SAP_NEAREST_QUERY (0x0003)
|
||||||
|
#define IPX_SAP_NEAREST_RESPONSE (0x0004)
|
||||||
|
|
||||||
|
#define IPX_SAP_FILE_SERVER (0x0004)
|
||||||
|
|
||||||
|
struct sap_query {
|
||||||
|
unsigned short query_type; /* net order */
|
||||||
|
unsigned short server_type; /* net order */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sap_server_ident {
|
||||||
|
unsigned short server_type __attribute__ ((packed));
|
||||||
|
char server_name[48] __attribute__ ((packed));
|
||||||
|
IPXNet server_network __attribute__ ((packed));
|
||||||
|
IPXNode server_node __attribute__ ((packed));
|
||||||
|
IPXPort server_port __attribute__ ((packed));
|
||||||
|
unsigned short intermediate_network __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IPX_RIP_REQUEST (0x1)
|
||||||
|
#define IPX_RIP_RESPONSE (0x2)
|
||||||
|
|
||||||
|
struct ipx_rip_packet {
|
||||||
|
__u16 operation __attribute__ ((packed));
|
||||||
|
struct ipx_rt_def {
|
||||||
|
__u32 network __attribute__ ((packed));
|
||||||
|
__u16 hops __attribute__ ((packed));
|
||||||
|
__u16 ticks __attribute__ ((packed));
|
||||||
|
} rt[1] __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IPX_BROADCAST_NODE ("\xff\xff\xff\xff\xff\xff")
|
||||||
|
#define IPX_THIS_NODE ("\0\0\0\0\0\0")
|
||||||
|
#define IPX_THIS_NET (0)
|
||||||
|
|
||||||
|
#ifndef IPX_NODE_LEN
|
||||||
|
#define IPX_NODE_LEN (6)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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, unsigned char node[IPX_NODE_LEN]);
|
||||||
|
void
|
||||||
|
ipx_assign_node(IPXNode dest, IPXNode src);
|
||||||
|
int
|
||||||
|
ipx_node_equal(IPXNode n1,IPXNode n2);
|
||||||
|
|
||||||
|
#endif /* _IPXLIB_H */
|
||||||
573
include/ncplib.h
Normal file
573
include/ncplib.h
Normal file
@@ -0,0 +1,573 @@
|
|||||||
|
/*
|
||||||
|
* ncplib.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995, 1996 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NCPLIB_H
|
||||||
|
#define _NCPLIB_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/ncp.h>
|
||||||
|
#include <linux/ncp_fs.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "ipxlib.h"
|
||||||
|
#include "com_err.h"
|
||||||
|
|
||||||
|
#ifndef memzero
|
||||||
|
#include <string.h>
|
||||||
|
#define memzero(object) memset(&(object), 0, sizeof(object))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
str_upper(char *name);
|
||||||
|
|
||||||
|
enum connect_state {
|
||||||
|
NOT_CONNECTED = 0,
|
||||||
|
CONN_PERMANENT,
|
||||||
|
CONN_TEMPORARY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ncp_conn {
|
||||||
|
|
||||||
|
enum connect_state is_connected;
|
||||||
|
|
||||||
|
char server[NCP_BINDERY_NAME_LEN];
|
||||||
|
char user [NCP_BINDERY_NAME_LEN];
|
||||||
|
|
||||||
|
struct ncp_fs_info i;
|
||||||
|
|
||||||
|
/* Fields for use with permanent connections */
|
||||||
|
int mount_fid;
|
||||||
|
char mount_point[MAXPATHLEN];
|
||||||
|
|
||||||
|
/* Fields for use with temporary connections */
|
||||||
|
int ncp_sock;
|
||||||
|
int wdog_sock;
|
||||||
|
int wdog_pid;
|
||||||
|
__u8 sequence;
|
||||||
|
int completion;
|
||||||
|
int conn_status;
|
||||||
|
int reply_size;
|
||||||
|
|
||||||
|
/* Fields used to setup ncp requests */
|
||||||
|
int current_size;
|
||||||
|
int has_subfunction;
|
||||||
|
int verbose;
|
||||||
|
int ncp_reply_size;
|
||||||
|
|
||||||
|
int lock;
|
||||||
|
|
||||||
|
char packet[NCP_PACKET_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ncp_conn_spec {
|
||||||
|
char server[NCP_BINDERY_NAME_LEN];
|
||||||
|
char user[NCP_BINDERY_NAME_LEN];
|
||||||
|
uid_t uid;
|
||||||
|
int login_type; /* NCP_BINDERY_USER / NCP_BINDERY_PSERVER */
|
||||||
|
char password[NCP_BINDERY_NAME_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ncp_search_seq {
|
||||||
|
struct nw_search_sequence s;
|
||||||
|
int namespace;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ncp_property_info {
|
||||||
|
__u8 property_name[16];
|
||||||
|
__u8 property_flags;
|
||||||
|
__u8 property_security;
|
||||||
|
__u32 search_instance;
|
||||||
|
__u8 value_available_flag;
|
||||||
|
__u8 more_properties_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ncp_initialize is the main entry point for user programs which want
|
||||||
|
to connect to a NetWare Server. It looks for -S, -U, -P and -n in
|
||||||
|
the argument list, opens the connection and removes the arguments
|
||||||
|
from the list. It was designed after the X Windows init
|
||||||
|
functions. */
|
||||||
|
struct ncp_conn *
|
||||||
|
ncp_initialize(int *argc, char **argv,
|
||||||
|
int login_necessary, long *err);
|
||||||
|
|
||||||
|
/* You can login as another object by this procedure. As a first use
|
||||||
|
pserver comes to mind. */
|
||||||
|
struct ncp_conn *
|
||||||
|
ncp_initialize_as(int *argc, char **argv,
|
||||||
|
int login_necessary, int login_type, long *err);
|
||||||
|
|
||||||
|
|
||||||
|
/* Open a connection */
|
||||||
|
struct ncp_conn *
|
||||||
|
ncp_open(const struct ncp_conn_spec *spec, long *err);
|
||||||
|
|
||||||
|
/* Open a connection on an existing mount point */
|
||||||
|
struct ncp_conn *
|
||||||
|
ncp_open_mount(const char *mount_point, long *err);
|
||||||
|
|
||||||
|
/* Find a permanent connection that fits the spec, return NULL if
|
||||||
|
* there is none. */
|
||||||
|
char *
|
||||||
|
ncp_find_permanent(const struct ncp_conn_spec *spec);
|
||||||
|
|
||||||
|
/* Find the address of a file server */
|
||||||
|
struct sockaddr_ipx *
|
||||||
|
ncp_find_fileserver(const char *server_name, long *err);
|
||||||
|
|
||||||
|
/* Find the address of a server */
|
||||||
|
struct sockaddr_ipx *
|
||||||
|
ncp_find_server(const char **server_name, int type, long *err);
|
||||||
|
|
||||||
|
/* Detach from a permanent connection or destroy a temporary
|
||||||
|
connection */
|
||||||
|
long
|
||||||
|
ncp_close(struct ncp_conn *conn);
|
||||||
|
|
||||||
|
/* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable
|
||||||
|
connections */
|
||||||
|
|
||||||
|
struct ncp_conn_ent {
|
||||||
|
char server[NCP_BINDERY_NAME_LEN];
|
||||||
|
char user[NCP_BINDERY_NAME_LEN];
|
||||||
|
uid_t uid;
|
||||||
|
char mount_point[MAXPATHLEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ncp_conn_ent *
|
||||||
|
ncp_get_conn_ent(FILE *filep);
|
||||||
|
|
||||||
|
#define NWCLIENT (".nwclient")
|
||||||
|
#define NWC_NOPASSWORD ("-")
|
||||||
|
|
||||||
|
/* find an appropriate connection */
|
||||||
|
|
||||||
|
struct ncp_conn_spec *
|
||||||
|
ncp_find_conn_spec(const char *server, const char *user, const char *password,
|
||||||
|
int login_necessary, uid_t uid, long *err);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_file_server_description_strings(struct ncp_conn *conn,
|
||||||
|
char target[512]);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_file_server_time(struct ncp_conn *conn, time_t *target);
|
||||||
|
|
||||||
|
struct ncp_file_server_info {
|
||||||
|
__u8 ServerName[48] __attribute__ ((packed));
|
||||||
|
__u8 FileServiceVersion __attribute__ ((packed));
|
||||||
|
__u8 FileServiceSubVersion __attribute__ ((packed));
|
||||||
|
__u16 MaximumServiceConnections __attribute__ ((packed));
|
||||||
|
__u16 ConnectionsInUse __attribute__ ((packed));
|
||||||
|
__u16 NumberMountedVolumes __attribute__ ((packed));
|
||||||
|
__u8 Revision __attribute__ ((packed));
|
||||||
|
__u8 SFTLevel __attribute__ ((packed));
|
||||||
|
__u8 TTSLevel __attribute__ ((packed));
|
||||||
|
__u16 MaxConnectionsEverUsed __attribute__ ((packed));
|
||||||
|
__u8 AccountVersion __attribute__ ((packed));
|
||||||
|
__u8 VAPVersion __attribute__ ((packed));
|
||||||
|
__u8 QueueVersion __attribute__ ((packed));
|
||||||
|
__u8 PrintVersion __attribute__ ((packed));
|
||||||
|
__u8 VirtualConsoleVersion __attribute__ ((packed));
|
||||||
|
__u8 RestrictionLevel __attribute__ ((packed));
|
||||||
|
__u8 InternetBridge __attribute__ ((packed));
|
||||||
|
__u8 Reserved[60] __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_file_server_information(struct ncp_conn *conn,
|
||||||
|
struct ncp_file_server_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_connlist(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
int *returned_no, __u8 conn_numbers[256]);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_stations_logged_info(struct ncp_conn *conn,
|
||||||
|
__u32 connection,
|
||||||
|
struct ncp_bindery_object *target,
|
||||||
|
time_t *login_time);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_internet_address(struct ncp_conn *conn,
|
||||||
|
__u32 connection,
|
||||||
|
struct sockaddr_ipx *target,
|
||||||
|
__u8 *conn_type);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_send_broadcast(struct ncp_conn *conn,
|
||||||
|
__u8 no_conn, const __u8 *connections,
|
||||||
|
const char *message);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_encryption_key(struct ncp_conn *conn,
|
||||||
|
char *target);
|
||||||
|
long
|
||||||
|
ncp_get_bindery_object_id(struct ncp_conn *conn,
|
||||||
|
__u16 object_type,
|
||||||
|
const char *object_name,
|
||||||
|
struct ncp_bindery_object *target);
|
||||||
|
long
|
||||||
|
ncp_get_bindery_object_name(struct ncp_conn *conn,
|
||||||
|
__u32 object_id,
|
||||||
|
struct ncp_bindery_object *target);
|
||||||
|
long
|
||||||
|
ncp_scan_bindery_object(struct ncp_conn *conn,
|
||||||
|
__u32 last_id, __u16 object_type, char *search_string,
|
||||||
|
struct ncp_bindery_object *target);
|
||||||
|
long
|
||||||
|
ncp_create_bindery_object(struct ncp_conn *conn,
|
||||||
|
__u16 object_type,
|
||||||
|
const char *object_name,
|
||||||
|
__u8 object_security,
|
||||||
|
__u8 object_status);
|
||||||
|
long
|
||||||
|
ncp_delete_bindery_object(struct ncp_conn *conn,
|
||||||
|
__u16 object_type,
|
||||||
|
const char *object_name);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_change_object_security(struct ncp_conn *conn,
|
||||||
|
__u16 object_type,
|
||||||
|
const char *object_name,
|
||||||
|
__u8 security);
|
||||||
|
|
||||||
|
struct ncp_station_addr {
|
||||||
|
__u32 NetWork __attribute__ ((packed));
|
||||||
|
__u8 Node[6] __attribute__ ((packed));
|
||||||
|
__u16 Socket __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ncp_prop_login_control {
|
||||||
|
__u8 AccountExpireDate[3] __attribute__ ((packed));
|
||||||
|
__u8 Disabled __attribute__ ((packed));
|
||||||
|
__u8 PasswordExpireDate[3] __attribute__ ((packed));
|
||||||
|
__u8 GraceLogins __attribute__ ((packed));
|
||||||
|
__u16 PasswordExpireInterval __attribute__ ((packed));
|
||||||
|
__u8 MaxGraceLogins __attribute__ ((packed));
|
||||||
|
__u8 MinPasswordLength __attribute__ ((packed));
|
||||||
|
__u16 MaxConnections __attribute__ ((packed));
|
||||||
|
__u8 ConnectionTimeMask[42] __attribute__ ((packed));
|
||||||
|
__u8 LastLogin[6] __attribute__ ((packed));
|
||||||
|
__u8 RestrictionMask __attribute__ ((packed));
|
||||||
|
__u8 reserved __attribute__ ((packed));
|
||||||
|
__u32 MaxDiskUsage __attribute__ ((packed));
|
||||||
|
__u16 BadLoginCount __attribute__ ((packed));
|
||||||
|
__u32 BadLoginCountDown __attribute__ ((packed));
|
||||||
|
struct ncp_station_addr LastIntruder __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_read_property_value(struct ncp_conn *conn,
|
||||||
|
int object_type, const char *object_name,
|
||||||
|
int segment, const char *prop_name,
|
||||||
|
struct nw_property *target);
|
||||||
|
long
|
||||||
|
ncp_scan_property(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
__u32 last_id, char *search_string,
|
||||||
|
struct ncp_property_info *property_info);
|
||||||
|
long
|
||||||
|
ncp_add_object_to_set(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const char *property_name,
|
||||||
|
__u16 member_type,
|
||||||
|
const char *member_name);
|
||||||
|
long
|
||||||
|
ncp_change_property_security(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const char *property_name,
|
||||||
|
__u8 property_security);
|
||||||
|
long
|
||||||
|
ncp_create_property(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const char *property_name,
|
||||||
|
__u8 property_flags, __u8 property_security);
|
||||||
|
long
|
||||||
|
ncp_delete_object_from_set(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const char *property_name,
|
||||||
|
__u16 member_type,
|
||||||
|
const char *member_name);
|
||||||
|
long
|
||||||
|
ncp_delete_property(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const char *property_name);
|
||||||
|
long
|
||||||
|
ncp_write_property_value(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const char *property_name,
|
||||||
|
__u8 segment,
|
||||||
|
struct nw_property *property_value);
|
||||||
|
|
||||||
|
/* Bit masks for security flag */
|
||||||
|
#define NCP_SEC_CHECKSUMMING_REQUESTED (1)
|
||||||
|
#define NCP_SEC_SIGNATURE_REQUESTED (2)
|
||||||
|
#define NCP_SEC_COMPLETE_SIGNATURES_REQUESTED (4)
|
||||||
|
#define NCP_SEC_ENCRYPTION_REQUESTED (8)
|
||||||
|
#define NCP_SEC_LIP_DISABLED (128)
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_big_ncp_max_packet_size(struct ncp_conn *conn,
|
||||||
|
__u16 proposed_max_size,
|
||||||
|
__u8 proposed_security_flag,
|
||||||
|
__u16 *accepted_max_size,
|
||||||
|
__u16 *echo_socket,
|
||||||
|
__u8 *accepted_security_flag);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_login_encrypted(struct ncp_conn *conn,
|
||||||
|
const struct ncp_bindery_object *object,
|
||||||
|
const unsigned char *key,
|
||||||
|
const unsigned char *passwd);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_login_unencrypted(struct ncp_conn *conn,
|
||||||
|
__u16 object_type, const char *object_name,
|
||||||
|
const unsigned char *passwd);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_change_login_passwd(struct ncp_conn *conn,
|
||||||
|
const struct ncp_bindery_object *object,
|
||||||
|
const unsigned char *key,
|
||||||
|
const unsigned char *oldpasswd,
|
||||||
|
const unsigned char *newpasswd);
|
||||||
|
|
||||||
|
#define NCP_GRACE_PERIOD (0xdf)
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_login_user(struct ncp_conn *conn,
|
||||||
|
const unsigned char *username,
|
||||||
|
const unsigned char *password);
|
||||||
|
long
|
||||||
|
ncp_get_volume_info_with_number(struct ncp_conn *conn, int n,
|
||||||
|
struct ncp_volume_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_volume_number(struct ncp_conn *conn, const char *name,
|
||||||
|
int *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_file_search_init(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
struct ncp_filesearch_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_file_search_continue(struct ncp_conn *conn,
|
||||||
|
struct ncp_filesearch_info *fsinfo,
|
||||||
|
int attributes, const char *path,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_finfo(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path, const char *name,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_open_file(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr, int access,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
long
|
||||||
|
ncp_close_file(struct ncp_conn *conn, const char *file_id);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_create_newfile(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_create_file(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_erase_file(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_rename_file(struct ncp_conn *conn,
|
||||||
|
int old_handle, const char *old_path,
|
||||||
|
int attr,
|
||||||
|
int new_handle, const char *new_path);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_create_directory(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int inherit_mask);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_delete_directory(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_rename_directory(struct ncp_conn *conn,
|
||||||
|
int dir_handle,
|
||||||
|
const char *old_path, const char *new_path);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_add_trustee(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
__u32 object_id, __u8 rights);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_delete_trustee(struct ncp_conn *conn,
|
||||||
|
int dir_handle, const char *path, __u32 object_id);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_read(struct ncp_conn *conn, const char *file_id,
|
||||||
|
off_t offset, size_t count, char *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_write(struct ncp_conn *conn, const char *file_id,
|
||||||
|
off_t offset, size_t count, const char *source);
|
||||||
|
|
||||||
|
long
|
||||||
|
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);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_obtain_file_or_subdir_info(struct ncp_conn *conn,
|
||||||
|
__u8 source_ns, __u8 target_ns,
|
||||||
|
__u16 search_attribs, __u32 rim,
|
||||||
|
__u8 vol, __u32 dirent, const char *path,
|
||||||
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
|
#define NCP_PERM_READ (0x001)
|
||||||
|
#define NCP_PERM_WRITE (0x002)
|
||||||
|
#define NCP_PERM_OPEN (0x004)
|
||||||
|
#define NCP_PERM_CREATE (0x008)
|
||||||
|
#define NCP_PERM_DELETE (0x010)
|
||||||
|
#define NCP_PERM_OWNER (0x020)
|
||||||
|
#define NCP_PERM_SEARCH (0x040)
|
||||||
|
#define NCP_PERM_MODIFY (0x080)
|
||||||
|
#define NCP_PERM_SUPER (0x100)
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_eff_directory_rights(struct ncp_conn *conn,
|
||||||
|
__u8 source_ns, __u8 target_ns,
|
||||||
|
__u16 search_attribs,
|
||||||
|
__u8 vol, __u32 dirent, const char *path,
|
||||||
|
__u16 *my_effective_rights);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_do_lookup(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *dir,
|
||||||
|
char *path, /* may only be one component */
|
||||||
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_modify_file_or_subdir_dos_info(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *file,
|
||||||
|
__u32 info_mask,
|
||||||
|
struct nw_modify_dos_info *info);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_del_file_or_subdir(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *dir, char *name);
|
||||||
|
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_open_create_file_or_subdir(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *dir, char *name,
|
||||||
|
int open_create_mode,
|
||||||
|
__u32 create_attributes,
|
||||||
|
int desired_acc_rights,
|
||||||
|
struct nw_file_info *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_initialize_search(struct ncp_conn *conn,
|
||||||
|
const struct nw_info_struct *dir,
|
||||||
|
int namespace,
|
||||||
|
struct ncp_search_seq *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_search_for_file_or_subdir(struct ncp_conn *conn,
|
||||||
|
struct ncp_search_seq *seq,
|
||||||
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_ren_or_mov_file_or_subdir(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *old_dir, char *old_name,
|
||||||
|
struct nw_info_struct *new_dir, char *new_name);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_create_queue_job_and_file(struct ncp_conn *conn,
|
||||||
|
__u32 queue_id,
|
||||||
|
struct queue_job *job);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_close_file_and_start_job(struct ncp_conn *conn,
|
||||||
|
__u32 queue_id,
|
||||||
|
struct queue_job *job);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_attach_to_queue(struct ncp_conn *conn,
|
||||||
|
__u32 queue_id);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_detach_from_queue(struct ncp_conn *conn,
|
||||||
|
__u32 queue_id);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type,
|
||||||
|
struct queue_job *job);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||||
|
__u32 job_number, __u32 charge_info);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||||
|
__u32 job_number);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]);
|
||||||
|
|
||||||
|
long
|
||||||
|
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)
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_alloc_short_dir_handle(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *dir,
|
||||||
|
__u16 alloc_mode,
|
||||||
|
__u8 *target);
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_get_effective_dir_rights(struct ncp_conn *conn,
|
||||||
|
struct nw_info_struct *file,
|
||||||
|
__u16 *target);
|
||||||
|
|
||||||
|
struct ncp_trustee_struct
|
||||||
|
{
|
||||||
|
__u32 object_id;
|
||||||
|
__u16 rights;
|
||||||
|
};
|
||||||
|
|
||||||
|
long
|
||||||
|
ncp_add_trustee_set(struct ncp_conn *conn,
|
||||||
|
__u8 volume_number, __u32 dir_entry,
|
||||||
|
__u16 rights_mask,
|
||||||
|
int object_count, struct ncp_trustee_struct *rights);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NCPLIB_H */
|
||||||
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.
|
||||||
|
|
||||||
19
ipx-1.0/Makefile
Normal file
19
ipx-1.0/Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
CFLAGS = -O2 -Wall
|
||||||
|
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
|
||||||
|
|
||||||
|
all: $(UTILS)
|
||||||
|
|
||||||
|
dep:
|
||||||
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
rm -f .depend
|
||||||
|
|
||||||
|
install: $(UTILS)
|
||||||
|
for i in $(UTILS); \
|
||||||
|
do \
|
||||||
|
install $$i $(BINDIR); \
|
||||||
|
done
|
||||||
65
ipx-1.0/README
Normal file
65
ipx-1.0/README
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
This file contains a very short introduction to the IPX implementation
|
||||||
|
on Linux. Feel free to forward comments (especially suggested additions)
|
||||||
|
to greg@caldera.com.
|
||||||
|
|
||||||
|
The following are important definitions in understanding the descriptions
|
||||||
|
in this README file.
|
||||||
|
|
||||||
|
IPX Interface - This is the item to which IPX sockets are bound.
|
||||||
|
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||||
|
to a physical device and frame type. A sample IPX Interface would be:
|
||||||
|
Network Number: 0x00ABCDEF
|
||||||
|
Device: Eth0
|
||||||
|
Frame Type: 802.2.
|
||||||
|
The particular interface is selected during binding by using the
|
||||||
|
Network Number (see sample code below).
|
||||||
|
|
||||||
|
Primary Interface - The interface that is selected by default when
|
||||||
|
binding a socket. This is selected when binding by using
|
||||||
|
a network number of 0 (see sample code below).
|
||||||
|
|
||||||
|
Internal Network - This is a special kind of IPX interface that does
|
||||||
|
not have a physical device or frame type. It is used to provide
|
||||||
|
a route-independent address for service providers. Internal network
|
||||||
|
numbers are optional; however, when one is present it is also the
|
||||||
|
Primary Interface.
|
||||||
|
|
||||||
|
This tar file contains the following IPX utilities:
|
||||||
|
|
||||||
|
ipx_interface.c
|
||||||
|
This program is used to create an IPX interface.
|
||||||
|
|
||||||
|
ipx_internal_net.c
|
||||||
|
This program is used to create an IPX Internal Network number.
|
||||||
|
|
||||||
|
ipx_route.c
|
||||||
|
This program creates an IPX route.
|
||||||
|
|
||||||
|
ipx_configure.c
|
||||||
|
This program is used to read/write two configuration parameters:
|
||||||
|
AUTO INTERFACE CREATE - IPX should/shouldn't automatically create
|
||||||
|
an IPX interface when it discovers one that has not been
|
||||||
|
registered via ipx_interface above.
|
||||||
|
AUTO PRIMARY SELECT - IPX should/shouldn't automatically select
|
||||||
|
a primary interface when it one an interface exists and
|
||||||
|
none are designated as the primary. Manual designation
|
||||||
|
is performed via ipx_interface.
|
||||||
|
|
||||||
|
By default, these are both turned off.
|
||||||
|
|
||||||
|
The following are sample IPX programs (found in directory Samples):
|
||||||
|
|
||||||
|
ipxrcv.c and ipxsend.c
|
||||||
|
ipxsend will send a single packet to an instance of ipxrcv running on the
|
||||||
|
same machine. It uses getsockname(2) to determine the address to which to
|
||||||
|
send the packet.
|
||||||
|
rip.c
|
||||||
|
rip passively monitors the rip traffic on the attached IPX network.
|
||||||
|
sap.c
|
||||||
|
sap passively monitors the sap traffic on the attached IPX network.
|
||||||
|
|
||||||
|
There are three files in /proc/net that relate to IPX.
|
||||||
|
ipx_interface contains the list of IPX interfaces.
|
||||||
|
ipx_route contains the list of IPX routes.
|
||||||
|
ipx contains the list of IPX sockets in use.
|
||||||
|
|
||||||
52
ipx-1.0/Samples/ipxrcv.c
Normal file
52
ipx-1.0/Samples/ipxrcv.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char msg[100];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx.sipx_family = AF_IPX;
|
||||||
|
sipx.sipx_network = 0;
|
||||||
|
sipx.sipx_port = htons(0x5000);
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
len = sizeof(sipx);
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg[0] = '\0';
|
||||||
|
result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||||
|
&len);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: recvfrom: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||||
|
htonl(sipx.sipx_network),
|
||||||
|
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||||
|
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||||
|
sipx.sipx_node[4], sipx.sipx_node[5],
|
||||||
|
htons(sipx.sipx_port));
|
||||||
|
printf("\tGot \"%s\"\n", msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
46
ipx-1.0/Samples/ipxsend.c
Normal file
46
ipx-1.0/Samples/ipxsend.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char msg[100] = "Hi Mom";
|
||||||
|
int len = sizeof(sipx);
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx.sipx_family = AF_IPX;
|
||||||
|
sipx.sipx_network = 0;
|
||||||
|
sipx.sipx_port = 0;
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = getsockname(s, (struct sockaddr *)&sipx, &len);
|
||||||
|
sipx.sipx_port = htons(0x5000);
|
||||||
|
result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||||
|
sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: send: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
68
ipx-1.0/Samples/rip.c
Normal file
68
ipx-1.0/Samples/rip.c
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
struct rip_data {
|
||||||
|
unsigned long rip_net;
|
||||||
|
unsigned short rip_hops __attribute__ ((packed));
|
||||||
|
unsigned short rip_ticks __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
int result;
|
||||||
|
int s;
|
||||||
|
char msg[1024];
|
||||||
|
int len;
|
||||||
|
char *bptr;
|
||||||
|
struct rip_data *rp;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx.sipx_family = AF_IPX;
|
||||||
|
sipx.sipx_network = 0;
|
||||||
|
sipx.sipx_port = htons(0x453);
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
len = sizeof(sipx);
|
||||||
|
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||||
|
(struct sockaddr *)&sipx, &len);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: recvfrom");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
bptr = msg;
|
||||||
|
result -= 2;
|
||||||
|
printf("RIP packet from: %08lX:%02X%02X%02X%02X%02X%02X\n",
|
||||||
|
htonl(sipx.sipx_network),
|
||||||
|
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||||
|
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||||
|
sipx.sipx_node[6], sipx.sipx_node[5]);
|
||||||
|
bptr += 2;
|
||||||
|
rp = (struct rip_data *) bptr;
|
||||||
|
while (result >= sizeof(struct rip_data)) {
|
||||||
|
printf("\tNET: %08lX HOPS: %d\n", ntohl(rp->rip_net),
|
||||||
|
ntohs(rp->rip_hops));
|
||||||
|
result -= sizeof(struct rip_data);
|
||||||
|
rp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
96
ipx-1.0/Samples/sap.c
Normal file
96
ipx-1.0/Samples/sap.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct sap_data {
|
||||||
|
unsigned short sap_type __attribute__ ((packed));
|
||||||
|
char sap_name[48] __attribute__ ((packed));
|
||||||
|
unsigned long sap_net __attribute__ ((packed));
|
||||||
|
unsigned char sap_node[6] __attribute__ ((packed));
|
||||||
|
unsigned short sap_sock __attribute__ ((packed));
|
||||||
|
unsigned short sap_hops __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
char msg[1024];
|
||||||
|
long val = 0;
|
||||||
|
int len;
|
||||||
|
char *bptr;
|
||||||
|
struct sap_data *sp;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: setsockopt: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx.sipx_family = PF_IPX;
|
||||||
|
sipx.sipx_network = 0L;
|
||||||
|
sipx.sipx_port = htons(0x452);
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
len = 1024;
|
||||||
|
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||||
|
(struct sockaddr *)&sipx, &len);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: recvfrom: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
bptr = msg;
|
||||||
|
result -= 2;
|
||||||
|
printf("SAP: OP is %x %x\n", bptr[0], bptr[1]);
|
||||||
|
printf("Length is %d\n", result);
|
||||||
|
if (bptr[1] != 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bptr += 2;
|
||||||
|
sp = (struct sap_data *) bptr;
|
||||||
|
while (result >= sizeof(struct sap_data)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sp->sap_name[32] = '\0';
|
||||||
|
for (i = 31; (i > 0) && (sp->sap_name[i] == '_'); i--);
|
||||||
|
i++;
|
||||||
|
sp->sap_name[i] = '\0';
|
||||||
|
printf("NAME: %s TYPE: %x HOPS: %x\n", sp->sap_name,
|
||||||
|
ntohs(sp->sap_type), ntohs(sp->sap_hops));
|
||||||
|
printf("%lx:%x %x %x %x %x %x: %x\n",
|
||||||
|
ntohl(sp->sap_net),
|
||||||
|
sp->sap_node[0],
|
||||||
|
sp->sap_node[1],
|
||||||
|
sp->sap_node[2],
|
||||||
|
sp->sap_node[3],
|
||||||
|
sp->sap_node[4],
|
||||||
|
sp->sap_node[5],
|
||||||
|
ntohs(sp->sap_sock));
|
||||||
|
result -= sizeof(struct sap_data);
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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>
|
||||||
@@ -7,6 +12,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
{ "auto_primary", required_argument, NULL, 1 },
|
{ "auto_primary", required_argument, NULL, 1 },
|
||||||
@@ -61,8 +67,14 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
|
int old_errno = errno;
|
||||||
sprintf(errmsg, "%s: socket", progname);
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
perror(errmsg);
|
perror(errmsg);
|
||||||
|
if (old_errno == -EINVAL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Probably you have no IPX support in "
|
||||||
|
"your kernel\n");
|
||||||
|
}
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
394
ipx-1.0/ipx_interface.c
Normal file
394
ipx-1.0/ipx_interface.c
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static struct ifreq id;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||||
|
Usage: %s del device frame_type\n\
|
||||||
|
Usage: %s delall\n\
|
||||||
|
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct frame_type {
|
||||||
|
char *ft_name;
|
||||||
|
unsigned char ft_val;
|
||||||
|
} frame_types[] = {
|
||||||
|
{"802.2", IPX_FRAME_8022},
|
||||||
|
#ifdef IPX_FRAME_TR_8022
|
||||||
|
{"802.2TR", IPX_FRAME_TR_8022},
|
||||||
|
#endif
|
||||||
|
{"802.3", IPX_FRAME_8023},
|
||||||
|
{"SNAP", IPX_FRAME_SNAP},
|
||||||
|
{"EtherII", IPX_FRAME_ETHERII}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
|
||||||
|
|
||||||
|
int
|
||||||
|
lookup_frame_type(char *frame)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; (j < NFTYPES) &&
|
||||||
|
(strcasecmp(frame_types[j].ft_name, frame));
|
||||||
|
j++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (j != NFTYPES)
|
||||||
|
return j;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: Frame type must be", progname);
|
||||||
|
for (j = 0; j < NFTYPES; j++) {
|
||||||
|
fprintf(stderr, "%s%s",
|
||||||
|
(j == NFTYPES-1) ? " or " : " ",
|
||||||
|
frame_types[j].ft_name);
|
||||||
|
}
|
||||||
|
fprintf(stderr, ".\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_add_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
int i, fti = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_type = IPX_FRAME_NONE;
|
||||||
|
while ((c = getopt(argc, argv, "p")) > 0) {
|
||||||
|
switch (c) {
|
||||||
|
case 'p': sipx->sipx_special = IPX_PRIMARY; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((i = (argc - optind)) < 2) || (i > 3)) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = optind; i < argc; i++) {
|
||||||
|
switch (i-optind) {
|
||||||
|
case 0: /* Physical Device - Required */
|
||||||
|
strcpy(id.ifr_name, argv[i]);
|
||||||
|
break;
|
||||||
|
case 1: /* Frame Type - Required */
|
||||||
|
fti = lookup_frame_type(argv[i]);
|
||||||
|
if (fti < 0)
|
||||||
|
exit(-1);
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* Network Number - Optional */
|
||||||
|
netnum = strtoul(argv[i], (char **)NULL, 16);
|
||||||
|
if (netnum == 0xffffffffL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_network = htonl(netnum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
int old_errno = errno;
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
if (old_errno == -EINVAL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Probably you have no IPX support in "
|
||||||
|
"your kernel\n");
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
sipx->sipx_action = IPX_CRTITF;
|
||||||
|
do {
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
i++;
|
||||||
|
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||||
|
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EEXIST:
|
||||||
|
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
case EADDRINUSE:
|
||||||
|
fprintf(stderr, "%s: Network number (%08lX) already in use.\n",
|
||||||
|
progname, htonl(sipx->sipx_network));
|
||||||
|
break;
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case ENETDOWN:
|
||||||
|
fprintf(stderr, "%s: Requested device (%s) is down.\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
fprintf(stderr, "%s: Invalid device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EAGAIN:
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Insufficient memory to create interface.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
ipx_del_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
int fti;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
|
strcpy(id.ifr_name, argv[1]);
|
||||||
|
fti = lookup_frame_type(argv[2]);
|
||||||
|
if (fti < 0)
|
||||||
|
exit(-1);
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_action = IPX_DLTITF;
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||||
|
id.ifr_name, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_check_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
int fti;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
strcpy(id.ifr_name, argv[1]);
|
||||||
|
fti = lookup_frame_type(argv[2]);
|
||||||
|
if (fti < 0)
|
||||||
|
exit(-1);
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
result = ioctl(s, SIOCGIFADDR, &id);
|
||||||
|
if (result == 0) {
|
||||||
|
printf(
|
||||||
|
"IPX Address for (%s, %s) is %08lX:%02X%02X%02X%02X%02X%02X.\n",
|
||||||
|
argv[1], frame_types[fti].ft_name,
|
||||||
|
htonl(sipx->sipx_network), sipx->sipx_node[0],
|
||||||
|
sipx->sipx_node[1], sipx->sipx_node[2],
|
||||||
|
sipx->sipx_node[3], sipx->sipx_node[4],
|
||||||
|
sipx->sipx_node[5]);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EADDRNOTAVAIL:
|
||||||
|
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||||
|
id.ifr_name, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
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) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_del_interface(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "check", 5) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_check_interface(argc-1, argv);
|
||||||
|
}
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
200
ipx-1.0/ipx_internal_net.c
Normal file
200
ipx-1.0/ipx_internal_net.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
static struct ifreq id;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\
|
||||||
|
Usage: %s del\n", progname, progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
map_char_to_val(char dig)
|
||||||
|
{
|
||||||
|
char digit = tolower(dig);
|
||||||
|
if ((digit >= '0') && (digit <= '9')) {
|
||||||
|
return digit - '0';
|
||||||
|
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||||
|
return (10 + (digit - 'a'));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_add_internal_net(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
int nodelen;
|
||||||
|
char *node;
|
||||||
|
char tmpnode[13];
|
||||||
|
unsigned char *tout;
|
||||||
|
char *tin;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0L) || (netnum == 0xffffffffL)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = argv[2];
|
||||||
|
nodelen = strlen(node);
|
||||||
|
if (nodelen > 12) {
|
||||||
|
fprintf(stderr, "%s: Node length is too long (> 12).\n", progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (i < nodelen) {
|
||||||
|
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmpnode, "000000000000");
|
||||||
|
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||||
|
for (tin = tmpnode, tout = sipx->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||||
|
*tout = (unsigned char) map_char_to_val(*tin);
|
||||||
|
*tout <<= 4;
|
||||||
|
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||||
|
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||||
|
fprintf(stderr, "%s: Node is invalid.\n", progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = htonl(netnum);
|
||||||
|
sipx->sipx_type = IPX_FRAME_NONE;
|
||||||
|
sipx->sipx_special = IPX_INTERNAL;
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
sipx->sipx_action = IPX_CRTITF;
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
i++;
|
||||||
|
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||||
|
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EEXIST:
|
||||||
|
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
case EADDRINUSE:
|
||||||
|
fprintf(stderr, "%s: Network number (%08lX) already in use.\n",
|
||||||
|
progname, htonl(sipx->sipx_network));
|
||||||
|
break;
|
||||||
|
case EAGAIN:
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Insufficient memory to create internal net.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_del_internal_net(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
|
||||||
|
if (argc != 1) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_special = IPX_INTERNAL;
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
sipx->sipx_action = IPX_DLTITF;
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT:
|
||||||
|
fprintf(stderr, "%s: No internal network configured.\n", progname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_add_internal_net(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_del_internal_net(argc-1, argv);
|
||||||
|
}
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
220
ipx-1.0/ipx_route.c
Normal file
220
ipx-1.0/ipx_route.c
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/route.h>
|
||||||
|
|
||||||
|
static struct rtentry rd;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
int
|
||||||
|
map_char_to_val(char dig)
|
||||||
|
{
|
||||||
|
char digit = tolower(dig);
|
||||||
|
if ((digit >= '0') && (digit <= '9')) {
|
||||||
|
return digit - '0';
|
||||||
|
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||||
|
return (10 + (digit - 'a'));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
|
||||||
|
Usage: %s del network(hex)\n", progname, progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_add_route(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Router */
|
||||||
|
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||||
|
/* Target */
|
||||||
|
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
int nodelen;
|
||||||
|
int i;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
char *node;
|
||||||
|
char *tin;
|
||||||
|
char tmpnode[13];
|
||||||
|
unsigned char *tout;
|
||||||
|
|
||||||
|
if (argc != 4)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
/* Network Number */
|
||||||
|
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
rd.rt_flags = RTF_GATEWAY;
|
||||||
|
st->sipx_network = htonl(netnum);
|
||||||
|
|
||||||
|
/* Router Network Number */
|
||||||
|
netnum = strtoul(argv[2], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sr->sipx_network = htonl(netnum);
|
||||||
|
|
||||||
|
/* Router Node */
|
||||||
|
node = argv[3];
|
||||||
|
nodelen = strlen(node);
|
||||||
|
if (nodelen > 12) {
|
||||||
|
fprintf(stderr, "%s: Node length is too long (> 12).\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (i < nodelen) {
|
||||||
|
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmpnode, "000000000000");
|
||||||
|
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||||
|
for (tin = tmpnode, tout = sr->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||||
|
*tout = (unsigned char) map_char_to_val(*tin);
|
||||||
|
*tout <<= 4;
|
||||||
|
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((memcmp(sr->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||||
|
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||||
|
fprintf(stderr, "%s: Node (%s) is invalid.\n", progname, tmpnode);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sr->sipx_family = st->sipx_family = AF_IPX;
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
result = ioctl(s, SIOCADDRT, &rd);
|
||||||
|
i++;
|
||||||
|
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||||
|
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case ENETUNREACH:
|
||||||
|
fprintf(stderr, "%s: Router network (%08lX) not reachable.\n",
|
||||||
|
progname, htonl(sr->sipx_network));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_del_route(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Router */
|
||||||
|
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||||
|
/* Target */
|
||||||
|
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
rd.rt_flags = RTF_GATEWAY;
|
||||||
|
/* Network Number */
|
||||||
|
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX.\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
st->sipx_network = htonl(netnum);
|
||||||
|
|
||||||
|
st->sipx_family = sr->sipx_family = AF_IPX;
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
result = ioctl(s, SIOCDELRT, &rd);
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT:
|
||||||
|
fprintf(stderr, "%s: Route not found for network %08lX.\n",
|
||||||
|
progname, netnum);
|
||||||
|
break;
|
||||||
|
case EPERM:
|
||||||
|
fprintf(stderr, "%s: Network %08lX is directly connected.\n",
|
||||||
|
progname, netnum);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_add_route(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_del_route(argc-1, argv);
|
||||||
|
}
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
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>
|
||||||
245
ipxdump/ipxdump.c
Normal file
245
ipxdump/ipxdump.c
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
/* 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(char *frame, 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 (char *frame, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s ", frame);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
handle_ipx("802.3", p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (*(unsigned short *)p == htons(0xe0e0))
|
||||||
|
&& (p[2] == 0x03))
|
||||||
|
{
|
||||||
|
handle_ipx("802.2", p+3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
||||||
|
{
|
||||||
|
handle_ipx("snap", 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):
|
||||||
|
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handle_other(buf, length, saddr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
1102
ipxdump/ipxparse.c
Normal file
1102
ipxdump/ipxparse.c
Normal file
File diff suppressed because it is too large
Load Diff
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(IPXNode))==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";
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
IPX support library
|
IPX support library
|
||||||
|
|
||||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,49 +24,42 @@
|
|||||||
|
|
||||||
#define __IPXUTIL_H__
|
#define __IPXUTIL_H__
|
||||||
|
|
||||||
#include <string.h>
|
#include <stdio.h>
|
||||||
#include <linux/ipx.h>
|
#include <linux/ipx.h>
|
||||||
|
|
||||||
#define IPX_RIP_PTYPE (0x01)
|
#define IPX_MAX_ERROR (255)
|
||||||
#define IPX_SAP_PTYPE (0x04)
|
#define IPX_THIS_NET (0)
|
||||||
#define IPX_SAP_PORT (0x0452)
|
#define IPX_THIS_NODE (ipx_this_node)
|
||||||
#define IPX_RIP_PORT (0x0453)
|
#define IPX_BROADCAST (ipx_broadcast_node)
|
||||||
|
#define IPX_AUTO_PORT (0)
|
||||||
|
#define IPX_USER_PTYPE (0)
|
||||||
|
#define IPX_IS_INTERNAL (1)
|
||||||
|
|
||||||
#define IPX_SAP_GENERAL_QUERY (0x0001)
|
typedef unsigned char IPXNode[6];
|
||||||
#define IPX_SAP_GENERAL_RESPONSE (0x0002)
|
typedef unsigned long int IPXNet;
|
||||||
#define IPX_SAP_NEAREST_QUERY (0x0003)
|
typedef unsigned short int IPXPort;
|
||||||
#define IPX_SAP_NEAREST_RESPONSE (0x0004)
|
typedef unsigned short int hop_t;
|
||||||
|
typedef unsigned short int tick_t;
|
||||||
#define IPX_SAP_FILE_SERVER (0x0004)
|
|
||||||
|
|
||||||
#define IPX_RIP_REQUEST (0x1)
|
|
||||||
#define IPX_RIP_RESPONSE (0x2)
|
|
||||||
|
|
||||||
struct ipx_rip_packet {
|
|
||||||
__u16 operation __attribute__ ((packed));
|
|
||||||
struct ipx_rt_def {
|
|
||||||
__u32 network __attribute__ ((packed));
|
|
||||||
__u16 hops __attribute__ ((packed));
|
|
||||||
__u16 ticks __attribute__ ((packed));
|
|
||||||
} rt[1] __attribute__ ((packed));
|
|
||||||
};
|
|
||||||
|
|
||||||
#define IPX_BROADCAST_NODE "\xff\xff\xff\xff\xff\xff"
|
|
||||||
#define IPX_THIS_NODE "\0\0\0\0\0\0"
|
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned long IPXNet;
|
|
||||||
typedef unsigned short IPXPort;
|
|
||||||
typedef unsigned char IPXNode[IPX_NODE_LEN];
|
|
||||||
|
|
||||||
void ipx_print_node(IPXNode node);
|
void ipx_print_node(IPXNode node);
|
||||||
void ipx_print_network(IPXNet net);
|
void ipx_print_network(IPXNet net);
|
||||||
void ipx_print_port(IPXPort port);
|
void ipx_print_port(IPXPort port);
|
||||||
void ipx_print_saddr(struct sockaddr_ipx* sipx);
|
void ipx_print_saddr(struct sockaddr_ipx* sipx);
|
||||||
|
|
||||||
static __inline__ void
|
void ipx_fprint_node(FILE* file,IPXNode node);
|
||||||
ipx_assign_node(IPXNode dest, IPXNode src) {
|
void ipx_fprint_network(FILE* file,IPXNet net);
|
||||||
memcpy(dest, src, IPX_NODE_LEN);
|
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
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* ncp_fs.h
|
* ncp.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 1995 by Volker Lendecke
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
*
|
*
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#define _LINUX_NCP_H
|
#define _LINUX_NCP_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
|
||||||
#define NCP_PTYPE (0x11)
|
#define NCP_PTYPE (0x11)
|
||||||
#define NCP_PORT (0x0451)
|
#define NCP_PORT (0x0451)
|
||||||
@@ -51,6 +52,9 @@ struct ncp_bindery_object {
|
|||||||
__u32 object_id;
|
__u32 object_id;
|
||||||
__u16 object_type;
|
__u16 object_type;
|
||||||
__u8 object_name[NCP_BINDERY_NAME_LEN];
|
__u8 object_name[NCP_BINDERY_NAME_LEN];
|
||||||
|
__u8 object_flags;
|
||||||
|
__u8 object_security;
|
||||||
|
__u8 object_has_prop;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nw_property {
|
struct nw_property {
|
||||||
@@ -59,6 +63,11 @@ struct nw_property {
|
|||||||
__u8 property_flag;
|
__u8 property_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct prop_net_address {
|
||||||
|
__u32 network __attribute__ ((packed));
|
||||||
|
__u8 node[IPX_NODE_LEN] __attribute__ ((packed));
|
||||||
|
__u16 port __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
#define NCP_VOLNAME_LEN (16)
|
#define NCP_VOLNAME_LEN (16)
|
||||||
#define NCP_NUMBER_OF_VOLUMES (64)
|
#define NCP_NUMBER_OF_VOLUMES (64)
|
||||||
@@ -107,6 +116,12 @@ struct ncp_file_info {
|
|||||||
__u16 update_time;
|
__u16 update_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Defines for Name Spaces */
|
||||||
|
#define NW_NS_DOS 0
|
||||||
|
#define NW_NS_MAC 1
|
||||||
|
#define NW_NS_NFS 2
|
||||||
|
#define NW_NS_FTAM 3
|
||||||
|
#define NW_NS_OS2 4
|
||||||
|
|
||||||
/* Defines for ReturnInformationMask */
|
/* Defines for ReturnInformationMask */
|
||||||
#define RIM_NAME (0x0001L)
|
#define RIM_NAME (0x0001L)
|
||||||
@@ -263,16 +278,23 @@ struct queue_job {
|
|||||||
|
|
||||||
/* ClientRecordArea for print jobs */
|
/* ClientRecordArea for print jobs */
|
||||||
|
|
||||||
|
#define KEEP_ON 0x0400
|
||||||
|
#define NO_FORM_FEED 0x0800
|
||||||
|
#define NOTIFICATION 0x1000
|
||||||
|
#define DELETE_FILE 0x2000
|
||||||
|
#define EXPAND_TABS 0x4000
|
||||||
|
#define PRINT_BANNER 0x8000
|
||||||
|
|
||||||
struct print_job_record {
|
struct print_job_record {
|
||||||
__u8 Version __attribute__ ((packed));
|
__u8 Version __attribute__ ((packed));
|
||||||
__u16 TabSize __attribute__ ((packed));
|
__u8 TabSize __attribute__ ((packed));
|
||||||
__u16 Copies __attribute__ ((packed));
|
__u16 Copies __attribute__ ((packed));
|
||||||
__u8 CtrlFlags __attribute__ ((packed));
|
__u16 CtrlFlags __attribute__ ((packed));
|
||||||
__u16 Lines __attribute__ ((packed));
|
__u16 Lines __attribute__ ((packed));
|
||||||
__u16 Rows __attribute__ ((packed));
|
__u16 Rows __attribute__ ((packed));
|
||||||
char FormName[16] __attribute__ ((packed));
|
char FormName[16] __attribute__ ((packed));
|
||||||
__u8 Reserved[6] __attribute__ ((packed));
|
__u8 Reserved[6] __attribute__ ((packed));
|
||||||
char Banner[13] __attribute__ ((packed));
|
char BannerName[13] __attribute__ ((packed));
|
||||||
char FnameBanner[13] __attribute__ ((packed));
|
char FnameBanner[13] __attribute__ ((packed));
|
||||||
char FnameHeader[14] __attribute__ ((packed));
|
char FnameHeader[14] __attribute__ ((packed));
|
||||||
char Path[80] __attribute__ ((packed));
|
char Path[80] __attribute__ ((packed));
|
||||||
@@ -26,8 +26,24 @@ struct ncp_ioctl_request {
|
|||||||
char *data;
|
char *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
struct ncp_fs_info {
|
||||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
int version;
|
||||||
|
struct sockaddr_ipx addr;
|
||||||
|
uid_t mounted_uid;
|
||||||
|
int connection; /* Connection number the server assigned us */
|
||||||
|
int buffer_size; /* The negotiated buffer size, to be
|
||||||
|
used for read/write requests! */
|
||||||
|
|
||||||
|
int volume_number;
|
||||||
|
__u32 directory_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request)
|
||||||
|
#define NCP_IOC_GETMOUNTUID _IOW('n', 2, uid_t)
|
||||||
|
#define NCP_IOC_CONN_LOGGED_IN _IO('n', 3)
|
||||||
|
|
||||||
|
#define NCP_GET_FS_INFO_VERSION (1)
|
||||||
|
#define NCP_IOC_GET_FS_INFO _IOWR('n', 4, struct ncp_fs_info)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The packet size to allocate. One page should be enough.
|
* The packet size to allocate. One page should be enough.
|
||||||
@@ -45,7 +61,7 @@ struct ncp_ioctl_request {
|
|||||||
#define NCP_READDIR_CACHE_SIZE 64
|
#define NCP_READDIR_CACHE_SIZE 64
|
||||||
|
|
||||||
|
|
||||||
#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
|
#define NCP_MAX_RPC_TIMEOUT (6*HZ)
|
||||||
|
|
||||||
/* Guess, what 0x564c is :-) */
|
/* Guess, what 0x564c is :-) */
|
||||||
#define NCP_SUPER_MAGIC 0x564c
|
#define NCP_SUPER_MAGIC 0x564c
|
||||||
@@ -58,10 +74,6 @@ struct ncp_ioctl_request {
|
|||||||
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
||||||
#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i))
|
#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i))
|
||||||
|
|
||||||
static inline int min(int a, int b) {
|
|
||||||
return a<b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_NCP_MALLOC
|
#ifdef DEBUG_NCP_MALLOC
|
||||||
|
|
||||||
#include <linux/malloc.h>
|
#include <linux/malloc.h>
|
||||||
@@ -113,9 +125,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);
|
||||||
@@ -13,10 +13,10 @@
|
|||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
enum ncp_inode_state {
|
enum ncp_inode_state {
|
||||||
INODE_VALID = 19, /* Inode currently in use */
|
NCP_INODE_VALID = 19, /* Inode currently in use */
|
||||||
INODE_LOOKED_UP, /* directly before iget */
|
NCP_INODE_LOOKED_UP, /* directly before iget */
|
||||||
INODE_CACHED, /* in a path to an inode which is in use */
|
NCP_INODE_CACHED, /* in a path to an inode which is in use */
|
||||||
INODE_INVALID
|
NCP_INODE_INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -21,8 +21,9 @@ struct ncp_server {
|
|||||||
interest for us later, so we store
|
interest for us later, so we store
|
||||||
it completely. */
|
it completely. */
|
||||||
|
|
||||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
__u8 name_space[NCP_NUMBER_OF_VOLUMES];
|
||||||
|
|
||||||
|
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 +36,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 +58,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? */
|
||||||
@@ -2,11 +2,9 @@
|
|||||||
# Makefile for the linux ncp-filesystem routines.
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
#
|
#
|
||||||
|
|
||||||
INCLUDES = -I/usr/src/linux/include -I..
|
|
||||||
|
|
||||||
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=2 -DDEBUG_NCP_MALLOC
|
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
||||||
# -DDEBUG_NCP_MALLOC
|
# -DDEBUG_NCP_MALLOC
|
||||||
|
|
||||||
CC = gcc -D__KERNEL__ -I.
|
CC = gcc -D__KERNEL__ -I.
|
||||||
@@ -20,14 +18,14 @@ ARCH = i386
|
|||||||
.s.o:
|
.s.o:
|
||||||
$(AS) -o $*.o $<
|
$(AS) -o $*.o $<
|
||||||
|
|
||||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o
|
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib_kernel.o mmap.o
|
||||||
|
|
||||||
all: ncpfs.o
|
all: $(INTERM_BINDIR)/ncpfs.o
|
||||||
|
|
||||||
ncpfs.o: $(OBJS)
|
$(INTERM_BINDIR)/ncpfs.o: $(OBJS)
|
||||||
$(LD) -r -o ncpfs.o $(OBJS)
|
$(LD) -r -o $@ $(OBJS)
|
||||||
|
|
||||||
ncplib.o: ncplib.c ncplib.h
|
ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h
|
||||||
$(CC) $(CFLAGS) -finline-functions -c $<
|
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,11 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* #include <linux/module.h>*/
|
#include <linux/config.h>
|
||||||
|
#ifdef MODULE
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/segment.h>
|
#include <asm/segment.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
@@ -17,9 +21,15 @@
|
|||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/ncp_fs.h>
|
#include <linux/ncp_fs.h>
|
||||||
#include "ncplib.h"
|
#include <linux/locks.h>
|
||||||
|
#include "ncplib_kernel.h"
|
||||||
#include <linux/malloc.h>
|
#include <linux/malloc.h>
|
||||||
|
|
||||||
|
static inline int min(int a, int b)
|
||||||
|
{
|
||||||
|
return a<b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncp_fsync(struct inode *inode, struct file *file)
|
ncp_fsync(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
@@ -31,7 +41,8 @@ ncp_make_open(struct inode *i, int right)
|
|||||||
{
|
{
|
||||||
struct nw_file_info *finfo;
|
struct nw_file_info *finfo;
|
||||||
|
|
||||||
if (i == NULL) {
|
if (i == NULL)
|
||||||
|
{
|
||||||
printk("ncp_make_open: got NULL inode\n");
|
printk("ncp_make_open: got NULL inode\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -40,27 +51,31 @@ ncp_make_open(struct inode *i, int right)
|
|||||||
|
|
||||||
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
|
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
|
||||||
|
|
||||||
if (finfo->opened == 0) {
|
lock_super(i->i_sb);
|
||||||
|
if (finfo->opened == 0)
|
||||||
|
{
|
||||||
|
finfo->access = -1;
|
||||||
/* tries max. rights */
|
/* tries max. rights */
|
||||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
OC_MODE_OPEN, 0,
|
OC_MODE_OPEN, 0,
|
||||||
AR_READ | AR_WRITE,
|
AR_READ | AR_WRITE,
|
||||||
finfo) == 0) {
|
finfo) == 0)
|
||||||
|
{
|
||||||
finfo->access = O_RDWR;
|
finfo->access = O_RDWR;
|
||||||
}
|
}
|
||||||
else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
OC_MODE_OPEN, 0,
|
OC_MODE_OPEN, 0,
|
||||||
AR_READ,
|
AR_READ,
|
||||||
finfo) == 0) {
|
finfo) == 0)
|
||||||
|
{
|
||||||
finfo->access = O_RDONLY;
|
finfo->access = O_RDONLY;
|
||||||
} else {
|
|
||||||
return -EACCES;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock_super(i->i_sb);
|
||||||
|
|
||||||
if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY)
|
if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY)
|
||||||
|| (finfo->access == O_RDWR)))
|
|| (finfo->access == O_RDWR)))
|
||||||
|| ((right == O_WRONLY) && ( (finfo->access == O_WRONLY)
|
|| ((right == O_WRONLY) && ( (finfo->access == O_WRONLY)
|
||||||
@@ -74,18 +89,24 @@ ncp_make_open(struct inode *i, int right)
|
|||||||
static int
|
static int
|
||||||
ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||||
{
|
{
|
||||||
int bufsize, to_read, already_read;
|
int bufsize, already_read;
|
||||||
off_t pos;
|
off_t pos;
|
||||||
int errno;
|
int errno;
|
||||||
|
|
||||||
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||||
|
|
||||||
if (!inode) {
|
if (inode == NULL)
|
||||||
|
{
|
||||||
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))
|
||||||
|
{
|
||||||
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
|
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
|
||||||
inode->i_mode);
|
inode->i_mode);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -94,33 +115,34 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
pos = file->f_pos;
|
pos = file->f_pos;
|
||||||
|
|
||||||
if (pos + count > inode->i_size)
|
if (pos + count > inode->i_size)
|
||||||
|
{
|
||||||
count = inode->i_size - pos;
|
count = inode->i_size - pos;
|
||||||
|
}
|
||||||
|
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
||||||
|
{
|
||||||
return errno;
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||||
|
|
||||||
already_read = 0;
|
already_read = 0;
|
||||||
|
|
||||||
/* First read in as much as possible for each bufsize. */
|
/* First read in as much as possible for each bufsize. */
|
||||||
while (already_read < count) {
|
while (already_read < count)
|
||||||
|
{
|
||||||
int read_this_time;
|
int read_this_time;
|
||||||
|
int to_read = min(bufsize - (pos % bufsize),
|
||||||
if ((pos % bufsize) != 0) {
|
count - already_read);
|
||||||
to_read = bufsize - (pos % bufsize);
|
|
||||||
} else {
|
|
||||||
to_read = bufsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_read = min(to_read, count - already_read);
|
|
||||||
|
|
||||||
if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||||
pos, to_read, buf, &read_this_time) != 0) {
|
pos, to_read, buf, &read_this_time) != 0)
|
||||||
|
{
|
||||||
return -EIO; /* This is not exact, i know.. */
|
return -EIO; /* This is not exact, i know.. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,14 +150,19 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
buf += read_this_time;
|
buf += read_this_time;
|
||||||
already_read += read_this_time;
|
already_read += read_this_time;
|
||||||
|
|
||||||
if (read_this_time < to_read) {
|
if (read_this_time < to_read)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file->f_pos = pos;
|
file->f_pos = pos;
|
||||||
|
|
||||||
if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
|
if (!IS_RDONLY(inode))
|
||||||
|
{
|
||||||
|
inode->i_atime = CURRENT_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
inode->i_dirt = 1;
|
inode->i_dirt = 1;
|
||||||
|
|
||||||
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||||
@@ -144,19 +171,25 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||||
int count)
|
int count)
|
||||||
{
|
{
|
||||||
int bufsize, to_write, already_written;
|
int bufsize, already_written;
|
||||||
off_t pos;
|
off_t pos;
|
||||||
int errno;
|
int errno;
|
||||||
|
|
||||||
if (!inode) {
|
if (inode == NULL)
|
||||||
|
{
|
||||||
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))
|
||||||
|
{
|
||||||
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
|
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
|
||||||
inode->i_mode);
|
inode->i_mode);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -165,33 +198,35 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
|||||||
DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||||
|
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((errno = ncp_make_open(inode, O_RDWR)) != 0)
|
if ((errno = ncp_make_open(inode, O_RDWR)) != 0)
|
||||||
|
{
|
||||||
return errno;
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
pos = file->f_pos;
|
pos = file->f_pos;
|
||||||
|
|
||||||
if (file->f_flags & O_APPEND)
|
if (file->f_flags & O_APPEND)
|
||||||
|
{
|
||||||
pos = inode->i_size;
|
pos = inode->i_size;
|
||||||
|
}
|
||||||
|
|
||||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||||
|
|
||||||
already_written = 0;
|
already_written = 0;
|
||||||
|
|
||||||
while (already_written < count) {
|
while (already_written < count)
|
||||||
|
{
|
||||||
int written_this_time;
|
int written_this_time;
|
||||||
|
int to_write = min(bufsize - (pos % bufsize),
|
||||||
|
count - already_written);
|
||||||
|
|
||||||
if ((pos % bufsize) != 0) {
|
|
||||||
to_write = bufsize - (pos % bufsize);
|
|
||||||
} else {
|
|
||||||
to_write = bufsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_write = min(to_write, count - already_written);
|
|
||||||
if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||||
pos, to_write, buf, &written_this_time) != 0) {
|
pos, to_write, buf, &written_this_time) != 0)
|
||||||
|
{
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +234,8 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
|||||||
buf += written_this_time;
|
buf += written_this_time;
|
||||||
already_written += written_this_time;
|
already_written += written_this_time;
|
||||||
|
|
||||||
if (written_this_time < to_write) {
|
if (written_this_time < to_write)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,8 +245,10 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
|||||||
|
|
||||||
file->f_pos = pos;
|
file->f_pos = pos;
|
||||||
|
|
||||||
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);
|
||||||
@@ -225,7 +263,7 @@ static struct file_operations ncp_file_operations = {
|
|||||||
NULL, /* readdir - bad */
|
NULL, /* readdir - bad */
|
||||||
NULL, /* select - default */
|
NULL, /* select - default */
|
||||||
ncp_ioctl, /* ioctl */
|
ncp_ioctl, /* ioctl */
|
||||||
NULL, /* mmap */
|
ncp_mmap, /* mmap */
|
||||||
NULL, /* open */
|
NULL, /* open */
|
||||||
NULL, /* release */
|
NULL, /* release */
|
||||||
ncp_fsync, /* fsync */
|
ncp_fsync, /* fsync */
|
||||||
@@ -5,7 +5,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#ifdef MODULE
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#else
|
||||||
|
#define MOD_INC_USE_COUNT
|
||||||
|
#define MOD_DEC_USE_COUNT
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/segment.h>
|
#include <asm/segment.h>
|
||||||
@@ -20,14 +27,14 @@
|
|||||||
#include <linux/locks.h>
|
#include <linux/locks.h>
|
||||||
#include <linux/fcntl.h>
|
#include <linux/fcntl.h>
|
||||||
#include <linux/malloc.h>
|
#include <linux/malloc.h>
|
||||||
#include "ncplib.h"
|
#include "ncplib_kernel.h"
|
||||||
|
|
||||||
extern int close_fp(struct file *filp);
|
extern int close_fp(struct file *filp);
|
||||||
|
|
||||||
static void ncp_put_inode(struct inode *);
|
static void ncp_put_inode(struct inode *);
|
||||||
static void ncp_read_inode(struct inode *);
|
static void ncp_read_inode(struct inode *);
|
||||||
static void ncp_put_super(struct super_block *);
|
static void ncp_put_super(struct super_block *);
|
||||||
static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
|
static void ncp_statfs(struct super_block *sb, struct statfs *stat);
|
||||||
static int ncp_notify_change(struct inode *inode, struct iattr *attr);
|
static int ncp_notify_change(struct inode *inode, struct iattr *attr);
|
||||||
|
|
||||||
static struct super_operations ncp_sops = {
|
static struct super_operations ncp_sops = {
|
||||||
@@ -39,7 +46,7 @@ static struct super_operations ncp_sops = {
|
|||||||
NULL, /* write superblock */
|
NULL, /* write superblock */
|
||||||
ncp_statfs, /* stat filesystem */
|
ncp_statfs, /* stat filesystem */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ncp_read_inode: Called from iget, it only traverses the allocated
|
/* ncp_read_inode: Called from iget, it only traverses the allocated
|
||||||
ncp_inode_info's and initializes the inode from the data found
|
ncp_inode_info's and initializes the inode from the data found
|
||||||
@@ -54,48 +61,29 @@ 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;
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
inode_info->state = NCP_INODE_VALID;
|
||||||
if (inode_info == check_info) {
|
|
||||||
if (check_info->state == INODE_LOOKED_UP) {
|
|
||||||
DDPRINTK("ncp_read_inode: found it!\n");
|
|
||||||
goto good;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printk("ncp_read_inode: "
|
|
||||||
"state != 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 = 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 = 0;
|
inode->i_size = 512;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
|
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
|
||||||
inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
|
inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
|
||||||
@@ -106,13 +94,18 @@ ncp_read_inode(struct inode *inode)
|
|||||||
inode->i_nlink = 1;
|
inode->i_nlink = 1;
|
||||||
inode->i_uid = NCP_SERVER(inode)->m.uid;
|
inode->i_uid = NCP_SERVER(inode)->m.uid;
|
||||||
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
||||||
inode->i_blksize = 1024;
|
inode->i_blksize = 512;
|
||||||
inode->i_rdev = 0;
|
inode->i_rdev = 0;
|
||||||
|
|
||||||
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
||||||
|
{
|
||||||
inode->i_blocks =
|
inode->i_blocks =
|
||||||
(inode->i_size - 1) / inode->i_blksize + 1;
|
(inode->i_size - 1) / inode->i_blksize + 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
inode->i_blocks = 0;
|
inode->i_blocks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
|
inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
|
||||||
NCP_ISTRUCT(inode)->modifyDate);
|
NCP_ISTRUCT(inode)->modifyDate);
|
||||||
@@ -122,36 +115,49 @@ ncp_read_inode(struct inode *inode)
|
|||||||
NCP_ISTRUCT(inode)->lastAccessDate);
|
NCP_ISTRUCT(inode)->lastAccessDate);
|
||||||
|
|
||||||
if (S_ISREG(inode->i_mode))
|
if (S_ISREG(inode->i_mode))
|
||||||
|
{
|
||||||
inode->i_op = &ncp_file_inode_operations;
|
inode->i_op = &ncp_file_inode_operations;
|
||||||
|
}
|
||||||
else if (S_ISDIR(inode->i_mode))
|
else if (S_ISDIR(inode->i_mode))
|
||||||
|
{
|
||||||
inode->i_op = &ncp_dir_inode_operations;
|
inode->i_op = &ncp_dir_inode_operations;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
inode->i_op = NULL;
|
inode->i_op = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ncp_put_inode(struct inode *inode)
|
ncp_put_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct nw_file_info *finfo = NCP_FINFO(inode);
|
struct nw_file_info *finfo = NCP_FINFO(inode);
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
|
||||||
if (finfo->opened != 0) {
|
lock_super(sb);
|
||||||
|
if (finfo->opened != 0)
|
||||||
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) {
|
{
|
||||||
|
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
|
||||||
|
{
|
||||||
/* We can't do anything but complain. */
|
/* We can't do anything but complain. */
|
||||||
printk("ncp_put_inode: could not close\n");
|
printk("ncp_put_inode: could not close\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DDPRINTK("ncp_put_inode: put %s\n",
|
||||||
|
finfo->i.entryName);
|
||||||
|
|
||||||
ncp_free_inode_info(NCP_INOP(inode));
|
ncp_free_inode_info(NCP_INOP(inode));
|
||||||
|
|
||||||
if (S_ISDIR(inode->i_mode)) {
|
if (S_ISDIR(inode->i_mode))
|
||||||
DPRINTK("ncp_put_inode: put directory %ld\n",
|
{
|
||||||
inode->i_ino);
|
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
||||||
ncp_invalid_dir_cache(inode->i_ino);
|
inode->i_ino);
|
||||||
|
ncp_invalid_dir_cache(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_inode(inode);
|
clear_inode(inode);
|
||||||
|
unlock_super(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct super_block *
|
struct super_block *
|
||||||
@@ -161,25 +167,29 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
struct ncp_server *server;
|
struct ncp_server *server;
|
||||||
struct file *ncp_filp;
|
struct file *ncp_filp;
|
||||||
struct file *wdog_filp;
|
struct file *wdog_filp;
|
||||||
kdev_t dev = sb->s_dev;
|
dev_t dev = sb->s_dev;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!data) {
|
if (data == NULL)
|
||||||
|
{
|
||||||
printk("ncp_read_super: missing data argument\n");
|
printk("ncp_read_super: missing data argument\n");
|
||||||
sb->s_dev = 0;
|
sb->s_dev = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->version != NCP_MOUNT_VERSION) {
|
if (data->version != NCP_MOUNT_VERSION)
|
||||||
|
{
|
||||||
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)
|
||||||
|| ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
|
|| ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
|
||||||
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode))) {
|
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
|
||||||
|
{
|
||||||
printk("ncp_read_super: invalid ncp socket\n");
|
printk("ncp_read_super: invalid ncp socket\n");
|
||||||
sb->s_dev = 0;
|
sb->s_dev = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -187,7 +197,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
|
|
||||||
if ( (data->wdog_fd >= NR_OPEN)
|
if ( (data->wdog_fd >= NR_OPEN)
|
||||||
|| ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
|
|| ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
|
||||||
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode))) {
|
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
|
||||||
|
{
|
||||||
printk("ncp_read_super: invalid wdog socket\n");
|
printk("ncp_read_super: invalid wdog socket\n");
|
||||||
sb->s_dev = 0;
|
sb->s_dev = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -197,7 +208,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
|
server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (server == NULL) {
|
if (server == NULL)
|
||||||
|
{
|
||||||
printk("ncp_read_super: could not alloc ncp_server\n");
|
printk("ncp_read_super: could not alloc ncp_server\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -221,6 +233,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 &
|
||||||
@@ -231,7 +244,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
server->packet_size = NCP_PACKET_SIZE;
|
server->packet_size = NCP_PACKET_SIZE;
|
||||||
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
|
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
|
||||||
|
|
||||||
if (server->packet == NULL) {
|
if (server->packet == NULL)
|
||||||
|
{
|
||||||
printk("ncpfs: could not alloc packet\n");
|
printk("ncpfs: could not alloc packet\n");
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
unlock_super(sb);
|
unlock_super(sb);
|
||||||
@@ -244,7 +258,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
* Make the connection to the server
|
* Make the connection to the server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ncp_catch_watchdog(server) != 0) {
|
if (ncp_catch_watchdog(server) != 0)
|
||||||
|
{
|
||||||
printk("ncp_read_super: Could not catch watchdog\n");
|
printk("ncp_read_super: Could not catch watchdog\n");
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
unlock_super(sb);
|
unlock_super(sb);
|
||||||
@@ -256,7 +271,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
unlock_super(sb);
|
unlock_super(sb);
|
||||||
|
|
||||||
if (error < 0) {
|
if (error < 0)
|
||||||
|
{
|
||||||
sb->s_dev = 0;
|
sb->s_dev = 0;
|
||||||
printk("ncp_read_super: Failed connection, bailing out "
|
printk("ncp_read_super: Failed connection, bailing out "
|
||||||
"(error = %d).\n", -error);
|
"(error = %d).\n", -error);
|
||||||
@@ -267,14 +283,16 @@ 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");
|
||||||
goto disconnect;
|
goto disconnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
|
if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
|
||||||
&(server->buffer_size)) != 0) {
|
&(server->buffer_size)) != 0)
|
||||||
|
{
|
||||||
sb->s_dev = 0;
|
sb->s_dev = 0;
|
||||||
printk("ncp_read_super: could not get bufsize\n");
|
printk("ncp_read_super: could not get bufsize\n");
|
||||||
goto disconnect;
|
goto disconnect;
|
||||||
@@ -282,14 +300,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
|||||||
|
|
||||||
DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
|
DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
|
||||||
|
|
||||||
/* if (ncp_login_user(server, server->m.username,
|
|
||||||
server->m.password) != 0) {
|
|
||||||
sb->s_dev = 0;
|
|
||||||
printk("ncp_read_super: login failed\n");
|
|
||||||
goto disconnect;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
MOD_INC_USE_COUNT;
|
MOD_INC_USE_COUNT;
|
||||||
return sb;
|
return sb;
|
||||||
|
|
||||||
@@ -336,7 +346,7 @@ ncp_put_super(struct super_block *sb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
|
ncp_statfs(struct super_block *sb, struct statfs *stat)
|
||||||
{
|
{
|
||||||
struct statfs tmp;
|
struct statfs tmp;
|
||||||
|
|
||||||
@@ -354,7 +364,7 @@ ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
|
|||||||
tmp.f_files = -1;
|
tmp.f_files = -1;
|
||||||
tmp.f_ffree = -1;
|
tmp.f_ffree = -1;
|
||||||
tmp.f_namelen = 12;
|
tmp.f_namelen = 12;
|
||||||
memcpy_tofs(buf, &tmp, bufsiz);
|
memcpy_tofs(stat, &tmp, sizeof(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -364,6 +374,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;
|
||||||
|
|
||||||
@@ -383,43 +398,59 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
|||||||
info_mask = 0;
|
info_mask = 0;
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
|
|
||||||
if ((attr->ia_valid & ATTR_CTIME) != 0) {
|
if ((attr->ia_valid & ATTR_CTIME) != 0)
|
||||||
|
{
|
||||||
info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
|
info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
|
||||||
ncp_date_unix2dos(attr->ia_ctime,
|
ncp_date_unix2dos(attr->ia_ctime,
|
||||||
&(info.creationTime), &(info.creationDate));
|
&(info.creationTime), &(info.creationDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((attr->ia_valid & ATTR_MTIME) != 0) {
|
if ((attr->ia_valid & ATTR_MTIME) != 0)
|
||||||
|
{
|
||||||
info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
|
info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
|
||||||
ncp_date_unix2dos(attr->ia_mtime,
|
ncp_date_unix2dos(attr->ia_mtime,
|
||||||
&(info.modifyTime), &(info.modifyDate));
|
&(info.modifyTime), &(info.modifyDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((attr->ia_valid & ATTR_ATIME) != 0) {
|
if ((attr->ia_valid & ATTR_ATIME) != 0)
|
||||||
|
{
|
||||||
__u16 dummy;
|
__u16 dummy;
|
||||||
info_mask |= (DM_LAST_ACCESS_DATE);
|
info_mask |= (DM_LAST_ACCESS_DATE);
|
||||||
ncp_date_unix2dos(attr->ia_ctime,
|
ncp_date_unix2dos(attr->ia_ctime,
|
||||||
&(dummy), &(info.lastAccessDate));
|
&(dummy), &(info.lastAccessDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info_mask != 0) {
|
if (info_mask != 0)
|
||||||
|
{
|
||||||
if ((result =
|
if ((result =
|
||||||
ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
|
ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
|
||||||
NCP_ISTRUCT(inode),
|
NCP_ISTRUCT(inode),
|
||||||
info_mask,
|
info_mask,
|
||||||
&info)) != 0) {
|
&info)) != 0)
|
||||||
|
{
|
||||||
result = -EACCES;
|
result = -EACCES;
|
||||||
|
|
||||||
|
if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
|
||||||
|
{
|
||||||
|
/* NetWare seems not to allow this. I
|
||||||
|
do not know why. So, just tell the
|
||||||
|
user everything went fine. This is
|
||||||
|
a terrible hack, but I do not know
|
||||||
|
how to do this correctly. */
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
if ((attr->ia_valid & ATTR_SIZE) != 0)
|
||||||
|
{
|
||||||
int written;
|
int written;
|
||||||
|
|
||||||
DPRINTK("ncpfs: trying to change size of %s to %ld\n",
|
DPRINTK("ncpfs: trying to change size of %s to %ld\n",
|
||||||
NCP_ISTRUCT(inode)->entryName, attr->ia_size);
|
NCP_ISTRUCT(inode)->entryName, attr->ia_size);
|
||||||
|
|
||||||
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
|
if ((result = ncp_make_open(inode, O_RDWR)) < 0)
|
||||||
|
{
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +466,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;
|
||||||
}
|
}
|
||||||
@@ -447,6 +478,8 @@ int ncp_current_malloced;
|
|||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
|
|
||||||
|
char kernel_version[] = UTS_RELEASE;
|
||||||
|
|
||||||
static struct file_system_type ncp_fs_type = {
|
static struct file_system_type ncp_fs_type = {
|
||||||
ncp_read_super, "ncpfs", 0, NULL
|
ncp_read_super, "ncpfs", 0, NULL
|
||||||
};
|
};
|
||||||
@@ -463,6 +496,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
166
kernel-1.2/src/ioctl.c
Normal file
166
kernel-1.2/src/ioctl.c
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* ioctl.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#ifdef MODULE
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <asm/segment.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/ncp_fs.h>
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/ncp.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_ioctl (struct inode * inode, struct file * filp,
|
||||||
|
unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
struct ncp_ioctl_request request;
|
||||||
|
struct ncp_fs_info info;
|
||||||
|
struct ncp_server *server = NCP_SERVER(inode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Binary compatible with 1.3.XX releases.
|
||||||
|
* Take this out in 2.1.0 development series.
|
||||||
|
* <mec@duracef.shout.net> 12 Mar 1996
|
||||||
|
*/
|
||||||
|
switch(cmd) {
|
||||||
|
case _IOR('n', 1, unsigned char *):
|
||||||
|
cmd = NCP_IOC_NCPREQUEST;
|
||||||
|
break;
|
||||||
|
case _IOR('u', 1, uid_t):
|
||||||
|
cmd = NCP_IOC_GETMOUNTUID;
|
||||||
|
break;
|
||||||
|
case _IO('l', 1):
|
||||||
|
cmd = NCP_IOC_CONN_LOGGED_IN;
|
||||||
|
break;
|
||||||
|
case _IOWR('i', 1, unsigned char *):
|
||||||
|
cmd = NCP_IOC_GET_FS_INFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cmd) {
|
||||||
|
case NCP_IOC_NCPREQUEST:
|
||||||
|
|
||||||
|
if ( (permission(inode, MAY_WRITE) != 0)
|
||||||
|
&& (current->uid != server->m.mounted_uid))
|
||||||
|
{
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = verify_area(VERIFY_READ, (char *)arg,
|
||||||
|
sizeof(request))) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
|
||||||
|
sizeof(request));
|
||||||
|
|
||||||
|
if ( (request.function > 255)
|
||||||
|
|| (request.size >
|
||||||
|
NCP_PACKET_SIZE - sizeof(struct ncp_request_header)))
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
|
||||||
|
NCP_PACKET_SIZE)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_lock_server(server);
|
||||||
|
|
||||||
|
/* FIXME: We hack around in the server's structures
|
||||||
|
here to be able to use ncp_request */
|
||||||
|
|
||||||
|
server->has_subfunction = 0;
|
||||||
|
server->current_size = request.size;
|
||||||
|
memcpy_fromfs(server->packet, request.data, request.size);
|
||||||
|
|
||||||
|
ncp_request(server, request.function);
|
||||||
|
|
||||||
|
DPRINTK("ncp_ioctl: copy %d bytes\n",
|
||||||
|
server->reply_size);
|
||||||
|
memcpy_tofs(request.data, server->packet, server->reply_size);
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
if ( (permission(inode, MAY_WRITE) != 0)
|
||||||
|
&& (current->uid != server->m.mounted_uid))
|
||||||
|
{
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = verify_area(VERIFY_WRITE, (char *)arg,
|
||||||
|
sizeof(info))) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy_fromfs(&info, (struct ncp_fs_info *)arg,
|
||||||
|
sizeof(info));
|
||||||
|
|
||||||
|
if (info.version != NCP_GET_FS_INFO_VERSION)
|
||||||
|
{
|
||||||
|
DPRINTK("info.version invalid: %d\n", info.version);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.addr = server->m.serv_addr;
|
||||||
|
info.mounted_uid = server->m.mounted_uid;
|
||||||
|
info.connection = server->connection;
|
||||||
|
info.buffer_size = server->buffer_size;
|
||||||
|
info.volume_number = NCP_ISTRUCT(inode)->volNumber;
|
||||||
|
info.directory_id = NCP_ISTRUCT(inode)->DosDirNum;
|
||||||
|
|
||||||
|
memcpy_tofs((struct ncp_fs_info *)arg, &info, sizeof(info));
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case NCP_IOC_GETMOUNTUID:
|
||||||
|
|
||||||
|
if ( (permission(inode, MAY_READ) != 0)
|
||||||
|
&& (current->uid != server->m.mounted_uid))
|
||||||
|
{
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
|
||||||
|
sizeof(uid_t))) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
put_fs_word(server->m.mounted_uid, (uid_t*) arg);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
157
kernel-1.2/src/mmap.c
Normal file
157
kernel-1.2/src/mmap.c
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* mmap.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#ifdef MODULE
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <linux/stat.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/shm.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/mman.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/malloc.h>
|
||||||
|
#include <linux/fcntl.h>
|
||||||
|
#include <linux/ncp_fs.h>
|
||||||
|
|
||||||
|
#include "ncplib_kernel.h"
|
||||||
|
#include <asm/segment.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
static inline int min(int a, int b)
|
||||||
|
{
|
||||||
|
return a<b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the supplied page for mmap
|
||||||
|
*/
|
||||||
|
static unsigned long
|
||||||
|
ncp_file_mmap_nopage(struct vm_area_struct * area,
|
||||||
|
unsigned long address, unsigned long page, int no_share)
|
||||||
|
{
|
||||||
|
struct inode * inode = area->vm_inode;
|
||||||
|
unsigned int clear;
|
||||||
|
unsigned long tmp;
|
||||||
|
int bufsize;
|
||||||
|
int pos;
|
||||||
|
unsigned short fs;
|
||||||
|
|
||||||
|
address &= PAGE_MASK;
|
||||||
|
pos = address - area->vm_start + area->vm_offset;
|
||||||
|
|
||||||
|
clear = 0;
|
||||||
|
if (address + PAGE_SIZE > area->vm_end)
|
||||||
|
{
|
||||||
|
clear = address + PAGE_SIZE - area->vm_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* what we can read in one go */
|
||||||
|
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||||
|
|
||||||
|
fs = get_fs();
|
||||||
|
set_fs(get_ds());
|
||||||
|
|
||||||
|
if (ncp_make_open(inode, O_RDONLY) < 0)
|
||||||
|
{
|
||||||
|
clear = PAGE_SIZE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int already_read = 0;
|
||||||
|
int count = PAGE_SIZE - clear;
|
||||||
|
int to_read;
|
||||||
|
|
||||||
|
while (already_read < count)
|
||||||
|
{
|
||||||
|
int read_this_time;
|
||||||
|
|
||||||
|
if ((pos % bufsize) != 0)
|
||||||
|
{
|
||||||
|
to_read = bufsize - (pos % bufsize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
to_read = bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
to_read = min(to_read, count - already_read);
|
||||||
|
|
||||||
|
if (ncp_read(NCP_SERVER(inode),
|
||||||
|
NCP_FINFO(inode)->file_handle,
|
||||||
|
pos, to_read,
|
||||||
|
(char *)(page + already_read),
|
||||||
|
&read_this_time) != 0)
|
||||||
|
{
|
||||||
|
read_this_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += read_this_time;
|
||||||
|
already_read += read_this_time;
|
||||||
|
|
||||||
|
if (read_this_time < to_read)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set_fs(fs);
|
||||||
|
|
||||||
|
tmp = page + PAGE_SIZE;
|
||||||
|
while (clear--) {
|
||||||
|
*(char *)--tmp = 0;
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vm_operations_struct ncp_file_mmap = {
|
||||||
|
NULL, /* open */
|
||||||
|
NULL, /* close */
|
||||||
|
NULL, /* unmap */
|
||||||
|
NULL, /* protect */
|
||||||
|
NULL, /* sync */
|
||||||
|
NULL, /* advise */
|
||||||
|
ncp_file_mmap_nopage, /* nopage */
|
||||||
|
NULL, /* wppage */
|
||||||
|
NULL, /* swapout */
|
||||||
|
NULL, /* swapin */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* This is used for a general mmap of a ncp file */
|
||||||
|
int
|
||||||
|
ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
|
||||||
|
{
|
||||||
|
DPRINTK("ncp_mmap: called\n");
|
||||||
|
|
||||||
|
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||||
|
{
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only PAGE_COW or read-only supported now */
|
||||||
|
if (vma->vm_flags & VM_SHARED)
|
||||||
|
return -EINVAL;
|
||||||
|
if (!inode->i_sb || !S_ISREG(inode->i_mode))
|
||||||
|
return -EACCES;
|
||||||
|
if (!IS_RDONLY(inode)) {
|
||||||
|
inode->i_atime = CURRENT_TIME;
|
||||||
|
inode->i_dirt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vma->vm_inode = inode;
|
||||||
|
inode->i_count++;
|
||||||
|
vma->vm_ops = &ncp_file_mmap;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,13 +1,25 @@
|
|||||||
#include "ncplib.h"
|
#include <linux/config.h>
|
||||||
|
#ifdef MODULE
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ncplib_kernel.h"
|
||||||
|
|
||||||
typedef __u8 byte;
|
typedef __u8 byte;
|
||||||
typedef __u16 word;
|
typedef __u16 word;
|
||||||
typedef __u32 dword;
|
typedef __u32 dword;
|
||||||
|
|
||||||
|
static inline int min(int a, int b)
|
||||||
|
{
|
||||||
|
return a<b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assert_server_locked(struct ncp_server *server)
|
assert_server_locked(struct ncp_server *server)
|
||||||
{
|
{
|
||||||
if (server->lock == 0) {
|
if (server->lock == 0)
|
||||||
|
{
|
||||||
DPRINTK("ncpfs: server not locked!\n");
|
DPRINTK("ncpfs: server not locked!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +74,8 @@ ncp_add_pstring(struct ncp_server *server, const char *s)
|
|||||||
{
|
{
|
||||||
int len = strlen(s);
|
int len = strlen(s);
|
||||||
assert_server_locked(server);
|
assert_server_locked(server);
|
||||||
if (len > 255) {
|
if (len > 255)
|
||||||
|
{
|
||||||
DPRINTK("ncpfs: string too long: %s\n", s);
|
DPRINTK("ncpfs: string too long: %s\n", s);
|
||||||
len = 255;
|
len = 255;
|
||||||
}
|
}
|
||||||
@@ -117,14 +130,15 @@ ncp_reply_dword(struct ncp_server *server, int offset)
|
|||||||
|
|
||||||
int
|
int
|
||||||
ncp_negotiate_buffersize(struct ncp_server *server,
|
ncp_negotiate_buffersize(struct ncp_server *server,
|
||||||
int size, int *target) {
|
int size, int *target)
|
||||||
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_word(server, htons(size));
|
ncp_add_word(server, htons(size));
|
||||||
|
|
||||||
if ((result = ncp_request(server, 33)) != 0) {
|
if ((result = ncp_request(server, 33)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -145,7 +159,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
|||||||
ncp_init_request_s(server, 44);
|
ncp_init_request_s(server, 44);
|
||||||
ncp_add_byte(server, n);
|
ncp_add_byte(server, n);
|
||||||
|
|
||||||
if ((result = ncp_request(server, 22)) != 0) {
|
if ((result = ncp_request(server, 22)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -161,7 +176,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
|||||||
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
||||||
|
|
||||||
len = ncp_reply_byte(server, 29);
|
len = ncp_reply_byte(server, 29);
|
||||||
if (len > NCP_VOLNAME_LEN) {
|
if (len > NCP_VOLNAME_LEN)
|
||||||
|
{
|
||||||
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -172,24 +188,6 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
ncp_init_request_s(server, 5);
|
|
||||||
ncp_add_pstring(server, name);
|
|
||||||
|
|
||||||
if ((result = ncp_request(server, 22)) != 0) {
|
|
||||||
ncp_unlock_server(server);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
*target = ncp_reply_byte(server, 0);
|
|
||||||
ncp_unlock_server(server);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_close_file(struct ncp_server *server, const char *file_id)
|
ncp_close_file(struct ncp_server *server, const char *file_id)
|
||||||
{
|
{
|
||||||
@@ -199,7 +197,8 @@ ncp_close_file(struct ncp_server *server, const char *file_id)
|
|||||||
ncp_add_byte(server, 0);
|
ncp_add_byte(server, 0);
|
||||||
ncp_add_mem(server, file_id, 6);
|
ncp_add_mem(server, file_id, 6);
|
||||||
|
|
||||||
if ((result = ncp_request(server, 66)) != 0) {
|
if ((result = ncp_request(server, 66)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -216,12 +215,16 @@ ncp_add_handle_path(struct ncp_server *server,
|
|||||||
{
|
{
|
||||||
ncp_add_byte(server, vol_num);
|
ncp_add_byte(server, vol_num);
|
||||||
ncp_add_dword(server, dir_base);
|
ncp_add_dword(server, dir_base);
|
||||||
if (have_dir_base != 0) {
|
if (have_dir_base != 0)
|
||||||
|
{
|
||||||
ncp_add_byte(server, 1); /* dir_base */
|
ncp_add_byte(server, 1); /* dir_base */
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ncp_add_byte(server, 0xff); /* no handle */
|
ncp_add_byte(server, 0xff); /* no handle */
|
||||||
}
|
}
|
||||||
if (path != NULL) {
|
if (path != NULL)
|
||||||
|
{
|
||||||
ncp_add_byte(server, 1); /* 1 component */
|
ncp_add_byte(server, 1); /* 1 component */
|
||||||
ncp_add_pstring(server, path);
|
ncp_add_pstring(server, path);
|
||||||
}
|
}
|
||||||
@@ -244,79 +247,122 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return -EINVAL;
|
||||||
dir_base = dir->DosDirNum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 6); /* subfunction */
|
ncp_add_byte(server, 6); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, server->name_space[vol_num]);
|
||||||
ncp_add_byte(server, 0); /* dos name space as dest */
|
ncp_add_byte(server, server->name_space[vol_num]);
|
||||||
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)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
static inline int
|
||||||
target->nameLen = strlen(volname);
|
ncp_has_os2_namespace(struct ncp_server *server, __u8 volume)
|
||||||
strcpy(target->entryName, volname);
|
{
|
||||||
|
int result;
|
||||||
|
__u8 *namespace;
|
||||||
|
__u16 no_namespaces;
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */
|
||||||
|
ncp_add_word(server, 0);
|
||||||
|
ncp_add_byte(server, volume);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
|
{
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_namespaces = ncp_reply_word(server, 0);
|
||||||
|
namespace = ncp_reply_data(server, 2);
|
||||||
|
|
||||||
|
while (no_namespaces > 0)
|
||||||
|
{
|
||||||
|
DPRINTK("get_namespaces: found %d on %d\n", *namespace,volume);
|
||||||
|
|
||||||
|
if (*namespace == 4)
|
||||||
|
{
|
||||||
|
DPRINTK("get_namespaces: found OS2\n");
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
namespace += 1;
|
||||||
|
no_namespaces -= 1;
|
||||||
|
}
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_lookup_volume(struct ncp_server *server,
|
||||||
|
char *volname,
|
||||||
|
struct nw_info_struct *target)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
int volnum;
|
||||||
|
|
||||||
|
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 namespace */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(target, 0, sizeof(*target));
|
||||||
|
target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
|
||||||
|
target->volNumber = volnum = ncp_reply_byte(server, 8);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
|
||||||
|
server->name_space[volnum] = ncp_has_os2_namespace(server,volnum)?4:0;
|
||||||
|
|
||||||
|
DPRINTK("lookup_vol: namespace[%d] = %d\n",
|
||||||
|
volnum, server->name_space[volnum]);
|
||||||
|
|
||||||
|
target->nameLen = strlen(volname);
|
||||||
|
strcpy(target->entryName, volname);
|
||||||
|
target->attributes = aDIR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||||
struct nw_info_struct *file,
|
struct nw_info_struct *file,
|
||||||
@@ -327,16 +373,17 @@ ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
|||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 7); /* subfunction */
|
ncp_add_byte(server, 7); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, server->name_space[file->volNumber]);
|
||||||
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||||
|
|
||||||
ncp_add_dword(server, info_mask);
|
ncp_add_dword(server, info_mask);
|
||||||
ncp_add_mem(server, info, sizeof(*info));
|
ncp_add_mem(server, info, sizeof(*info));
|
||||||
ncp_add_handle_path(server, file->volNumber,
|
ncp_add_handle_path(server, file->volNumber,
|
||||||
file->DosDirNum, 1, NULL);
|
file->dirEntNum, 1, NULL);
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0) {
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -353,13 +400,14 @@ ncp_del_file_or_subdir(struct ncp_server *server,
|
|||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 8); /* subfunction */
|
ncp_add_byte(server, 8); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, server->name_space[dir->volNumber]);
|
||||||
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||||
ncp_add_handle_path(server, dir->volNumber,
|
ncp_add_handle_path(server, dir->volNumber,
|
||||||
dir->DosDirNum, 1, name);
|
dir->dirEntNum, 1, name);
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0) {
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -388,28 +436,37 @@ 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;
|
||||||
|
__u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber;
|
||||||
|
|
||||||
|
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, server->name_space[volume]);
|
||||||
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
|
||||||
for directories */
|
for directories */
|
||||||
ncp_add_word(server, desired_acc_rights);
|
ncp_add_word(server, desired_acc_rights);
|
||||||
|
|
||||||
if (dir != NULL) {
|
if (dir != NULL)
|
||||||
ncp_add_handle_path(server, dir->volNumber,
|
{
|
||||||
dir->DosDirNum, 1, name);
|
ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name);
|
||||||
} else {
|
}
|
||||||
ncp_add_handle_path(server,
|
else
|
||||||
target->i.volNumber, target->i.DosDirNum,
|
{
|
||||||
|
ncp_add_handle_path(server, volume, target->i.dirEntNum,
|
||||||
1, NULL);
|
1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0) {
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -418,7 +475,8 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
|||||||
target->server_file_handle = ncp_reply_dword(server, 0);
|
target->server_file_handle = ncp_reply_dword(server, 0);
|
||||||
target->open_create_action = ncp_reply_byte(server, 4);
|
target->open_create_action = ncp_reply_byte(server, 4);
|
||||||
|
|
||||||
if (dir != NULL) {
|
if (dir != NULL)
|
||||||
|
{
|
||||||
/* in target there's a new finfo to fill */
|
/* in target there's a new finfo to fill */
|
||||||
ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
|
ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
|
||||||
}
|
}
|
||||||
@@ -439,11 +497,12 @@ ncp_initialize_search(struct ncp_server *server,
|
|||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 2); /* subfunction */
|
ncp_add_byte(server, 2); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, server->name_space[dir->volNumber]);
|
||||||
ncp_add_byte(server, 0); /* reserved */
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
|
ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL);
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0) {
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -464,7 +523,7 @@ ncp_search_for_file_or_subdir(struct ncp_server *server,
|
|||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 3); /* subfunction */
|
ncp_add_byte(server, 3); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, server->name_space[seq->volNumber]);
|
||||||
ncp_add_byte(server, 0); /* data stream (???) */
|
ncp_add_byte(server, 0); /* data stream (???) */
|
||||||
ncp_add_word(server, 0xffff); /* Search attribs */
|
ncp_add_word(server, 0xffff); /* Search attribs */
|
||||||
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
||||||
@@ -473,7 +532,8 @@ ncp_search_for_file_or_subdir(struct ncp_server *server,
|
|||||||
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
||||||
ncp_add_byte(server, '*');
|
ncp_add_byte(server, '*');
|
||||||
|
|
||||||
if ((result = ncp_request(server, 87)) != 0) {
|
if ((result = ncp_request(server, 87)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -498,19 +558,19 @@ ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
|
|||||||
|
|
||||||
ncp_init_request(server);
|
ncp_init_request(server);
|
||||||
ncp_add_byte(server, 4); /* subfunction */
|
ncp_add_byte(server, 4); /* subfunction */
|
||||||
ncp_add_byte(server, 0); /* dos name space */
|
ncp_add_byte(server, server->name_space[old_dir->volNumber]);
|
||||||
ncp_add_byte(server, 1); /* rename flag */
|
ncp_add_byte(server, 1); /* rename flag */
|
||||||
ncp_add_word(server, 0x8006); /* search attributes */
|
ncp_add_word(server, 0x8006); /* search attributes */
|
||||||
|
|
||||||
/* source Handle Path */
|
/* source Handle Path */
|
||||||
ncp_add_byte(server, old_dir->volNumber);
|
ncp_add_byte(server, old_dir->volNumber);
|
||||||
ncp_add_dword(server, old_dir->DosDirNum);
|
ncp_add_dword(server, old_dir->dirEntNum);
|
||||||
ncp_add_byte(server, 1);
|
ncp_add_byte(server, 1);
|
||||||
ncp_add_byte(server, 1); /* 1 source component */
|
ncp_add_byte(server, 1); /* 1 source component */
|
||||||
|
|
||||||
/* dest Handle Path */
|
/* dest Handle Path */
|
||||||
ncp_add_byte(server, new_dir->volNumber);
|
ncp_add_byte(server, new_dir->volNumber);
|
||||||
ncp_add_dword(server, new_dir->DosDirNum);
|
ncp_add_dword(server, new_dir->dirEntNum);
|
||||||
ncp_add_byte(server, 1);
|
ncp_add_byte(server, 1);
|
||||||
ncp_add_byte(server, 1); /* 1 destination component */
|
ncp_add_byte(server, 1); /* 1 destination component */
|
||||||
|
|
||||||
@@ -539,14 +599,15 @@ ncp_read(struct ncp_server *server, const char *file_id,
|
|||||||
ncp_add_dword(server, htonl(offset));
|
ncp_add_dword(server, htonl(offset));
|
||||||
ncp_add_word(server, htons(to_read));
|
ncp_add_word(server, htons(to_read));
|
||||||
|
|
||||||
if ((result = ncp_request(server, 72)) != 0) {
|
if ((result = ncp_request(server, 72)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
||||||
|
|
||||||
memcpy_tofs(target, ncp_reply_data(server, 2), *bytes_read);
|
memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
|
||||||
|
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -566,7 +627,8 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
|||||||
ncp_add_word(server, htons(to_write));
|
ncp_add_word(server, htons(to_write));
|
||||||
ncp_add_mem_fromfs(server, source, to_write);
|
ncp_add_mem_fromfs(server, source, to_write);
|
||||||
|
|
||||||
if ((result = ncp_request(server, 73)) != 0) {
|
if ((result = ncp_request(server, 73)) != 0)
|
||||||
|
{
|
||||||
ncp_unlock_server(server);
|
ncp_unlock_server(server);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
@@ -7,7 +7,11 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* #include <linux/module.h> */
|
#include <linux/config.h>
|
||||||
|
#ifdef MODULE
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/ncp_fs.h>
|
#include <linux/ncp_fs.h>
|
||||||
@@ -25,52 +29,10 @@
|
|||||||
#include <linux/ncp.h>
|
#include <linux/ncp.h>
|
||||||
#include <linux/ncp_fs.h>
|
#include <linux/ncp_fs.h>
|
||||||
#include <linux/ncp_fs_sb.h>
|
#include <linux/ncp_fs_sb.h>
|
||||||
#include <net/sock.h>
|
#include "/usr/src/linux/net/inet/sock.h"
|
||||||
|
|
||||||
|
|
||||||
#define _S(nr) (1<<((nr)-1))
|
#define _S(nr) (1<<((nr)-1))
|
||||||
static int _recvfrom(struct socket *sock, unsigned char *ubuf,
|
|
||||||
int size, int noblock, unsigned flags,
|
|
||||||
struct sockaddr_ipx *sa, int *addr_len)
|
|
||||||
{
|
|
||||||
struct iovec iov;
|
|
||||||
struct msghdr msg;
|
|
||||||
|
|
||||||
iov.iov_base = ubuf;
|
|
||||||
iov.iov_len = size;
|
|
||||||
|
|
||||||
msg.msg_name = (void *)sa;
|
|
||||||
msg.msg_namelen = 0;
|
|
||||||
if (addr_len)
|
|
||||||
msg.msg_namelen = *addr_len;
|
|
||||||
msg.msg_accrights = NULL;
|
|
||||||
msg.msg_iov = &iov;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
|
|
||||||
return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _sendto(struct socket *sock, const void *buff,
|
|
||||||
int len, int nonblock, unsigned flags,
|
|
||||||
struct sockaddr_ipx *sa, int addr_len)
|
|
||||||
|
|
||||||
{
|
|
||||||
struct iovec iov;
|
|
||||||
struct msghdr msg;
|
|
||||||
|
|
||||||
iov.iov_base = (void *)buff;
|
|
||||||
iov.iov_len = len;
|
|
||||||
|
|
||||||
msg.msg_name = (void *)sa;
|
|
||||||
msg.msg_namelen = addr_len;
|
|
||||||
msg.msg_accrights = NULL;
|
|
||||||
msg.msg_iov = &iov;
|
|
||||||
msg.msg_iovlen = 1;
|
|
||||||
|
|
||||||
return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ncp_wdog_data_ready(struct sock *sk, int len)
|
ncp_wdog_data_ready(struct sock *sk, int len)
|
||||||
{
|
{
|
||||||
@@ -80,15 +42,16 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
|||||||
{
|
{
|
||||||
unsigned char packet_buf[2];
|
unsigned char packet_buf[2];
|
||||||
struct sockaddr_ipx sender;
|
struct sockaddr_ipx sender;
|
||||||
int addr_len;
|
int addr_len = sizeof(struct sockaddr_ipx);
|
||||||
int result;
|
int result;
|
||||||
unsigned short fs;
|
unsigned short fs;
|
||||||
|
|
||||||
fs = get_fs();
|
fs = get_fs();
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
|
|
||||||
result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
result = sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||||
&sender, &addr_len);
|
(struct sockaddr *)&sender,
|
||||||
|
&addr_len);
|
||||||
|
|
||||||
if ( (result != 2)
|
if ( (result != 2)
|
||||||
|| (packet_buf[1] != '?')
|
|| (packet_buf[1] != '?')
|
||||||
@@ -96,16 +59,19 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Error, throw away the complete packet */
|
/* Error, throw away the complete packet */
|
||||||
_recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||||
&sender, &addr_len);
|
(struct sockaddr *)&sender,
|
||||||
|
&addr_len);
|
||||||
|
|
||||||
printk("ncpfs: got strange packet on watchdog "
|
printk("ncpfs: got strange packet on watchdog "
|
||||||
"socket\n");
|
"socket\n");
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
int result;
|
int result;
|
||||||
DPRINTK("ncpfs: got watchdog from:\n");
|
DDPRINTK("ncpfs: got watchdog from:\n");
|
||||||
DPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
|
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
|
||||||
" conn:%02X,type:%c\n",
|
" conn:%02X,type:%c\n",
|
||||||
htonl(sender.sipx_network),
|
htonl(sender.sipx_network),
|
||||||
sender.sipx_node[0], sender.sipx_node[1],
|
sender.sipx_node[0], sender.sipx_node[1],
|
||||||
@@ -115,9 +81,11 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
|||||||
packet_buf[0], packet_buf[1]);
|
packet_buf[0], packet_buf[1]);
|
||||||
|
|
||||||
packet_buf[1] = 'Y';
|
packet_buf[1] = 'Y';
|
||||||
result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
|
result = sock->ops->sendto(sock, (void *)packet_buf,
|
||||||
&sender, sizeof(sender));
|
2, 1, 0,
|
||||||
DPRINTK("send result: %d\n", result);
|
(struct sockaddr *)&sender,
|
||||||
|
sizeof(sender));
|
||||||
|
DDPRINTK("send result: %d\n", result);
|
||||||
}
|
}
|
||||||
set_fs(fs);
|
set_fs(fs);
|
||||||
}
|
}
|
||||||
@@ -135,8 +103,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
|||||||
if ( (server == NULL)
|
if ( (server == NULL)
|
||||||
|| ((file = server->wdog_filp) == NULL)
|
|| ((file = server->wdog_filp) == NULL)
|
||||||
|| ((inode = file->f_inode) == NULL)
|
|| ((inode = file->f_inode) == NULL)
|
||||||
|| (!S_ISSOCK(inode->i_mode))) {
|
|| (!S_ISSOCK(inode->i_mode)))
|
||||||
|
{
|
||||||
printk("ncp_catch_watchdog: did not get valid server!\n");
|
printk("ncp_catch_watchdog: did not get valid server!\n");
|
||||||
server->data_ready = NULL;
|
server->data_ready = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -144,7 +112,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
|||||||
|
|
||||||
sock = &(inode->u.socket_i);
|
sock = &(inode->u.socket_i);
|
||||||
|
|
||||||
if (sock->type != SOCK_DGRAM) {
|
if (sock->type != SOCK_DGRAM)
|
||||||
|
{
|
||||||
printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
|
printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
|
||||||
server->data_ready = NULL;
|
server->data_ready = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -152,7 +121,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
|||||||
|
|
||||||
sk = (struct sock *)(sock->data);
|
sk = (struct sock *)(sock->data);
|
||||||
|
|
||||||
if (sk == NULL) {
|
if (sk == NULL)
|
||||||
|
{
|
||||||
printk("ncp_catch_watchdog: sk == NULL");
|
printk("ncp_catch_watchdog: sk == NULL");
|
||||||
server->data_ready = NULL;
|
server->data_ready = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -162,7 +132,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
|||||||
(unsigned int)(sk->data_ready),
|
(unsigned int)(sk->data_ready),
|
||||||
(unsigned int)(server->data_ready));
|
(unsigned int)(server->data_ready));
|
||||||
|
|
||||||
if (sk->data_ready == ncp_wdog_data_ready) {
|
if (sk->data_ready == ncp_wdog_data_ready)
|
||||||
|
{
|
||||||
printk("ncp_catch_watchdog: already done\n");
|
printk("ncp_catch_watchdog: already done\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -183,8 +154,8 @@ ncp_dont_catch_watchdog(struct ncp_server *server)
|
|||||||
if ( (server == NULL)
|
if ( (server == NULL)
|
||||||
|| ((file = server->wdog_filp) == NULL)
|
|| ((file = server->wdog_filp) == NULL)
|
||||||
|| ((inode = file->f_inode) == NULL)
|
|| ((inode = file->f_inode) == NULL)
|
||||||
|| (!S_ISSOCK(inode->i_mode))) {
|
|| (!S_ISSOCK(inode->i_mode)))
|
||||||
|
{
|
||||||
printk("ncp_dont_catch_watchdog: "
|
printk("ncp_dont_catch_watchdog: "
|
||||||
"did not get valid server!\n");
|
"did not get valid server!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -192,25 +163,29 @@ ncp_dont_catch_watchdog(struct ncp_server *server)
|
|||||||
|
|
||||||
sock = &(inode->u.socket_i);
|
sock = &(inode->u.socket_i);
|
||||||
|
|
||||||
if (sock->type != SOCK_DGRAM) {
|
if (sock->type != SOCK_DGRAM)
|
||||||
|
{
|
||||||
printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
|
printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk = (struct sock *)(sock->data);
|
sk = (struct sock *)(sock->data);
|
||||||
|
|
||||||
if (sk == NULL) {
|
if (sk == NULL)
|
||||||
|
{
|
||||||
printk("ncp_dont_catch_watchdog: sk == NULL");
|
printk("ncp_dont_catch_watchdog: sk == NULL");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->data_ready == NULL) {
|
if (server->data_ready == NULL)
|
||||||
|
{
|
||||||
printk("ncp_dont_catch_watchdog: "
|
printk("ncp_dont_catch_watchdog: "
|
||||||
"server->data_ready == NULL\n");
|
"server->data_ready == NULL\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sk->data_ready != ncp_wdog_data_ready) {
|
if (sk->data_ready != ncp_wdog_data_ready)
|
||||||
|
{
|
||||||
printk("ncp_dont_catch_watchdog: "
|
printk("ncp_dont_catch_watchdog: "
|
||||||
"sk->data_callback != ncp_data_callback\n");
|
"sk->data_callback != ncp_data_callback\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -247,7 +222,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
int timeout;
|
int timeout;
|
||||||
int retrans;
|
int retrans;
|
||||||
int major_timeout_seen;
|
int major_timeout_seen;
|
||||||
char *server_name;
|
int acknowledge_seen;
|
||||||
int n;
|
int n;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
unsigned long old_mask;
|
unsigned long old_mask;
|
||||||
@@ -263,30 +238,32 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
inode = file->f_inode;
|
inode = file->f_inode;
|
||||||
select = file->f_op->select;
|
select = file->f_op->select;
|
||||||
sock = &inode->u.socket_i;
|
sock = &inode->u.socket_i;
|
||||||
if (!sock) {
|
if (!sock)
|
||||||
|
{
|
||||||
printk("ncp_rpc_call: socki_lookup failed\n");
|
printk("ncp_rpc_call: socki_lookup failed\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
init_timeout = server->m.time_out;
|
init_timeout = server->m.time_out;
|
||||||
max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
|
max_timeout = NCP_MAX_RPC_TIMEOUT;
|
||||||
|
acknowledge_seen = 0;
|
||||||
retrans = server->m.retry_count;
|
retrans = server->m.retry_count;
|
||||||
major_timeout_seen = 0;
|
major_timeout_seen = 0;
|
||||||
server_name = server->m.server_name;
|
|
||||||
old_mask = current->blocked;
|
old_mask = current->blocked;
|
||||||
current->blocked |= ~(_S(SIGKILL)
|
current->blocked |= ~(_S(SIGKILL)
|
||||||
#if 0
|
#if 0
|
||||||
| _S(SIGSTOP)
|
| _S(SIGSTOP)
|
||||||
#endif
|
#endif
|
||||||
| ((server->m.flags & NCP_MOUNT_INTR)
|
| ((server->m.flags & NCP_MOUNT_INTR)
|
||||||
? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
|
? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
|
||||||
? _S(SIGINT) : 0)
|
? _S(SIGINT) : 0)
|
||||||
| (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
|
| (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
|
||||||
? _S(SIGQUIT) : 0))
|
? _S(SIGQUIT) : 0))
|
||||||
: 0));
|
: 0));
|
||||||
fs = get_fs();
|
fs = get_fs();
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
|
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
|
||||||
/* DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
{
|
||||||
|
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||||
htonl(server->m.serv_addr.sipx_network),
|
htonl(server->m.serv_addr.sipx_network),
|
||||||
server->m.serv_addr.sipx_node[0],
|
server->m.serv_addr.sipx_node[0],
|
||||||
server->m.serv_addr.sipx_node[1],
|
server->m.serv_addr.sipx_node[1],
|
||||||
@@ -294,7 +271,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
server->m.serv_addr.sipx_node[3],
|
server->m.serv_addr.sipx_node[3],
|
||||||
server->m.serv_addr.sipx_node[4],
|
server->m.serv_addr.sipx_node[4],
|
||||||
server->m.serv_addr.sipx_node[5],
|
server->m.serv_addr.sipx_node[5],
|
||||||
ntohs(server->m.serv_addr.sipx_port));*/
|
ntohs(server->m.serv_addr.sipx_port));
|
||||||
DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
|
DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
|
||||||
"seq: %d",
|
"seq: %d",
|
||||||
request.type,
|
request.type,
|
||||||
@@ -303,10 +280,12 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
DDPRINTK(" func: %d\n",
|
DDPRINTK(" func: %d\n",
|
||||||
request.function);
|
request.function);
|
||||||
|
|
||||||
result = _sendto(sock, (void *) start, size, 0, 0,
|
result = sock->ops->sendto(sock, (void *) start, size, 0, 0,
|
||||||
&(server->m.serv_addr),
|
(struct sockaddr *)
|
||||||
sizeof(server->m.serv_addr));
|
&(server->m.serv_addr),
|
||||||
if (result < 0) {
|
sizeof(server->m.serv_addr));
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
printk("ncp_rpc_call: send error = %d\n", result);
|
printk("ncp_rpc_call: send error = %d\n", result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -315,39 +294,45 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
wait_table.entry = &entry;
|
wait_table.entry = &entry;
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
if ( !select(inode, file, SEL_IN, &wait_table)
|
if ( !select(inode, file, SEL_IN, &wait_table)
|
||||||
&& !select(inode, file, SEL_IN, NULL)) {
|
&& !select(inode, file, SEL_IN, NULL))
|
||||||
if (timeout > max_timeout) {
|
{
|
||||||
/* JEJB/JSP 2/7/94
|
if (timeout > max_timeout)
|
||||||
* This is useful to see if the system is
|
{
|
||||||
* hanging */
|
/* JEJB/JSP 2/7/94
|
||||||
printk("NCP max timeout reached on %s\n",
|
* This is useful to see if the system is
|
||||||
server_name);
|
* hanging */
|
||||||
timeout = max_timeout;
|
if (acknowledge_seen == 0)
|
||||||
|
{
|
||||||
|
printk("NCP max timeout reached\n");
|
||||||
|
}
|
||||||
|
timeout = max_timeout;
|
||||||
}
|
}
|
||||||
current->timeout = jiffies + timeout;
|
current->timeout = jiffies + timeout;
|
||||||
schedule();
|
schedule();
|
||||||
remove_wait_queue(entry.wait_address, &entry.wait);
|
remove_wait_queue(entry.wait_address, &entry.wait);
|
||||||
current->state = TASK_RUNNING;
|
current->state = TASK_RUNNING;
|
||||||
if (current->signal & ~current->blocked) {
|
if (current->signal & ~current->blocked)
|
||||||
|
{
|
||||||
current->timeout = 0;
|
current->timeout = 0;
|
||||||
result = -ERESTARTSYS;
|
result = -ERESTARTSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!current->timeout) {
|
if (!current->timeout)
|
||||||
|
{
|
||||||
if (n < retrans)
|
if (n < retrans)
|
||||||
continue;
|
continue;
|
||||||
if (server->m.flags & NCP_MOUNT_SOFT) {
|
if (server->m.flags & NCP_MOUNT_SOFT)
|
||||||
printk("NCP server %s not responding, "
|
{
|
||||||
"timed out\n", server_name);
|
printk("NCP server not responding\n");
|
||||||
result = -EIO;
|
result = -EIO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n = 0;
|
n = 0;
|
||||||
timeout = init_timeout;
|
timeout = init_timeout;
|
||||||
init_timeout <<= 1;
|
init_timeout <<= 1;
|
||||||
if (!major_timeout_seen) {
|
if (!major_timeout_seen)
|
||||||
printk("NCP server %s not responding, "
|
{
|
||||||
"still trying\n", server_name);
|
printk("NCP server not responding\n");
|
||||||
}
|
}
|
||||||
major_timeout_seen = 1;
|
major_timeout_seen = 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -363,30 +348,39 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
/* Get the header from the next packet using a peek, so keep it
|
/* Get the header from the next packet using a peek, so keep it
|
||||||
* on the recv queue. If it is wrong, it will be some reply
|
* on the recv queue. If it is wrong, it will be some reply
|
||||||
* we don't now need, so discard it */
|
* we don't now need, so discard it */
|
||||||
result = _recvfrom(sock, (void *)&reply,
|
result = sock->ops->recvfrom(sock, (void *)&reply,
|
||||||
sizeof(reply), 1, MSG_PEEK,
|
sizeof(reply), 1, MSG_PEEK,
|
||||||
NULL, &addrlen);
|
NULL, &addrlen);
|
||||||
if (result < 0) {
|
if (result < 0)
|
||||||
if (result == -EAGAIN) {
|
{
|
||||||
|
if (result == -EAGAIN)
|
||||||
|
{
|
||||||
DPRINTK("ncp_rpc_call: bad select ready\n");
|
DPRINTK("ncp_rpc_call: bad select ready\n");
|
||||||
goto re_select;
|
goto re_select;
|
||||||
}
|
}
|
||||||
if (result == -ECONNREFUSED) {
|
if (result == -ECONNREFUSED)
|
||||||
|
{
|
||||||
DPRINTK("ncp_rpc_call: server playing coy\n");
|
DPRINTK("ncp_rpc_call: server playing coy\n");
|
||||||
goto re_select;
|
goto re_select;
|
||||||
}
|
}
|
||||||
if (result != -ERESTARTSYS) {
|
if (result != -ERESTARTSYS)
|
||||||
|
{
|
||||||
printk("ncp_rpc_call: recv error = %d\n",
|
printk("ncp_rpc_call: recv error = %d\n",
|
||||||
-result);
|
-result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( (result == sizeof(reply))
|
if ( (result == sizeof(reply))
|
||||||
&& (reply.type == NCP_POSITIVE_ACK)) {
|
&& (reply.type == NCP_POSITIVE_ACK))
|
||||||
|
{
|
||||||
/* Throw away the packet */
|
/* Throw away the packet */
|
||||||
DPRINTK("ncp_rpc_call: got positive acknowledge\n");
|
DPRINTK("ncp_rpc_call: got positive acknowledge\n");
|
||||||
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
sock->ops->recvfrom(sock, (void *)&reply,
|
||||||
NULL, &addrlen);
|
sizeof(reply), 1, 0,
|
||||||
|
NULL, &addrlen);
|
||||||
|
n = 0;
|
||||||
|
timeout = max_timeout;
|
||||||
|
acknowledge_seen = 1;
|
||||||
goto re_select;
|
goto re_select;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,31 +397,34 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
|| ( (reply.sequence == request.sequence)
|
|| ( (reply.sequence == request.sequence)
|
||||||
&& (reply.conn_low == request.conn_low)
|
&& (reply.conn_low == request.conn_low)
|
||||||
/* seem to get wrong task from NW311 && (reply.task == request.task)*/
|
/* seem to get wrong task from NW311 && (reply.task == request.task)*/
|
||||||
&& (reply.conn_high == request.conn_high)))) {
|
&& (reply.conn_high == request.conn_high))))
|
||||||
|
{
|
||||||
if (major_timeout_seen)
|
if (major_timeout_seen)
|
||||||
printk("NCP server %s OK\n", server_name);
|
printk("NCP server OK\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* JEJB/JSP 2/7/94
|
/* JEJB/JSP 2/7/94
|
||||||
* we have xid mismatch, so discard the packet and start
|
* we have xid mismatch, so discard the packet and start
|
||||||
* again. What a hack! but I can't call recvfrom with
|
* again. What a hack! but I can't call recvfrom with
|
||||||
* a null buffer yet. */
|
* a null buffer yet. */
|
||||||
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
|
sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
||||||
&addrlen);
|
NULL, &addrlen);
|
||||||
#if 1
|
|
||||||
printk("ncp_rpc_call: reply mismatch\n");
|
DPRINTK("ncp_rpc_call: reply mismatch\n");
|
||||||
#endif
|
|
||||||
goto re_select;
|
goto re_select;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* we have the correct reply, so read into the correct place and
|
* we have the correct reply, so read into the correct place and
|
||||||
* return it
|
* return it
|
||||||
*/
|
*/
|
||||||
result = _recvfrom(sock, (void *)start, server->packet_size, 1, 0,
|
result = sock->ops->recvfrom(sock, (void *)start, server->packet_size,
|
||||||
NULL, &addrlen);
|
1, 0, NULL, &addrlen);
|
||||||
if (result < 0) {
|
if (result < 0)
|
||||||
|
{
|
||||||
printk("NCP: notice message: result=%d\n", result);
|
printk("NCP: notice message: result=%d\n", result);
|
||||||
} else if (result < sizeof(struct ncp_reply_header)) {
|
}
|
||||||
|
else if (result < sizeof(struct ncp_reply_header))
|
||||||
|
{
|
||||||
printk("NCP: just caught a too small read memory size..., "
|
printk("NCP: just caught a too small read memory size..., "
|
||||||
"email to NET channel\n");
|
"email to NET channel\n");
|
||||||
printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
|
printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
|
||||||
@@ -447,7 +444,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
static int
|
static int
|
||||||
ncp_do_request(struct ncp_server *server, int size)
|
ncp_do_request(struct ncp_server *server, int size)
|
||||||
{
|
{
|
||||||
if (server->lock == 0) {
|
if (server->lock == 0)
|
||||||
|
{
|
||||||
printk("ncpfs: Server not locked!\n");
|
printk("ncpfs: Server not locked!\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@@ -471,7 +469,8 @@ ncp_request(struct ncp_server *server, int function)
|
|||||||
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (server->has_subfunction != 0) {
|
if (server->has_subfunction != 0)
|
||||||
|
{
|
||||||
*(__u16 *)&(h->data[0]) = request_size - 2;
|
*(__u16 *)&(h->data[0]) = request_size - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +483,8 @@ ncp_request(struct ncp_server *server, int function)
|
|||||||
h->task = (current->pid) & 0xff;
|
h->task = (current->pid) & 0xff;
|
||||||
h->function = function;
|
h->function = function;
|
||||||
|
|
||||||
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0) {
|
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
|
||||||
|
{
|
||||||
DPRINTK("ncp_request_error: %d\n", result);
|
DPRINTK("ncp_request_error: %d\n", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -496,8 +496,9 @@ ncp_request(struct ncp_server *server, int function)
|
|||||||
|
|
||||||
result = reply->completion_code;
|
result = reply->completion_code;
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0)
|
||||||
DPRINTK("ncp_completion_code: %d\n", result);
|
{
|
||||||
|
DPRINTK("ncp_completion_code: %x\n", result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -518,7 +519,8 @@ ncp_connect(struct ncp_server *server)
|
|||||||
h->task = (current->pid) & 0xff;
|
h->task = (current->pid) & 0xff;
|
||||||
h->function = 0;
|
h->function = 0;
|
||||||
|
|
||||||
if ((result = ncp_do_request(server, sizeof(*h))) < 0) {
|
if ((result = ncp_do_request(server, sizeof(*h))) < 0)
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,9 +550,10 @@ ncp_disconnect(struct ncp_server *server)
|
|||||||
void
|
void
|
||||||
ncp_lock_server(struct ncp_server *server)
|
ncp_lock_server(struct ncp_server *server)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 0
|
||||||
/* For testing, only 1 process */
|
/* For testing, only 1 process */
|
||||||
if (server->lock != 0) {
|
if (server->lock != 0)
|
||||||
|
{
|
||||||
DPRINTK("ncpfs: server locked!!!\n");
|
DPRINTK("ncpfs: server locked!!!\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -562,7 +565,8 @@ ncp_lock_server(struct ncp_server *server)
|
|||||||
void
|
void
|
||||||
ncp_unlock_server(struct ncp_server *server)
|
ncp_unlock_server(struct ncp_server *server)
|
||||||
{
|
{
|
||||||
if (server->lock != 1) {
|
if (server->lock != 1)
|
||||||
|
{
|
||||||
printk("ncp_unlock_server: was not locked!\n");
|
printk("ncp_unlock_server: was not locked!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* ioctl.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 1995 by Volker Lendecke
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/* #include <linux/module.h>*/
|
|
||||||
|
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/ncp_fs.h>
|
|
||||||
#include <linux/ioctl.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/ncp.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
ncp_ioctl (struct inode * inode, struct file * filp,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
struct ncp_ioctl_request request;
|
|
||||||
struct ncp_server *server;
|
|
||||||
|
|
||||||
switch(cmd) {
|
|
||||||
case NCP_IOC_NCPREQUEST:
|
|
||||||
|
|
||||||
if (!suser()) {
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((result = verify_area(VERIFY_READ, (char *)arg,
|
|
||||||
sizeof(request))) != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
|
|
||||||
sizeof(request));
|
|
||||||
|
|
||||||
if ( (request.function > 255)
|
|
||||||
|| (request.size >
|
|
||||||
NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
|
|
||||||
NCP_PACKET_SIZE)) != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
server = NCP_SERVER(inode);
|
|
||||||
ncp_lock_server(server);
|
|
||||||
|
|
||||||
/* FIXME: We hack around in the server's structures
|
|
||||||
here to be able to use ncp_request */
|
|
||||||
|
|
||||||
server->has_subfunction = 0;
|
|
||||||
server->current_size =
|
|
||||||
request.size + sizeof(struct ncp_request_header);
|
|
||||||
memcpy_fromfs(server->packet, request.data,
|
|
||||||
request.size+sizeof(struct ncp_request_header));
|
|
||||||
|
|
||||||
|
|
||||||
ncp_request(server, request.function);
|
|
||||||
|
|
||||||
DPRINTK("ncp_ioctl: copy %d bytes\n",
|
|
||||||
server->reply_size);
|
|
||||||
memcpy_tofs(request.data, server->packet,
|
|
||||||
server->reply_size);
|
|
||||||
|
|
||||||
ncp_unlock_server(server);
|
|
||||||
|
|
||||||
return server->reply_size;
|
|
||||||
|
|
||||||
case NCP_IOC_GETMOUNTUID:
|
|
||||||
if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
|
|
||||||
sizeof(uid_t))) != 0) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
put_fs_word(NCP_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
76
lib/Makefile
Normal file
76
lib/Makefile
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#
|
||||||
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
|
#
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
ifeq ($(HAVE_ELF),yes)
|
||||||
|
PIC_FLAG = -fPIC
|
||||||
|
NCP_LIB = libncp.so.1.0
|
||||||
|
LIB_LINK_COMMAND = gcc -shared -Wl,-soname,libncp.so.1 -o $(NCP_LIB)
|
||||||
|
INSTALL_LIB = install $(NCP_LIB) -m 755 /lib; \
|
||||||
|
ln -sf $(NCP_LIB) /lib/libncp.so.1; \
|
||||||
|
ldconfig
|
||||||
|
export PIC_FLAG
|
||||||
|
else
|
||||||
|
NCP_LIB = libncp.a
|
||||||
|
LIB_LINK_COMMAND = ar r libncp.a
|
||||||
|
endif
|
||||||
|
|
||||||
|
CFLAGS += $(PIC_FLAG)
|
||||||
|
|
||||||
|
default:
|
||||||
|
make -C ..
|
||||||
|
|
||||||
|
all: libcom_err.a ncplib_err.o $(NCP_LIB)
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(INSTALL_LIB)
|
||||||
|
|
||||||
|
ncplib.o: ncplib.c ncplib_err.h
|
||||||
|
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
|
||||||
|
|
||||||
|
COM_ERR_CFILES = com_err/com_err.c com_err/error_message.c com_err/et_name.c \
|
||||||
|
com_err/init_et.c
|
||||||
|
COM_ERR_OFILES = com_err/com_err.o com_err/error_message.o com_err/et_name.o \
|
||||||
|
com_err/init_et.o
|
||||||
|
|
||||||
|
libcom_err.a: $(COM_ERR_CFILES)
|
||||||
|
make -C com_err
|
||||||
|
|
||||||
|
$(NCP_LIB): ncplib.o ncplib_err.o libcom_err.a
|
||||||
|
$(LIB_LINK_COMMAND) ncplib.o ncplib_err.o $(COM_ERR_OFILES)
|
||||||
|
ln -sf libncp.so.1.0 libncp.so.1
|
||||||
|
ln -sf libncp.so.1 libncp.so
|
||||||
|
export LD_LIBRARY_PATH=`pwd`:LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
ncplib_err.o: ncplib_err.h ncplib_err.c
|
||||||
|
$(CC) $(CFLAGS) -c ncplib_err.c
|
||||||
|
|
||||||
|
ncplib_err.h: ncplib_err.et
|
||||||
|
com_err/compile_et ncplib_err
|
||||||
|
ln -sf ../lib/ncplib_err.h ../include/ncplib_err.h
|
||||||
|
|
||||||
|
ncplib_err.c: ncplib_err.et
|
||||||
|
com_err/compile_et ncplib_err
|
||||||
|
|
||||||
|
dep: ncplib_err.h
|
||||||
|
make -C com_err dep
|
||||||
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
|
|
||||||
|
clean:
|
||||||
|
make -C com_err clean
|
||||||
|
rm -f *.o *~ ncplib_err.[ch] ../include/ncplib_err.h
|
||||||
|
rm -f libncp.*
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
make -C com_err mrproper
|
||||||
|
rm -f $(UTILS) .depend $(DISTFILE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# include a dependency file if one exists
|
||||||
|
#
|
||||||
|
ifeq (.depend,$(wildcard .depend))
|
||||||
|
include .depend
|
||||||
|
endif
|
||||||
|
|
||||||
49
lib/com_err/ChangeLog
Normal file
49
lib/com_err/ChangeLog
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
|
* Release of E2fsprogs version 1.02
|
||||||
|
|
||||||
|
Mon Sep 4 21:44:47 1995 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile.in: Added support for BSD shared libraries.
|
||||||
|
|
||||||
|
Sat Aug 12 03:11:28 1995 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile.in (install): Install static libraries in $(ulibdir)
|
||||||
|
(/usr/lib on Linux) instead of $(libdir) (/lib on Linux).
|
||||||
|
|
||||||
|
Sat Aug 5 11:44:17 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
|
||||||
|
|
||||||
|
* Makefile.in (DLL_INSTALL_DIR, ELF_INSTALL_DIR): Set the
|
||||||
|
installation directories correctly.
|
||||||
|
|
||||||
|
Thu Jun 15 23:39:51 1995 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile.in: Added support for ELF shared libraries.
|
||||||
|
Fixed typos in the compilation rules.
|
||||||
|
(distclean): Added compile_et.sh.
|
||||||
|
|
||||||
|
Sat Jun 10 19:56:13 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
|
||||||
|
|
||||||
|
* compile_et.sh.in: Use ET_DIR instead of srcdir to determine the
|
||||||
|
location of the et directory.
|
||||||
|
|
||||||
|
Thu Jun 8 12:45:41 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* vfprintf.c (vfprintf): Only compile this function if vfprintf
|
||||||
|
doesn't already exist and _doprnt does.
|
||||||
|
|
||||||
|
* compile_et.sh: Moved to compile_et.sh.in.
|
||||||
|
|
||||||
|
* Makefile.in: Rewritten to conform to GNU coding standards and
|
||||||
|
support separate compilation directories.
|
||||||
|
Don't preprocess compile_et.sh, as this is now done by configure.
|
||||||
|
|
||||||
|
Mon Nov 7 21:17:48 1994 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile: Added a dummy install target in case shared libraries
|
||||||
|
are not built.
|
||||||
|
|
||||||
|
Thu Sep 8 22:33:33 1994 (tytso@rsx-11)
|
||||||
|
|
||||||
|
* com_err.c (default_com_err_proc): Reversed order of \n\r to make
|
||||||
|
jik happy.
|
||||||
28
lib/com_err/Makefile
Normal file
28
lib/com_err/Makefile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# Makefile for the com_err library
|
||||||
|
#
|
||||||
|
|
||||||
|
OBJECTS = com_err.o error_message.o et_name.o init_et.o
|
||||||
|
CFLAGS = -Wall -O2 $(PIC_FLAG)
|
||||||
|
|
||||||
|
all: ../libcom_err.a
|
||||||
|
|
||||||
|
../libcom_err.a: $(OBJECTS)
|
||||||
|
ar r ../libcom_err.a $(OBJECTS)
|
||||||
|
|
||||||
|
dep:
|
||||||
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o ../libcom_err.a
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
rm -f .depend
|
||||||
|
|
||||||
|
#
|
||||||
|
# include a dependency file if one exists
|
||||||
|
#
|
||||||
|
ifeq (.depend,$(wildcard .depend))
|
||||||
|
include .depend
|
||||||
|
endif
|
||||||
|
|
||||||
96
lib/com_err/com_err.3
Normal file
96
lib/com_err/com_err.3
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
|
||||||
|
.\" Student Information Processing Board. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" $Header: /mit/krb5/.cvsroot/src/util/et/com_err.3,v 1.1 1993/06/03 12:29:34 tytso Exp $
|
||||||
|
.\"
|
||||||
|
.TH COM_ERR 3 "22 Nov 1988" SIPB
|
||||||
|
.SH NAME
|
||||||
|
com_err \- common error display routine
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
#include <com_err.h>
|
||||||
|
.PP
|
||||||
|
void com_err (whoami, code, format, ...);
|
||||||
|
const char *whoami;
|
||||||
|
long code;
|
||||||
|
const char *format;
|
||||||
|
.PP
|
||||||
|
proc = set_com_err_hook (proc);
|
||||||
|
.fi
|
||||||
|
void (*
|
||||||
|
.I proc
|
||||||
|
) (const char *, long, const char *, va_list);
|
||||||
|
.nf
|
||||||
|
.PP
|
||||||
|
proc = reset_com_err_hook ();
|
||||||
|
.PP
|
||||||
|
void initialize_XXXX_error_table ();
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.I Com_err
|
||||||
|
displays an error message on the standard error stream
|
||||||
|
.I stderr
|
||||||
|
(see
|
||||||
|
.IR stdio (3S))
|
||||||
|
composed of the
|
||||||
|
.I whoami
|
||||||
|
string, which should specify the program name or some subportion of
|
||||||
|
a program, followed by an error message generated from the
|
||||||
|
.I code
|
||||||
|
value (derived from
|
||||||
|
.IR compile_et (1)),
|
||||||
|
and a string produced using the
|
||||||
|
.I format
|
||||||
|
string and any following arguments, in the same style as
|
||||||
|
.IR fprintf (3).
|
||||||
|
|
||||||
|
The behavior of
|
||||||
|
.I com_err
|
||||||
|
can be modified using
|
||||||
|
.I set_com_err_hook;
|
||||||
|
this defines a procedure which is called with the arguments passed to
|
||||||
|
.I com_err,
|
||||||
|
instead of the default internal procedure which sends the formatted
|
||||||
|
text to error output. Thus the error messages from a program can all
|
||||||
|
easily be diverted to another form of diagnostic logging, such as
|
||||||
|
.IR syslog (3).
|
||||||
|
.I Reset_com_err_hook
|
||||||
|
may be used to restore the behavior of
|
||||||
|
.I com_err
|
||||||
|
to its default form. Both procedures return the previous ``hook''
|
||||||
|
value. These ``hook'' procedures must have the declaration given for
|
||||||
|
.I proc
|
||||||
|
above in the synopsis.
|
||||||
|
|
||||||
|
The
|
||||||
|
.I initialize_XXXX_error_table
|
||||||
|
routine is generated mechanically by
|
||||||
|
.IR compile_et (1)
|
||||||
|
from a source file containing names and associated strings. Each
|
||||||
|
table has a name of up to four characters, which is used in place of
|
||||||
|
the
|
||||||
|
.B XXXX
|
||||||
|
in the name of the routine. These routines should be called before
|
||||||
|
any of the corresponding error codes are used, so that the
|
||||||
|
.I com_err
|
||||||
|
library will recognize error codes from these tables when they are
|
||||||
|
used.
|
||||||
|
|
||||||
|
The
|
||||||
|
.B com_err.h
|
||||||
|
header file should be included in any source file that uses routines
|
||||||
|
from the
|
||||||
|
.I com_err
|
||||||
|
library; executable files must be linked using
|
||||||
|
.I ``-lcom_err''
|
||||||
|
in order to cause the
|
||||||
|
.I com_err
|
||||||
|
library to be included.
|
||||||
|
|
||||||
|
.\" .IR for manual entries
|
||||||
|
.\" .PP for paragraph breaks
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
compile_et (1), syslog (3).
|
||||||
|
|
||||||
|
Ken Raeburn, "A Common Error Description Library for UNIX".
|
||||||
114
lib/com_err/com_err.c
Normal file
114
lib/com_err/com_err.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1987, 1988 by MIT Student Information Processing Board.
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "com_err.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#if !defined(__STDC__) && !defined(STDARG_PROTOTYPES)
|
||||||
|
#include <varargs.h>
|
||||||
|
#define VARARGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
#ifdef __STDC__
|
||||||
|
default_com_err_proc (const char *whoami, errcode_t code, const
|
||||||
|
char *fmt, va_list args)
|
||||||
|
#else
|
||||||
|
default_com_err_proc (whoami, code, fmt, args)
|
||||||
|
const char *whoami;
|
||||||
|
errcode_t code;
|
||||||
|
const char *fmt;
|
||||||
|
va_list args;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (whoami) {
|
||||||
|
fputs(whoami, stderr);
|
||||||
|
fputs(": ", stderr);
|
||||||
|
}
|
||||||
|
if (code) {
|
||||||
|
fputs(error_message(code), stderr);
|
||||||
|
fputs(" ", stderr);
|
||||||
|
}
|
||||||
|
if (fmt) {
|
||||||
|
vfprintf (stderr, fmt, args);
|
||||||
|
}
|
||||||
|
/* should do this only on a tty in raw mode */
|
||||||
|
putc('\r', stderr);
|
||||||
|
putc('\n', stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
typedef void (*errf) (const char *, errcode_t, const char *, va_list);
|
||||||
|
#else
|
||||||
|
typedef void (*errf) ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
errf com_err_hook = default_com_err_proc;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||||
|
va_list args)
|
||||||
|
#else
|
||||||
|
void com_err_va (whoami, code, fmt, args)
|
||||||
|
const char *whoami;
|
||||||
|
errcode_t code;
|
||||||
|
const char *fmt;
|
||||||
|
va_list args;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
(*com_err_hook) (whoami, code, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef VARARGS
|
||||||
|
void com_err (const char *whoami,
|
||||||
|
errcode_t code,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
void com_err (va_alist)
|
||||||
|
va_dcl
|
||||||
|
{
|
||||||
|
const char *whoami, *fmt;
|
||||||
|
errcode_t code;
|
||||||
|
#endif
|
||||||
|
va_list pvar;
|
||||||
|
|
||||||
|
if (!com_err_hook)
|
||||||
|
com_err_hook = default_com_err_proc;
|
||||||
|
#ifdef VARARGS
|
||||||
|
va_start (pvar);
|
||||||
|
whoami = va_arg (pvar, const char *);
|
||||||
|
code = va_arg (pvar, errcode_t);
|
||||||
|
fmt = va_arg (pvar, const char *);
|
||||||
|
#else
|
||||||
|
va_start(pvar, fmt);
|
||||||
|
#endif
|
||||||
|
com_err_va (whoami, code, fmt, pvar);
|
||||||
|
va_end(pvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
errf set_com_err_hook (new_proc)
|
||||||
|
errf new_proc;
|
||||||
|
{
|
||||||
|
errf x = com_err_hook;
|
||||||
|
|
||||||
|
if (new_proc)
|
||||||
|
com_err_hook = new_proc;
|
||||||
|
else
|
||||||
|
com_err_hook = default_com_err_proc;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
errf reset_com_err_hook () {
|
||||||
|
errf x = com_err_hook;
|
||||||
|
com_err_hook = default_com_err_proc;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
40
lib/com_err/com_err.h
Normal file
40
lib/com_err/com_err.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Header file for common error description library.
|
||||||
|
*
|
||||||
|
* Copyright 1988, Student Information Processing Board of the
|
||||||
|
* Massachusetts Institute of Technology.
|
||||||
|
*
|
||||||
|
* For copyright and distribution info, see the documentation supplied
|
||||||
|
* with this package.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COM_ERR_H
|
||||||
|
|
||||||
|
typedef long errcode_t;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* ANSI C -- use prototypes etc */
|
||||||
|
void com_err (const char *, long, const char *, ...);
|
||||||
|
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||||
|
va_list args);
|
||||||
|
char const *error_message (long);
|
||||||
|
extern void (*com_err_hook) (const char *, long, const char *, va_list);
|
||||||
|
void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
|
||||||
|
(const char *, long, const char *, va_list);
|
||||||
|
void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
|
||||||
|
int init_error_table(const char * const *msgs, int base, int count);
|
||||||
|
#else
|
||||||
|
/* no prototypes */
|
||||||
|
void com_err ();
|
||||||
|
void com_err_va ();
|
||||||
|
char *error_message ();
|
||||||
|
extern void (*com_err_hook) ();
|
||||||
|
void (*set_com_err_hook ()) ();
|
||||||
|
void (*reset_com_err_hook ()) ();
|
||||||
|
int init_error_table();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __COM_ERR_H
|
||||||
|
#endif /* ! defined(__COM_ERR_H) */
|
||||||
554
lib/com_err/com_err.texinfo
Normal file
554
lib/com_err/com_err.texinfo
Normal file
@@ -0,0 +1,554 @@
|
|||||||
|
\input texinfo @c -*-texinfo-*-
|
||||||
|
|
||||||
|
@c $Header: /mit/krb5/.cvsroot/src/util/et/com_err.texinfo,v 1.1 1993/06/03 12:29:38 tytso Exp $
|
||||||
|
@c $Source: /mit/krb5/.cvsroot/src/util/et/com_err.texinfo,v $
|
||||||
|
@c $Locker: $
|
||||||
|
|
||||||
|
@c Note that although this source file is in texinfo format (more
|
||||||
|
@c or less), it is not yet suitable for turning into an ``info''
|
||||||
|
@c file. Sorry, maybe next time.
|
||||||
|
@c
|
||||||
|
@c In order to produce hardcopy documentation from a texinfo file,
|
||||||
|
@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
|
||||||
|
@c provided in this distribution. (texinfo.tex is from the Free
|
||||||
|
@c Software Foundation, and is under different copyright restrictions
|
||||||
|
@c from the rest of this package.)
|
||||||
|
|
||||||
|
@ifinfo
|
||||||
|
@barfo
|
||||||
|
@end ifinfo
|
||||||
|
|
||||||
|
@iftex
|
||||||
|
@tolerance 10000
|
||||||
|
|
||||||
|
@c Mutate section headers...
|
||||||
|
@begingroup
|
||||||
|
@catcode#=6
|
||||||
|
@gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
|
||||||
|
@endgroup
|
||||||
|
@end iftex
|
||||||
|
|
||||||
|
@setfilename com_err
|
||||||
|
@settitle A Common Error Description Library for UNIX
|
||||||
|
|
||||||
|
@ifinfo
|
||||||
|
This file documents the use of the Common Error Description library.
|
||||||
|
|
||||||
|
Copyright (C) 1987, 1988 Student Information Processing Board of the
|
||||||
|
Massachusetts Institute of Technology.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
that the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the software
|
||||||
|
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
|
||||||
|
make no representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
Note that the file texinfo.tex, provided with this distribution, is from
|
||||||
|
the Free Software Foundation, and is under different copyright restrictions
|
||||||
|
from the remainder of this package.
|
||||||
|
|
||||||
|
@end ifinfo
|
||||||
|
|
||||||
|
@ignore
|
||||||
|
Permission is granted to process this file through Tex and print the
|
||||||
|
results, provided the printed document carries copying permission
|
||||||
|
notice identical to this one except for the removal of this paragraph
|
||||||
|
(this paragraph not being relevant to the printed manual).
|
||||||
|
|
||||||
|
@end ignore
|
||||||
|
|
||||||
|
@setchapternewpage odd
|
||||||
|
|
||||||
|
@titlepage
|
||||||
|
@center @titlefont{A Common Error Description}
|
||||||
|
@center @titlefont{Library for UNIX}
|
||||||
|
@sp 2
|
||||||
|
@center Ken Raeburn
|
||||||
|
@center Bill Sommerfeld
|
||||||
|
@sp 1
|
||||||
|
@center MIT Student Information Processing Board
|
||||||
|
@sp 3
|
||||||
|
@center last updated 1 January 1989
|
||||||
|
@center for version 1.2
|
||||||
|
@center ***DRAFT COPY ONLY***
|
||||||
|
|
||||||
|
@vskip 2in
|
||||||
|
|
||||||
|
@center @b{Abstract}
|
||||||
|
|
||||||
|
UNIX has always had a clean and simple system call interface, with a
|
||||||
|
standard set of error codes passed between the kernel and user
|
||||||
|
programs. Unfortunately, the same cannot be said of many of the
|
||||||
|
libraries layered on top of the primitives provided by the kernel.
|
||||||
|
Typically, each one has used a different style of indicating errors to
|
||||||
|
their callers, leading to a total hodgepodge of error handling, and
|
||||||
|
considerable amounts of work for the programmer. This paper describes
|
||||||
|
a library and associated utilities which allows a more uniform way for
|
||||||
|
libraries to return errors to their callers, and for programs to
|
||||||
|
describe errors and exceptional conditions to their users.
|
||||||
|
|
||||||
|
@page
|
||||||
|
@vskip 0pt plus 1filll
|
||||||
|
|
||||||
|
Copyright @copyright{} 1987, 1988 by the Student Information Processing
|
||||||
|
Board of the Massachusetts Institute of Technology.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
that the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the software
|
||||||
|
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
|
||||||
|
make no representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
Note that the file texinfo.tex, provided with this distribution, is from
|
||||||
|
the Free Software Foundation, and is under different copyright restrictions
|
||||||
|
from the remainder of this package.
|
||||||
|
|
||||||
|
@end titlepage
|
||||||
|
|
||||||
|
@ifinfo
|
||||||
|
@c should put a menu here someday....
|
||||||
|
@end ifinfo
|
||||||
|
|
||||||
|
@page
|
||||||
|
|
||||||
|
@section Why com_err?
|
||||||
|
|
||||||
|
In building application software packages, a programmer often has to
|
||||||
|
deal with a number of libraries, each of which can use a different
|
||||||
|
error-reporting mechanism. Sometimes one of two values is returned,
|
||||||
|
indicating simply SUCCESS or FAILURE, with no description of errors
|
||||||
|
encountered. Sometimes it is an index into a table of text strings,
|
||||||
|
where the name of the table used is dependent on the library being
|
||||||
|
used when the error is generated; since each table starts numbering at
|
||||||
|
0 or 1, additional information as to the source of the error code is
|
||||||
|
needed to determine which table to look at. Sometimes no text messages are
|
||||||
|
supplied at all, and the programmer must supply them at any point at which
|
||||||
|
he may wish to report error conditions.
|
||||||
|
Often, a global variable is assigned some value describing the error, but
|
||||||
|
the programmer has to know in each case whether to look at @code{errno},
|
||||||
|
@code{h_errno}, the return value from @code{hes_err()}, or whatever other
|
||||||
|
variables or routines are specified.
|
||||||
|
And what happens if something
|
||||||
|
in the procedure of
|
||||||
|
examining or reporting the error changes the same variable?
|
||||||
|
|
||||||
|
The package we have developed is an attempt to present a common
|
||||||
|
error-handling mechanism to manipulate the most common form of error code
|
||||||
|
in a fashion that does not have the problems listed above.
|
||||||
|
|
||||||
|
A list of up to 256 text messages is supplied to a translator we have
|
||||||
|
written, along with the three- to four-character ``name'' of the error
|
||||||
|
table. The library using this error table need only call a routine
|
||||||
|
generated from this error-table source to make the table ``known'' to the
|
||||||
|
com_err library, and any error code the library generates can be converted
|
||||||
|
to the corresponding error message. There is also a default format for
|
||||||
|
error codes accidentally returned before making the table known, which is
|
||||||
|
of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
|
||||||
|
of the table.
|
||||||
|
|
||||||
|
@section Error codes
|
||||||
|
|
||||||
|
Error codes themselves are 32 bit (signed) integers, of which the high
|
||||||
|
order 24 bits are an identifier of which error table the error code is
|
||||||
|
from, and the low order 8 bits are a sequential error number within
|
||||||
|
the table. An error code may thus be easily decomposed into its component
|
||||||
|
parts. Only the lowest 32 bits of an error code are considered significant
|
||||||
|
on systems which support wider values.
|
||||||
|
|
||||||
|
Error table 0 is defined to match the UNIX system call error table
|
||||||
|
(@code{sys_errlist}); this allows @code{errno} values to be used directly
|
||||||
|
in the library (assuming that @code{errno} is of a type with the same width
|
||||||
|
as @t{long}). Other error table numbers are formed by compacting together
|
||||||
|
the first four characters of the error table name. The mapping between
|
||||||
|
characters in the name and numeric values in the error code are defined in
|
||||||
|
a system-independent fashion, so that two systems that can pass integral
|
||||||
|
values between them can reliably pass error codes without loss of meaning;
|
||||||
|
this should work even if the character sets used are not the same.
|
||||||
|
(However, if this is to be done, error table 0 should be avoided, since the
|
||||||
|
local system call error tables may differ.)
|
||||||
|
|
||||||
|
Any variable which is to contain an error code should be declared @t{long}.
|
||||||
|
The draft proposed American National Standard for C (as of May, 1988)
|
||||||
|
requires that @t{long} variables be at least 32 bits; any system which does
|
||||||
|
not support 32-bit @t{long} values cannot make use of this package (nor
|
||||||
|
much other software that assumes an ANSI-C environment base) without
|
||||||
|
significant effort.
|
||||||
|
|
||||||
|
@section Error table source file
|
||||||
|
|
||||||
|
The error table source file begins with the declaration of the table name,
|
||||||
|
as
|
||||||
|
|
||||||
|
@example
|
||||||
|
error_table @var{tablename}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Individual error codes are
|
||||||
|
specified with
|
||||||
|
|
||||||
|
@example
|
||||||
|
error_code @var{ERROR_NAME}, @var{"text message"}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
where @samp{ec} can also be used as a short form of @samp{error_code}. To
|
||||||
|
indicate the end of the table, use @samp{end}. Thus, a (short) sample
|
||||||
|
error table might be:
|
||||||
|
|
||||||
|
@example
|
||||||
|
|
||||||
|
error_table dsc
|
||||||
|
|
||||||
|
error_code DSC_DUP_MTG_NAME,
|
||||||
|
"Meeting already exists"
|
||||||
|
|
||||||
|
ec DSC_BAD_PATH,
|
||||||
|
"A bad meeting pathname was given"
|
||||||
|
|
||||||
|
ec DSC_BAD_MODES,
|
||||||
|
"Invalid mode for this access control list"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@section The error-table compiler
|
||||||
|
|
||||||
|
The error table compiler is named @code{compile_et}. It takes one
|
||||||
|
argument, the pathname of a file (ending in @samp{.et}, e.g.,
|
||||||
|
@samp{dsc_err.et}) containing an error table source file. It parses the
|
||||||
|
error table, and generates two output files -- a C header file
|
||||||
|
(@samp{discuss_err.h}) which contains definitions of the numerical values
|
||||||
|
of the error codes defined in the error table, and a C source file which
|
||||||
|
should be compiled and linked with the executable. The header file must be
|
||||||
|
included in the source of a module which wishes to reference the error
|
||||||
|
codes defined; the object module generated from the C code may be linked in
|
||||||
|
to a program which wishes to use the printed forms of the error codes.
|
||||||
|
|
||||||
|
This translator accepts a @kbd{-language @var{lang}} argument, which
|
||||||
|
determines for which language (or language variant) the output should be
|
||||||
|
written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
|
||||||
|
and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will
|
||||||
|
be extended to include some support for C++. The default is currently
|
||||||
|
@kbd{K&R-C}, though the generated sources will have ANSI-C code
|
||||||
|
conditionalized on the symbol @t{__STDC__}.
|
||||||
|
|
||||||
|
@section Run-time support routines
|
||||||
|
|
||||||
|
Any source file which uses the routines supplied with or produced by the
|
||||||
|
com_err package should include the header file @file{<com_err.h>}. It
|
||||||
|
contains declarations and definitions which may be needed on some systems.
|
||||||
|
(Some functions cannot be referenced properly without the return type
|
||||||
|
declarations in this file. Some functions may work properly on most
|
||||||
|
architectures even without the header file, but relying on this is not
|
||||||
|
recommended.)
|
||||||
|
|
||||||
|
The run-time support routines and variables provided via this package
|
||||||
|
include the following:
|
||||||
|
|
||||||
|
@example
|
||||||
|
void initialize_@var{xxxx}_error_table (void);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
One of these routines is built by the error compiler for each error table.
|
||||||
|
It makes the @var{xxxx} error table ``known'' to the error reporting
|
||||||
|
system. By convention, this routine should be called in the initialization
|
||||||
|
routine of the @var{xxxx} library. If the library has no initialization
|
||||||
|
routine, some combination of routines which form the core of the library
|
||||||
|
should ensure that this routine is called. It is not advised to leave it
|
||||||
|
the caller to make this call.
|
||||||
|
|
||||||
|
There is no harm in calling this routine more than once.
|
||||||
|
|
||||||
|
@example
|
||||||
|
#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This symbol contains the value of the first error code entry in the
|
||||||
|
specified table.
|
||||||
|
This rarely needs be used by the
|
||||||
|
programmer.
|
||||||
|
|
||||||
|
@example
|
||||||
|
const char *error_message (long code);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This routine returns the character string error message associated
|
||||||
|
with @code{code}; if this is associated with an unknown error table, or
|
||||||
|
if the code is associated with a known error table but the code is not
|
||||||
|
in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
|
||||||
|
returned, where @var{xxxx} is the error table name produced by
|
||||||
|
reversing the compaction performed on the error table number implied
|
||||||
|
by that error code, and @var{nn} is the offset from that base value.
|
||||||
|
|
||||||
|
Although this routine is available for use when needed, its use should be
|
||||||
|
left to circumstances which render @code{com_err} (below) unusable.
|
||||||
|
|
||||||
|
@example
|
||||||
|
void com_err (const char *whoami, /* module reporting error */
|
||||||
|
long code, /* error code */
|
||||||
|
const char *format, /* format for additional detail */
|
||||||
|
...); /* (extra parameters) */
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This routine provides an alternate way to print error messages to
|
||||||
|
standard error; it allows the error message to be passed in as a
|
||||||
|
parameter, rather than in an external variable. @emph{Provide grammatical
|
||||||
|
context for ``message.''}
|
||||||
|
|
||||||
|
If @var{format} is @code{(char *)NULL}, the formatted message will not be
|
||||||
|
printed. @var{format} may not be omitted.
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void com_err_va (const char *whoami,
|
||||||
|
long code,
|
||||||
|
const char *format,
|
||||||
|
va_list args);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This routine provides an interface, equivalent to @code{com_err} above,
|
||||||
|
which may be used by higher-level variadic functions (functions which
|
||||||
|
accept variable numbers of arguments).
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void (*set_com_err_hook (void (*proc) ())) ();
|
||||||
|
|
||||||
|
void (*@var{proc}) (const char *whoami, long code, va_list args);
|
||||||
|
|
||||||
|
void reset_com_err_hook ();
|
||||||
|
@end example
|
||||||
|
|
||||||
|
These two routines allow a routine to be dynamically substituted for
|
||||||
|
@samp{com_err}. After @samp{set_com_err_hook} has been called,
|
||||||
|
calls to @samp{com_err} will turn into calls to the new hook routine.
|
||||||
|
@samp{reset_com_err_hook} turns off this hook. This may intended to
|
||||||
|
be used in daemons (to use a routine which calls @var{syslog(3)}), or
|
||||||
|
in a window system application (which could pop up a dialogue box).
|
||||||
|
|
||||||
|
If a program is to be used in an environment in which simply printing
|
||||||
|
messages to the @code{stderr} stream would be inappropriate (such as in a
|
||||||
|
daemon program which runs without a terminal attached),
|
||||||
|
@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
|
||||||
|
The following is an example of an error handler which uses @var{syslog(3)}
|
||||||
|
as supplied in BSD 4.3:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
/* extern openlog (const char * name, int logopt, int facility); */
|
||||||
|
/* extern syslog (int priority, char * message, ...); */
|
||||||
|
|
||||||
|
void hook (const char * whoami, long code,
|
||||||
|
const char * format, va_list args)
|
||||||
|
@{
|
||||||
|
char buffer[BUFSIZ];
|
||||||
|
static int initialized = 0;
|
||||||
|
if (!initialized) @{
|
||||||
|
openlog (whoami,
|
||||||
|
LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
|
||||||
|
LOG_DAEMON);
|
||||||
|
initialized = 1;
|
||||||
|
@}
|
||||||
|
vsprintf (buffer, format, args);
|
||||||
|
syslog (LOG_ERR, "%s %s", error_message (code), buffer);
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
After making the call
|
||||||
|
@code{set_com_err_hook (hook);},
|
||||||
|
any calls to @code{com_err} will result in messages being sent to the
|
||||||
|
@var{syslogd} daemon for logging.
|
||||||
|
The name of the program, @samp{whoami}, is supplied to the
|
||||||
|
@samp{openlog()} call, and the message is formatted into a buffer and
|
||||||
|
passed to @code{syslog}.
|
||||||
|
|
||||||
|
Note that since the extra arguments to @code{com_err} are passed by
|
||||||
|
reference via the @code{va_list} value @code{args}, the hook routine may
|
||||||
|
place any form of interpretation on them, including ignoring them. For
|
||||||
|
consistency, @code{printf}-style interpretation is suggested, via
|
||||||
|
@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
|
||||||
|
the ANSI C library).
|
||||||
|
|
||||||
|
@section Coding Conventions
|
||||||
|
|
||||||
|
The following conventions are just some general stylistic conventions
|
||||||
|
to follow when writing robust libraries and programs. Conventions
|
||||||
|
similar to this are generally followed inside the UNIX kernel and most
|
||||||
|
routines in the Multics operating system. In general, a routine
|
||||||
|
either succeeds (returning a zero error code, and doing some side
|
||||||
|
effects in the process), or it fails, doing minimal side effects; in
|
||||||
|
any event, any invariant which the library assumes must be maintained.
|
||||||
|
|
||||||
|
In general, it is not in the domain of non user-interface library
|
||||||
|
routines to write error messages to the user's terminal, or halt the
|
||||||
|
process. Such forms of ``error handling'' should be reserved for
|
||||||
|
failures of internal invariants and consistancy checks only, as it
|
||||||
|
provides the user of the library no way to clean up for himself in the
|
||||||
|
event of total failure.
|
||||||
|
|
||||||
|
Library routines which can fail should be set up to return an error
|
||||||
|
code. This should usually be done as the return value of the
|
||||||
|
function; if this is not acceptable, the routine should return a
|
||||||
|
``null'' value, and put the error code into a parameter passed by
|
||||||
|
reference.
|
||||||
|
|
||||||
|
Routines which use the first style of interface can be used from
|
||||||
|
user-interface levels of a program as follows:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@{
|
||||||
|
if ((code = initialize_world(getuid(), random())) != 0) @{
|
||||||
|
com_err("demo", code,
|
||||||
|
"when trying to initialize world");
|
||||||
|
exit(1);
|
||||||
|
@}
|
||||||
|
if ((database = open_database("my_secrets", &code))==NULL) @{
|
||||||
|
com_err("demo", code,
|
||||||
|
"while opening my_secrets");
|
||||||
|
exit(1);
|
||||||
|
@}
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
A caller which fails to check the return status is in error. It is
|
||||||
|
possible to look for code which ignores error returns by using lint;
|
||||||
|
look for error messages of the form ``foobar returns value which is
|
||||||
|
sometimes ignored'' or ``foobar returns value which is always
|
||||||
|
ignored.''
|
||||||
|
|
||||||
|
Since libraries may be built out of other libraries, it is often necessary
|
||||||
|
for the success of one routine to depend on another. When a lower level
|
||||||
|
routine returns an error code, the middle level routine has a few possible
|
||||||
|
options. It can simply return the error code to its caller after doing
|
||||||
|
some form of cleanup, it can substitute one of its own, or it can take
|
||||||
|
corrective action of its own and continue normally. For instance, a
|
||||||
|
library routine which makes a ``connect'' system call to make a network
|
||||||
|
connection may reflect the system error code @code{ECONNREFUSED}
|
||||||
|
(Connection refused) to its caller, or it may return a ``server not
|
||||||
|
available, try again later,'' or it may try a different server.
|
||||||
|
|
||||||
|
Cleanup which is typically necessary may include, but not be limited
|
||||||
|
to, freeing allocated memory which will not be needed any more,
|
||||||
|
unlocking concurrancy locks, dropping reference counts, closing file
|
||||||
|
descriptors, or otherwise undoing anything which the procedure did up
|
||||||
|
to this point. When there are a lot of things which can go wrong, it
|
||||||
|
is generally good to write one block of error-handling code which is
|
||||||
|
branched to, using a goto, in the event of failure. A common source
|
||||||
|
of errors in UNIX programs is failing to close file descriptors on
|
||||||
|
error returns; this leaves a number of ``zombied'' file descriptors
|
||||||
|
open, which eventually causes the process to run out of file
|
||||||
|
descriptors and fall over.
|
||||||
|
|
||||||
|
@example
|
||||||
|
@{
|
||||||
|
FILE *f1=NULL, *f2=NULL, *f3=NULL;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
if ( (f1 = fopen(FILE1, "r")) == NULL) @{
|
||||||
|
status = errno;
|
||||||
|
goto error;
|
||||||
|
@}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crunch for a while
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( (f2 = fopen(FILE2, "w")) == NULL) @{
|
||||||
|
status = errno;
|
||||||
|
goto error;
|
||||||
|
@}
|
||||||
|
|
||||||
|
if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
|
||||||
|
status = errno;
|
||||||
|
goto error;
|
||||||
|
@}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do more processing.
|
||||||
|
*/
|
||||||
|
fclose(f1);
|
||||||
|
fclose(f2);
|
||||||
|
fclose(f3);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (f1) fclose(f1);
|
||||||
|
if (f2) fclose(f2);
|
||||||
|
if (f3) fclose(f3);
|
||||||
|
return status;
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@section Building and Installation
|
||||||
|
|
||||||
|
The distribution of this package will probably be done as a compressed
|
||||||
|
``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
|
||||||
|
Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory
|
||||||
|
@t{profiled} should be created to hold objects compiled for profiling.
|
||||||
|
Running ``make all'' should then be sufficient to build the library and
|
||||||
|
error-table compiler. The files @samp{libcom_err.a},
|
||||||
|
@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
|
||||||
|
installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
|
||||||
|
installed as manual pages.
|
||||||
|
|
||||||
|
Potential problems:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
|
||||||
|
@item Use of @code{strcasecmp}, a routine provided in BSD for
|
||||||
|
case-insensitive string comparisons. If an equivalent routine is
|
||||||
|
available, you can modify @code{CFLAGS} in the makefile to define
|
||||||
|
@code{strcasecmp} to the name of that routine.
|
||||||
|
|
||||||
|
@item Compilers that defined @code{__STDC__} without providing the header
|
||||||
|
file @code{<stdarg.h>}. One such example is Metaware's High ``C''
|
||||||
|
compiler, as provided at Project Athena on the IBM RT/PC workstation; if
|
||||||
|
@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
|
||||||
|
available, and therefore @code{<varargs.h>} must be used. If the symbol
|
||||||
|
@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
|
||||||
|
be used.
|
||||||
|
|
||||||
|
@item If your linker rejects symbols that are simultaneously defined in two
|
||||||
|
library files, edit @samp{Makefile} to remove @samp{perror.c} from the
|
||||||
|
library. This file contains a version of @var{perror(3)} which calls
|
||||||
|
@code{com_err} instead of calling @code{write} directly.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
As I do not have access to non-BSD systems, there are probably
|
||||||
|
bugs present that may interfere with building or using this package on
|
||||||
|
other systems. If they are reported to me, they can probably be fixed for
|
||||||
|
the next version.
|
||||||
|
|
||||||
|
@section Bug Reports
|
||||||
|
|
||||||
|
Please send any comments or bug reports to the principal author: Ken
|
||||||
|
Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
|
||||||
|
|
||||||
|
@section Acknowledgements
|
||||||
|
|
||||||
|
I would like to thank: Bill Sommerfeld, for his help with some of this
|
||||||
|
documentation, and catching some of the bugs the first time around;
|
||||||
|
Honeywell Information Systems, for not killing off the @emph{Multics}
|
||||||
|
operating system before I had an opportunity to use it; Honeywell's
|
||||||
|
customers, who persuaded them not to do so, for a while; Ted Anderson of
|
||||||
|
CMU, for catching some problems before version 1.2 left the nest; Stan
|
||||||
|
Zanarotti and several others of MIT's Student Information Processing Board,
|
||||||
|
for getting us started with ``discuss,'' for which this package was
|
||||||
|
originally written; and everyone I've talked into --- I mean, asked to read
|
||||||
|
this document and the ``man'' pages.
|
||||||
|
|
||||||
|
@bye
|
||||||
11
lib/com_err/compile_et
Executable file
11
lib/com_err/compile_et
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
#
|
||||||
|
AWK=/usr/bin/awk
|
||||||
|
DIR=com_err/
|
||||||
|
|
||||||
|
ROOT=`echo $1 | sed -e s/.et$//`
|
||||||
|
BASE=`basename $ROOT`
|
||||||
|
|
||||||
|
$AWK -f ${DIR}/et_h.awk outfile=${BASE}.h $ROOT.et
|
||||||
|
$AWK -f ${DIR}/et_c.awk outfile=${BASE}.c $ROOT.et
|
||||||
79
lib/com_err/compile_et.1
Normal file
79
lib/com_err/compile_et.1
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
|
||||||
|
.\" Student Information Processing Board. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" $Header: /mit/krb5/.cvsroot/src/util/et/compile_et.1,v 1.1 1993/06/03 12:29:46 tytso Exp $
|
||||||
|
.\"
|
||||||
|
.TH COMPILE_ET 1 "22 Nov 1988" SIPB
|
||||||
|
.SH NAME
|
||||||
|
compile_et \- error table compiler
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B compile_et
|
||||||
|
file
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B Compile_et
|
||||||
|
converts a table listing error-code names and associated messages into
|
||||||
|
a C source file suitable for use with the
|
||||||
|
.IR com_err (3)
|
||||||
|
library.
|
||||||
|
|
||||||
|
The source file name must end with a suffix of ``.et''; the file
|
||||||
|
consists of a declaration supplying the name (up to four characters
|
||||||
|
long) of the error-code table:
|
||||||
|
|
||||||
|
.B error_table
|
||||||
|
.I name
|
||||||
|
|
||||||
|
followed by up to 256 entries of the form:
|
||||||
|
|
||||||
|
.B error_code
|
||||||
|
.I name,
|
||||||
|
"
|
||||||
|
.I string
|
||||||
|
"
|
||||||
|
|
||||||
|
and a final
|
||||||
|
|
||||||
|
.B end
|
||||||
|
|
||||||
|
to indicate the end of the table.
|
||||||
|
|
||||||
|
The name of the table is used to construct the name of a subroutine
|
||||||
|
.I initialize_XXXX_error_table
|
||||||
|
which must be called in order for the
|
||||||
|
.I com_err
|
||||||
|
library to recognize the error table.
|
||||||
|
|
||||||
|
The various error codes defined are assigned sequentially increasing
|
||||||
|
numbers (starting with a large number computed as a hash function of
|
||||||
|
the name of the table); thus for compatibility it is suggested that
|
||||||
|
new codes be added only to the end of an existing table, and that no
|
||||||
|
codes be removed from tables.
|
||||||
|
|
||||||
|
The names defined in the table are placed into a C header file with
|
||||||
|
preprocessor directives defining them as integer constants of up to
|
||||||
|
32 bits in magnitude.
|
||||||
|
|
||||||
|
A C source file is also generated which should be compiled and linked
|
||||||
|
with the object files which reference these error codes; it contains
|
||||||
|
the text of the messages and the initialization subroutine. Both C
|
||||||
|
files have names derived from that of the original source file, with
|
||||||
|
the ``.et'' suffix replaced by ``.c'' and ``.h''.
|
||||||
|
|
||||||
|
A ``#'' in the source file is treated as a comment character, and all
|
||||||
|
remaining text to the end of the source line will be ignored.
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
|
||||||
|
Since
|
||||||
|
.B compile_et
|
||||||
|
uses a very simple parser based on
|
||||||
|
.IR yacc (1),
|
||||||
|
its error recovery leaves much to be desired.
|
||||||
|
|
||||||
|
.\" .IR for manual entries
|
||||||
|
.\" .PP for paragraph breaks
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
com_err (3).
|
||||||
|
|
||||||
|
Ken Raeburn, "A Common Error Description Library for UNIX".
|
||||||
82
lib/com_err/error_message.c
Normal file
82
lib/com_err/error_message.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* $Header: /mit/krb5/.cvsroot/src/util/et/error_message.c,v 5.0 1993/04/13 19:56:17 tytso Exp $
|
||||||
|
* $Source: /mit/krb5/.cvsroot/src/util/et/error_message.c,v $
|
||||||
|
* $Locker: $
|
||||||
|
*
|
||||||
|
* Copyright 1987 by the Student Information Processing Board
|
||||||
|
* of the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* For copyright info, see "mit-sipb-copyright.h".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "com_err.h"
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static char buffer[25];
|
||||||
|
|
||||||
|
struct et_list * _et_list = (struct et_list *) NULL;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
const char * error_message (errcode_t code)
|
||||||
|
#else
|
||||||
|
const char * error_message (code)
|
||||||
|
errcode_t code;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
struct et_list *et;
|
||||||
|
int table_num;
|
||||||
|
int started = 0;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
offset = code & ((1<<ERRCODE_RANGE)-1);
|
||||||
|
table_num = code - offset;
|
||||||
|
if (!table_num) {
|
||||||
|
#ifdef HAS_SYS_ERRLIST
|
||||||
|
if (offset < sys_nerr)
|
||||||
|
return(sys_errlist[offset]);
|
||||||
|
else
|
||||||
|
goto oops;
|
||||||
|
#else
|
||||||
|
cp = strerror(offset);
|
||||||
|
if (cp)
|
||||||
|
return(cp);
|
||||||
|
else
|
||||||
|
goto oops;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
for (et = _et_list; et; et = et->next) {
|
||||||
|
if (et->table->base == table_num) {
|
||||||
|
/* This is the right table */
|
||||||
|
if (et->table->n_msgs <= offset)
|
||||||
|
goto oops;
|
||||||
|
return(et->table->msgs[offset]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oops:
|
||||||
|
strcpy (buffer, "Unknown code ");
|
||||||
|
if (table_num) {
|
||||||
|
strcat (buffer, error_table_name (table_num));
|
||||||
|
strcat (buffer, " ");
|
||||||
|
}
|
||||||
|
for (cp = buffer; *cp; cp++)
|
||||||
|
;
|
||||||
|
if (offset >= 100) {
|
||||||
|
*cp++ = '0' + offset / 100;
|
||||||
|
offset %= 100;
|
||||||
|
started++;
|
||||||
|
}
|
||||||
|
if (started || offset >= 10) {
|
||||||
|
*cp++ = '0' + offset / 10;
|
||||||
|
offset %= 10;
|
||||||
|
}
|
||||||
|
*cp++ = '0' + offset;
|
||||||
|
*cp = '\0';
|
||||||
|
return(buffer);
|
||||||
|
}
|
||||||
35
lib/com_err/error_table.h
Normal file
35
lib/com_err/error_table.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1988 by the Student Information Processing Board of the
|
||||||
|
* Massachusetts Institute of Technology.
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ET_H
|
||||||
|
/* Are we using ANSI C? */
|
||||||
|
#ifndef __STDC__
|
||||||
|
#define const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct error_table {
|
||||||
|
char const * const * msgs;
|
||||||
|
long base;
|
||||||
|
int n_msgs;
|
||||||
|
};
|
||||||
|
struct et_list {
|
||||||
|
struct et_list *next;
|
||||||
|
const struct error_table *table;
|
||||||
|
};
|
||||||
|
extern struct et_list * _et_list;
|
||||||
|
|
||||||
|
#define ERRCODE_RANGE 8 /* # of bits to shift table number */
|
||||||
|
#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
extern const char *error_table_name(int num);
|
||||||
|
#else
|
||||||
|
extern const char *error_table_name();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _ET_H
|
||||||
|
#endif
|
||||||
185
lib/com_err/et_c.awk
Normal file
185
lib/com_err/et_c.awk
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
BEGIN {
|
||||||
|
char_shift=64
|
||||||
|
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||||
|
c2n["A"]=1
|
||||||
|
c2n["B"]=2
|
||||||
|
c2n["C"]=3
|
||||||
|
c2n["D"]=4
|
||||||
|
c2n["E"]=5
|
||||||
|
c2n["F"]=6
|
||||||
|
c2n["G"]=7
|
||||||
|
c2n["H"]=8
|
||||||
|
c2n["I"]=9
|
||||||
|
c2n["J"]=10
|
||||||
|
c2n["K"]=11
|
||||||
|
c2n["L"]=12
|
||||||
|
c2n["M"]=13
|
||||||
|
c2n["N"]=14
|
||||||
|
c2n["O"]=15
|
||||||
|
c2n["P"]=16
|
||||||
|
c2n["Q"]=17
|
||||||
|
c2n["R"]=18
|
||||||
|
c2n["S"]=19
|
||||||
|
c2n["T"]=20
|
||||||
|
c2n["U"]=21
|
||||||
|
c2n["V"]=22
|
||||||
|
c2n["W"]=23
|
||||||
|
c2n["X"]=24
|
||||||
|
c2n["Y"]=25
|
||||||
|
c2n["Z"]=26
|
||||||
|
c2n["a"]=27
|
||||||
|
c2n["b"]=28
|
||||||
|
c2n["c"]=29
|
||||||
|
c2n["d"]=30
|
||||||
|
c2n["e"]=31
|
||||||
|
c2n["f"]=32
|
||||||
|
c2n["g"]=33
|
||||||
|
c2n["h"]=34
|
||||||
|
c2n["i"]=35
|
||||||
|
c2n["j"]=36
|
||||||
|
c2n["k"]=37
|
||||||
|
c2n["l"]=38
|
||||||
|
c2n["m"]=39
|
||||||
|
c2n["n"]=40
|
||||||
|
c2n["o"]=41
|
||||||
|
c2n["p"]=42
|
||||||
|
c2n["q"]=43
|
||||||
|
c2n["r"]=44
|
||||||
|
c2n["s"]=45
|
||||||
|
c2n["t"]=46
|
||||||
|
c2n["u"]=47
|
||||||
|
c2n["v"]=48
|
||||||
|
c2n["w"]=49
|
||||||
|
c2n["x"]=50
|
||||||
|
c2n["y"]=51
|
||||||
|
c2n["z"]=52
|
||||||
|
c2n["0"]=53
|
||||||
|
c2n["1"]=54
|
||||||
|
c2n["2"]=55
|
||||||
|
c2n["3"]=56
|
||||||
|
c2n["4"]=57
|
||||||
|
c2n["5"]=58
|
||||||
|
c2n["6"]=59
|
||||||
|
c2n["7"]=60
|
||||||
|
c2n["8"]=61
|
||||||
|
c2n["9"]=62
|
||||||
|
c2n["_"]=63
|
||||||
|
}
|
||||||
|
/^#/ { next }
|
||||||
|
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
|
||||||
|
table_number = 0
|
||||||
|
table_name = $2
|
||||||
|
mod_base = 1000000
|
||||||
|
for(i=1; i<=length(table_name); i++) {
|
||||||
|
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
# We start playing *_high, *low games here because the some
|
||||||
|
# awk programs do not have the necessary precision (sigh)
|
||||||
|
tab_base_low = table_number % mod_base
|
||||||
|
tab_base_high = int(table_number / mod_base)
|
||||||
|
tab_base_sign = 1;
|
||||||
|
|
||||||
|
# figure out: table_number_base=table_number*256
|
||||||
|
tab_base_low = tab_base_low * 256
|
||||||
|
tab_base_high = (tab_base_high * 256) + \
|
||||||
|
int(tab_base_low / mod_base)
|
||||||
|
tab_base_low = tab_base_low % mod_base
|
||||||
|
|
||||||
|
if (table_number > 128*256*256) {
|
||||||
|
# figure out: table_number_base -= 256*256*256*256
|
||||||
|
# sub_high, sub_low is 256*256*256*256
|
||||||
|
sub_low = 256*256*256 % mod_base
|
||||||
|
sub_high = int(256*256*256 / mod_base)
|
||||||
|
|
||||||
|
sub_low = sub_low * 256
|
||||||
|
sub_high = (sub_high * 256) + int(sub_low / mod_base)
|
||||||
|
sub_low = sub_low % mod_base
|
||||||
|
|
||||||
|
tab_base_low = sub_low - tab_base_low;
|
||||||
|
tab_base_high = sub_high - tab_base_high;
|
||||||
|
tab_base_sign = -1;
|
||||||
|
if (tab_base_low < 0) {
|
||||||
|
tab_base_low = tab_base_low + mod_base
|
||||||
|
tab_base_high--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "/*" > outfile
|
||||||
|
print " * " outfile ":" > outfile
|
||||||
|
print " * This file is automatically generated; please do not edit it." > outfile
|
||||||
|
print " */" > outfile
|
||||||
|
|
||||||
|
print "#ifdef __STDC__" > outfile
|
||||||
|
print "#define NOARGS void" > outfile
|
||||||
|
print "#else" > outfile
|
||||||
|
print "#define NOARGS" > outfile
|
||||||
|
print "#define const" > outfile
|
||||||
|
print "#endif" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "static const char * const text[] = {" > outfile
|
||||||
|
table_item_count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
|
||||||
|
skipone=1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
|
||||||
|
text=""
|
||||||
|
for (i=3; i<=NF; i++) {
|
||||||
|
text = text FS $i
|
||||||
|
}
|
||||||
|
text=substr(text,2,length(text)-1);
|
||||||
|
printf "\t%s,\n", text > outfile
|
||||||
|
table_item_count++
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if (skipone) {
|
||||||
|
printf "\t%s,\n", $0 > outfile
|
||||||
|
table_item_count++
|
||||||
|
}
|
||||||
|
skipone=0
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
|
||||||
|
|
||||||
|
print " 0" > outfile
|
||||||
|
print "};" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "struct error_table {" > outfile
|
||||||
|
print " char const * const * msgs;" > outfile
|
||||||
|
print " long base;" > outfile
|
||||||
|
print " int n_msgs;" > outfile
|
||||||
|
print "};" > outfile
|
||||||
|
print "struct et_list {" > outfile
|
||||||
|
print " struct et_list *next;" > outfile
|
||||||
|
print " const struct error_table * table;" > outfile
|
||||||
|
print "};" > outfile
|
||||||
|
print "extern struct et_list *_et_list;" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
if (tab_base_high == 0) {
|
||||||
|
print "static const struct error_table et = { text, " \
|
||||||
|
sprintf("%dL, %d };", tab_base_sign*tab_base_low, \
|
||||||
|
table_item_count) > outfile
|
||||||
|
} else {
|
||||||
|
print "static const struct error_table et = { text, " \
|
||||||
|
sprintf("%d%06dL, %d };", tab_base_sign*tab_base_high, \
|
||||||
|
tab_base_low, table_item_count) > outfile
|
||||||
|
}
|
||||||
|
print "" > outfile
|
||||||
|
print "static struct et_list link = { 0, 0 };" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "void initialize_" table_name "_error_table (NOARGS);" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "void initialize_" table_name "_error_table (NOARGS) {" > outfile
|
||||||
|
print " if (!link.table) {" > outfile
|
||||||
|
print " link.next = _et_list;" > outfile
|
||||||
|
print " link.table = &et;" > outfile
|
||||||
|
print " _et_list = &link;" > outfile
|
||||||
|
print " }" > outfile
|
||||||
|
print "}" > outfile
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
157
lib/com_err/et_h.awk
Normal file
157
lib/com_err/et_h.awk
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
BEGIN {
|
||||||
|
char_shift=64
|
||||||
|
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||||
|
c2n["A"]=1
|
||||||
|
c2n["B"]=2
|
||||||
|
c2n["C"]=3
|
||||||
|
c2n["D"]=4
|
||||||
|
c2n["E"]=5
|
||||||
|
c2n["F"]=6
|
||||||
|
c2n["G"]=7
|
||||||
|
c2n["H"]=8
|
||||||
|
c2n["I"]=9
|
||||||
|
c2n["J"]=10
|
||||||
|
c2n["K"]=11
|
||||||
|
c2n["L"]=12
|
||||||
|
c2n["M"]=13
|
||||||
|
c2n["N"]=14
|
||||||
|
c2n["O"]=15
|
||||||
|
c2n["P"]=16
|
||||||
|
c2n["Q"]=17
|
||||||
|
c2n["R"]=18
|
||||||
|
c2n["S"]=19
|
||||||
|
c2n["T"]=20
|
||||||
|
c2n["U"]=21
|
||||||
|
c2n["V"]=22
|
||||||
|
c2n["W"]=23
|
||||||
|
c2n["X"]=24
|
||||||
|
c2n["Y"]=25
|
||||||
|
c2n["Z"]=26
|
||||||
|
c2n["a"]=27
|
||||||
|
c2n["b"]=28
|
||||||
|
c2n["c"]=29
|
||||||
|
c2n["d"]=30
|
||||||
|
c2n["e"]=31
|
||||||
|
c2n["f"]=32
|
||||||
|
c2n["g"]=33
|
||||||
|
c2n["h"]=34
|
||||||
|
c2n["i"]=35
|
||||||
|
c2n["j"]=36
|
||||||
|
c2n["k"]=37
|
||||||
|
c2n["l"]=38
|
||||||
|
c2n["m"]=39
|
||||||
|
c2n["n"]=40
|
||||||
|
c2n["o"]=41
|
||||||
|
c2n["p"]=42
|
||||||
|
c2n["q"]=43
|
||||||
|
c2n["r"]=44
|
||||||
|
c2n["s"]=45
|
||||||
|
c2n["t"]=46
|
||||||
|
c2n["u"]=47
|
||||||
|
c2n["v"]=48
|
||||||
|
c2n["w"]=49
|
||||||
|
c2n["x"]=50
|
||||||
|
c2n["y"]=51
|
||||||
|
c2n["z"]=52
|
||||||
|
c2n["0"]=53
|
||||||
|
c2n["1"]=54
|
||||||
|
c2n["2"]=55
|
||||||
|
c2n["3"]=56
|
||||||
|
c2n["4"]=57
|
||||||
|
c2n["5"]=58
|
||||||
|
c2n["6"]=59
|
||||||
|
c2n["7"]=60
|
||||||
|
c2n["8"]=61
|
||||||
|
c2n["9"]=62
|
||||||
|
c2n["_"]=63
|
||||||
|
}
|
||||||
|
/^#/ { next }
|
||||||
|
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
|
||||||
|
table_number = 0
|
||||||
|
table_name = $2
|
||||||
|
mod_base = 1000000
|
||||||
|
for(i=1; i<=length(table_name); i++) {
|
||||||
|
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
|
||||||
|
}
|
||||||
|
# We start playing *_high, *low games here because the some
|
||||||
|
# awk programs do not have the necessary precision (sigh)
|
||||||
|
tab_base_low = table_number % mod_base
|
||||||
|
tab_base_high = int(table_number / mod_base)
|
||||||
|
tab_base_sign = 1;
|
||||||
|
|
||||||
|
# figure out: table_number_base=table_number*256
|
||||||
|
tab_base_low = tab_base_low * 256
|
||||||
|
tab_base_high = (tab_base_high * 256) + \
|
||||||
|
int(tab_base_low / mod_base)
|
||||||
|
tab_base_low = tab_base_low % mod_base
|
||||||
|
|
||||||
|
if (table_number > 128*256*256) {
|
||||||
|
# figure out: table_number_base -= 256*256*256*256
|
||||||
|
# sub_high, sub_low is 256*256*256*256
|
||||||
|
sub_low = 256*256*256 % mod_base
|
||||||
|
sub_high = int(256*256*256 / mod_base)
|
||||||
|
|
||||||
|
sub_low = sub_low * 256
|
||||||
|
sub_high = (sub_high * 256) + int(sub_low / mod_base)
|
||||||
|
sub_low = sub_low % mod_base
|
||||||
|
|
||||||
|
tab_base_low = sub_low - tab_base_low;
|
||||||
|
tab_base_high = sub_high - tab_base_high;
|
||||||
|
tab_base_sign = -1;
|
||||||
|
if (tab_base_low < 0) {
|
||||||
|
tab_base_low = tab_base_low + mod_base
|
||||||
|
tab_base_high--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr_low = tab_base_low
|
||||||
|
curr_high = tab_base_high
|
||||||
|
curr_sign = tab_base_sign
|
||||||
|
print "/*" > outfile
|
||||||
|
print " * " outfile ":" > outfile
|
||||||
|
print " * This file is automatically generated; please do not edit it." > outfile
|
||||||
|
print " */" > outfile
|
||||||
|
print "#ifdef __STDC__" > outfile
|
||||||
|
print "#define NOARGS void" > outfile
|
||||||
|
print "#else" > outfile
|
||||||
|
print "#define NOARGS" > outfile
|
||||||
|
print "#define const" > outfile
|
||||||
|
print "#endif" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/ {
|
||||||
|
tag=substr($2,1,length($2)-1)
|
||||||
|
if (curr_high == 0) {
|
||||||
|
printf "#define %-40s (%dL)\n", tag, \
|
||||||
|
curr_sign*curr_low > outfile
|
||||||
|
} else {
|
||||||
|
printf "#define %-40s (%d%06dL)\n", tag, curr_high*curr_sign, \
|
||||||
|
curr_low > outfile
|
||||||
|
}
|
||||||
|
curr_low += curr_sign;
|
||||||
|
if (curr_low >= mod_base) {
|
||||||
|
curr_low -= mod_base;
|
||||||
|
curr_high++
|
||||||
|
}
|
||||||
|
if (curr_low < 0) {
|
||||||
|
cur_low += mod_base
|
||||||
|
cur_high--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print "extern void initialize_" table_name "_error_table (NOARGS);" > outfile
|
||||||
|
if (tab_base_high == 0) {
|
||||||
|
print "#define ERROR_TABLE_BASE_" table_name " (" \
|
||||||
|
sprintf("%d", tab_base_sign*tab_base_low) \
|
||||||
|
"L)" > outfile
|
||||||
|
} else {
|
||||||
|
print "#define ERROR_TABLE_BASE_" table_name " (" \
|
||||||
|
sprintf("%d%06d", tab_base_sign*tab_base_high, \
|
||||||
|
tab_base_low) "L)" > outfile
|
||||||
|
}
|
||||||
|
print "" > outfile
|
||||||
|
print "/* for compatibility with older versions... */" > outfile
|
||||||
|
print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
|
||||||
|
print "#define " table_name "_err_base ERROR_TABLE_BASE_" table_name > outfile
|
||||||
|
}
|
||||||
36
lib/com_err/et_name.c
Normal file
36
lib/com_err/et_name.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1987 by MIT Student Information Processing Board
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static const char char_set[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||||
|
|
||||||
|
static char buf[6];
|
||||||
|
|
||||||
|
const char * error_table_name(num)
|
||||||
|
int num;
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
|
||||||
|
p = buf;
|
||||||
|
num >>= ERRCODE_RANGE;
|
||||||
|
/* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
|
||||||
|
num &= 077777777;
|
||||||
|
/* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
|
||||||
|
for (i = 4; i >= 0; i--) {
|
||||||
|
ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
|
||||||
|
if (ch != 0)
|
||||||
|
*p++ = char_set[ch-1];
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return(buf);
|
||||||
|
}
|
||||||
58
lib/com_err/init_et.c
Normal file
58
lib/com_err/init_et.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* $Header: /mit/krb5/.cvsroot/src/util/et/init_et.c,v 5.0 1993/04/13 19:56:25 tytso Exp $
|
||||||
|
* $Source: /mit/krb5/.cvsroot/src/util/et/init_et.c,v $
|
||||||
|
* $Locker: $
|
||||||
|
*
|
||||||
|
* Copyright 1986, 1987, 1988 by MIT Information Systems and
|
||||||
|
* the MIT Student Information Processing Board.
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#include "com_err.h"
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
|
||||||
|
#ifndef __STDC__
|
||||||
|
#define const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct foobar {
|
||||||
|
struct et_list etl;
|
||||||
|
struct error_table et;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct et_list * _et_list;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
int init_error_table(const char * const *msgs, int base, int count)
|
||||||
|
#else
|
||||||
|
int init_error_table(msgs, base, count)
|
||||||
|
const char * const * msgs;
|
||||||
|
int base;
|
||||||
|
int count;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct foobar * new_et;
|
||||||
|
|
||||||
|
if (!base || !count || !msgs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_et = (struct foobar *) malloc(sizeof(struct foobar));
|
||||||
|
if (!new_et)
|
||||||
|
return ENOMEM; /* oops */
|
||||||
|
new_et->etl.table = &new_et->et;
|
||||||
|
new_et->et.msgs = msgs;
|
||||||
|
new_et->et.base = base;
|
||||||
|
new_et->et.n_msgs= count;
|
||||||
|
|
||||||
|
new_et->etl.next = _et_list;
|
||||||
|
_et_list = &new_et->etl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
22
lib/com_err/internal.h
Normal file
22
lib/com_err/internal.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* internal include file for com_err package
|
||||||
|
*/
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#ifndef __STDC__
|
||||||
|
#undef const
|
||||||
|
#define const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef NEED_SYS_ERRLIST
|
||||||
|
extern char const * const sys_errlist[];
|
||||||
|
extern const int sys_nerr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* AIX and Ultrix have standard conforming header files. */
|
||||||
|
#if !defined(ultrix) && !defined(_AIX)
|
||||||
|
#ifdef __STDC__
|
||||||
|
void perror (const char *);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
19
lib/com_err/mit-sipb-copyright.h
Normal file
19
lib/com_err/mit-sipb-copyright.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 1987, 1988 by the Student Information Processing Board
|
||||||
|
of the Massachusetts Institute of Technology
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software
|
||||||
|
and its documentation for any purpose and without fee is
|
||||||
|
hereby granted, provided that the above copyright notice
|
||||||
|
appear in all copies and that both that copyright notice and
|
||||||
|
this permission notice appear in supporting documentation,
|
||||||
|
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||||
|
used in advertising or publicity pertaining to distribution
|
||||||
|
of the software without specific, written prior permission.
|
||||||
|
M.I.T. and the M.I.T. S.I.P.B. make no representations about
|
||||||
|
the suitability of this software for any purpose. It is
|
||||||
|
provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
32
lib/ipx_sap_types
Normal file
32
lib/ipx_sap_types
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
0001 User
|
||||||
|
0002 User Group
|
||||||
|
0003 Print Queue
|
||||||
|
0004 File Server
|
||||||
|
0005 Job Server
|
||||||
|
0006 Gateway
|
||||||
|
0007 Print Server
|
||||||
|
0008 Archive Server
|
||||||
|
0009 Archive Server
|
||||||
|
000A Job Queue
|
||||||
|
000B Administration
|
||||||
|
0021 NAS SNA Gateway
|
||||||
|
0024 Remote Bridge
|
||||||
|
0026 Bridge Server
|
||||||
|
0027 TCP/IP Gateway
|
||||||
|
002D Time Synchronization VAP
|
||||||
|
002E Archive Server Dynamic SAP
|
||||||
|
0047 Advertising Print Server
|
||||||
|
004B Btrieve VAP 5.0
|
||||||
|
0050 Btrieve VAP
|
||||||
|
0053 Print Queue User
|
||||||
|
007A TES NetWare for VMS
|
||||||
|
0098 NetWare Access Server
|
||||||
|
009A Named Pipe Server
|
||||||
|
009E Portable NetWare Unix
|
||||||
|
0107 NetWare 386
|
||||||
|
0111 Test Server
|
||||||
|
0133 NetWare Name Service
|
||||||
|
0166 NetWare Management
|
||||||
|
026A NetWare Management
|
||||||
|
026B Time Server (NetWare 4.0)
|
||||||
|
0278 NetWare Directory Server (NetWare 4.0)
|
||||||
3343
lib/ncplib.c
Normal file
3343
lib/ncplib.c
Normal file
File diff suppressed because it is too large
Load Diff
45
lib/ncplib_err.et
Normal file
45
lib/ncplib_err.et
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
error_table NCPL
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_SERVER,
|
||||||
|
"No server found"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_USER,
|
||||||
|
"No username found"
|
||||||
|
|
||||||
|
ec NCPL_ET_HOST_UNKNOWN,
|
||||||
|
"Server Unknown"
|
||||||
|
|
||||||
|
ec NCPL_ET_REQUEST_ERROR,
|
||||||
|
"NCP Request returned error code"
|
||||||
|
|
||||||
|
ec NCPL_ET_NAMETOOLONG,
|
||||||
|
"Name too long"
|
||||||
|
|
||||||
|
ec NCPL_ET_MSG_TOO_LONG,
|
||||||
|
"Message too long"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_SPEC,
|
||||||
|
"Could not find valid connection spec"
|
||||||
|
|
||||||
|
ec NCPL_ET_INVALID_MODE,
|
||||||
|
"$HOME/.nwclient has invalid mode, must be 600"
|
||||||
|
|
||||||
|
ec NCPL_ET_LOGIN_DENIED,
|
||||||
|
"Login denied"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_INTERFACE,
|
||||||
|
"No primary IPX interface found"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_PASSWORD,
|
||||||
|
"Could not get password"
|
||||||
|
|
||||||
|
ec NCPL_ET_PWD_TOO_LONG,
|
||||||
|
"Password too long"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_IPX,
|
||||||
|
"Could not alloc IPX socket. Probably no IPX support in kernel"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_NCPFS_FILE,
|
||||||
|
"The file is probably not on a ncpfs mounted directory"
|
||||||
|
|
||||||
|
end
|
||||||
339
lib/nwcrypt.c
Normal file
339
lib/nwcrypt.c
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
/*$*********************************************************
|
||||||
|
$*
|
||||||
|
$* This code has been taken from DDJ 11/93, from an
|
||||||
|
$* article by Pawel Szczerbina.
|
||||||
|
$*
|
||||||
|
$* Password encryption routines follow.
|
||||||
|
$* Converted to C from Barry Nance's Pascal
|
||||||
|
$* prog published in the March -93 issue of Byte.
|
||||||
|
$*
|
||||||
|
$* Adapted to be useable for ncpfs by
|
||||||
|
$* Volker Lendecke <lendecke@namu01.gwdg.de> in
|
||||||
|
$* October 1995.
|
||||||
|
$*
|
||||||
|
$**********************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
|
||||||
|
I read that Novell is not very open when it comes to technical details
|
||||||
|
of the Netware Core Protocol. This might be especially true for the
|
||||||
|
encryption stuff. I took the necessary code from Dr. Dobb's Journal
|
||||||
|
11/93, Undocumented Corner. I asked Jon Erickson <jon@ddj.com> about
|
||||||
|
the legal status of this piece of code:
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Date: Thu, 12 Oct 1995 13:44:18 +0100
|
||||||
|
From: Volker Lendecke <lendecke>
|
||||||
|
To: jon@ddj.com
|
||||||
|
Subject: legal status of your source code?
|
||||||
|
|
||||||
|
|
||||||
|
Hello!
|
||||||
|
|
||||||
|
I hope that you're the right one to write to, you are the first on your WWW
|
||||||
|
server. If you are not, could you please forward this message to the right
|
||||||
|
person? Thanks.
|
||||||
|
|
||||||
|
I'm currently exploring the possibility to write a free (in the GNU GPL
|
||||||
|
sense) NCP filesystem, which would allow me to access a novell server
|
||||||
|
transparently. For that I would like to use the encryption functions you
|
||||||
|
published in DDJ 11/93, Undocumented Corner. I would make some cosmetic
|
||||||
|
changes, such as other indentations, minor code changes and so on. But I do
|
||||||
|
not know if that allows me to publish this code under GPL. One alternative
|
||||||
|
would be to publish a diff against your listing, but that would probably
|
||||||
|
contain much of your code as well, and it would be very inconvenient for
|
||||||
|
the average user.
|
||||||
|
|
||||||
|
I think that you have some kind of standard procedure for such a
|
||||||
|
case. Please tell me what I should do.
|
||||||
|
|
||||||
|
Many thanks in advance,
|
||||||
|
|
||||||
|
Volker
|
||||||
|
|
||||||
|
+=================================================================+
|
||||||
|
! Volker Lendecke Internet: lendecke@namu01.gwdg.de !
|
||||||
|
! D-37081 Goettingen, Germany !
|
||||||
|
+=================================================================+
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
|
||||||
|
I got the following answer:
|
||||||
|
|
||||||
|
---
|
||||||
|
From: Jon Erickson <jon@ddj.com>
|
||||||
|
X-Mailer: SCO System V Mail (version 3.2)
|
||||||
|
To: lendecke@namu01.gwdg.de
|
||||||
|
Subject: Re: legal status of your source code?
|
||||||
|
Date: Thu, 12 Oct 95 5:42:56 PDT
|
||||||
|
|
||||||
|
Volker,
|
||||||
|
Code from Dr. Dobb's Journal related articles is provided for
|
||||||
|
anyone to use. Clearly, the author of the article should be
|
||||||
|
given credit.
|
||||||
|
Jon Erickson
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
With this answer in mind, I took the code and made it a bit more
|
||||||
|
C-like. The original seemed to be translated by a mechanical pascal->c
|
||||||
|
translator. Jon's answer encouraged me to publish nwcrypt.c under the
|
||||||
|
GPL. If anybody who knows more about copyright and sees any problems
|
||||||
|
with this, please tell me.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/******************* Data types ***************************/
|
||||||
|
typedef unsigned char buf32[32];
|
||||||
|
typedef unsigned char buf16[16];
|
||||||
|
typedef unsigned char buf8[8];
|
||||||
|
typedef unsigned char buf4[4];
|
||||||
|
|
||||||
|
static unsigned char encrypttable[256] =
|
||||||
|
{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
|
||||||
|
0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
|
||||||
|
0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
|
||||||
|
0x0,0x7,0x3,0x8,0x2,0x9,0x3,0xF,0x7,0xF,0xC,0xF,0x6,0x4,0xA,0x0,
|
||||||
|
0x2,0x3,0xA,0xB,0xD,0x8,0x3,0xA,0x1,0x7,0xC,0xF,0x1,0x8,0x9,0xD,
|
||||||
|
0x9,0x1,0x9,0x4,0xE,0x4,0xC,0x5,0x5,0xC,0x8,0xB,0x2,0x3,0x9,0xE,
|
||||||
|
0x7,0x7,0x6,0x9,0xE,0xF,0xC,0x8,0xD,0x1,0xA,0x6,0xE,0xD,0x0,0x7,
|
||||||
|
0x7,0xA,0x0,0x1,0xF,0x5,0x4,0xB,0x7,0xB,0xE,0xC,0x9,0x5,0xD,0x1,
|
||||||
|
0xB,0xD,0x1,0x3,0x5,0xD,0xE,0x6,0x3,0x0,0xB,0xB,0xF,0x3,0x6,0x4,
|
||||||
|
0x9,0xD,0xA,0x3,0x1,0x4,0x9,0x4,0x8,0x3,0xB,0xE,0x5,0x0,0x5,0x2,
|
||||||
|
0xC,0xB,0xD,0x5,0xD,0x5,0xD,0x2,0xD,0x9,0xA,0xC,0xA,0x0,0xB,0x3,
|
||||||
|
0x5,0x3,0x6,0x9,0x5,0x1,0xE,0xE,0x0,0xE,0x8,0x2,0xD,0x2,0x2,0x0,
|
||||||
|
0x4,0xF,0x8,0x5,0x9,0x6,0x8,0x6,0xB,0xA,0xB,0xF,0x0,0x7,0x2,0x8,
|
||||||
|
0xC,0x7,0x3,0xA,0x1,0x4,0x2,0x5,0xF,0x7,0xA,0xC,0xE,0x5,0x9,0x3,
|
||||||
|
0xE,0x7,0x1,0x2,0xE,0x1,0xF,0x4,0xA,0x6,0xC,0x6,0xF,0x4,0x3,0x0,
|
||||||
|
0xC,0x0,0x3,0x6,0xF,0x8,0x7,0xB,0x2,0xD,0xC,0x6,0xA,0xA,0x8,0xD};
|
||||||
|
|
||||||
|
static buf32 encryptkeys =
|
||||||
|
{0x48,0x93,0x46,0x67,0x98,0x3D,0xE6,0x8D,
|
||||||
|
0xB7,0x10,0x7A,0x26,0x5A,0xB9,0xB1,0x35,
|
||||||
|
0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
|
||||||
|
0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
shuffle1(buf32 temp, unsigned char *target)
|
||||||
|
{
|
||||||
|
short b4;
|
||||||
|
unsigned char b3;
|
||||||
|
int s, b2, i;
|
||||||
|
|
||||||
|
b4 = 0;
|
||||||
|
|
||||||
|
for (b2 = 0; b2 <= 1; ++b2)
|
||||||
|
{
|
||||||
|
for (s = 0; s <= 31; ++s)
|
||||||
|
{
|
||||||
|
b3 = (temp[s]+b4) ^ (temp[(s+b4)&31] - encryptkeys[s]);
|
||||||
|
b4 = b4 + b3;
|
||||||
|
temp[s] = b3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= 15; ++i) {
|
||||||
|
target[i] = encrypttable[temp[ 2*i ]]
|
||||||
|
| (encrypttable[temp[ 2*i + 1]] << 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
shuffle(const unsigned char *lon, const unsigned char *buf, int buflen,
|
||||||
|
unsigned char *target)
|
||||||
|
{
|
||||||
|
int b2, d, s;
|
||||||
|
buf32 temp;
|
||||||
|
|
||||||
|
while ( (buflen > 0)
|
||||||
|
&& (buf[buflen - 1] == 0)) {
|
||||||
|
buflen = buflen - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (s = 0; s < 32; s++) {
|
||||||
|
temp[s] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = 0;
|
||||||
|
while (buflen >= 32)
|
||||||
|
{
|
||||||
|
for (s = 0; s <= 31; ++s)
|
||||||
|
{
|
||||||
|
temp[s] = temp[s] ^ buf[d];
|
||||||
|
d = d + 1;
|
||||||
|
}
|
||||||
|
buflen = buflen - 32;
|
||||||
|
}
|
||||||
|
b2 = d;
|
||||||
|
if (buflen > 0)
|
||||||
|
{
|
||||||
|
for (s = 0; s <= 31; ++s)
|
||||||
|
{
|
||||||
|
if (d + buflen == b2)
|
||||||
|
{
|
||||||
|
b2 = d;
|
||||||
|
temp[s] = temp[s] ^ encryptkeys[s];
|
||||||
|
} else {
|
||||||
|
temp[s] = temp[s] ^ buf[b2];
|
||||||
|
b2 = b2 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (s = 0; s <= 31; ++s)
|
||||||
|
temp[s] = temp[s] ^ lon[s & 3];
|
||||||
|
|
||||||
|
shuffle1(temp,target);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
nw_encrypt(const unsigned char *fra,
|
||||||
|
const unsigned char *buf,
|
||||||
|
unsigned char *til)
|
||||||
|
{
|
||||||
|
buf32 k;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
shuffle(&(fra[0]), buf, 16, &(k[ 0]));
|
||||||
|
shuffle(&(fra[4]), buf, 16, &(k[16]));
|
||||||
|
|
||||||
|
for (s = 0; s <= 15; ++s)
|
||||||
|
k[s] = k[s] ^ k[31 - s];
|
||||||
|
|
||||||
|
for (s = 0; s <= 7; ++s)
|
||||||
|
til[s] = k[s] ^ k[15 - s];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* The following code was contributed by */
|
||||||
|
/* Guntram Blohm <gbl%th7csun1@str.daimler-benz.com> */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* server side (mars etc.) should:
|
||||||
|
* store the *encrypted* password internally (output from shuffle)
|
||||||
|
* verify if nw_encrypt(cryptkey from GetCryptKey, old stored password)
|
||||||
|
== cryptkey in EncryptedChangePassword request buffer (this means
|
||||||
|
old password was correct)
|
||||||
|
* decrypt new password in request buffer using (yet to write) inverse of
|
||||||
|
newpassencrypt with old stored password as parameter
|
||||||
|
* compute the length of the unencrypted new password as len ^ (first byte of
|
||||||
|
old internal password) ^ (second byte of old internal password)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char
|
||||||
|
newshuffle[256+16] = {
|
||||||
|
0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
|
||||||
|
0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
|
||||||
|
0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
|
||||||
|
0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
|
||||||
|
|
||||||
|
0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
|
||||||
|
0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
|
||||||
|
0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
|
||||||
|
0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
|
||||||
|
|
||||||
|
0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
|
||||||
|
0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
|
||||||
|
0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
|
||||||
|
0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
|
||||||
|
|
||||||
|
0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
|
||||||
|
0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
|
||||||
|
0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
|
||||||
|
0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
|
||||||
|
|
||||||
|
0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
|
||||||
|
0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
|
||||||
|
0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
|
||||||
|
0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
|
||||||
|
|
||||||
|
0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
|
||||||
|
0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
|
||||||
|
0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
|
||||||
|
0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
|
||||||
|
|
||||||
|
0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
|
||||||
|
0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
|
||||||
|
0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
|
||||||
|
0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
|
||||||
|
|
||||||
|
0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
|
||||||
|
0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
|
||||||
|
0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
|
||||||
|
0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
|
||||||
|
|
||||||
|
0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
|
||||||
|
0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* verschluesseln des neuen Passworts fuer keyed change password
|
||||||
|
* Verwendung:
|
||||||
|
* - Shuffle (aus nwcrypt.c) altes passwort nach old (16 bytes)
|
||||||
|
* - shuffle neues passwort nach new (16 bytes)
|
||||||
|
* - nwpassencrypt (diese Funktion) zweimal aufrufen fuer je 8 bytes:
|
||||||
|
* nwpassencrypt(old+0, new+0, out+0)
|
||||||
|
* nwpassencrypt(old+8, new+8, out+8)
|
||||||
|
* - NCP-Buffer aufbauen:
|
||||||
|
* 2 byte Laenge im Hi-Lo-Format
|
||||||
|
* 1 byte Funktion (0x4b)
|
||||||
|
* 8 byte (nwcrypt Ergebnis analog login/verify password)
|
||||||
|
* 2 byte Objecttype
|
||||||
|
* 1 byte Objectname-Laenge
|
||||||
|
* n byte Objectname
|
||||||
|
* 1 byte (Laenge des eingegebenen neuen Passworts ^ old[0] ^ old[1])&0x7f|0x40
|
||||||
|
* 16 byte (Ergebnis dieser Funktion doppelt aufgerufen, s.o.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encrypt the new password for keyed change password
|
||||||
|
* For info on how to use this function, look at ncp_change_login_passwd
|
||||||
|
* in ncplib.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
newpassencrypt(char *old, char *new, char *out)
|
||||||
|
{
|
||||||
|
char *p, *bx;
|
||||||
|
char copy[8];
|
||||||
|
int i, di, ax;
|
||||||
|
char cl, dl, ch;
|
||||||
|
|
||||||
|
memcpy(copy, new, 8);
|
||||||
|
|
||||||
|
for (i=0; i<16; i++)
|
||||||
|
{
|
||||||
|
for (di=0, ax=0, p=old; di<8; di++, ax+=0x20, p++)
|
||||||
|
{
|
||||||
|
cl=newshuffle[(((copy[di]^*p)>>4)&0x0f)+ax+0x10]<<4;
|
||||||
|
dl=newshuffle[((copy[di]^*p)&0xf)+ax];
|
||||||
|
copy[di]=cl|dl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch=old[7];
|
||||||
|
for (bx=old+7; bx>old; bx--)
|
||||||
|
{
|
||||||
|
*bx=((bx[-1]>>4)&0x0f)|((*bx)<<4);
|
||||||
|
}
|
||||||
|
*old=((ch>>4)&0x0f)|(*old)<<4;
|
||||||
|
|
||||||
|
memset(out, '\0', 8);
|
||||||
|
|
||||||
|
for (di=0; di<16; di++)
|
||||||
|
{
|
||||||
|
if (newshuffle[di+0x100]&1)
|
||||||
|
ch=((copy[newshuffle[di+0x100]/2]>>4)&0x0f);
|
||||||
|
else
|
||||||
|
ch=copy[newshuffle[di+0x100]/2]&0x0f;
|
||||||
|
out[di/2]|=((di&1) ? ch<<4 : ch);
|
||||||
|
}
|
||||||
|
memcpy(copy, out, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
man/Makefile
Normal file
12
man/Makefile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
all:
|
||||||
|
|
||||||
|
dep:
|
||||||
|
|
||||||
|
install:
|
||||||
|
for i in *.1; do install $$i -m 755 /usr/local/man/man1; done
|
||||||
|
for i in *.5; do install $$i -m 755 /usr/local/man/man5; done
|
||||||
|
for i in *.8; do install $$i -m 755 /usr/local/man/man8; done
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~
|
||||||
67
man/ipx_interface.8
Normal file
67
man/ipx_interface.8
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_interface \- add, delete, or display an IPX interface
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_interface
|
||||||
|
add [-p] device frame_type [network number]
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
del device frame_type
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
delall
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
check device frame_type
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
help
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_interface
|
||||||
|
adds, deletes, or displays IPX interfaces depending on the option selected.
|
||||||
|
.P
|
||||||
|
An IPX interface is the item to which IPX sockets are bound.
|
||||||
|
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||||
|
to a physical device and frame type. A sample IPX Interface would be:
|
||||||
|
.LP
|
||||||
|
Network Number: 0x00ABCDEF
|
||||||
|
.LP
|
||||||
|
Device: Eth0
|
||||||
|
.LP
|
||||||
|
Frame Type: 802.2.
|
||||||
|
.P
|
||||||
|
There is a special IPX interface per host known as the
|
||||||
|
.B PRIMARY
|
||||||
|
or default interface.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I add
|
||||||
|
This option is used to create an IPX interface. If the
|
||||||
|
.B -p
|
||||||
|
flag is used, the interface is made
|
||||||
|
.B
|
||||||
|
PRIMARY.
|
||||||
|
The network number can be optionally assigned. If it is not assigned, it
|
||||||
|
is set to 0 which indicates it should be detected from the traffic on the
|
||||||
|
network.
|
||||||
|
.TP
|
||||||
|
.I del
|
||||||
|
This option is used to delete an IPX interface.
|
||||||
|
.TP
|
||||||
|
.I delall
|
||||||
|
This option is used to delete all IPX interfaces.
|
||||||
|
.TP
|
||||||
|
.I check
|
||||||
|
This option is used to display the device, frame type, and network number
|
||||||
|
of an IPX interface.
|
||||||
|
.TP
|
||||||
|
.I help
|
||||||
|
This option displays information about the utility.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
|
.SH BUGS
|
||||||
|
This functionality really belongs in
|
||||||
|
.B
|
||||||
|
ifconfig(8).
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
32
man/ipx_internal_net.8
Normal file
32
man/ipx_internal_net.8
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
.TH IPX_INTERNAL_NET 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_internal_net \- add or delete the IPX internal network
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_internal_net
|
||||||
|
add network_number node_number
|
||||||
|
.LP
|
||||||
|
.B ipx_internal_net
|
||||||
|
del
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_internal_net
|
||||||
|
adds or deletes the IPX internal network.
|
||||||
|
An IPX internal network is a special kind of IPX interface that does
|
||||||
|
not have a physical device or frame type. It is used to provide
|
||||||
|
a route-independent address for service providers. Internal networks
|
||||||
|
are optional; however, when one is present it is also the
|
||||||
|
Primary Interface. There can only be one internal network per host.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I add
|
||||||
|
This option is used to create the IPX internal network.
|
||||||
|
.TP
|
||||||
|
.I del
|
||||||
|
This option is used to delete the IPX internal network.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
|
.SH BUGS
|
||||||
|
This functionality really belongs in
|
||||||
|
.B
|
||||||
|
ifconfig(8).
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
24
man/ipx_route.8
Normal file
24
man/ipx_route.8
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_route \- add or delete IPX route
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_route
|
||||||
|
add target_network router_network router_node
|
||||||
|
.LP
|
||||||
|
.B ipx_route
|
||||||
|
del target_network
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_route
|
||||||
|
adds or deletes an IPX route.
|
||||||
|
The kernel IPX stores only one route per target network at a time.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I add
|
||||||
|
This option is used to set up the route to a target network.
|
||||||
|
.TP
|
||||||
|
.I del
|
||||||
|
This option is used to delete the route to a target network.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
96
man/ncopy.1
Normal file
96
man/ncopy.1
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
.\"
|
||||||
|
.\" Man page for the ncopy program
|
||||||
|
.\"
|
||||||
|
.TH NCOPY 1 17/03/1996 ncopy ncopy
|
||||||
|
.SH NAME
|
||||||
|
ncopy \- NetWare file copy
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ncopy -V
|
||||||
|
|
||||||
|
.B ncopy
|
||||||
|
[
|
||||||
|
.B -vn
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.B -s
|
||||||
|
.I amount
|
||||||
|
]
|
||||||
|
.B file destinationfile|directory
|
||||||
|
|
||||||
|
.B ncopy
|
||||||
|
[
|
||||||
|
.B -vn
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.B -s
|
||||||
|
.I amount
|
||||||
|
]
|
||||||
|
.B file1
|
||||||
|
[
|
||||||
|
.B file2 ...
|
||||||
|
]
|
||||||
|
.B directory
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
With
|
||||||
|
.B ncopy
|
||||||
|
you can copy files to different locations on a single NetWare file
|
||||||
|
server without generating excess network traffic. The program uses
|
||||||
|
a NetWare function to do the copy rather than transferring the file
|
||||||
|
across the network for both the read and write.
|
||||||
|
|
||||||
|
If the last argument is a directory,
|
||||||
|
.B ncopy
|
||||||
|
will copy the source file(s) into the directory. If only two files
|
||||||
|
are given and the last argument is not a directory, it will copy the
|
||||||
|
source file to the destination file.
|
||||||
|
|
||||||
|
If the source and destination files are not on the same NetWare server
|
||||||
|
(or are not on NetWare servers at all),
|
||||||
|
.B ncopy
|
||||||
|
will do a normal file copy.
|
||||||
|
.SH OPTIONS
|
||||||
|
.B -V
|
||||||
|
.RS 3
|
||||||
|
Show version number and exit
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -v
|
||||||
|
.RS 3
|
||||||
|
Verbose copy. Will show current file and percentage completion.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -n
|
||||||
|
.RS 3
|
||||||
|
Nice NetWare copy. Will sleep for a second between copying blocks on
|
||||||
|
the NetWare server. Gives other people a chance to do some work on
|
||||||
|
the NetWare server when you are copying large files. This has no
|
||||||
|
effect if you are not copying on a NetWare server.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -s
|
||||||
|
.I amount
|
||||||
|
.RS 3
|
||||||
|
Nice time slice factor. Used in conjunction with the
|
||||||
|
.B -n
|
||||||
|
option, this specifies the number of 100K blocks to copy before sleeping.
|
||||||
|
Default is 10. (1 Megabyte)
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
.B ncopy
|
||||||
|
cannot recurse into directories.
|
||||||
|
Does not work on NetWare volumes mounted with the
|
||||||
|
.I -V
|
||||||
|
option to
|
||||||
|
.B ncpmount.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.B ncpmount(8), ncpumount(8)
|
||||||
|
|
||||||
|
.SH CREDITS
|
||||||
|
ncopy was written by Brian G. Reid (breid@tim.com) and Tom
|
||||||
|
C. Henderson (thenderson@tim.com). Many thanks to Volker Lendecke
|
||||||
|
(lendecke@math.uni-goettingen.de) for the ncpfs and ncplib which made
|
||||||
|
ncopy possible.
|
||||||
229
man/ncpmount.8
229
man/ncpmount.8
@@ -1,29 +1,27 @@
|
|||||||
.TH NCPMOUNT 8 25/11/1995 ncpmount ncpmount
|
.TH NCPMOUNT 8 12/27/1995 ncpmount ncpmount
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ncpmount \- mount program for ncpfs
|
ncpmount \- mount all volumes of a specified Novell fileserver.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ncpmount
|
.B ncpmount
|
||||||
.B server mount-point
|
|
||||||
[
|
[
|
||||||
.B -h
|
.B -h
|
||||||
] [
|
] [
|
||||||
.B -n
|
.B -S
|
||||||
.I
|
.I server
|
||||||
] [
|
|
||||||
.B -P
|
|
||||||
.I password
|
|
||||||
] [
|
|
||||||
.B -C
|
|
||||||
] [
|
|
||||||
.B -s
|
|
||||||
.I server name
|
|
||||||
] [
|
|
||||||
.B -c
|
|
||||||
.I client name
|
|
||||||
] [
|
] [
|
||||||
.B -U
|
.B -U
|
||||||
.I user name
|
.I user name
|
||||||
] [
|
] [
|
||||||
|
.B -P
|
||||||
|
.I password
|
||||||
|
|
|
||||||
|
.B -n
|
||||||
|
] [
|
||||||
|
.B -C
|
||||||
|
] [
|
||||||
|
.B -c
|
||||||
|
.I client name
|
||||||
|
] [
|
||||||
.B -u
|
.B -u
|
||||||
.I uid
|
.I uid
|
||||||
] [
|
] [
|
||||||
@@ -35,43 +33,69 @@ ncpmount \- mount program for ncpfs
|
|||||||
] [
|
] [
|
||||||
.B -d
|
.B -d
|
||||||
.I dir mode
|
.I dir mode
|
||||||
]
|
] [
|
||||||
|
.B -V
|
||||||
|
.I volume
|
||||||
|
] [
|
||||||
|
.B -t
|
||||||
|
.I time_out
|
||||||
|
] [
|
||||||
|
.B -r
|
||||||
|
.I retry_count
|
||||||
|
] [
|
||||||
|
.B -v
|
||||||
|
]
|
||||||
|
mount-point
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This program is an interface to the NCP filesystem.
|
This program is used to mount all volumes of the specified NetWare Fileserver
|
||||||
|
under the specified mount point.
|
||||||
|
|
||||||
.B ncpfs
|
.B ncpfs
|
||||||
is a filesystem which understands the NCP protocol. This is the
|
is a linux filesystem which understands the NCP protocol. This is the
|
||||||
protocol Novell NetWare clients use to talk to NetWare servers. ncpfs
|
protocol Novell NetWare clients use to talk to NetWare servers. ncpfs
|
||||||
was inspired by
|
was inspired by
|
||||||
.B lwared,
|
.B lwared,
|
||||||
a free NetWare emulator for Linux written by Ales Dryak. See
|
a free NetWare emulator for Linux written by Ales Dryak. See
|
||||||
ftp://klokan.sh.cvut.cz/pub/linux for this very intersting program.
|
ftp://klokan.sh.cvut.cz/pub/linux for this very interesting program.
|
||||||
|
|
||||||
|
.B ncpmount
|
||||||
|
when invoked with all appropriate arguments attaches, logs in and
|
||||||
|
mounts all of the volumes associated with the specified fileserver that are
|
||||||
|
readable by the user id under the specified mount point.
|
||||||
|
.B ncpmount
|
||||||
|
when invoked without any arguments specifying the fileserver, user id and
|
||||||
|
password checks the file
|
||||||
|
.I $HOME/.nwclient
|
||||||
|
to find a file server, a user name and possibly a password to use for the
|
||||||
|
specified mount point. See nwclient(5) for more information. Please note
|
||||||
|
that the access permissions of .nwclient MUST be 600, for security reasons.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.B server
|
|
||||||
.RS 3
|
|
||||||
.B server
|
|
||||||
is the name of the server you want to use on the server.
|
|
||||||
.RE
|
|
||||||
|
|
||||||
.B mount-point
|
.B mount-point
|
||||||
.RS 3
|
.RS 3
|
||||||
.B mount-point
|
.B mount-point
|
||||||
is the directory you want to mount the filesystem over. It's the same
|
is the directory you want to mount the filesystem over. Its function is the
|
||||||
as in the normal mount command.
|
the same as for a normal mount command.
|
||||||
|
|
||||||
If the real uid of the caller is not root,
|
If the real uid of the caller is not root,
|
||||||
.B ncpmount
|
.B ncpmount
|
||||||
checks whether the user is allowed to mount a filesystem on the
|
checks whether the user is allowed to mount a filesystem on the
|
||||||
mount-point. So it should be safe to make
|
mount-point. So it should be safe to make
|
||||||
.B ncpmount
|
.B ncpmount
|
||||||
setuid root. The filesystem stores the uid of the user who called
|
setuid root. The filesystem stores the uid of the user who called
|
||||||
ncpmount. So
|
ncpmount. So
|
||||||
.B ncpumount
|
.B ncpumount
|
||||||
can check whether the caller is allowed to unmount the filesystem.
|
can check whether the caller is allowed to unmount the filesystem.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
.B -S
|
||||||
|
.I server
|
||||||
|
.RS 3
|
||||||
|
.B server
|
||||||
|
is the name of the server you want to use.
|
||||||
|
.RE
|
||||||
|
|
||||||
.B -h
|
.B -h
|
||||||
.RS 3
|
.RS 3
|
||||||
.B -h
|
.B -h
|
||||||
@@ -80,42 +104,40 @@ is used to print out a short help text.
|
|||||||
|
|
||||||
.B -C
|
.B -C
|
||||||
.RS 3
|
.RS 3
|
||||||
By default, passwords are converted to uppercase before they are sent
|
By default passwords are converted to uppercase before they are sent
|
||||||
to the server, because most servers require this. You can turn off
|
to the server because most servers require this. This option disables this
|
||||||
this conversion by
|
feature ensuring that passwords are sent without any case conversion.
|
||||||
.B -C.
|
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.B -n
|
.B -n
|
||||||
.RS 3
|
.RS 3
|
||||||
.B -n
|
.B -n
|
||||||
should be given to mount shares which do not require a password to log in.
|
must be specified for logins that do not have a password configured.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.B -P
|
.B -P
|
||||||
.I password
|
.I password
|
||||||
.RS 3
|
.RS 3
|
||||||
You may want to give the password required by the server on the
|
specifies the password to use for the Netware user id.
|
||||||
command line. You should be careful to use passwords in scripts.
|
|
||||||
|
|
||||||
If neither
|
If neither
|
||||||
.B -n
|
.B -n
|
||||||
nor
|
nor the
|
||||||
.B -P
|
.B -P
|
||||||
are given, ncpmount prompts for a password. This makes it difficult to
|
arguments are specified ncpmount will prompt for a password. This
|
||||||
use in scripts such as /etc/rc. But that's not ncpmount's fault, but a
|
makes it difficult to use in scripts such as /etc/rc. If you want to
|
||||||
general problem with the fact that you need a password on every
|
have ncpmount work automatically from a script you must include the
|
||||||
login. If anybody has a satisfying solution to this problem, please
|
appropriate option and be very careful to ensure that appopriate file
|
||||||
tell me.
|
permissions are set for the script that includes your password to
|
||||||
|
ensure that others can not read it.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.B -U
|
.B -U
|
||||||
.I user name
|
.I user name
|
||||||
.RS 3
|
.RS 3
|
||||||
If the user name your NetWare administrator gave to you differs
|
Specifies the Netware user id to use when logging in to the fileserver. If
|
||||||
from your unix user-id, you should use
|
this option is not specified then ncpmount will attempt to login to the
|
||||||
.B -U
|
fileserver using the Linux login id of the user invoking ncpmount.
|
||||||
to tell the server about you NetWare user name.
|
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.B -u
|
.B -u
|
||||||
@@ -123,18 +145,37 @@ to tell the server about you NetWare user name.
|
|||||||
.B -g
|
.B -g
|
||||||
.I gid
|
.I gid
|
||||||
.RS 3
|
.RS 3
|
||||||
Currently I did not implement a mapping from NetWare users/groups to
|
ncpmount does not yet implement a scheme for mapping NetWare users/groups
|
||||||
unix users/groups. Unix requires that each file has an owner
|
to Linux users/groups. Linux requires that each file has an owner and group id.
|
||||||
and a group it belongs to. With
|
With
|
||||||
.B -u
|
.B -u
|
||||||
and
|
and
|
||||||
.B -g
|
.B -g
|
||||||
you can tell ncpmount which id's it should assign to the files in the
|
you can tell ncpmount which id's it should assign to the files in the
|
||||||
mounted direcory.
|
mounted directory.
|
||||||
|
|
||||||
The defaults for these values are the current uid and gid.
|
The defaults for these values are the current uid and gid.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
.B -c
|
||||||
|
.I user name
|
||||||
|
.RS 3
|
||||||
|
.B -c
|
||||||
|
names the user who is the
|
||||||
|
.I owner
|
||||||
|
of the connection, where owner does not refer to file ownership (that
|
||||||
|
"owner" is set by the -u argument), but the owner of the mount, ie: who
|
||||||
|
is allowed to call ncpumount on this mount. The default owner of the
|
||||||
|
connection and the mount is the user who called ncpmount. This option
|
||||||
|
allows you to specify that some other user should be set as the owner.
|
||||||
|
|
||||||
|
In this this way it is possible to mount a public read-only directory,
|
||||||
|
but to allow the lp daemon to print on NetWare queues. This is
|
||||||
|
possible because only users who have write permissions on a directory
|
||||||
|
may issue ncp requests over a connection. The exception to this rule
|
||||||
|
is the 'mount owner', who is also granted 'request permission'.
|
||||||
|
.RE
|
||||||
|
|
||||||
.B -f
|
.B -f
|
||||||
.I file mode,
|
.I file mode,
|
||||||
.B -d
|
.B -d
|
||||||
@@ -144,14 +185,11 @@ Like
|
|||||||
.B -u
|
.B -u
|
||||||
and
|
and
|
||||||
.B -g,
|
.B -g,
|
||||||
these options are also used to cover deficiencies in the
|
these options are used to determine what permissions should be assigned
|
||||||
implementation of ncpfs. I did not implement a scheme to map NetWare
|
files and directories of the mounted volumes. The values must be specified
|
||||||
permissions to unix permissions. So ncpmount has to be told which
|
as octal numbers. The default values are taken from the current umask, where
|
||||||
permissions it should assign to the mounted files and direcories. The
|
the file mode is the current umask, and the dir mode adds execute permissions
|
||||||
values have to be given as octal numbers. The default values are taken
|
where the file mode gives read permissions.
|
||||||
from the current umask, where the file mode is the current umask, and
|
|
||||||
the dir mode adds execute permissions where the file mode gives read
|
|
||||||
permissions.
|
|
||||||
|
|
||||||
Note that these permissions can differ from the rights the server
|
Note that these permissions can differ from the rights the server
|
||||||
gives to us. If you do not have write permissions on the server, you
|
gives to us. If you do not have write permissions on the server, you
|
||||||
@@ -159,14 +197,81 @@ 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 -t
|
||||||
|
.I time_out
|
||||||
|
.RS 3
|
||||||
|
With
|
||||||
|
.B -t
|
||||||
|
you can adjust the time ncpfs waits for the server to answer a request
|
||||||
|
it sent. Use the option to raise the timeout value when your ncpfs
|
||||||
|
connections seem to be unstable although your servers are well
|
||||||
|
up. This can happen when you have very busy servers, or servers that
|
||||||
|
are very far away.
|
||||||
|
|
||||||
|
.I time_out
|
||||||
|
is specified in 1/100s, the current default value is 60.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -r
|
||||||
|
.I retry_count
|
||||||
|
.RS 3
|
||||||
|
As
|
||||||
|
.B -t, -r
|
||||||
|
can be used to tune the ncpfs connection to the server. With
|
||||||
|
retry_count you can specify how many times ncpfs will attempt to send
|
||||||
|
a packet to the server before it decides the connection is dead. The
|
||||||
|
current default value is 5.
|
||||||
|
|
||||||
|
Currently ncpfs is not too clever when trying to find out that
|
||||||
|
connections are dead. If anybody knows how to do that correctly, as it
|
||||||
|
is done by commercial workstations, please tell me.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -v
|
||||||
|
.RS 3
|
||||||
|
Print ncpfs version number
|
||||||
|
.RE
|
||||||
|
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
If you have difficulties in mounting, please make sure that you have configured your ipx subsystem correctly. It is especially important that there is a route to the internal network of your server.
|
You must configure the IPX subsystem before ncpmount will work.
|
||||||
|
It is especially important that there is a route to the internal network
|
||||||
|
of your server.
|
||||||
|
|
||||||
.SH ENVIRONMENT VARIABLES
|
.SH ENVIRONMENT VARIABLES
|
||||||
.B USER / LOGNAME
|
.B USER / LOGNAME
|
||||||
.RS 3
|
.RS 3
|
||||||
The variables USER or LOGNAME may contain the username of the person
|
The variables USER or LOGNAME may contain the username of the person
|
||||||
using the client. USER is tried first. If it's emtpy, LOGNAME is
|
using the client. USER is tried first. If it's empty, LOGNAME is
|
||||||
tried.
|
tried.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
@@ -176,7 +281,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
|
||||||
@@ -186,5 +291,5 @@ The encryption code was taken from Dr. Dobbs's Journal 11/93. There
|
|||||||
Pawel Szczerbina described it in an article on NCP.
|
Pawel Szczerbina described it in an article on NCP.
|
||||||
|
|
||||||
The ncpfs code was initially hacked from smbfs by Volker Lendecke
|
The ncpfs code was initially hacked from smbfs by Volker Lendecke
|
||||||
(lendecke@namu01.gwdg.de). smbfs was put together by Paal-Kr. Engstad
|
(lendecke@math.uni-goettingen.de). smbfs was put together by Paal-Kr. Engstad
|
||||||
(pke@engstad.ingok.hitos.no) and later polished by Volker.
|
(pke@engstad.ingok.hitos.no) and later polished by Volker.
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
.TH NCPUMOUNT 8 25/11/1995 ncpumount ncpumount
|
.TH NCPUMOUNT 8 12/27/1995 ncpumount ncpumount
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ncpumount \- umount for normal users
|
ncpumount \- unmount a NetWare filesystem mounted with ncpmount.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ncpumount
|
.B ncpumount
|
||||||
.B mount-point
|
.B mount-point
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
With this program, normal users can unmount ncp-filesystems, provided
|
This utility unmounts a NetWare filesystem that was previously mounted
|
||||||
that it is suid root.
|
with the ncpmount utility. If the this utility is made suid root then
|
||||||
|
non-root users will also be able to make use of it.
|
||||||
|
|
||||||
.B ncpumount
|
.B ncpumount
|
||||||
has been written to give normal linux-users more control over their
|
has been written to give normal linux-users more control over their
|
||||||
|
|||||||
222
man/nprint.1
Normal file
222
man/nprint.1
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
.TH NPRINT 1 12/27/1995 nprint nprint
|
||||||
|
.SH NAME
|
||||||
|
nprint \- NetWare print client
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B nprint
|
||||||
|
[
|
||||||
|
.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 -d
|
||||||
|
.I job description
|
||||||
|
] [
|
||||||
|
.B -p
|
||||||
|
.I path name
|
||||||
|
] [
|
||||||
|
.B -b
|
||||||
|
.I banner name
|
||||||
|
] [
|
||||||
|
.B -f
|
||||||
|
.I file name in banner
|
||||||
|
] [
|
||||||
|
.B -l
|
||||||
|
.I lines
|
||||||
|
] [
|
||||||
|
.B -r
|
||||||
|
.I rows
|
||||||
|
] [
|
||||||
|
.B -c
|
||||||
|
.I copies
|
||||||
|
] [
|
||||||
|
.B -t
|
||||||
|
.I tab size
|
||||||
|
] [
|
||||||
|
.B -T
|
||||||
|
] [
|
||||||
|
.B -N
|
||||||
|
] [
|
||||||
|
.B -F
|
||||||
|
.I form number
|
||||||
|
]
|
||||||
|
.B file
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
With
|
||||||
|
.B nprint,
|
||||||
|
you can print files on print queues of a NetWare file server.
|
||||||
|
|
||||||
|
There are a lot of options, so you should probably wrap some default
|
||||||
|
configurations into some shell scripts.
|
||||||
|
|
||||||
|
.B nprint
|
||||||
|
looks up the file
|
||||||
|
.I $HOME/.nwclient
|
||||||
|
to find a file server, a user name and possibly a password. See
|
||||||
|
nwclient(5) for more information. Please note that the access
|
||||||
|
permissions of .nwclient MUST be 600, for security reasons.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
.B file
|
||||||
|
.RS 3
|
||||||
|
.B file
|
||||||
|
is the name of the file you want to print. If file is '-', or no
|
||||||
|
filename is given, standard input is used.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.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 user name to use for the print request at the server.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -P
|
||||||
|
.I password
|
||||||
|
.RS 3
|
||||||
|
.B password
|
||||||
|
is the password to use for the print request at the server. If neither
|
||||||
|
.B -n
|
||||||
|
nor
|
||||||
|
.B -P
|
||||||
|
are given, and the user has no open connection to the server, nprint
|
||||||
|
prompts for a password.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -n
|
||||||
|
.RS 3
|
||||||
|
.B -n
|
||||||
|
should be given if no password is required for the print request.
|
||||||
|
.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 to use at the print server. At
|
||||||
|
present, you must specify it in upper case characters.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -d
|
||||||
|
.I job description
|
||||||
|
.RS 3
|
||||||
|
.B job description
|
||||||
|
is the string that appears in pconsole when you list the jobs for the
|
||||||
|
print queue. It is also printed somewhere on the top of the banner
|
||||||
|
page.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -p
|
||||||
|
.I pathname
|
||||||
|
.RS 3
|
||||||
|
.B pathname
|
||||||
|
is the string you want to be printed on the banner page in the field
|
||||||
|
'path'.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -b
|
||||||
|
.I bannername
|
||||||
|
.RS 3
|
||||||
|
.B bannername
|
||||||
|
is the string (up to 12 characters) you want to appear on the lower
|
||||||
|
part of the banner page.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -f
|
||||||
|
.I filename
|
||||||
|
.RS 3
|
||||||
|
.B filename
|
||||||
|
is the string (up to 12 characters) you want to appear on the upper
|
||||||
|
part of the banner page. Default: the name of the file that is
|
||||||
|
printed, or 'stdin'.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -l
|
||||||
|
.I lines
|
||||||
|
.RS 3
|
||||||
|
.B lines
|
||||||
|
is the number of lines to put on one page. Default: 66
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -r
|
||||||
|
.I rows
|
||||||
|
.RS 3
|
||||||
|
.B rows
|
||||||
|
is the number of rows to put on one page. Default: 80
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -c
|
||||||
|
.I copies
|
||||||
|
.RS 3
|
||||||
|
.B copies
|
||||||
|
tells the print server to the specified number of copies. Default: 1
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -t
|
||||||
|
.I tabs
|
||||||
|
.RS 3
|
||||||
|
.B tabs
|
||||||
|
is the number of spaces to print for a Tab-Character. Default: 8
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -T
|
||||||
|
.RS 3
|
||||||
|
tells the print server to expand Tab-Character and use 8 spaces
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -N
|
||||||
|
.RS 3
|
||||||
|
tells the print server
|
||||||
|
.B not
|
||||||
|
to use Form Feeds
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -F
|
||||||
|
.I form number
|
||||||
|
.RS 3
|
||||||
|
.B form number
|
||||||
|
is the the number of the form to be put into the printer. If it's
|
||||||
|
different from the one currently in the printer, your job is only
|
||||||
|
printed if a printer operator has put in the correct form.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
|
||||||
|
|
||||||
|
.SH CREDITS
|
||||||
|
nprint was written by Volker Lendecke (lendecke@math.uni-goettingen.de)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user